@enigmax/primitives 0.23.0 → 0.24.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 (39) hide show
  1. package/dist/{chunk-DSBYVA7V.js → chunk-DZMHY3SU.js} +73 -9
  2. package/dist/{chunk-KEVZ5XQV.js → chunk-QJJ34E4G.js} +33 -9
  3. package/dist/chunk-S2FPN5ID.js +115 -0
  4. package/dist/chunk-S7EE57YB.js +9 -0
  5. package/dist/{chunk-3BQVOOAM.js → chunk-Z3VDE7OA.js} +145 -1
  6. package/dist/{context-menu-D3FtTn7v.d.ts → clipboard-menu-B_ouitfS.d.ts} +91 -1
  7. package/dist/color-D_rZ83Oc.d.ts +152 -0
  8. package/dist/color-OPV3BJV6.js +452 -0
  9. package/dist/{index-DQNnohoo.d.ts → index-ZPvlf9vs.d.ts} +52 -4
  10. package/dist/index.d.ts +2 -2
  11. package/dist/index.js +2 -1
  12. package/dist/next/index.d.ts +3 -3
  13. package/dist/next/index.js +6 -4
  14. package/dist/react/context-menu.d.ts +23 -6
  15. package/dist/react/context-menu.js +2 -2
  16. package/dist/react/index.d.ts +5 -5
  17. package/dist/react/index.js +6 -4
  18. package/dist/react/input.d.ts +2 -2
  19. package/dist/react/input.js +2 -1
  20. package/dist/react-router/index.d.ts +3 -3
  21. package/dist/react-router/index.js +6 -4
  22. package/package.json +3 -1
  23. package/recipes/color/styles.css +143 -0
  24. package/recipes/context-menu/styles.css +8 -0
  25. package/registry.json +77 -7
  26. package/src/core/clipboard-menu.ts +270 -0
  27. package/src/core/color.ts +248 -0
  28. package/src/index.ts +32 -0
  29. package/src/react/context-menu/context.ts +9 -2
  30. package/src/react/context-menu/index.tsx +14 -0
  31. package/src/react/context-menu/root.tsx +132 -8
  32. package/src/react/context-menu/styles.ts +8 -0
  33. package/src/react/index.ts +32 -0
  34. package/src/react/input/color-styles.ts +156 -0
  35. package/src/react/input/color.tsx +466 -0
  36. package/src/react/input/index.tsx +54 -6
  37. package/src/react/input/types.ts +59 -3
  38. package/dist/password-C8lG4Zm9.d.ts +0 -71
  39. /package/dist/{chunk-3HDEZ2E7.js → chunk-MSOCCQGH.js} +0 -0
package/dist/index.d.ts CHANGED
@@ -2,14 +2,14 @@ export { M as MarqueeHover, a as MarqueeInstance, b as MarqueeOptions, c as crea
2
2
  export { I as InputAction, a as InputActionState, b as InputIcon, c as InputInstance, d as InputOptions, e as createInput } from './input-BwXjFenq.js';
3
3
  export { F as FuseConstructor, a as FuseLike, S as SearchInstance, b as SearchMatch, c as SearchOptions, d as createSearch, s as shortenQuery, e as subsequenceMatcher } from './search-DYgqRp37.js';
4
4
  export { B as ButtonCooldown, a as ButtonElement, b as ButtonInstance, c as ButtonOptions, d as ButtonState, e as createButton } from './button-CaXaqG_K.js';
5
- export { E as EstimateOptions, G as GeneratePasswordOptions, P as PasswordAlphabet, a as PasswordScore, b as PasswordStrengthReport, e as estimatePasswordStrength, g as generatePassword } from './password-C8lG4Zm9.js';
5
+ export { C as ColorFormat, E as EstimateOptions, F as FormatColorOptions, G as GeneratePasswordOptions, H as Hsl, a as Hsv, P as PasswordAlphabet, 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';
6
6
  export { N as Notification, a as NotificationAction, b as NotificationInput, c as NotificationTone, d as Notifications, e as NotificationsOptions, P as PromiseMessages, f as createNotifications } from './notifications-BpVV6sel.js';
7
7
  export { N as NetworkMonitor, a as NetworkState, S as SERVER_NETWORK_STATE, c as createNetworkMonitor } from './network-D2LsBG_k.js';
8
8
  export { R as RelativeTimeFormat, a as RelativeTimeOptions, b as RelativeTimePrecision, c as RelativeTimeStyle, d as RelativeTimeTense, e as RelativeTimeView, f as ensureZone, n as normalizeDate, p as parseDuration, r as relativeTimeAttributes, g as relativeTimeView } from './relative-time-YpRTG7YH.js';
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-D3FtTn7v.js';
12
+ export { C as CLIPBOARD_PREFIX, a as CONTEXT_MENU_SEARCH_KEYS, b as ClipboardAction, c as ClipboardMenuLabels, d as ClipboardMenuOptions, e as ClipboardTarget, f as ContextMenuAction, g as ContextMenuEntry, h as ContextMenuInstance, i as ContextMenuLabel, j as ContextMenuLevel, k as ContextMenuMoveKey, l as ContextMenuOptions, m as ContextMenuPoint, n as ContextMenuSeparator, 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';
13
13
  export { D as DEFAULT_SELECTION_SHORTCUTS, S as SelectionClickModifiers, a as SelectionCommand, b as SelectionCommandEvent, c as SelectionCommandName, d as SelectionInstance, e as SelectionOptions, f as SelectionShortcuts, g as SelectionState, h as createSelection } from './selection-B_pmzHpy.js';
14
14
  export { S as Shortcut, a as ShortcutEvent, b as ShortcutSpec, T as TYPEAHEAD_MS, c as TypeaheadState, d as TypeaheadStep, i as isApplePlatform, m as matchesShortcut, p as parseShortcut, s as shortcutList, e as shortcutText, f as shortcutTokens, t as typeaheadStep } from './keys-D2zJs1uB.js';
15
15
 
package/dist/index.js CHANGED
@@ -1,7 +1,8 @@
1
1
  export { createInput } from './chunk-KJINGUQN.js';
2
2
  export { ensureZone, normalizeDate, parseDuration, relativeTimeAttributes, relativeTimeView } from './chunk-IXVMRVD4.js';
3
3
  export { estimatePasswordStrength, generatePassword } from './chunk-HC2ME5PU.js';
4
- export { CONTEXT_MENU_SEARCH_KEYS, createContextMenu, isAction } from './chunk-3BQVOOAM.js';
4
+ export { colorEquals, formatColor, hslToRgb, hsvToRgb, parseColor, rgbToHsl, rgbToHsv, toHex } from './chunk-S2FPN5ID.js';
5
+ export { CLIPBOARD_PREFIX, CONTEXT_MENU_SEARCH_KEYS, clipboardAction, clipboardEntries, clipboardHasText, createContextMenu, inspectClipboardTarget, isAction, performClipboardAction } from './chunk-Z3VDE7OA.js';
5
6
  export { DEFAULT_SELECTION_SHORTCUTS, createSelection } from './chunk-WSQC3PCC.js';
6
7
  export { createButton } from './chunk-MMQPZGSU.js';
7
8
  export { FLAG_CDN, FLAG_RATIO, configureFlags, flagAttributes, flagConfig, flagName, flagSrc, flagView, normalizeFlagCode, resetFlagConfig } from './chunk-LMZJBOZG.js';
@@ -7,9 +7,9 @@ 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, F as FieldAction, I as Input, c as InputBaseProps, d as InputProps, e as InputType, P as PasswordOnlyProps, g as PlainOnlyProps, S as SearchOnlyProps } from '../index-DQNnohoo.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';
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';
11
12
  export { Slot, SlotProps, mergeSlotProps } from '../react/slot.js';
12
- export { E as EstimateOptions, G as GeneratePasswordOptions, a as PasswordScore, b as PasswordStrengthReport, e as estimatePasswordStrength, g as generatePassword } from '../password-C8lG4Zm9.js';
13
13
  export { UseNotificationsResult, createNotificationQueue, defaultQueue, useNotifications } from '../react/notifications.js';
14
14
  export { Action, ExternalToast, ToastClassnames, ToastT, Toaster, ToasterProps, toast, useSonner } from '../react/toast.js';
15
15
  export { useNetworkState } from '../react/network.js';
@@ -24,7 +24,7 @@ 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, ContextMenuContextValue, ContextMenuItem, ContextMenuList, ContextMenuNode, ContextMenuPanel, ContextMenuProps, ContextMenuRoot, ContextMenuRootProps, ContextMenuRow, ContextMenuSearch, ContextMenuTrigger, ContextMenuTriggerProps, useContextMenuContext } from '../react/context-menu.js';
27
- 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';
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';
28
28
  export { MarqueeRect, SelectionList, SelectionListProps, SelectionRenderer, SelectionRowRender, UseSelectionOptions, UseSelectionResult, useSelection } from '../react/selection.js';
29
29
  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
30
  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';
@@ -1,8 +1,8 @@
1
1
  "use client";
2
- export { useInput } from '../chunk-3HDEZ2E7.js';
2
+ export { useInput } from '../chunk-MSOCCQGH.js';
3
3
  export { RelativeTime } from '../chunk-OCMI7R6H.js';
4
4
  export { PasswordStrength } from '../chunk-XQHCZAPJ.js';
5
- export { ContextMenu, ContextMenuContent, ContextMenuList, ContextMenuPanel, ContextMenuRoot, ContextMenuRow, ContextMenuSearch, ContextMenuTrigger, useContextMenuContext } from '../chunk-DSBYVA7V.js';
5
+ export { ContextMenu, ContextMenuContent, ContextMenuList, ContextMenuPanel, ContextMenuRoot, ContextMenuRow, ContextMenuSearch, ContextMenuTrigger, useContextMenuContext } from '../chunk-DZMHY3SU.js';
6
6
  export { SelectionList, useSelection } from '../chunk-N6PDHMAX.js';
7
7
  import { Button } from '../chunk-6BGBYUSZ.js';
8
8
  export { getLinkComponent, setLinkComponent, useButton } from '../chunk-6BGBYUSZ.js';
@@ -15,14 +15,16 @@ export { useNetworkState } from '../chunk-S653GLSF.js';
15
15
  import '../chunk-KJINGUQN.js';
16
16
  import '../chunk-IXVMRVD4.js';
17
17
  export { estimatePasswordStrength, generatePassword } from '../chunk-HC2ME5PU.js';
18
- export { createContextMenu, isAction } from '../chunk-3BQVOOAM.js';
18
+ export { colorEquals, formatColor, hslToRgb, hsvToRgb, parseColor, rgbToHsl, rgbToHsv, toHex } from '../chunk-S2FPN5ID.js';
19
+ export { CLIPBOARD_PREFIX, clipboardAction, clipboardEntries, clipboardHasText, createContextMenu, inspectClipboardTarget, isAction, performClipboardAction } from '../chunk-Z3VDE7OA.js';
19
20
  export { DEFAULT_SELECTION_SHORTCUTS, createSelection } from '../chunk-WSQC3PCC.js';
20
21
  import '../chunk-MMQPZGSU.js';
21
22
  export { configureFlags, flagAttributes, flagName, flagSrc, flagView, normalizeFlagCode } from '../chunk-LMZJBOZG.js';
22
23
  import '../chunk-SNYUBXWQ.js';
23
24
  import '../chunk-UOSSNUSC.js';
24
25
  import '../chunk-2QFTRNAZ.js';
25
- export { Input } from '../chunk-KEVZ5XQV.js';
26
+ export { Input } from '../chunk-QJJ34E4G.js';
27
+ import '../chunk-S7EE57YB.js';
26
28
  import '../chunk-F25CGNQC.js';
27
29
  export { PaletteContent, PaletteField, PaletteFooter, PaletteItem, PaletteList, PaletteRoot, PaletteTrigger, SearchPalette, usePaletteContext } from '../chunk-FGBIZDV2.js';
28
30
  export { Select, SelectContent, SelectList, SelectOptionRow, SelectRoot, SelectSearch, SelectTrigger, SelectValue, useSelectContext } from '../chunk-VKL3DEIQ.js';
@@ -1,6 +1,6 @@
1
1
  import { ReactNode, RefObject, ComponentPropsWithoutRef } from 'react';
2
- import { a as ContextMenuAction, b as ContextMenuEntry, c as ContextMenuInstance, j as ContextMenuState, h as ContextMenuPoint, g as ContextMenuOptions } from '../context-menu-D3FtTn7v.js';
3
- export { C as CONTEXT_MENU_SEARCH_KEYS, d as ContextMenuLabel, e as ContextMenuLevel, f as ContextMenuMoveKey, i as ContextMenuSeparator, k as createContextMenu, l as isAction } from '../context-menu-D3FtTn7v.js';
2
+ import { f as ContextMenuAction, g as ContextMenuEntry, h as ContextMenuInstance, o as ContextMenuState, m as ContextMenuPoint, d as ClipboardMenuOptions, l as ContextMenuOptions } from '../clipboard-menu-B_ouitfS.js';
3
+ export { C as CLIPBOARD_PREFIX, a as CONTEXT_MENU_SEARCH_KEYS, b as ClipboardAction, c as ClipboardMenuLabels, e as ClipboardTarget, i as ContextMenuLabel, j as ContextMenuLevel, k as ContextMenuMoveKey, n as ContextMenuSeparator, 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';
4
4
  export { S as Shortcut, b as ShortcutSpec, m as matchesShortcut, p as parseShortcut, e as shortcutText, f as shortcutTokens } from '../keys-D2zJs1uB.js';
5
5
  import '../search-DYgqRp37.js';
6
6
 
@@ -17,8 +17,15 @@ type ContextMenuNode = ContextMenuItem | Exclude<ContextMenuEntry, ContextMenuAc
17
17
  interface ContextMenuContextValue {
18
18
  instance: ContextMenuInstance;
19
19
  state: ContextMenuState;
20
- /** Open at a point. False when there was nothing to show, so the press is left alone. */
21
- open: (point: ContextMenuPoint) => boolean;
20
+ /**
21
+ * Open at a point, over what the press landed on. False when there was nothing to show,
22
+ * so the press is left alone.
23
+ *
24
+ * `target` is what the clipboard rows are built from - the field or the selection under
25
+ * the pointer - and a caller that leaves it out gets a menu with none of them, which is
26
+ * the right answer for a menu opened from somewhere that is not a press.
27
+ */
28
+ open: (point: ContextMenuPoint, target?: EventTarget | null) => boolean;
22
29
  close: () => void;
23
30
  /** ids the parts need to point at each other. */
24
31
  ids: {
@@ -57,6 +64,16 @@ interface ContextMenuRootProps {
57
64
  onOpenChange?: (open: boolean) => void;
58
65
  /** Nothing opens, and the press is left to the browser. For a disabled row or a read-only view. */
59
66
  disabled?: boolean;
67
+ /**
68
+ * Copy, Cut and Paste, built from whatever was right-clicked. ON by default, and `false`
69
+ * turns them off; an object turns off one of the three, renames them, or both.
70
+ *
71
+ * On by default because the browser's own menu has them and this one replaces it - a
72
+ * custom menu over a text field that cannot copy is a loss the visitor discovers rather
73
+ * than one anybody decided on. They appear only where they mean something: Copy over a
74
+ * selection, Cut over a selection in something writable, Paste in anything writable.
75
+ */
76
+ clipboard?: boolean | ClipboardMenuOptions;
60
77
  /** Fuse.js's constructor, for fuzzy filtering. Omit it for the built-in matcher. */
61
78
  fuse?: ContextMenuOptions["fuse"];
62
79
  fuseOptions?: Record<string, unknown>;
@@ -153,7 +170,7 @@ declare function ContextMenuRow({ level, index, entry, children, ...props }: Con
153
170
  * is PREPENDED to `<head>`, so anything the document already has wins on source order at
154
171
  * equal specificity.
155
172
  */
156
- 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: 60;\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@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";
173
+ 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: 60;\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";
157
174
 
158
175
  type ContextMenuProps = ContextMenuRootProps & {
159
176
  /** How many rows to put in the document at once. `Infinity` renders the lot. */
@@ -199,4 +216,4 @@ declare namespace ContextMenu {
199
216
  var Item: typeof ContextMenuRow;
200
217
  }
201
218
 
202
- export { CONTEXT_MENU_STYLES, ContextMenu, ContextMenuAction, ContextMenuContent, type ContextMenuContentProps, type ContextMenuContextValue, ContextMenuEntry, ContextMenuInstance, type ContextMenuItem, ContextMenuList, type ContextMenuListProps, type ContextMenuNode, ContextMenuOptions, ContextMenuPanel, type ContextMenuPanelProps, ContextMenuPoint, type ContextMenuProps, ContextMenuRoot, type ContextMenuRootProps, ContextMenuRow, type ContextMenuRowProps, ContextMenuSearch, type ContextMenuSearchProps, ContextMenuState, ContextMenuTrigger, type ContextMenuTriggerProps, useContextMenuContext };
219
+ export { CONTEXT_MENU_STYLES, ClipboardMenuOptions, ContextMenu, ContextMenuAction, ContextMenuContent, type ContextMenuContentProps, type ContextMenuContextValue, ContextMenuEntry, ContextMenuInstance, type ContextMenuItem, ContextMenuList, type ContextMenuListProps, type ContextMenuNode, ContextMenuOptions, ContextMenuPanel, type ContextMenuPanelProps, ContextMenuPoint, type ContextMenuProps, ContextMenuRoot, type ContextMenuRootProps, ContextMenuRow, type ContextMenuRowProps, ContextMenuSearch, type ContextMenuSearchProps, ContextMenuState, ContextMenuTrigger, type ContextMenuTriggerProps, useContextMenuContext };
@@ -1,6 +1,6 @@
1
1
  "use client";
2
- export { CONTEXT_MENU_STYLES, ContextMenu, ContextMenuContent, ContextMenuList, ContextMenuPanel, ContextMenuRoot, ContextMenuRow, ContextMenuSearch, ContextMenuTrigger, useContextMenuContext } from '../chunk-DSBYVA7V.js';
3
- export { CONTEXT_MENU_SEARCH_KEYS, createContextMenu, isAction } from '../chunk-3BQVOOAM.js';
2
+ export { CONTEXT_MENU_STYLES, ContextMenu, ContextMenuContent, ContextMenuList, ContextMenuPanel, ContextMenuRoot, ContextMenuRow, ContextMenuSearch, ContextMenuTrigger, useContextMenuContext } from '../chunk-DZMHY3SU.js';
3
+ export { CLIPBOARD_PREFIX, CONTEXT_MENU_SEARCH_KEYS, clipboardAction, clipboardEntries, clipboardHasText, createContextMenu, inspectClipboardTarget, isAction, performClipboardAction } from '../chunk-Z3VDE7OA.js';
4
4
  export { matchesShortcut, parseShortcut, shortcutText, shortcutTokens } from '../chunk-4VUHQFAT.js';
5
5
  import '../chunk-HS3X3XCW.js';
6
6
  import '../chunk-4ZPMP47J.js';
@@ -7,10 +7,10 @@ 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 { f as PasswordStrengthClassNames } from '../index-DQNnohoo.js';
11
- export { B as BreachChecker, a as BreachState, b as BreachStatus, F as FieldAction, I as Input, c as InputBaseProps, d as InputProps, e as InputType, P as PasswordOnlyProps, g as PlainOnlyProps, S as SearchOnlyProps } from '../index-DQNnohoo.js';
12
- import { b as PasswordStrengthReport } from '../password-C8lG4Zm9.js';
13
- export { E as EstimateOptions, G as GeneratePasswordOptions, a as PasswordScore, e as estimatePasswordStrength, g as generatePassword } from '../password-C8lG4Zm9.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';
12
+ import { c as PasswordStrengthReport } from '../color-D_rZ83Oc.js';
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';
15
15
  export { UseNotificationsResult, createNotificationQueue, defaultQueue, useNotifications } from './notifications.js';
16
16
  export { Action, ExternalToast, ToastClassnames, ToastT, Toaster, ToasterProps, toast, useSonner } from './toast.js';
@@ -26,7 +26,7 @@ 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, ContextMenuContextValue, ContextMenuItem, ContextMenuList, ContextMenuNode, ContextMenuPanel, ContextMenuProps, ContextMenuRoot, ContextMenuRootProps, ContextMenuRow, ContextMenuSearch, ContextMenuTrigger, ContextMenuTriggerProps, useContextMenuContext } from './context-menu.js';
29
- 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';
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';
30
30
  export { MarqueeRect, SelectionList, SelectionListProps, SelectionRenderer, SelectionRowRender, UseSelectionOptions, UseSelectionResult, useSelection } from './selection.js';
31
31
  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
32
  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';
@@ -1,8 +1,8 @@
1
1
  "use client";
2
- export { useInput } from '../chunk-3HDEZ2E7.js';
2
+ export { useInput } from '../chunk-MSOCCQGH.js';
3
3
  export { RelativeTime } from '../chunk-OCMI7R6H.js';
4
4
  export { PasswordStrength } from '../chunk-XQHCZAPJ.js';
5
- export { ContextMenu, ContextMenuContent, ContextMenuList, ContextMenuPanel, ContextMenuRoot, ContextMenuRow, ContextMenuSearch, ContextMenuTrigger, useContextMenuContext } from '../chunk-DSBYVA7V.js';
5
+ export { ContextMenu, ContextMenuContent, ContextMenuList, ContextMenuPanel, ContextMenuRoot, ContextMenuRow, ContextMenuSearch, ContextMenuTrigger, useContextMenuContext } from '../chunk-DZMHY3SU.js';
6
6
  export { SelectionList, useSelection } from '../chunk-N6PDHMAX.js';
7
7
  export { Button, getLinkComponent, setLinkComponent, useButton } from '../chunk-6BGBYUSZ.js';
8
8
  export { Flag } from '../chunk-NPHRS2Q7.js';
@@ -14,14 +14,16 @@ export { useNetworkState } from '../chunk-S653GLSF.js';
14
14
  import '../chunk-KJINGUQN.js';
15
15
  import '../chunk-IXVMRVD4.js';
16
16
  export { estimatePasswordStrength, generatePassword } from '../chunk-HC2ME5PU.js';
17
- export { createContextMenu, isAction } from '../chunk-3BQVOOAM.js';
17
+ export { colorEquals, formatColor, hslToRgb, hsvToRgb, parseColor, rgbToHsl, rgbToHsv, toHex } from '../chunk-S2FPN5ID.js';
18
+ export { CLIPBOARD_PREFIX, clipboardAction, clipboardEntries, clipboardHasText, createContextMenu, inspectClipboardTarget, isAction, performClipboardAction } from '../chunk-Z3VDE7OA.js';
18
19
  export { DEFAULT_SELECTION_SHORTCUTS, createSelection } from '../chunk-WSQC3PCC.js';
19
20
  import '../chunk-MMQPZGSU.js';
20
21
  export { configureFlags, flagAttributes, flagName, flagSrc, flagView, normalizeFlagCode } from '../chunk-LMZJBOZG.js';
21
22
  import '../chunk-SNYUBXWQ.js';
22
23
  import '../chunk-UOSSNUSC.js';
23
24
  import '../chunk-2QFTRNAZ.js';
24
- export { Input } from '../chunk-KEVZ5XQV.js';
25
+ export { Input } from '../chunk-QJJ34E4G.js';
26
+ import '../chunk-S7EE57YB.js';
25
27
  import '../chunk-F25CGNQC.js';
26
28
  export { PaletteContent, PaletteField, PaletteFooter, PaletteItem, PaletteList, PaletteRoot, PaletteTrigger, SearchPalette, usePaletteContext } from '../chunk-FGBIZDV2.js';
27
29
  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, F as FieldAction, I as Input, c as InputBaseProps, d as InputProps, e as InputType, P as PasswordOnlyProps, g as PlainOnlyProps, S as SearchOnlyProps } from '../index-DQNnohoo.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-ZPvlf9vs.js';
2
2
  import 'react';
3
+ import '../color-D_rZ83Oc.js';
3
4
  import '../search-DYgqRp37.js';
4
- import '../password-C8lG4Zm9.js';
@@ -1,3 +1,4 @@
1
1
  "use client";
2
- export { Input } from '../chunk-KEVZ5XQV.js';
2
+ export { Input } from '../chunk-QJJ34E4G.js';
3
+ import '../chunk-S7EE57YB.js';
3
4
  import '../chunk-F25CGNQC.js';
@@ -7,9 +7,9 @@ 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, F as FieldAction, I as Input, c as InputBaseProps, d as InputProps, e as InputType, P as PasswordOnlyProps, g as PlainOnlyProps, S as SearchOnlyProps } from '../index-DQNnohoo.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';
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';
11
12
  export { Slot, SlotProps, mergeSlotProps } from '../react/slot.js';
12
- export { E as EstimateOptions, G as GeneratePasswordOptions, a as PasswordScore, b as PasswordStrengthReport, e as estimatePasswordStrength, g as generatePassword } from '../password-C8lG4Zm9.js';
13
13
  export { UseNotificationsResult, createNotificationQueue, defaultQueue, useNotifications } from '../react/notifications.js';
14
14
  export { Action, ExternalToast, ToastClassnames, ToastT, Toaster, ToasterProps, toast, useSonner } from '../react/toast.js';
15
15
  export { useNetworkState } from '../react/network.js';
@@ -24,7 +24,7 @@ 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, ContextMenuContextValue, ContextMenuItem, ContextMenuList, ContextMenuNode, ContextMenuPanel, ContextMenuProps, ContextMenuRoot, ContextMenuRootProps, ContextMenuRow, ContextMenuSearch, ContextMenuTrigger, ContextMenuTriggerProps, useContextMenuContext } from '../react/context-menu.js';
27
- 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';
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';
28
28
  export { MarqueeRect, SelectionList, SelectionListProps, SelectionRenderer, SelectionRowRender, UseSelectionOptions, UseSelectionResult, useSelection } from '../react/selection.js';
29
29
  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
30
  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';
@@ -1,8 +1,8 @@
1
1
  "use client";
2
- export { useInput } from '../chunk-3HDEZ2E7.js';
2
+ export { useInput } from '../chunk-MSOCCQGH.js';
3
3
  export { RelativeTime } from '../chunk-OCMI7R6H.js';
4
4
  export { PasswordStrength } from '../chunk-XQHCZAPJ.js';
5
- export { ContextMenu, ContextMenuContent, ContextMenuList, ContextMenuPanel, ContextMenuRoot, ContextMenuRow, ContextMenuSearch, ContextMenuTrigger, useContextMenuContext } from '../chunk-DSBYVA7V.js';
5
+ export { ContextMenu, ContextMenuContent, ContextMenuList, ContextMenuPanel, ContextMenuRoot, ContextMenuRow, ContextMenuSearch, ContextMenuTrigger, useContextMenuContext } from '../chunk-DZMHY3SU.js';
6
6
  export { SelectionList, useSelection } from '../chunk-N6PDHMAX.js';
7
7
  import { Button } from '../chunk-6BGBYUSZ.js';
8
8
  export { getLinkComponent, setLinkComponent, useButton } from '../chunk-6BGBYUSZ.js';
@@ -15,14 +15,16 @@ export { useNetworkState } from '../chunk-S653GLSF.js';
15
15
  import '../chunk-KJINGUQN.js';
16
16
  import '../chunk-IXVMRVD4.js';
17
17
  export { estimatePasswordStrength, generatePassword } from '../chunk-HC2ME5PU.js';
18
- export { createContextMenu, isAction } from '../chunk-3BQVOOAM.js';
18
+ export { colorEquals, formatColor, hslToRgb, hsvToRgb, parseColor, rgbToHsl, rgbToHsv, toHex } from '../chunk-S2FPN5ID.js';
19
+ export { CLIPBOARD_PREFIX, clipboardAction, clipboardEntries, clipboardHasText, createContextMenu, inspectClipboardTarget, isAction, performClipboardAction } from '../chunk-Z3VDE7OA.js';
19
20
  export { DEFAULT_SELECTION_SHORTCUTS, createSelection } from '../chunk-WSQC3PCC.js';
20
21
  import '../chunk-MMQPZGSU.js';
21
22
  export { configureFlags, flagAttributes, flagName, flagSrc, flagView, normalizeFlagCode } from '../chunk-LMZJBOZG.js';
22
23
  import '../chunk-SNYUBXWQ.js';
23
24
  import '../chunk-UOSSNUSC.js';
24
25
  import '../chunk-2QFTRNAZ.js';
25
- export { Input } from '../chunk-KEVZ5XQV.js';
26
+ export { Input } from '../chunk-QJJ34E4G.js';
27
+ import '../chunk-S7EE57YB.js';
26
28
  import '../chunk-F25CGNQC.js';
27
29
  export { PaletteContent, PaletteField, PaletteFooter, PaletteItem, PaletteList, PaletteRoot, PaletteTrigger, SearchPalette, usePaletteContext } from '../chunk-FGBIZDV2.js';
28
30
  export { Select, SelectContent, SelectList, SelectOptionRow, SelectRoot, SelectSearch, SelectTrigger, SelectValue, useSelectContext } from '../chunk-VKL3DEIQ.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@enigmax/primitives",
3
- "version": "0.23.0",
3
+ "version": "0.24.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": [
@@ -89,6 +89,7 @@
89
89
  "./relative-time.css": "./recipes/relative-time/styles.css",
90
90
  "./toast.css": "./recipes/toast/styles.css",
91
91
  "./input.css": "./recipes/input/styles.css",
92
+ "./color.css": "./recipes/color/styles.css",
92
93
  "./marquee.css": "./recipes/marquee/styles.css",
93
94
  "./logo-marquee.css": "./recipes/logo-marquee/styles.css",
94
95
  "./palette.css": "./recipes/palette/styles.css",
@@ -157,6 +158,7 @@
157
158
  },
158
159
  "keywords": [
159
160
  "carousel",
161
+ "color-picker",
160
162
  "context-menu",
161
163
  "enigma",
162
164
  "flags",
@@ -0,0 +1,143 @@
1
+ /*
2
+ * The color stylesheet.
3
+ *
4
+ * GENERATED from src/react/input/color-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 input --copy`, or fork it outright.
8
+ */
9
+ :root {
10
+ --enigma-color-panel-bg: #1c1c1c;
11
+ --enigma-color-panel-border: #333333;
12
+ --enigma-color-panel-radius: 0.625rem;
13
+ --enigma-color-panel-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);
14
+ --enigma-color-panel-width: 13.5rem;
15
+ --enigma-color-text: #f5f5f5;
16
+ --enigma-color-muted: #a3a3a3;
17
+ --enigma-color-border: #404040;
18
+ --enigma-color-focus: #a3a3a3;
19
+ --enigma-color-area-height: 8rem;
20
+ --enigma-color-rail-height: 0.625rem;
21
+ --enigma-color-thumb: #ffffff;
22
+ --enigma-color-thumb-ring: rgba(0, 0, 0, 0.55);
23
+ /* The light square of the transparency chequerboard. The dark one is the surface it sits
24
+ on, which is why only one colour is a property. */
25
+ --enigma-color-checker: rgba(255, 255, 255, 0.22);
26
+ --enigma-color-checker-size: 0.5rem;
27
+ }
28
+
29
+ @media (prefers-color-scheme: light) {
30
+ :root {
31
+ --enigma-color-panel-bg: #ffffff;
32
+ --enigma-color-panel-border: #e5e5e5;
33
+ --enigma-color-panel-shadow: 0 12px 32px rgba(0, 0, 0, 0.12);
34
+ --enigma-color-text: #171717;
35
+ --enigma-color-muted: #737373;
36
+ --enigma-color-border: #d4d4d4;
37
+ --enigma-color-focus: #737373;
38
+ --enigma-color-thumb-ring: rgba(0, 0, 0, 0.35);
39
+ --enigma-color-checker: rgba(0, 0, 0, 0.14);
40
+ }
41
+ }
42
+
43
+ /* The anchor the panel hangs from. Inline so it sits in the field's own row, and the
44
+ positioning context so the panel needs no portal and no scroll listener: it moves with
45
+ the field because it is INSIDE it. */
46
+ [data-enigma-color] { position: relative; display: inline-flex; flex: none; }
47
+
48
+ [data-enigma-color-swatch] {
49
+ display: block; width: 1.25rem; height: 1.25rem; padding: 0;
50
+ background: none; border: 1px solid var(--enigma-color-border); border-radius: 0.3125rem;
51
+ cursor: pointer; overflow: hidden;
52
+ }
53
+ [data-enigma-color-swatch]:focus-visible { outline: 2px solid var(--enigma-color-focus); outline-offset: 2px; }
54
+ [data-enigma-color-swatch]:disabled { opacity: 0.5; cursor: not-allowed; }
55
+
56
+ /* The chequerboard, so a colour with alpha reads as transparent rather than as a lighter
57
+ colour - which is the whole difference between #ff000080 and #ff8080. */
58
+ [data-enigma-color-checkers] {
59
+ background-image:
60
+ conic-gradient(var(--enigma-color-checker) 0 25%, transparent 0 50%, var(--enigma-color-checker) 0 75%, transparent 0);
61
+ background-size: var(--enigma-color-checker-size) var(--enigma-color-checker-size);
62
+ }
63
+
64
+ [data-enigma-color-fill] { display: block; width: 100%; height: 100%; }
65
+ /* An unparseable field has no colour to show, so the swatch shows the chequerboard alone
66
+ rather than the last good colour: a stale swatch says the value is fine when it is not. */
67
+ [data-enigma-color-swatch][data-invalid] [data-enigma-color-fill] { background: none; }
68
+
69
+ [data-enigma-color-panel] {
70
+ position: absolute; z-index: 60; top: calc(100% + 0.375rem); left: 0;
71
+ display: grid; gap: 0.625rem;
72
+ box-sizing: border-box; width: var(--enigma-color-panel-width); padding: 0.625rem;
73
+ color: var(--enigma-color-text); background: var(--enigma-color-panel-bg);
74
+ border: 1px solid var(--enigma-color-panel-border);
75
+ border-radius: var(--enigma-color-panel-radius);
76
+ box-shadow: var(--enigma-color-panel-shadow);
77
+ }
78
+ /* Flipped when the field sits near the bottom of the window. Without it the panel opens off
79
+ the screen and the controls are unreachable, which is the same defect the select fixes. */
80
+ [data-enigma-color-panel][data-side="top"] { top: auto; bottom: calc(100% + 0.375rem); }
81
+
82
+ [data-enigma-color-area] {
83
+ position: relative; height: var(--enigma-color-area-height);
84
+ border-radius: 0.375rem; cursor: crosshair;
85
+ /* The drag IS the control here, so the page must not scroll under it. The marquee's
86
+ warning about touch-action is the opposite case: a full-width row still has to let the
87
+ page move. */
88
+ touch-action: none;
89
+ background:
90
+ linear-gradient(to top, #000000, rgba(0, 0, 0, 0)),
91
+ linear-gradient(to right, #ffffff, rgba(255, 255, 255, 0)),
92
+ hsl(var(--enigma-color-hue, 0), 100%, 50%);
93
+ }
94
+ [data-enigma-color-area]:focus-visible,
95
+ [data-enigma-color-rail]:focus-visible { outline: 2px solid var(--enigma-color-focus); outline-offset: 2px; }
96
+
97
+ [data-enigma-color-controls] { display: flex; align-items: center; gap: 0.5rem; }
98
+ [data-enigma-color-rails] { display: grid; gap: 0.5rem; flex: 1; min-width: 0; }
99
+
100
+ [data-enigma-color-rail] {
101
+ position: relative; height: var(--enigma-color-rail-height);
102
+ border-radius: 999px; cursor: pointer; touch-action: none;
103
+ }
104
+ [data-enigma-color-rail="hue"] {
105
+ background: linear-gradient(to right, #ff0000, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000);
106
+ }
107
+ [data-enigma-color-rail="alpha"] { background-image: none; }
108
+ [data-enigma-color-rail="alpha"] [data-enigma-color-gradient] {
109
+ position: absolute; inset: 0; border-radius: inherit;
110
+ background: linear-gradient(to right, transparent, var(--enigma-color-opaque, #000000));
111
+ }
112
+
113
+ /* One handle for the square and the rails. It must never take the pointer: a press that
114
+ lands on the handle instead of the surface under it would start no drag at all. */
115
+ [data-enigma-color-thumb] {
116
+ position: absolute; pointer-events: none;
117
+ width: 0.75rem; height: 0.75rem; margin: -0.375rem 0 0 -0.375rem;
118
+ border: 2px solid var(--enigma-color-thumb); border-radius: 999px;
119
+ box-shadow: 0 0 0 1px var(--enigma-color-thumb-ring), inset 0 0 0 1px var(--enigma-color-thumb-ring);
120
+ }
121
+ [data-enigma-color-rail] [data-enigma-color-thumb] { top: 50%; }
122
+
123
+ [data-enigma-color-preview] {
124
+ position: relative; flex: none; width: 1.75rem; height: 1.75rem;
125
+ border: 1px solid var(--enigma-color-border); border-radius: 999px; overflow: hidden;
126
+ }
127
+
128
+ [data-enigma-color-eyedropper] {
129
+ display: grid; place-items: center; flex: none;
130
+ width: 1.75rem; height: 1.75rem; padding: 0;
131
+ color: var(--enigma-color-muted); background: none;
132
+ border: 1px solid var(--enigma-color-border); border-radius: 0.375rem; cursor: pointer;
133
+ }
134
+ [data-enigma-color-eyedropper]:hover { color: var(--enigma-color-text); }
135
+ [data-enigma-color-eyedropper]:focus-visible { outline: 2px solid var(--enigma-color-focus); outline-offset: 2px; }
136
+
137
+ [data-enigma-color-swatches] { display: flex; flex-wrap: wrap; gap: 0.25rem; }
138
+ [data-enigma-color-preset] {
139
+ width: 1.125rem; height: 1.125rem; padding: 0;
140
+ border: 1px solid var(--enigma-color-border); border-radius: 0.25rem; cursor: pointer;
141
+ }
142
+ [data-enigma-color-preset]:focus-visible { outline: 2px solid var(--enigma-color-focus); outline-offset: 2px; }
143
+ [data-enigma-color-preset][aria-pressed="true"] { box-shadow: 0 0 0 2px var(--enigma-color-focus); }
@@ -58,6 +58,14 @@
58
58
  visibility: hidden;
59
59
  }
60
60
  [data-enigma-menu-panel][data-placed] { visibility: visible; }
61
+ /* No focus ring around the panel. It takes focus so the keyboard has somewhere to be, not
62
+ because it is a control: what MOVES is the highlighted row, drawn by [data-active] and
63
+ announced through aria-activedescendant. A ring around the whole menu says the menu is the
64
+ thing focused, which is not what is happening - and it appears the moment you press an
65
+ arrow, over a surface that was already showing you where you are. Nothing is lost by
66
+ removing it, because nothing inside is reachable by Tab: the menu owns that key. */
67
+ [data-enigma-menu-panel]:focus,
68
+ [data-enigma-menu-panel]:focus-visible { outline: none; }
61
69
  @keyframes enigma-menu-in {
62
70
  from { opacity: 0; transform: scale(0.98); }
63
71
  to { opacity: 1; transform: none; }