@nextlyhq/ui 0.0.2-alpha.52 → 0.0.2-alpha.56
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/color.cjs +160 -0
- package/dist/color.cjs.map +1 -0
- package/dist/color.d.cts +168 -0
- package/dist/color.d.ts +168 -0
- package/dist/color.mjs +152 -0
- package/dist/color.mjs.map +1 -0
- package/dist/index.cjs +1181 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +488 -1
- package/dist/index.d.ts +488 -1
- package/dist/index.mjs +1168 -6
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/styles.scoped.css +1 -1
- package/dist/theme.css +97 -91
- package/package.json +18 -5
package/dist/index.d.ts
CHANGED
|
@@ -26,6 +26,7 @@ import { ToasterProps } from 'sonner';
|
|
|
26
26
|
export { ToasterProps, toast } from 'sonner';
|
|
27
27
|
import * as ContextMenuPrimitive from '@radix-ui/react-context-menu';
|
|
28
28
|
import * as ResizablePrimitive from 'react-resizable-panels';
|
|
29
|
+
import * as SliderPrimitive from '@radix-ui/react-slider';
|
|
29
30
|
|
|
30
31
|
/** @public */
|
|
31
32
|
interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
|
|
@@ -2453,4 +2454,490 @@ declare const ResizableHandle: ({ withGrip, className, children, ...props }: rea
|
|
|
2453
2454
|
withGrip?: boolean;
|
|
2454
2455
|
}) => react_jsx_runtime.JSX.Element;
|
|
2455
2456
|
|
|
2456
|
-
|
|
2457
|
+
/**
|
|
2458
|
+
* TreeView
|
|
2459
|
+
*
|
|
2460
|
+
* A keyboard-operable, virtualized tree. The layers panel of an editor is this control: a
|
|
2461
|
+
* hierarchy that can hold thousands of nodes, that someone navigates with arrow keys as much as
|
|
2462
|
+
* with a pointer, and that has to stay responsive while they do.
|
|
2463
|
+
*
|
|
2464
|
+
* **Why virtualized, and why that decides the markup.** A document of a few thousand blocks
|
|
2465
|
+
* renders a few thousand rows, and the cost is not the React work — it is layout and paint on
|
|
2466
|
+
* every expand, scroll and selection. Only the visible window is rendered here.
|
|
2467
|
+
*
|
|
2468
|
+
* That has a consequence the accessibility notes below depend on: with only a window in the DOM,
|
|
2469
|
+
* the nested `role="group"` markup the tree pattern usually uses **cannot be built**, because an
|
|
2470
|
+
* item's children may not be rendered at all. The APG covers this exact case by allowing a FLAT
|
|
2471
|
+
* set of `treeitem`s that describe the hierarchy through `aria-level`, `aria-setsize` and
|
|
2472
|
+
* `aria-posinset` instead of through nesting. A screen reader reads depth and position from those
|
|
2473
|
+
* attributes, so they are not decoration — without them a virtualized tree announces itself as a
|
|
2474
|
+
* flat list of whatever happens to be on screen.
|
|
2475
|
+
*
|
|
2476
|
+
* **Why a headless virtualizer.** The markup above is the requirement, so anything that owns the
|
|
2477
|
+
* DOM is unusable. `@tanstack/react-virtual` computes offsets and renders nothing.
|
|
2478
|
+
*
|
|
2479
|
+
* **State is controllable, not controlled.** `expandedIds`/`selectedId` may be passed with their
|
|
2480
|
+
* `onChange` partners to drive the tree from a store — which an editor will do, since selection is
|
|
2481
|
+
* shared with the canvas and the inspector — or omitted entirely, in which case the tree keeps its
|
|
2482
|
+
* own. Requiring a store for a tree in a settings dialog would be a poor trade.
|
|
2483
|
+
*
|
|
2484
|
+
* **Design specifications**:
|
|
2485
|
+
* - Row height: fixed 28px (`--tree-row`), so the virtualizer needs no measurement pass
|
|
2486
|
+
* - Indent: 12px per level, applied as padding so the whole row stays a hit target
|
|
2487
|
+
* - Selection: `bg-muted`, matching the menu highlight rather than a full-contrast flip
|
|
2488
|
+
* - Focus: `focus-visible` ring in the focus token
|
|
2489
|
+
*
|
|
2490
|
+
* **Accessibility**:
|
|
2491
|
+
* - `role="tree"` with flat `role="treeitem"` children carrying `aria-level`, `aria-setsize`,
|
|
2492
|
+
* `aria-posinset`, and `aria-expanded` on anything with children
|
|
2493
|
+
* - Roving tabindex: exactly one row is in the tab order, so Tab enters and leaves the tree once
|
|
2494
|
+
* rather than walking every node
|
|
2495
|
+
* - Arrow keys move and expand, per the APG tree pattern: Right expands then descends, Left
|
|
2496
|
+
* collapses then ascends, Home/End jump to the ends, `*` expands every sibling
|
|
2497
|
+
* - Typeahead focuses the next row whose label starts with what was typed
|
|
2498
|
+
* - Moving focus scrolls the row into view, which virtualization would otherwise prevent: a row
|
|
2499
|
+
* outside the window has no element to focus
|
|
2500
|
+
*
|
|
2501
|
+
* @example
|
|
2502
|
+
* ```tsx
|
|
2503
|
+
* <TreeView
|
|
2504
|
+
* nodes={layers}
|
|
2505
|
+
* aria-label="Layers"
|
|
2506
|
+
* selectedId={selected}
|
|
2507
|
+
* onSelectedChange={setSelected}
|
|
2508
|
+
* className="h-full"
|
|
2509
|
+
* />
|
|
2510
|
+
* ```
|
|
2511
|
+
*
|
|
2512
|
+
* @module
|
|
2513
|
+
*/
|
|
2514
|
+
|
|
2515
|
+
/**
|
|
2516
|
+
* One node of the tree. Children are omitted or empty for a leaf.
|
|
2517
|
+
*
|
|
2518
|
+
* @experimental
|
|
2519
|
+
*/
|
|
2520
|
+
interface TreeNode {
|
|
2521
|
+
/** Stable identity. What selection and expansion are keyed by. */
|
|
2522
|
+
id: string;
|
|
2523
|
+
/** What the row shows. A string also feeds typeahead; anything else needs `textValue`. */
|
|
2524
|
+
label: react.ReactNode;
|
|
2525
|
+
/**
|
|
2526
|
+
* The text typeahead matches on, when `label` is not a string.
|
|
2527
|
+
*
|
|
2528
|
+
* Without it a row rendered as markup cannot be typed to, and a keyboard user loses the fastest
|
|
2529
|
+
* way through a long tree.
|
|
2530
|
+
*/
|
|
2531
|
+
textValue?: string;
|
|
2532
|
+
/** Children, if any. An empty array still marks the node as a parent. */
|
|
2533
|
+
children?: readonly TreeNode[];
|
|
2534
|
+
/** Shown before the label, after the twisty. */
|
|
2535
|
+
icon?: react.ReactNode;
|
|
2536
|
+
/** Skipped by every keyboard move and not selectable. */
|
|
2537
|
+
disabled?: boolean;
|
|
2538
|
+
}
|
|
2539
|
+
/** @experimental */
|
|
2540
|
+
interface TreeViewProps extends Omit<react.HTMLAttributes<HTMLDivElement>, "onSelect"> {
|
|
2541
|
+
/** The roots of the tree. */
|
|
2542
|
+
nodes: readonly TreeNode[];
|
|
2543
|
+
/** Expanded node ids, if the caller owns them. */
|
|
2544
|
+
expandedIds?: readonly string[];
|
|
2545
|
+
/** Which ids start expanded when the caller does not own expansion. */
|
|
2546
|
+
defaultExpandedIds?: readonly string[];
|
|
2547
|
+
/** Called with the full next set whenever a branch opens or closes. */
|
|
2548
|
+
onExpandedChange?: (ids: string[]) => void;
|
|
2549
|
+
/** The selected node id, if the caller owns it. */
|
|
2550
|
+
selectedId?: string | null;
|
|
2551
|
+
/** Which id starts selected when the caller does not own selection. */
|
|
2552
|
+
defaultSelectedId?: string | null;
|
|
2553
|
+
/** Called when a row is chosen, by pointer or by Enter. */
|
|
2554
|
+
onSelectedChange?: (id: string) => void;
|
|
2555
|
+
/**
|
|
2556
|
+
* Names the tree for a screen reader. One of this or `aria-labelledby` is required: a tree
|
|
2557
|
+
* announced only as "tree" tells a user nothing about which one they are in.
|
|
2558
|
+
*/
|
|
2559
|
+
"aria-label"?: string;
|
|
2560
|
+
}
|
|
2561
|
+
/**
|
|
2562
|
+
* A virtualized tree.
|
|
2563
|
+
*
|
|
2564
|
+
* @experimental
|
|
2565
|
+
*/
|
|
2566
|
+
declare const TreeView: react.ForwardRefExoticComponent<TreeViewProps & react.RefAttributes<HTMLDivElement>>;
|
|
2567
|
+
|
|
2568
|
+
/**
|
|
2569
|
+
* The assistive-technology attributes a single thumb can carry.
|
|
2570
|
+
*
|
|
2571
|
+
* @experimental
|
|
2572
|
+
*/
|
|
2573
|
+
interface SliderThumbProps {
|
|
2574
|
+
/** The thumb's accessible name. */
|
|
2575
|
+
"aria-label"?: string;
|
|
2576
|
+
/** An element naming the thumb, when the name is already on screen. */
|
|
2577
|
+
"aria-labelledby"?: string;
|
|
2578
|
+
/**
|
|
2579
|
+
* What the value MEANS, when the number alone does not say it — "40
|
|
2580
|
+
* percent", "Medium". Announced in place of the raw number.
|
|
2581
|
+
*/
|
|
2582
|
+
"aria-valuetext"?: string;
|
|
2583
|
+
/** An element carrying help text for this thumb. */
|
|
2584
|
+
"aria-describedby"?: string;
|
|
2585
|
+
}
|
|
2586
|
+
/**
|
|
2587
|
+
* The slider's props, mirroring the Radix root.
|
|
2588
|
+
*
|
|
2589
|
+
* @experimental
|
|
2590
|
+
*/
|
|
2591
|
+
type SliderProps = Omit<react.ComponentPropsWithoutRef<typeof SliderPrimitive.Root>, "asChild"> & {
|
|
2592
|
+
/**
|
|
2593
|
+
* Assistive-technology attributes per thumb, in value order.
|
|
2594
|
+
*
|
|
2595
|
+
* The reason this exists at all: the focusable element with the `slider`
|
|
2596
|
+
* role is the THUMB, and none of these attributes are inherited from the
|
|
2597
|
+
* root. Anything a caller puts on the root is therefore announced by
|
|
2598
|
+
* nothing, and the thumbs are generated internally so they cannot be
|
|
2599
|
+
* reached any other way.
|
|
2600
|
+
*
|
|
2601
|
+
* Deliberately a curated set rather than the thumb's full prop type. This
|
|
2602
|
+
* is the surface assistive technology reads; opening it to arbitrary props
|
|
2603
|
+
* would let a caller replace the class names or the role the control
|
|
2604
|
+
* depends on, and every escape hatch in a design system eventually gets
|
|
2605
|
+
* used that way.
|
|
2606
|
+
*
|
|
2607
|
+
* Required for a RANGE: two thumbs sharing one name are announced
|
|
2608
|
+
* identically, so nothing says which end is held. A single thumb falls back
|
|
2609
|
+
* to the root's `aria-label`/`aria-labelledby`, so the one-thumb API stays
|
|
2610
|
+
* as documented.
|
|
2611
|
+
*/
|
|
2612
|
+
thumbs?: readonly SliderThumbProps[];
|
|
2613
|
+
};
|
|
2614
|
+
/**
|
|
2615
|
+
* A bounded numeric value chosen by dragging.
|
|
2616
|
+
*
|
|
2617
|
+
* @experimental
|
|
2618
|
+
*/
|
|
2619
|
+
declare const Slider: react.ForwardRefExoticComponent<Omit<Omit<SliderPrimitive.SliderProps & react.RefAttributes<HTMLSpanElement>, "ref">, "asChild"> & {
|
|
2620
|
+
/**
|
|
2621
|
+
* Assistive-technology attributes per thumb, in value order.
|
|
2622
|
+
*
|
|
2623
|
+
* The reason this exists at all: the focusable element with the `slider`
|
|
2624
|
+
* role is the THUMB, and none of these attributes are inherited from the
|
|
2625
|
+
* root. Anything a caller puts on the root is therefore announced by
|
|
2626
|
+
* nothing, and the thumbs are generated internally so they cannot be
|
|
2627
|
+
* reached any other way.
|
|
2628
|
+
*
|
|
2629
|
+
* Deliberately a curated set rather than the thumb's full prop type. This
|
|
2630
|
+
* is the surface assistive technology reads; opening it to arbitrary props
|
|
2631
|
+
* would let a caller replace the class names or the role the control
|
|
2632
|
+
* depends on, and every escape hatch in a design system eventually gets
|
|
2633
|
+
* used that way.
|
|
2634
|
+
*
|
|
2635
|
+
* Required for a RANGE: two thumbs sharing one name are announced
|
|
2636
|
+
* identically, so nothing says which end is held. A single thumb falls back
|
|
2637
|
+
* to the root's `aria-label`/`aria-labelledby`, so the one-thumb API stays
|
|
2638
|
+
* as documented.
|
|
2639
|
+
*/
|
|
2640
|
+
thumbs?: readonly SliderThumbProps[];
|
|
2641
|
+
} & react.RefAttributes<HTMLSpanElement>>;
|
|
2642
|
+
|
|
2643
|
+
/**
|
|
2644
|
+
* The single owner of keyboard shortcuts for an application.
|
|
2645
|
+
*
|
|
2646
|
+
* ## Why this exists
|
|
2647
|
+
*
|
|
2648
|
+
* Shortcuts are usually registered by whoever needs them, each component adding its own
|
|
2649
|
+
* `document` listener. That works until two of them want the same key, and then it fails in a way
|
|
2650
|
+
* that is very hard to see: `stopPropagation()` does NOT stop other listeners on the same node —
|
|
2651
|
+
* that requires `stopImmediatePropagation()`, and even then only for listeners registered later.
|
|
2652
|
+
* So every global handler runs, in mount order, and mount order is not something a developer
|
|
2653
|
+
* chose. Pressing Escape during a drag can cancel the drag AND navigate away from the page,
|
|
2654
|
+
* because two independent listeners each believed they owned the key.
|
|
2655
|
+
*
|
|
2656
|
+
* This module replaces that with one listener and an explicit precedence rule.
|
|
2657
|
+
*
|
|
2658
|
+
* ## The model: a stack of layers
|
|
2659
|
+
*
|
|
2660
|
+
* A **layer** is a set of bindings belonging to one interactive context — the application shell,
|
|
2661
|
+
* a dialog, an editor canvas mid-drag. Layers are ordered, the topmost is offered each keystroke
|
|
2662
|
+
* first, and the first binding that matches consumes it.
|
|
2663
|
+
*
|
|
2664
|
+
* Precedence is `(depth, sequence)`: the deeper layer wins, and between layers at equal depth the
|
|
2665
|
+
* more recently registered wins.
|
|
2666
|
+
*
|
|
2667
|
+
* Of those two, **depth is declared and sequence is incidental** — and only declared properties
|
|
2668
|
+
* survive a refactor. A layer that unmounts and remounts takes a fresh sequence number, so a
|
|
2669
|
+
* subtree rebuilt for unrelated reasons can change equal-depth ordering. The guidance that falls
|
|
2670
|
+
* out: if relative order matters to you, express it as depth, because depth is the part of the
|
|
2671
|
+
* tuple you control. Equal-depth ordering is for stacking things that arrive in genuine
|
|
2672
|
+
* mount order, such as one dialog over another. Depth comes from how the application nests, so precedence
|
|
2673
|
+
* follows the component tree rather than a set of coordinated numbers — the z-index problem,
|
|
2674
|
+
* avoided. Equal-depth ordering is what stacks a second dialog above the first.
|
|
2675
|
+
*
|
|
2676
|
+
* A layer may be **blocking**, meaning it also swallows the keys it does NOT bind. That is the
|
|
2677
|
+
* property a drag or a modal needs: while it is up, nothing beneath it can act. This is the same
|
|
2678
|
+
* shape as a window manager's keyboard grab, and as the dismissable-layer stack this kit's
|
|
2679
|
+
* dialogs already sit on.
|
|
2680
|
+
*
|
|
2681
|
+
* ## What it deliberately does not do
|
|
2682
|
+
*
|
|
2683
|
+
* It listens in the BUBBLE phase, so a focused component that handles its own keys and calls
|
|
2684
|
+
* `stopPropagation()` wins without needing to know this module exists. React attaches its
|
|
2685
|
+
* handlers at the app root, below `document`, so an `onKeyDown` prop is a sufficient opt-out.
|
|
2686
|
+
* Capturing instead would make this module outrank every component in the tree, including the
|
|
2687
|
+
* kit's own dialogs, and there would be no way for a component to decline.
|
|
2688
|
+
*
|
|
2689
|
+
* @module lib/shortcuts/manager
|
|
2690
|
+
*/
|
|
2691
|
+
/**
|
|
2692
|
+
* One shortcut and what it does.
|
|
2693
|
+
*
|
|
2694
|
+
* @experimental
|
|
2695
|
+
*/
|
|
2696
|
+
interface ShortcutBinding {
|
|
2697
|
+
/** The keys, as understood by `parseKeys` — `"mod+s"`, `"Escape"`, `"g d"`. */
|
|
2698
|
+
keys: string;
|
|
2699
|
+
/**
|
|
2700
|
+
* What this does, in words, for a shortcuts help panel. Required because an undiscoverable
|
|
2701
|
+
* shortcut helps only the person who wrote it.
|
|
2702
|
+
*/
|
|
2703
|
+
description: string;
|
|
2704
|
+
/** Runs when the shortcut fires. */
|
|
2705
|
+
run: (event: KeyboardEvent) => void;
|
|
2706
|
+
/** Checked at press time; a binding whose condition is false is skipped and passes the key on. */
|
|
2707
|
+
when?: () => boolean;
|
|
2708
|
+
/**
|
|
2709
|
+
* Whether this fires while the user is typing in a field.
|
|
2710
|
+
*
|
|
2711
|
+
* Defaults to true for bindings whose FIRST chord carries a non-shift modifier or is Escape,
|
|
2712
|
+
* and false otherwise — the rule nearly every application converges on. `mod+s` must save
|
|
2713
|
+
* mid-sentence and Escape must dismiss, while a bare `n` must be able to be the letter n.
|
|
2714
|
+
*
|
|
2715
|
+
* The first chord decides because it is the keystroke that has to be taken from the field.
|
|
2716
|
+
* `mod+k c` is a command from its opening chord, so its bare `c` completes it in an input. A
|
|
2717
|
+
* sequence that OPENS on a plain character cannot fire while typing whatever it ends with:
|
|
2718
|
+
* allowing `g Escape` would mean swallowing the `g` of every word containing one.
|
|
2719
|
+
*/
|
|
2720
|
+
whenTyping?: boolean;
|
|
2721
|
+
/** Whether to call `preventDefault()` when it fires. Defaults to true. */
|
|
2722
|
+
preventDefault?: boolean;
|
|
2723
|
+
}
|
|
2724
|
+
/**
|
|
2725
|
+
* How a layer behaves for keys it does not bind.
|
|
2726
|
+
*
|
|
2727
|
+
* @experimental
|
|
2728
|
+
*/
|
|
2729
|
+
interface ShortcutLayerOptions {
|
|
2730
|
+
/** Identifies the layer in diagnostics and in a help panel. */
|
|
2731
|
+
name: string;
|
|
2732
|
+
/** Precedence: deeper layers are offered keystrokes first. */
|
|
2733
|
+
depth: number;
|
|
2734
|
+
/**
|
|
2735
|
+
* Whether unmatched keys stop here instead of reaching layers beneath.
|
|
2736
|
+
*
|
|
2737
|
+
* The reason a drag can be interrupted safely: everything below is inert for as long as this
|
|
2738
|
+
* is set, so no other context can act on a keystroke aimed at this one.
|
|
2739
|
+
*/
|
|
2740
|
+
blocking?: boolean;
|
|
2741
|
+
/** Whether the layer participates at all. A disabled layer neither matches nor blocks. */
|
|
2742
|
+
enabled?: boolean;
|
|
2743
|
+
}
|
|
2744
|
+
/**
|
|
2745
|
+
* A layer's registration, held by whoever created it.
|
|
2746
|
+
*
|
|
2747
|
+
* @experimental
|
|
2748
|
+
*/
|
|
2749
|
+
interface ShortcutRegistration {
|
|
2750
|
+
/** Replace this layer's bindings and options without changing its precedence. */
|
|
2751
|
+
update: (bindings: readonly ShortcutBinding[], options: ShortcutLayerOptions) => void;
|
|
2752
|
+
/** Remove the layer. */
|
|
2753
|
+
dispose: () => void;
|
|
2754
|
+
}
|
|
2755
|
+
/**
|
|
2756
|
+
* Options for creating a manager.
|
|
2757
|
+
*
|
|
2758
|
+
* @experimental
|
|
2759
|
+
*/
|
|
2760
|
+
interface ShortcutManagerOptions {
|
|
2761
|
+
/** Whether `mod` means Command. Detected from the platform when omitted. */
|
|
2762
|
+
isApple?: boolean;
|
|
2763
|
+
/** How long a partially typed sequence waits for its next key, in milliseconds. */
|
|
2764
|
+
sequenceTimeoutMs?: number;
|
|
2765
|
+
/** Clock source, for tests that need to control sequence expiry. */
|
|
2766
|
+
now?: () => number;
|
|
2767
|
+
}
|
|
2768
|
+
/**
|
|
2769
|
+
* A shortcut manager: the registry, the matcher, and the one listener.
|
|
2770
|
+
*
|
|
2771
|
+
* @experimental
|
|
2772
|
+
*/
|
|
2773
|
+
interface ShortcutManager {
|
|
2774
|
+
/** Add a layer. */
|
|
2775
|
+
register: (bindings: readonly ShortcutBinding[], options: ShortcutLayerOptions) => ShortcutRegistration;
|
|
2776
|
+
/**
|
|
2777
|
+
* Offer a keystroke to the stack. Returns whether it was consumed.
|
|
2778
|
+
*
|
|
2779
|
+
* Public so the behaviour can be tested without a DOM, and so a host that already owns its
|
|
2780
|
+
* event plumbing can drive the manager itself.
|
|
2781
|
+
*/
|
|
2782
|
+
handle: (event: KeyboardEvent) => boolean;
|
|
2783
|
+
/** Install the single listener on a target, returning a function that removes it. */
|
|
2784
|
+
attach: (target: Pick<EventTarget, "addEventListener" | "removeEventListener">) => () => void;
|
|
2785
|
+
/**
|
|
2786
|
+
* Every active binding, most-precedent layer first, for a shortcuts help panel.
|
|
2787
|
+
*
|
|
2788
|
+
* The same array is returned until the layer stack changes, so it is safe to use as an external
|
|
2789
|
+
* store snapshot without re-rendering on every read.
|
|
2790
|
+
*/
|
|
2791
|
+
activeBindings: () => readonly ActiveShortcut[];
|
|
2792
|
+
/**
|
|
2793
|
+
* Watch for changes to the layer stack.
|
|
2794
|
+
*
|
|
2795
|
+
* A help panel mounting alongside the components that register shortcuts would otherwise read
|
|
2796
|
+
* BEFORE their effects run and show nothing, with no later render to correct it.
|
|
2797
|
+
*/
|
|
2798
|
+
subscribe: (onChange: () => void) => () => void;
|
|
2799
|
+
}
|
|
2800
|
+
/**
|
|
2801
|
+
* A binding as presented to a help panel, with the layer it came from.
|
|
2802
|
+
*
|
|
2803
|
+
* @experimental
|
|
2804
|
+
*/
|
|
2805
|
+
interface ActiveShortcut {
|
|
2806
|
+
keys: string;
|
|
2807
|
+
description: string;
|
|
2808
|
+
layer: string;
|
|
2809
|
+
}
|
|
2810
|
+
/**
|
|
2811
|
+
* Create a shortcut manager.
|
|
2812
|
+
*
|
|
2813
|
+
* @experimental
|
|
2814
|
+
*/
|
|
2815
|
+
declare function createShortcutManager(options?: ShortcutManagerOptions): ShortcutManager;
|
|
2816
|
+
|
|
2817
|
+
/**
|
|
2818
|
+
* Props for {@link ShortcutProvider}.
|
|
2819
|
+
*
|
|
2820
|
+
* @experimental
|
|
2821
|
+
*/
|
|
2822
|
+
interface ShortcutProviderProps extends ShortcutManagerOptions {
|
|
2823
|
+
children?: react.ReactNode;
|
|
2824
|
+
/**
|
|
2825
|
+
* Where the listener is installed. Defaults to `document`.
|
|
2826
|
+
*
|
|
2827
|
+
* The bubble phase is deliberate: a component that handles its own keys and calls
|
|
2828
|
+
* `stopPropagation` wins without knowing this exists, because React attaches its handlers
|
|
2829
|
+
* below `document`.
|
|
2830
|
+
*/
|
|
2831
|
+
target?: Pick<EventTarget, "addEventListener" | "removeEventListener"> | null;
|
|
2832
|
+
}
|
|
2833
|
+
/**
|
|
2834
|
+
* Installs the application's one keydown listener and roots the layer stack.
|
|
2835
|
+
*
|
|
2836
|
+
* @experimental
|
|
2837
|
+
*/
|
|
2838
|
+
declare function ShortcutProvider({ children, target, ...managerOptions }: ShortcutProviderProps): react.JSX.Element;
|
|
2839
|
+
/**
|
|
2840
|
+
* Raises the precedence of everything inside it by one level.
|
|
2841
|
+
*
|
|
2842
|
+
* @experimental
|
|
2843
|
+
*/
|
|
2844
|
+
declare function ShortcutScope({ children, }: {
|
|
2845
|
+
children?: react.ReactNode;
|
|
2846
|
+
}): react.JSX.Element;
|
|
2847
|
+
/**
|
|
2848
|
+
* Options for {@link useShortcuts}, minus the depth, which comes from the tree.
|
|
2849
|
+
*
|
|
2850
|
+
* @experimental
|
|
2851
|
+
*/
|
|
2852
|
+
interface UseShortcutsOptions {
|
|
2853
|
+
/** Identifies this layer in a help panel. */
|
|
2854
|
+
name: string;
|
|
2855
|
+
/** Whether the layer participates. A disabled layer neither matches nor blocks. */
|
|
2856
|
+
enabled?: boolean;
|
|
2857
|
+
/**
|
|
2858
|
+
* Whether unmatched keys stop here rather than reaching layers beneath.
|
|
2859
|
+
*
|
|
2860
|
+
* Set this while a drag or a modal interaction owns the keyboard.
|
|
2861
|
+
*/
|
|
2862
|
+
blocking?: boolean;
|
|
2863
|
+
}
|
|
2864
|
+
/**
|
|
2865
|
+
* Register shortcuts for as long as the calling component is mounted.
|
|
2866
|
+
*
|
|
2867
|
+
* The bindings array may be rebuilt on every render; it is re-read in place rather than
|
|
2868
|
+
* re-registered, so inline closures are fine and the layer keeps its position in the stack.
|
|
2869
|
+
*
|
|
2870
|
+
* @experimental
|
|
2871
|
+
*/
|
|
2872
|
+
declare function useShortcuts(bindings: readonly ShortcutBinding[], options: UseShortcutsOptions): void;
|
|
2873
|
+
/**
|
|
2874
|
+
* The manager itself, for a help panel that lists what is currently bound.
|
|
2875
|
+
*
|
|
2876
|
+
* @experimental
|
|
2877
|
+
*/
|
|
2878
|
+
declare function useShortcutManager(): ShortcutManager;
|
|
2879
|
+
/**
|
|
2880
|
+
* The shortcuts currently in effect, most precedent first.
|
|
2881
|
+
*
|
|
2882
|
+
* SUBSCRIBED rather than read once. A help panel mounting alongside the components that register
|
|
2883
|
+
* shortcuts reads before their effects have run, so a one-time read returns an empty list and no
|
|
2884
|
+
* later render corrects it — the panel simply shows nothing. The same applies whenever a layer is
|
|
2885
|
+
* enabled, disabled or replaced while the panel is open.
|
|
2886
|
+
*
|
|
2887
|
+
* The manager returns the same array until its stack changes, so this re-renders when the
|
|
2888
|
+
* shortcuts change and not on every read.
|
|
2889
|
+
*
|
|
2890
|
+
* @experimental
|
|
2891
|
+
*/
|
|
2892
|
+
declare function useActiveShortcuts(): readonly ActiveShortcut[];
|
|
2893
|
+
|
|
2894
|
+
/**
|
|
2895
|
+
* Parsing and matching for keyboard shortcut specifications.
|
|
2896
|
+
*
|
|
2897
|
+
* A spec is written the way it is spoken: `"mod+s"`, `"Escape"`, `"shift+alt+f"`, and — for a
|
|
2898
|
+
* sequence — `"g d"`, meaning `g` then `d`. Steps are separated by spaces; within a step,
|
|
2899
|
+
* modifiers are joined to the key with `+`.
|
|
2900
|
+
*
|
|
2901
|
+
* The space bar is written `"Space"`, because the character the browser reports for it is `" "`
|
|
2902
|
+
* and a spec split on whitespace has no way to carry that.
|
|
2903
|
+
*
|
|
2904
|
+
* **`mod` is the point of this module.** It resolves to Command on Apple platforms and Control
|
|
2905
|
+
* everywhere else, so a binding is written once. Writing `ctrl` or `meta` explicitly is still
|
|
2906
|
+
* possible and then means exactly that, which is what lets a platform-specific binding coexist
|
|
2907
|
+
* with a portable one — a distinction lost by any implementation that treats the two as
|
|
2908
|
+
* interchangeable.
|
|
2909
|
+
*
|
|
2910
|
+
* @module lib/shortcuts/key-spec
|
|
2911
|
+
*/
|
|
2912
|
+
/**
|
|
2913
|
+
* One keystroke: a key plus the modifier state required with it.
|
|
2914
|
+
*
|
|
2915
|
+
* @experimental
|
|
2916
|
+
*/
|
|
2917
|
+
interface KeyChord {
|
|
2918
|
+
/** The `KeyboardEvent.key` value, normalized to lower case for single characters. */
|
|
2919
|
+
readonly key: string;
|
|
2920
|
+
/** Command on Apple platforms, Control elsewhere. */
|
|
2921
|
+
readonly mod: boolean;
|
|
2922
|
+
readonly ctrl: boolean;
|
|
2923
|
+
readonly meta: boolean;
|
|
2924
|
+
readonly alt: boolean;
|
|
2925
|
+
readonly shift: boolean;
|
|
2926
|
+
}
|
|
2927
|
+
/**
|
|
2928
|
+
* A shortcut: one chord, or several pressed in order.
|
|
2929
|
+
*
|
|
2930
|
+
* @experimental
|
|
2931
|
+
*/
|
|
2932
|
+
type KeySequence = readonly KeyChord[];
|
|
2933
|
+
/**
|
|
2934
|
+
* Parse a spec into the sequence of chords it describes.
|
|
2935
|
+
*
|
|
2936
|
+
* @param spec - For example `"mod+s"`, `"Escape"`, or `"g d"`.
|
|
2937
|
+
* @throws If the spec is empty, or a step names modifiers but no key.
|
|
2938
|
+
*
|
|
2939
|
+
* @experimental
|
|
2940
|
+
*/
|
|
2941
|
+
declare function parseKeys(spec: string): KeySequence;
|
|
2942
|
+
|
|
2943
|
+
export { Accordion, AccordionContent, type AccordionContentProps, AccordionItem, type AccordionItemProps, type AccordionProps, AccordionTrigger, type AccordionTriggerProps, type ActionCallbacks, type ActiveShortcut, Alert, AlertDescription, type AlertDescriptionProps, AlertDialog, AlertDialogAction, type AlertDialogActionProps, AlertDialogCancel, type AlertDialogCancelProps, AlertDialogContent, type AlertDialogContentProps, AlertDialogDescription, type AlertDialogDescriptionProps, AlertDialogFooter, type AlertDialogFooterProps, AlertDialogHeader, type AlertDialogHeaderProps, AlertDialogOverlay, type AlertDialogOverlayProps, AlertDialogPortal, AlertDialogTitle, type AlertDialogTitleProps, AlertDialogTrigger, type AlertProps, AlertTitle, type AlertTitleProps, Avatar, AvatarFallback, type AvatarFallbackProps, AvatarImage, type AvatarImageProps, type AvatarProps, Badge, type BadgeProps, Button, type ButtonProps, Card, CardAction, type CardActionProps, CardContent, type CardContentProps, CardDescription, type CardDescriptionProps, CardFooter, type CardFooterProps, CardHeader, type CardHeaderProps, type CardProps, CardTitle, type CardTitleProps, Checkbox, Collapsible, CollapsibleContent, CollapsibleTrigger, Command, CommandDialog, type CommandDialogProps, CommandEmpty, type CommandEmptyProps, CommandGroup, type CommandGroupProps, CommandInput, type CommandInputProps, CommandItem, type CommandItemProps, CommandList, type CommandListProps, type CommandProps, CommandSeparator, type CommandSeparatorProps, CommandShortcut, type CommandShortcutProps, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, type DataFetcher, Dialog, DialogClose, DialogContent, type DialogContentProps, DialogDescription, type DialogDescriptionProps, DialogFooter, type DialogFooterProps, DialogHeader, type DialogHeaderProps, DialogOverlay, type DialogOverlayProps, DialogPortal, DialogTitle, type DialogTitleProps, DialogTrigger, DropdownMenu, DropdownMenuCheckboxItem, type DropdownMenuCheckboxItemProps, DropdownMenuContent, type DropdownMenuContentProps, DropdownMenuGroup, DropdownMenuItem, type DropdownMenuItemProps, DropdownMenuLabel, type DropdownMenuLabelProps, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, type DropdownMenuRadioItemProps, DropdownMenuSeparator, type DropdownMenuSeparatorProps, DropdownMenuShortcut, type DropdownMenuShortcutProps, DropdownMenuSub, DropdownMenuSubContent, type DropdownMenuSubContentProps, DropdownMenuSubTrigger, type DropdownMenuSubTriggerProps, DropdownMenuTrigger, type FilterInfo, FormLabelWithTooltip, type FormLabelWithTooltipProps, Grid, type GridProps, Input, type InputProps, type KeyChord, type KeySequence, Label, type ListResponse, type PaginationConfig, type PaginationMeta, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, PortalProvider, Progress, type ProgressProps, RadioGroup, RadioGroupItem, ResizableHandle, ResizablePanel, ResizablePanelGroup, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, type SelectTriggerProps, SelectValue, Separator, Sheet, SheetClose, type SheetCloseProps, SheetContent, type SheetContentProps, type SheetContentRef, SheetDescription, type SheetDescriptionProps, type SheetDescriptionRef, SheetFooter, type SheetFooterProps, SheetHeader, type SheetHeaderProps, SheetOverlay, type SheetOverlayProps, type SheetOverlayRef, SheetPortal, type SheetProps, SheetTitle, type SheetTitleProps, type SheetTitleRef, SheetTrigger, type SheetTriggerProps, type ShortcutBinding, type ShortcutLayerOptions, type ShortcutManager, type ShortcutManagerOptions, ShortcutProvider, type ShortcutProviderProps, type ShortcutRegistration, ShortcutScope, Skeleton, type SkeletonProps, Slider, type SliderProps, type SliderThumbProps, type SortInfo, Spinner, type SpinnerProps, Stack, type StackProps, Stat, type StatProps, Switch, Table, TableBody, TableCaption, TableCell, TableEmpty, type TableEmptyProps, TableError, type TableErrorProps, TableFooter, TableHead, TableHeader, TableLoading, type TableParams, TableRow, TableSearch, type TableSearchProps, TableSkeleton, type TableSkeletonProps, Tabs, TabsContent, type TabsContentProps, TabsList, type TabsListProps, type TabsProps, TabsTrigger, type TabsTriggerProps, Textarea, Toaster, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, type TreeNode, TreeView, type TreeViewProps, type UseShortcutsOptions, alertVariants, avatarVariants, badgeVariants, buttonVariants, cardVariants, createShortcutManager, dialogContentVariants, inputVariants, parseKeys, progressVariants, selectTriggerVariants, sheetVariants, spinnerVariants, useActiveShortcuts, usePortalContainer, useShortcutManager, useShortcuts };
|