@enigmax/primitives 0.24.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.
Files changed (59) hide show
  1. package/dist/chunk-4SZ5N7BA.js +121 -0
  2. package/dist/chunk-EYZ366LP.js +189 -0
  3. package/dist/chunk-ISXB5RUH.js +380 -0
  4. package/dist/chunk-JJVZYW5C.js +946 -0
  5. package/dist/chunk-KVLSOQTI.js +66 -0
  6. package/dist/chunk-QIIV2QSV.js +108 -0
  7. package/dist/{chunk-QJJ34E4G.js → chunk-RMNXVWQ4.js} +32 -15
  8. package/dist/chunk-RUEQ3TGP.js +155 -0
  9. package/dist/clipboard-menu-BvXJCSFN.d.ts +93 -0
  10. package/dist/{color-OPV3BJV6.js → color-T63FLJNH.js} +183 -120
  11. package/dist/context-BfjYGPnH.d.ts +54 -0
  12. package/dist/{clipboard-menu-B_ouitfS.d.ts → context-menu-D3FtTn7v.d.ts} +1 -91
  13. package/dist/{index-ZPvlf9vs.d.ts → index-qXOkYQCU.d.ts} +4 -0
  14. package/dist/index.d.ts +266 -2
  15. package/dist/index.js +4 -2
  16. package/dist/menu-MSQSE6U5.js +54 -0
  17. package/dist/menu-PNQRTRNV.js +33 -0
  18. package/dist/next/index.d.ts +7 -3
  19. package/dist/next/index.js +11 -7
  20. package/dist/react/context-menu.d.ts +8 -54
  21. package/dist/react/image.d.ts +109 -0
  22. package/dist/react/image.js +3 -0
  23. package/dist/react/index.d.ts +8 -4
  24. package/dist/react/index.js +11 -7
  25. package/dist/react/input.d.ts +1 -1
  26. package/dist/react/input.js +2 -2
  27. package/dist/react/video.d.ts +120 -0
  28. package/dist/react/video.js +3 -0
  29. package/dist/react-router/index.d.ts +7 -3
  30. package/dist/react-router/index.js +11 -7
  31. package/dist/viewer-73LSE6RR.js +3 -0
  32. package/package.json +15 -2
  33. package/recipes/color/styles.css +20 -0
  34. package/recipes/image/styles.css +182 -0
  35. package/recipes/video/styles.css +154 -0
  36. package/registry.json +477 -3
  37. package/src/core/image-viewer.ts +222 -0
  38. package/src/core/player.ts +303 -0
  39. package/src/index.ts +52 -0
  40. package/src/react/image/icons.tsx +55 -0
  41. package/src/react/image/index.tsx +185 -0
  42. package/src/react/image/menu.tsx +76 -0
  43. package/src/react/image/styles.ts +213 -0
  44. package/src/react/image/types.ts +113 -0
  45. package/src/react/image/viewer.tsx +571 -0
  46. package/src/react/index.ts +3 -0
  47. package/src/react/input/color-styles.ts +20 -0
  48. package/src/react/input/color-swatch.tsx +96 -0
  49. package/src/react/input/color.tsx +84 -23
  50. package/src/react/input/index.tsx +27 -4
  51. package/src/react/input/types.ts +4 -0
  52. package/src/react/video/icons.tsx +135 -0
  53. package/src/react/video/index.tsx +724 -0
  54. package/src/react/video/menu.tsx +66 -0
  55. package/src/react/video/rail.tsx +99 -0
  56. package/src/react/video/styles.ts +161 -0
  57. package/src/react/video/types.ts +135 -0
  58. package/dist/chunk-S7EE57YB.js +0 -9
  59. /package/dist/{chunk-MSOCCQGH.js → chunk-T7I6WJSN.js} +0 -0
@@ -7,8 +7,8 @@ export { UseSearchResult, useSearch } from './search.js';
7
7
  export { F as FuseConstructor, a as FuseLike, S as SearchInstance, b as SearchMatch, c as SearchOptions, s as shortenQuery } from '../search-DYgqRp37.js';
8
8
  import { d as ButtonState, c as ButtonOptions } from '../button-CaXaqG_K.js';
9
9
  export { Button, ButtonProps } from './button.js';
10
- import { h as PasswordStrengthClassNames } from '../index-ZPvlf9vs.js';
11
- export { B as BreachChecker, a as BreachState, b as BreachStatus, C as ColorLabels, c as ColorOnlyProps, d as ColorPanelPlacement, F as FieldAction, I as Input, e as InputBaseProps, f as InputProps, g as InputType, P as PasswordOnlyProps, i as PlainOnlyProps, S as SearchOnlyProps } from '../index-ZPvlf9vs.js';
10
+ import { h as PasswordStrengthClassNames } from '../index-qXOkYQCU.js';
11
+ export { B as BreachChecker, a as BreachState, b as BreachStatus, C as ColorLabels, c as ColorOnlyProps, d as ColorPanelPlacement, F as FieldAction, I as Input, e as InputBaseProps, f as InputProps, g as InputType, P as PasswordOnlyProps, i as PlainOnlyProps, S as SearchOnlyProps } from '../index-qXOkYQCU.js';
12
12
  import { c as PasswordStrengthReport } from '../color-D_rZ83Oc.js';
13
13
  export { C as ColorFormat, E as EstimateOptions, F as FormatColorOptions, G as GeneratePasswordOptions, H as Hsl, a as Hsv, b as PasswordScore, R as Rgb, d as colorEquals, e as estimatePasswordStrength, f as formatColor, g as generatePassword, h as hslToRgb, i as hsvToRgb, p as parseColor, r as rgbToHsl, j as rgbToHsv, t as toHex } from '../color-D_rZ83Oc.js';
14
14
  export { Slot, SlotProps, mergeSlotProps } from './slot.js';
@@ -25,11 +25,15 @@ export { PaletteContent, PaletteContextValue, PaletteField, PaletteFooter, Palet
25
25
  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';
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
- export { ContextMenu, ContextMenuContent, ContextMenuContentProps, ContextMenuContextValue, ContextMenuItem, ContextMenuList, ContextMenuNode, ContextMenuPanel, ContextMenuProps, ContextMenuRoot, ContextMenuRootProps, ContextMenuRow, ContextMenuSearch, ContextMenuTrigger, ContextMenuTriggerProps, useContextMenuContext } from './context-menu.js';
29
- export { C as CLIPBOARD_PREFIX, b as ClipboardAction, c as ClipboardMenuLabels, d as ClipboardMenuOptions, e as ClipboardTarget, f as ContextMenuAction, g as ContextMenuEntry, h as ContextMenuInstance, l as ContextMenuOptions, o as ContextMenuState, p as clipboardAction, q as clipboardEntries, r as clipboardHasText, s as createContextMenu, t as inspectClipboardTarget, u as isAction, v as performClipboardAction } from '../clipboard-menu-B_ouitfS.js';
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-BvXJCSFN.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-D3FtTn7v.js';
30
31
  export { MarqueeRect, SelectionList, SelectionListProps, SelectionRenderer, SelectionRowRender, UseSelectionOptions, UseSelectionResult, useSelection } from './selection.js';
31
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';
32
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
+ export { Image, ImageItem, ImageLabels, ImageMenuOptions, ImageProps, ImageSource, ZoomOptions } from './image.js';
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-BfjYGPnH.js';
33
37
 
34
38
  interface UseInputResult {
35
39
  /** Attach to the `<input>`. */
@@ -1,29 +1,33 @@
1
1
  "use client";
2
- export { useInput } from '../chunk-MSOCCQGH.js';
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
  export { Button, getLinkComponent, setLinkComponent, useButton } from '../chunk-6BGBYUSZ.js';
8
13
  export { Flag } from '../chunk-NPHRS2Q7.js';
9
14
  export { Toaster, toast, useSonner } from '../chunk-WPTBURIC.js';
10
15
  export { createNotificationQueue, defaultQueue, useNotifications } from '../chunk-QYMUIW5I.js';
11
16
  export { useMarquee } from '../chunk-ZWR2EXHQ.js';
12
- export { useSearch } from '../chunk-45UHLZYT.js';
13
- export { useNetworkState } from '../chunk-S653GLSF.js';
14
17
  import '../chunk-KJINGUQN.js';
18
+ export { colorEquals, formatColor, hslToRgb, hsvToRgb, parseColor, rgbToHsl, rgbToHsv, toHex } from '../chunk-S2FPN5ID.js';
19
+ import '../chunk-2QFTRNAZ.js';
15
20
  import '../chunk-IXVMRVD4.js';
16
21
  export { estimatePasswordStrength, generatePassword } from '../chunk-HC2ME5PU.js';
17
- export { colorEquals, formatColor, hslToRgb, hsvToRgb, parseColor, rgbToHsl, rgbToHsv, toHex } from '../chunk-S2FPN5ID.js';
18
22
  export { CLIPBOARD_PREFIX, clipboardAction, clipboardEntries, clipboardHasText, createContextMenu, inspectClipboardTarget, isAction, performClipboardAction } from '../chunk-Z3VDE7OA.js';
19
23
  export { DEFAULT_SELECTION_SHORTCUTS, createSelection } from '../chunk-WSQC3PCC.js';
24
+ import '../chunk-RUEQ3TGP.js';
20
25
  import '../chunk-MMQPZGSU.js';
21
26
  export { configureFlags, flagAttributes, flagName, flagSrc, flagView, normalizeFlagCode } from '../chunk-LMZJBOZG.js';
22
27
  import '../chunk-SNYUBXWQ.js';
23
28
  import '../chunk-UOSSNUSC.js';
24
- import '../chunk-2QFTRNAZ.js';
25
- export { Input } from '../chunk-QJJ34E4G.js';
26
- import '../chunk-S7EE57YB.js';
29
+ export { Input } from '../chunk-RMNXVWQ4.js';
30
+ import '../chunk-KVLSOQTI.js';
27
31
  import '../chunk-F25CGNQC.js';
28
32
  export { PaletteContent, PaletteField, PaletteFooter, PaletteItem, PaletteList, PaletteRoot, PaletteTrigger, SearchPalette, usePaletteContext } from '../chunk-FGBIZDV2.js';
29
33
  export { Select, SelectContent, SelectList, SelectOptionRow, SelectRoot, SelectSearch, SelectTrigger, SelectValue, useSelectContext } from '../chunk-VKL3DEIQ.js';
@@ -1,4 +1,4 @@
1
- export { B as BreachChecker, a as BreachState, b as BreachStatus, C as ColorLabels, c as ColorOnlyProps, d as ColorPanelPlacement, F as FieldAction, I as Input, e as InputBaseProps, f as InputProps, g as InputType, P as PasswordOnlyProps, i as PlainOnlyProps, S as SearchOnlyProps } from '../index-ZPvlf9vs.js';
1
+ export { B as BreachChecker, a as BreachState, b as BreachStatus, C as ColorLabels, c as ColorOnlyProps, d as ColorPanelPlacement, F as FieldAction, I as Input, e as InputBaseProps, f as InputProps, g as InputType, P as PasswordOnlyProps, i as PlainOnlyProps, S as SearchOnlyProps } from '../index-qXOkYQCU.js';
2
2
  import 'react';
3
3
  import '../color-D_rZ83Oc.js';
4
4
  import '../search-DYgqRp37.js';
@@ -1,4 +1,4 @@
1
1
  "use client";
2
- export { Input } from '../chunk-QJJ34E4G.js';
3
- import '../chunk-S7EE57YB.js';
2
+ export { Input } from '../chunk-RMNXVWQ4.js';
3
+ import '../chunk-KVLSOQTI.js';
4
4
  import '../chunk-F25CGNQC.js';
@@ -0,0 +1,120 @@
1
+ import { ComponentPropsWithoutRef, ReactNode } from 'react';
2
+ import { b as ContextMenuNode, a as ContextMenuItem } from '../context-BfjYGPnH.js';
3
+ import '../context-menu-D3FtTn7v.js';
4
+ import '../search-DYgqRp37.js';
5
+
6
+ /**
7
+ * The prop shapes for `<Video>`.
8
+ *
9
+ * Shaped after Plyr, which is the player this one is measured against: the same control set,
10
+ * the same shortcuts, the same auto-hiding bar. What differs is that the controls are the
11
+ * component's own markup rather than a string of HTML it parses, so a project styles them
12
+ * with the attributes below instead of overriding a stylesheet it did not write.
13
+ */
14
+
15
+ interface VideoSource {
16
+ src: string;
17
+ /** `video/mp4`, `video/webm`. The browser picks the first one it can play. */
18
+ type?: string;
19
+ }
20
+ interface VideoTrack {
21
+ src: string;
22
+ /** BCP 47: `en`, `es-419`. */
23
+ srcLang: string;
24
+ label: string;
25
+ kind?: "subtitles" | "captions" | "descriptions" | "chapters" | "metadata";
26
+ default?: boolean;
27
+ }
28
+ /** Which controls the bar carries. Everything is on except `download`, as Plyr has it. */
29
+ interface VideoControls {
30
+ play?: boolean;
31
+ progress?: boolean;
32
+ currentTime?: boolean;
33
+ duration?: boolean;
34
+ volume?: boolean;
35
+ captions?: boolean;
36
+ settings?: boolean;
37
+ pip?: boolean;
38
+ /** Play on a TV. Feature-detected, and absent until the browser reports a screen to cast to. */
39
+ cast?: boolean;
40
+ fullscreen?: boolean;
41
+ /** Off by default: a video a page shows is not always one it means to hand over. */
42
+ download?: boolean;
43
+ }
44
+ interface VideoLabels {
45
+ play?: string;
46
+ pause?: string;
47
+ mute?: string;
48
+ unmute?: string;
49
+ volume?: string;
50
+ seek?: string;
51
+ captions?: string;
52
+ /** The row that turns subtitles off. Default "Off". */
53
+ captionsOff?: string;
54
+ /** The heading over the language rows. Default "Subtitles". */
55
+ subtitles?: string;
56
+ settings?: string;
57
+ speed?: string;
58
+ normal?: string;
59
+ pip?: string;
60
+ cast?: string;
61
+ /** While it is playing on the other screen. Default "Stop casting". */
62
+ stopCast?: string;
63
+ /** The context menu's rows. */
64
+ loop?: string;
65
+ copyUrl?: string;
66
+ copyUrlAtTime?: string;
67
+ enterFullscreen?: string;
68
+ exitFullscreen?: string;
69
+ download?: string;
70
+ /** The player itself, as a screen reader announces the region. Default "Video player". */
71
+ player?: string;
72
+ }
73
+ interface VideoProps extends Omit<ComponentPropsWithoutRef<"video">, "controls" | "children" | "src" | "contextMenu"> {
74
+ /** One file, or the list the browser should choose from. */
75
+ src?: string | readonly VideoSource[];
76
+ poster?: string;
77
+ tracks?: readonly VideoTrack[];
78
+ /** The control bar. `false` leaves a bare `<video>` with nothing over it. */
79
+ controls?: boolean | VideoControls;
80
+ /** Rates the settings menu offers. Defaults to Plyr's 0.5 through 2. */
81
+ speeds?: readonly number[];
82
+ /** Space, arrows, M, F, C and the digits. On by default, and never while typing. */
83
+ keyboard?: boolean;
84
+ /** A press on the picture plays and pauses. On by default. */
85
+ clickToPlay?: boolean;
86
+ /** Hide the bar while playing, until the pointer moves. On by default. */
87
+ autoHide?: boolean;
88
+ /** How long the pointer has to be still before the bar goes, in ms. Default 2600. */
89
+ autoHideDelay?: number;
90
+ /**
91
+ * The menu a right-click opens, shaped the way YouTube's is. ON by default.
92
+ *
93
+ * `false` gives the browser's own menu back - which is what a page wants when the point of
94
+ * the video is that it can be saved from the native menu.
95
+ */
96
+ contextMenu?: boolean | VideoContextMenuOptions;
97
+ /** The player's stylesheet, injected once. There is no useful unstyled player. */
98
+ styles?: boolean;
99
+ labels?: VideoLabels;
100
+ /** The URL the download control saves. Defaults to what is playing. */
101
+ download?: string;
102
+ /** Rendered over the picture, under the controls - a title, a badge, your own overlay. */
103
+ children?: ReactNode;
104
+ /** Props for the element wrapping the video and its controls; this is what you size. */
105
+ wrapperProps?: ComponentPropsWithoutRef<"div">;
106
+ }
107
+ interface VideoContextMenuOptions {
108
+ /** Rows of your own, after the built-in ones. */
109
+ items?: readonly ContextMenuNode[];
110
+ /** A row was invoked - yours, or one of the built-in ids. */
111
+ onSelect?: (item: ContextMenuItem) => void;
112
+ /** The two "copy the link" rows. On whenever the menu is, where there is a URL to copy. */
113
+ copyUrl?: boolean;
114
+ /** The heading over the rows, naming what the menu is acting on. */
115
+ title?: string;
116
+ }
117
+
118
+ declare function Video(props: VideoProps): ReactNode;
119
+
120
+ export { Video, type VideoContextMenuOptions, type VideoControls, type VideoLabels, type VideoProps, type VideoSource, type VideoTrack };
@@ -0,0 +1,3 @@
1
+ "use client";
2
+ export { Video } from '../chunk-JJVZYW5C.js';
3
+ import '../chunk-RUEQ3TGP.js';
@@ -7,7 +7,7 @@ export { UseSearchResult, useSearch } from '../react/search.js';
7
7
  export { I as InputAction, b as InputIcon, d as InputOptions } from '../input-BwXjFenq.js';
8
8
  export { F as FuseConstructor, a as FuseLike, S as SearchInstance, b as SearchMatch, c as SearchOptions, s as shortenQuery } from '../search-DYgqRp37.js';
9
9
  export { c as ButtonOptions, d as ButtonState } from '../button-CaXaqG_K.js';
10
- export { B as BreachChecker, a as BreachState, b as BreachStatus, C as ColorLabels, c as ColorOnlyProps, d as ColorPanelPlacement, F as FieldAction, I as Input, e as InputBaseProps, f as InputProps, g as InputType, P as PasswordOnlyProps, i as PlainOnlyProps, S as SearchOnlyProps } from '../index-ZPvlf9vs.js';
10
+ export { B as BreachChecker, a as BreachState, b as BreachStatus, C as ColorLabels, c as ColorOnlyProps, d as ColorPanelPlacement, F as FieldAction, I as Input, e as InputBaseProps, f as InputProps, g as InputType, P as PasswordOnlyProps, i as PlainOnlyProps, S as SearchOnlyProps } from '../index-qXOkYQCU.js';
11
11
  export { C as ColorFormat, E as EstimateOptions, F as FormatColorOptions, G as GeneratePasswordOptions, H as Hsl, a as Hsv, b as PasswordScore, c as PasswordStrengthReport, R as Rgb, d as colorEquals, e as estimatePasswordStrength, f as formatColor, g as generatePassword, h as hslToRgb, i as hsvToRgb, p as parseColor, r as rgbToHsl, j as rgbToHsv, t as toHex } from '../color-D_rZ83Oc.js';
12
12
  export { Slot, SlotProps, mergeSlotProps } from '../react/slot.js';
13
13
  export { UseNotificationsResult, createNotificationQueue, defaultQueue, useNotifications } from '../react/notifications.js';
@@ -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, ContextMenuContextValue, ContextMenuItem, ContextMenuList, ContextMenuNode, ContextMenuPanel, ContextMenuProps, ContextMenuRoot, ContextMenuRootProps, ContextMenuRow, ContextMenuSearch, ContextMenuTrigger, ContextMenuTriggerProps, useContextMenuContext } from '../react/context-menu.js';
27
- export { C as CLIPBOARD_PREFIX, b as ClipboardAction, c as ClipboardMenuLabels, d as ClipboardMenuOptions, e as ClipboardTarget, f as ContextMenuAction, g as ContextMenuEntry, h as ContextMenuInstance, l as ContextMenuOptions, o as ContextMenuState, p as clipboardAction, q as clipboardEntries, r as clipboardHasText, s as createContextMenu, t as inspectClipboardTarget, u as isAction, v as performClipboardAction } from '../clipboard-menu-B_ouitfS.js';
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
  declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLElement>>;
33
37
 
@@ -1,30 +1,34 @@
1
1
  "use client";
2
- export { useInput } from '../chunk-MSOCCQGH.js';
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
- import '../chunk-2QFTRNAZ.js';
26
- export { Input } from '../chunk-QJJ34E4G.js';
27
- import '../chunk-S7EE57YB.js';
30
+ export { Input } from '../chunk-RMNXVWQ4.js';
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';
30
34
  export { Select, SelectContent, SelectList, SelectOptionRow, SelectRoot, SelectSearch, SelectTrigger, SelectValue, useSelectContext } from '../chunk-VKL3DEIQ.js';
@@ -0,0 +1,3 @@
1
+ export { ImageViewer, MenuButton } from './chunk-ISXB5RUH.js';
2
+ import './chunk-QIIV2QSV.js';
3
+ import './chunk-EYZ366LP.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@enigmax/primitives",
3
- "version": "0.24.0",
3
+ "version": "0.26.0",
4
4
  "description": "Headless components: the behaviour, the timing and the accessibility, with no styles of their own. Framework-agnostic core plus thin adapters.",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -37,6 +37,14 @@
37
37
  "types": "./dist/react/selection.d.ts",
38
38
  "import": "./dist/react/selection.js"
39
39
  },
40
+ "./react/image": {
41
+ "types": "./dist/react/image.d.ts",
42
+ "import": "./dist/react/image.js"
43
+ },
44
+ "./react/video": {
45
+ "types": "./dist/react/video.d.ts",
46
+ "import": "./dist/react/video.js"
47
+ },
40
48
  "./react/button": {
41
49
  "types": "./dist/react/button.d.ts",
42
50
  "import": "./dist/react/button.js"
@@ -90,6 +98,8 @@
90
98
  "./toast.css": "./recipes/toast/styles.css",
91
99
  "./input.css": "./recipes/input/styles.css",
92
100
  "./color.css": "./recipes/color/styles.css",
101
+ "./image.css": "./recipes/image/styles.css",
102
+ "./video.css": "./recipes/video/styles.css",
93
103
  "./marquee.css": "./recipes/marquee/styles.css",
94
104
  "./logo-marquee.css": "./recipes/logo-marquee/styles.css",
95
105
  "./palette.css": "./recipes/palette/styles.css",
@@ -179,7 +189,10 @@
179
189
  "shortcuts",
180
190
  "toast",
181
191
  "unstyled",
182
- "vanilla"
192
+ "vanilla",
193
+ "lightbox",
194
+ "image-viewer",
195
+ "video-player"
183
196
  ],
184
197
  "license": "Apache-2.0",
185
198
  "author": "FJRG2007 <fjrg2007@tpeoficial.com>",
@@ -134,6 +134,26 @@
134
134
  [data-enigma-color-eyedropper]:hover { color: var(--enigma-color-text); }
135
135
  [data-enigma-color-eyedropper]:focus-visible { outline: 2px solid var(--enigma-color-focus); outline-offset: 2px; }
136
136
 
137
+ /* The value as text, with the notation beside it. Monospace on purpose: a hex whose digits
138
+ shift width as you drag is a value nobody can read at a glance. */
139
+ [data-enigma-color-value] { display: flex; align-items: center; gap: 0.375rem; }
140
+ [data-enigma-color-format] {
141
+ flex: none; padding: 0.3125rem 0.375rem;
142
+ font: inherit; font-size: 0.625rem; line-height: 1; letter-spacing: 0.06em;
143
+ color: var(--enigma-color-muted); background: none;
144
+ border: 1px solid var(--enigma-color-border); border-radius: 0.25rem; cursor: pointer;
145
+ }
146
+ [data-enigma-color-format]:hover { color: var(--enigma-color-text); }
147
+ [data-enigma-color-input] {
148
+ flex: 1; min-width: 0; padding: 0.25rem 0.375rem;
149
+ font: inherit; font-family: var(--enigma-color-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
150
+ font-size: 0.75rem; line-height: 1.4;
151
+ color: var(--enigma-color-text); background: none;
152
+ border: 1px solid var(--enigma-color-border); border-radius: 0.25rem;
153
+ }
154
+ [data-enigma-color-format]:focus-visible,
155
+ [data-enigma-color-input]:focus-visible { outline: 2px solid var(--enigma-color-focus); outline-offset: 1px; }
156
+
137
157
  [data-enigma-color-swatches] { display: flex; flex-wrap: wrap; gap: 0.25rem; }
138
158
  [data-enigma-color-preset] {
139
159
  width: 1.125rem; height: 1.125rem; padding: 0;
@@ -0,0 +1,182 @@
1
+ /*
2
+ * The image stylesheet.
3
+ *
4
+ * GENERATED from src/react/image/styles.ts by scripts/sync-recipes.mjs - edit that file, not
5
+ * this one. It exists as a stylesheet as well as a string because the component injects it,
6
+ * and this is the same sheet for anyone who would rather import it, copy it with
7
+ * `enigma add image --copy`, or fork it outright.
8
+ */
9
+ :root {
10
+ --enigma-image-backdrop: rgba(0, 0, 0, 0.92);
11
+ --enigma-image-text: #f5f5f5;
12
+ --enigma-image-muted: #a3a3a3;
13
+ --enigma-image-control-bg: rgba(23, 23, 23, 0.72);
14
+ --enigma-image-control-hover: rgba(64, 64, 64, 0.82);
15
+ --enigma-image-control-size: 2.25rem;
16
+ --enigma-image-radius: 0.625rem;
17
+ --enigma-image-gap: 0.75rem;
18
+ --enigma-image-thumb-size: 3.5rem;
19
+ --enigma-image-focus: #f5f5f5;
20
+ /* Above the page's own chrome, not merely above its content: a header or a sticky sidebar
21
+ with a z-index of its own would otherwise paint over the dialog covering it. */
22
+ --enigma-image-z: 9999;
23
+ /* How long the picture takes to fly out of the page and back into it, and the curve it
24
+ flies on. They are the numbers core/image-viewer.ts waits for, so a project that
25
+ changes one here changes it there - see the note above the keyframes. */
26
+ --enigma-image-flight: 300ms;
27
+ --enigma-image-flight-ease: cubic-bezier(0.2, 0, 0.2, 1);
28
+ }
29
+
30
+ /* The thumbnail in the page. Only what the behaviour needs: the pointer says it opens, and
31
+ the box is the caller's to size. */
32
+ [data-enigma-image] { display: inline-flex; max-width: 100%; }
33
+ [data-enigma-image][data-clickable] { cursor: zoom-in; }
34
+ /* Stated on the picture as well as inherited: a project that restyles the trigger button is
35
+ one cursor: pointer away from a thumbnail that no longer says it enlarges. */
36
+ [data-enigma-image][data-clickable] img { cursor: zoom-in; }
37
+ [data-enigma-image] img { display: block; max-width: 100%; height: auto; }
38
+ /* A real box, never display:contents: an element without one cannot be focused in Chromium,
39
+ so a viewer closed with Escape would hand focus to the body instead of back to the picture
40
+ it was opened from, and the next Tab would start at the top of the page. */
41
+ [data-enigma-image-trigger] {
42
+ display: inline-flex; max-width: 100%; padding: 0; margin: 0;
43
+ background: none; border: 0; color: inherit; font: inherit; cursor: inherit;
44
+ }
45
+ [data-enigma-image-trigger]:focus-visible img { outline: 2px solid var(--enigma-image-focus); outline-offset: 3px; }
46
+
47
+ /* The viewer. Fixed and portalled: a lightbox inside the page's own stacking context is a
48
+ lightbox some ancestor's overflow or transform will clip. */
49
+ [data-enigma-image-viewer] {
50
+ position: fixed; inset: 0; z-index: var(--enigma-image-z);
51
+ display: grid; grid-template-rows: auto minmax(0, 1fr) auto;
52
+ background: var(--enigma-image-backdrop);
53
+ color: var(--enigma-image-text);
54
+ }
55
+
56
+ /* The opening: the backdrop arrives while the picture flies out of the page, and the toolbar
57
+ and the strip arrive with it rather than being there first over a picture that is still on
58
+ its way. data-state is only ever "opening" or "closing" while an animation is meant to be
59
+ running, so a viewer that skipped the flight - reduced motion, animate={false} - matches
60
+ none of these rules and simply exists. */
61
+ @keyframes enigma-image-in { from { background-color: transparent; } to { background-color: var(--enigma-image-backdrop); } }
62
+ @keyframes enigma-image-chrome { from { opacity: 0; } to { opacity: 1; } }
63
+ [data-enigma-image-viewer][data-state="opening"] { animation: enigma-image-in var(--enigma-image-flight) ease-out; }
64
+ [data-enigma-image-viewer][data-state="opening"] [data-enigma-image-bar],
65
+ [data-enigma-image-viewer][data-state="opening"] [data-enigma-image-foot],
66
+ [data-enigma-image-viewer][data-state="opening"] [data-enigma-image-nav] {
67
+ animation: enigma-image-chrome var(--enigma-image-flight) ease-out;
68
+ }
69
+ /* On the way out the backdrop drains, and the dialog stops taking presses: it is over the
70
+ page again, so a click through it would land on whatever is now under the pointer. */
71
+ [data-enigma-image-viewer][data-state="closing"] {
72
+ background-color: transparent; pointer-events: none;
73
+ transition: background-color var(--enigma-image-flight) var(--enigma-image-flight-ease);
74
+ }
75
+ [data-enigma-image-viewer][data-state="closing"] [data-enigma-image-bar],
76
+ [data-enigma-image-viewer][data-state="closing"] [data-enigma-image-foot],
77
+ [data-enigma-image-viewer][data-state="closing"] [data-enigma-image-nav] {
78
+ opacity: 0; transition: opacity calc(var(--enigma-image-flight) / 2) ease-in;
79
+ }
80
+
81
+ [data-enigma-image-bar] {
82
+ display: flex; align-items: center; gap: 0.5rem;
83
+ padding: var(--enigma-image-gap);
84
+ }
85
+ [data-enigma-image-counter] {
86
+ font-size: 0.8125rem; font-variant-numeric: tabular-nums; color: var(--enigma-image-muted);
87
+ margin-inline-end: auto;
88
+ }
89
+
90
+ [data-enigma-image-button] {
91
+ display: grid; place-items: center; flex: none;
92
+ width: var(--enigma-image-control-size); height: var(--enigma-image-control-size);
93
+ padding: 0; color: var(--enigma-image-text);
94
+ background: var(--enigma-image-control-bg); border: 0; border-radius: 999px;
95
+ cursor: pointer;
96
+ }
97
+ [data-enigma-image-button]:hover { background: var(--enigma-image-control-hover); }
98
+ [data-enigma-image-button]:focus-visible { outline: 2px solid var(--enigma-image-focus); outline-offset: 2px; }
99
+ [data-enigma-image-button][disabled] { opacity: 0.35; cursor: not-allowed; }
100
+
101
+ /* The frame the picture is fitted into, and the surface every gesture is measured against. */
102
+ [data-enigma-image-frame] {
103
+ position: relative; overflow: hidden;
104
+ display: grid; place-items: center;
105
+ /* Room for the arrows down each side, so they sit beside the picture rather than on it. */
106
+ padding: 0 calc(var(--enigma-image-control-size) + var(--enigma-image-gap) * 1.5);
107
+ /* The drag IS the control once zoomed, so the page must not scroll under it. */
108
+ touch-action: none;
109
+ -webkit-user-select: none; user-select: none;
110
+ }
111
+ [data-enigma-image-frame] img {
112
+ max-width: 100%; max-height: 100%;
113
+ -webkit-user-drag: none;
114
+ will-change: transform;
115
+ }
116
+ /* Only while it is MOVING, which is not the same as "during the flight".
117
+ A transition left on permanently would put 300ms of lag between the wheel and the zoom, and
118
+ turn every pan into a drag the picture follows late. And one left on during "pending" is
119
+ worse than useless: putting the picture on the thumbnail is itself a transform change, so it
120
+ animated there over 300ms - behind a hidden element - and by the time anybody could see it
121
+ the flight was nearly over. */
122
+ [data-enigma-image-frame][data-flying="moving"] img { transition: transform var(--enigma-image-flight) var(--enigma-image-flight-ease); }
123
+ /* Not drawn until there is somewhere to fly from - see the note on the attribute. The spinner
124
+ is what stands in for it, the same one a slow picture gets. */
125
+ [data-enigma-image-frame][data-flying="pending"] img { visibility: hidden; }
126
+ @media (prefers-reduced-motion: reduce) {
127
+ [data-enigma-image-frame][data-flying="moving"] img { transition: none; }
128
+ }
129
+
130
+ /* The cursor says what a press does, which in a lightbox is three different things. The empty
131
+ part of the frame IS the backdrop and closes it; the picture at rest takes a double press to
132
+ enlarge; once it is enlarged the gesture is a drag. */
133
+ [data-enigma-image-frame] { cursor: zoom-out; }
134
+ [data-enigma-image-frame][data-zoom] img { cursor: zoom-in; }
135
+ [data-enigma-image-frame][data-zoomed],
136
+ [data-enigma-image-frame][data-zoomed] img { cursor: grab; }
137
+ [data-enigma-image-frame][data-panning],
138
+ [data-enigma-image-frame][data-panning] img { cursor: grabbing; }
139
+ [data-enigma-image-frame][data-loading] img { opacity: 0.35; }
140
+
141
+ /* Left and right sit over the picture rather than beside it: the frame is the biggest thing
142
+ on screen and the arrows have to be reachable without hunting for an edge. */
143
+ [data-enigma-image-nav] {
144
+ position: absolute; top: 50%; translate: 0 -50%;
145
+ width: var(--enigma-image-control-size); height: var(--enigma-image-control-size);
146
+ }
147
+ [data-enigma-image-nav="previous"] { left: var(--enigma-image-gap); }
148
+ [data-enigma-image-nav="next"] { right: var(--enigma-image-gap); }
149
+
150
+ [data-enigma-image-spinner] {
151
+ position: absolute; width: 1.75rem; height: 1.75rem;
152
+ border: 2px solid rgba(255, 255, 255, 0.25); border-top-color: var(--enigma-image-text);
153
+ border-radius: 999px; animation: enigma-image-spin 700ms linear infinite;
154
+ }
155
+ @keyframes enigma-image-spin { to { rotate: 360deg; } }
156
+ @media (prefers-reduced-motion: reduce) {
157
+ [data-enigma-image-spinner] { animation-duration: 2s; }
158
+ }
159
+
160
+ [data-enigma-image-foot] { display: grid; gap: 0.5rem; padding: var(--enigma-image-gap); }
161
+ [data-enigma-image-caption] {
162
+ margin: 0; text-align: center; font-size: 0.8125rem; line-height: 1.5;
163
+ color: var(--enigma-image-muted);
164
+ }
165
+
166
+ /* The strip. Scrolls on its own rather than wrapping: a gallery of forty is one row you drag
167
+ through, not five rows that push the picture off the screen. */
168
+ [data-enigma-image-strip] {
169
+ display: flex; gap: 0.5rem; overflow-x: auto; scrollbar-width: thin;
170
+ justify-content: safe center;
171
+ padding-bottom: 0.25rem;
172
+ }
173
+ [data-enigma-image-thumb] {
174
+ flex: none; width: var(--enigma-image-thumb-size); height: var(--enigma-image-thumb-size);
175
+ padding: 0; overflow: hidden;
176
+ background: none; border: 0; border-radius: 0.375rem;
177
+ opacity: 0.55; cursor: pointer;
178
+ }
179
+ [data-enigma-image-thumb] img { width: 100%; height: 100%; object-fit: cover; }
180
+ [data-enigma-image-thumb]:hover { opacity: 0.85; }
181
+ [data-enigma-image-thumb][aria-current="true"] { opacity: 1; box-shadow: 0 0 0 2px var(--enigma-image-focus); }
182
+ [data-enigma-image-thumb]:focus-visible { outline: 2px solid var(--enigma-image-focus); outline-offset: 2px; }