@vitavision/ui 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -5
- package/dist/index.d.ts +235 -6
- package/dist/index.js +395 -26
- package/dist/index.js.map +1 -1
- package/package.json +3 -1
- package/src/components/ui/DropdownMenu.tsx +179 -0
- package/src/components/ui/Input.tsx +133 -8
- package/src/components/ui/Kbd.tsx +27 -0
- package/src/components/ui/Listbox.tsx +160 -0
- package/src/components/ui/Popover.tsx +96 -0
- package/src/components/ui/VectorInput.tsx +6 -2
- package/src/components/ui/index.ts +19 -0
- package/src/components/ui/listboxModel.ts +63 -0
- package/src/components/ui/numberText.ts +2 -2
package/README.md
CHANGED
|
@@ -123,13 +123,25 @@ keep independent preferences.
|
|
|
123
123
|
### Components
|
|
124
124
|
|
|
125
125
|
**Primitives** — `Badge`, `CountRun`, `StatusDot` · `Button`, `ButtonLink` (a navigation styled as a button — never nest a `Button` in a link), `buttonClasses` · `Dialog`, `ConfirmDialog`,
|
|
126
|
-
`DialogClose` · `Disclosure` · `
|
|
127
|
-
`
|
|
128
|
-
|
|
129
|
-
`
|
|
126
|
+
`DialogClose` · `Disclosure` · `DropdownMenu`, `MenuItem`, `MenuCheckboxItem`, `MenuLabel`,
|
|
127
|
+
`MenuSeparator` (a non-modal command and toggle menu) · `Callout`, `Empty`, `ErrorBox`,
|
|
128
|
+
`ProgressBar`, `Skeleton`, `SkeletonRows` · `Field` · `Input`, `NumberInput` (with an optional
|
|
129
|
+
`unit` written in the field; number-valued with `onValueChange`), `Textarea` · `VectorInput`,
|
|
130
|
+
`PoseInput` · `Kbd` · `Listbox` (single choice among options that render their own content) ·
|
|
131
|
+
`PageHeader`, `Panel`, `ReadoutStrip`, `Section` · `Popover`, `PopoverClose` ·
|
|
132
|
+
`SegmentedControl` · `Select` · `Slider` · `Table` ·
|
|
130
133
|
`Checkbox`, `Switch` · `ToggleChip` · `Toaster`, `toast()` (notifications from anywhere; mount one `<Toaster />` near the root) ·
|
|
131
134
|
`InfoHint`, `Tooltip`, `TooltipProvider` ·
|
|
132
|
-
`ThemeToggle` · plus `cn`, `focusRing`, `focusRingInset
|
|
135
|
+
`ThemeToggle` · plus `cn`, `focusRing`, `focusRingInset`, and `formatNumber` / `parseNumber`
|
|
136
|
+
(the text ↔ number helpers behind the number fields).
|
|
137
|
+
|
|
138
|
+
A number-valued `NumberInput` keeps what is being typed and reports only finite numbers inside
|
|
139
|
+
`[min, max]`, so clearing a field to retype it never passes through 0. `onClear` is for a
|
|
140
|
+
quantity that may be unset:
|
|
141
|
+
|
|
142
|
+
```tsx
|
|
143
|
+
<NumberInput unit="px" precision={1} min={4} value={roi.width} onValueChange={setWidth} />
|
|
144
|
+
```
|
|
133
145
|
|
|
134
146
|
`PoseInput` edits an SE(3) pose in the wire form `{ rotation: [qx, qy, qz, qw], translation:
|
|
135
147
|
[tx, ty, tz] }` as a translation and roll/pitch/yaw in degrees, but does no rotation
|
package/dist/index.d.ts
CHANGED
|
@@ -335,6 +335,77 @@ export declare function Disclosure({ summary, count, defaultOpen, className, chi
|
|
|
335
335
|
children: ReactNode;
|
|
336
336
|
}): import("react").JSX.Element;
|
|
337
337
|
//#endregion
|
|
338
|
+
//#region src/components/ui/DropdownMenu.d.ts
|
|
339
|
+
/** Props of `DropdownMenu`. */
|
|
340
|
+
interface DropdownMenuProps {
|
|
341
|
+
/** The element that opens it: one focusable element that accepts a ref (Radix `asChild`). */
|
|
342
|
+
trigger: ReactNode;
|
|
343
|
+
/** `MenuItem`, `MenuCheckboxItem`, `MenuLabel` and `MenuSeparator` elements. */
|
|
344
|
+
children: ReactNode;
|
|
345
|
+
/** Controlled open state. */
|
|
346
|
+
open?: boolean | undefined;
|
|
347
|
+
/** Called when it opens or closes. */
|
|
348
|
+
onOpenChange?: ((open: boolean) => void) | undefined;
|
|
349
|
+
/** Its alignment along the trigger. Defaults to `start`. */
|
|
350
|
+
align?: "start" | "center" | "end" | undefined;
|
|
351
|
+
/** The trigger's side it opens on. Defaults to `bottom`. */
|
|
352
|
+
side?: "top" | "right" | "bottom" | "left" | undefined;
|
|
353
|
+
/** Merged with the menu's own classes through `cn`. */
|
|
354
|
+
className?: string | undefined;
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* A menu (`role="menu"`) that opens from `trigger`, with arrow-key navigation, typeahead,
|
|
358
|
+
* Escape or a press outside to close, and focus returned to the trigger. It is non-modal: the
|
|
359
|
+
* page behind stays readable and operable. Toggling a `MenuCheckboxItem` keeps the menu open,
|
|
360
|
+
* so several layers can be switched in one visit.
|
|
361
|
+
*/
|
|
362
|
+
export declare function DropdownMenu({ trigger, children, open, onOpenChange, align, side, className }: DropdownMenuProps): import("react").JSX.Element;
|
|
363
|
+
/** Props of `MenuItem`. */
|
|
364
|
+
interface MenuItemProps {
|
|
365
|
+
/** The item's text. */
|
|
366
|
+
children: ReactNode;
|
|
367
|
+
/** Runs the command. */
|
|
368
|
+
onSelect?: (() => void) | undefined;
|
|
369
|
+
/** An icon before the text, in the indicator column. */
|
|
370
|
+
icon?: ReactNode;
|
|
371
|
+
/** `defect` for a destructive command. */
|
|
372
|
+
tone?: "defect" | undefined;
|
|
373
|
+
/** A shortcut shown at the end of the row, as a `Kbd`. Display only: binding it is the app's. */
|
|
374
|
+
shortcut?: string | undefined;
|
|
375
|
+
/** Blocks the item. */
|
|
376
|
+
disabled?: boolean | undefined;
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* A command. `onSelect` runs when it is clicked or chosen with Enter, and the menu then
|
|
380
|
+
* closes. `tone="defect"` marks a destructive command.
|
|
381
|
+
*/
|
|
382
|
+
export declare function MenuItem({ children, onSelect, shortcut, disabled, icon, tone }: MenuItemProps): import("react").JSX.Element;
|
|
383
|
+
/** Props of `MenuCheckboxItem`. */
|
|
384
|
+
interface MenuCheckboxItemProps {
|
|
385
|
+
/** The item's text. */
|
|
386
|
+
children: ReactNode;
|
|
387
|
+
/** Whether it is on. */
|
|
388
|
+
checked: boolean;
|
|
389
|
+
/** Called with the new state. */
|
|
390
|
+
onCheckedChange: (checked: boolean) => void;
|
|
391
|
+
/** A shortcut shown at the end of the row, as a `Kbd`. Display only: binding it is the app's. */
|
|
392
|
+
shortcut?: string | undefined;
|
|
393
|
+
/** Blocks the item. */
|
|
394
|
+
disabled?: boolean | undefined;
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* A toggle (`role="menuitemcheckbox"`): a layer on or off. A check marks it on. Choosing it
|
|
398
|
+
* leaves the menu open.
|
|
399
|
+
*/
|
|
400
|
+
export declare function MenuCheckboxItem({ children, checked, onCheckedChange, shortcut, disabled }: MenuCheckboxItemProps): import("react").JSX.Element;
|
|
401
|
+
/** A heading over a group of items, in the eyebrow role. Not focusable. */
|
|
402
|
+
export declare function MenuLabel({ children }: {
|
|
403
|
+
/** The heading. */
|
|
404
|
+
children: ReactNode;
|
|
405
|
+
}): import("react").JSX.Element;
|
|
406
|
+
/** A divider between groups of items. */
|
|
407
|
+
export declare function MenuSeparator(): import("react").JSX.Element;
|
|
408
|
+
//#endregion
|
|
338
409
|
//#region src/components/ui/Feedback.d.ts
|
|
339
410
|
/** A callout's kind: a fact (`info`), a caveat (`warning`), a failure (`error`) or `success`. */
|
|
340
411
|
type CalloutTone = "info" | "warning" | "error" | "success";
|
|
@@ -460,8 +531,40 @@ export declare function useControlHeight(): string;
|
|
|
460
531
|
* is described by the field's description and error.
|
|
461
532
|
*/
|
|
462
533
|
export declare function Input({ className, "aria-describedby": describedBy, ...rest }: ComponentProps<"input">): import("react").JSX.Element;
|
|
463
|
-
/**
|
|
464
|
-
|
|
534
|
+
/**
|
|
535
|
+
* Props of `NumberInput`: every `<input>` prop, `ref` included, with numeric bounds, a `unit`,
|
|
536
|
+
* and an optional number-valued API (`onValueChange`, `precision`).
|
|
537
|
+
*/
|
|
538
|
+
type NumberInputProps = Omit<ComponentProps<"input">, "min" | "max" | "value"> & {
|
|
539
|
+
/**
|
|
540
|
+
* The value. As text, it is the native input's `value`. With `onValueChange` it is a
|
|
541
|
+
* number, and `null` shows an empty field.
|
|
542
|
+
*/
|
|
543
|
+
value?: string | number | readonly string[] | null | undefined;
|
|
544
|
+
/**
|
|
545
|
+
* Makes the field number-valued.
|
|
546
|
+
*
|
|
547
|
+
* - **While focused** it keeps the text as typed. A keystroke is reported only when the
|
|
548
|
+
* text is a finite number inside `[min, max]` and differs from `value`. Empty, partial
|
|
549
|
+
* (`-`, `1e`) and out-of-range text is never reported, so clearing a field to retype it
|
|
550
|
+
* does not pass through 0, and typing `5` on the way to `50` does not report a value under
|
|
551
|
+
* `min`.
|
|
552
|
+
* - **Enter** shows the value at `precision`. **Escape** restores the value the field had
|
|
553
|
+
* on focus.
|
|
554
|
+
* - **On leaving**, the field shows `value` again.
|
|
555
|
+
*/
|
|
556
|
+
onValueChange?: ((value: number) => void) | undefined;
|
|
557
|
+
/**
|
|
558
|
+
* Called when a number-valued field is committed empty (left, or Enter pressed, with no
|
|
559
|
+
* text), for a quantity that may be unset. Without it, emptying the field and leaving it
|
|
560
|
+
* restores `value`.
|
|
561
|
+
*/
|
|
562
|
+
onClear?: (() => void) | undefined;
|
|
563
|
+
/**
|
|
564
|
+
* Decimals shown when a number-valued field is not being edited. Without it the number is
|
|
565
|
+
* shown as JavaScript prints it.
|
|
566
|
+
*/
|
|
567
|
+
precision?: number | undefined;
|
|
465
568
|
/** The smallest accepted value. */
|
|
466
569
|
min?: number | undefined;
|
|
467
570
|
/** The largest accepted value. */
|
|
@@ -485,14 +588,97 @@ type NumberInputProps = Omit<ComponentProps<"input">, "min" | "max"> & {
|
|
|
485
588
|
* With a `unit`, the input sits in a `relative` full-width wrapper carrying `data-unit`, keeps
|
|
486
589
|
* room on its right for the unit, and is described by it; size such a field through its
|
|
487
590
|
* container. Without one — or with `""` — the markup is exactly the plain input.
|
|
591
|
+
*
|
|
592
|
+
* With `onValueChange` the field is number-valued: `value` is a number (`null` shows empty), the
|
|
593
|
+
* typed text survives while the field has focus, and only finite numbers inside `[min, max]`
|
|
594
|
+
* are reported (see `onValueChange`; `onClear` reports an emptied field). Without it the field
|
|
595
|
+
* is the native text-valued input.
|
|
488
596
|
*/
|
|
489
|
-
export declare function NumberInput({
|
|
597
|
+
export declare function NumberInput({ onValueChange, onClear, precision, ...props }: NumberInputProps): import("react").JSX.Element;
|
|
490
598
|
/**
|
|
491
599
|
* Multi-line text — set in mono, for JSON and lists. Takes every `<textarea>` prop, `ref`
|
|
492
600
|
* included.
|
|
493
601
|
*/
|
|
494
602
|
export declare function Textarea({ className, "aria-describedby": describedBy, ...rest }: ComponentProps<"textarea">): import("react").JSX.Element;
|
|
495
603
|
//#endregion
|
|
604
|
+
//#region src/components/ui/Kbd.d.ts
|
|
605
|
+
/**
|
|
606
|
+
* A keyboard key or chord (`F`, `⌘K`, `[`), set in mono on a raised key cap.
|
|
607
|
+
*
|
|
608
|
+
* Renders `<kbd>`, which screen readers announce as text. Write the key as the user's keyboard
|
|
609
|
+
* labels it; for a chord, one `Kbd` with the whole chord reads better than several. Takes
|
|
610
|
+
* every `<kbd>` prop, `ref` included.
|
|
611
|
+
*/
|
|
612
|
+
export declare function Kbd({ className, ...rest }: ComponentProps<"kbd">): import("react").JSX.Element;
|
|
613
|
+
//#endregion
|
|
614
|
+
//#region src/components/ui/Listbox.d.ts
|
|
615
|
+
/** One option of a `Listbox`. */
|
|
616
|
+
interface ListboxOption {
|
|
617
|
+
/** Its value, unique in the list. */
|
|
618
|
+
value: string;
|
|
619
|
+
/** Its name: the default rendering, and what a screen reader announces. */
|
|
620
|
+
label: string;
|
|
621
|
+
/** A second line under the label, in the default rendering. */
|
|
622
|
+
description?: string | undefined;
|
|
623
|
+
/** Shown but not choosable. */
|
|
624
|
+
disabled?: boolean | undefined;
|
|
625
|
+
}
|
|
626
|
+
/** What `renderOption` is told about an option. */
|
|
627
|
+
interface ListboxOptionState {
|
|
628
|
+
/** It is the value. */
|
|
629
|
+
selected: boolean;
|
|
630
|
+
/** It has the keyboard cursor or the pointer. */
|
|
631
|
+
active: boolean;
|
|
632
|
+
}
|
|
633
|
+
/** Props of `Listbox`. */
|
|
634
|
+
interface ListboxProps {
|
|
635
|
+
/** The options, in order. */
|
|
636
|
+
options: readonly ListboxOption[];
|
|
637
|
+
/** The selected value, or `null` for none. */
|
|
638
|
+
value: string | null;
|
|
639
|
+
/** Called with the value of the option chosen by click, Enter or Space. */
|
|
640
|
+
onValueChange?: ((value: string) => void) | undefined;
|
|
641
|
+
/**
|
|
642
|
+
* Renders an option's content (the row keeps its own padding, states and accessibility).
|
|
643
|
+
* Defaults to the label, with the description under it.
|
|
644
|
+
*/
|
|
645
|
+
renderOption?: ((option: ListboxOption, state: ListboxOptionState) => ReactNode) | undefined;
|
|
646
|
+
/** Names the list. */
|
|
647
|
+
"aria-label": string;
|
|
648
|
+
/** Focus the list when it mounts, e.g. when it opens in a `Popover`. */
|
|
649
|
+
autoFocus?: boolean | undefined;
|
|
650
|
+
/** Merged with the list's own classes through `cn`. */
|
|
651
|
+
className?: string | undefined;
|
|
652
|
+
}
|
|
653
|
+
/**
|
|
654
|
+
* A single-select list (`role="listbox"`) of options that each render their own content.
|
|
655
|
+
*
|
|
656
|
+
* The list is one tab stop. The arrow keys, Home, End and Page keys move the active option
|
|
657
|
+
* (`aria-activedescendant`), skipping disabled ones, and Enter or Space choose it. A click
|
|
658
|
+
* chooses the option under the pointer. Controlled: the caller keeps `value`. Each option
|
|
659
|
+
* carries `aria-selected`, `data-selected` and `data-active`; the list scrolls the active
|
|
660
|
+
* option into view.
|
|
661
|
+
*/
|
|
662
|
+
export declare function Listbox({ options, value, onValueChange, renderOption, "aria-label": ariaLabel, autoFocus, className }: ListboxProps): import("react").JSX.Element;
|
|
663
|
+
//#endregion
|
|
664
|
+
//#region src/components/ui/numberText.d.ts
|
|
665
|
+
/**
|
|
666
|
+
* A number at a fixed number of decimals, without a negative zero (`-0.000` reads as a sign
|
|
667
|
+
* error in a coordinate readout).
|
|
668
|
+
*
|
|
669
|
+
* @param value - The number. Non-finite values print as `NaN`, `Infinity`, `-Infinity`.
|
|
670
|
+
* @param precision - Decimals, 0–20.
|
|
671
|
+
* @returns The text.
|
|
672
|
+
*/
|
|
673
|
+
export declare function formatNumber(value: number, precision: number): string;
|
|
674
|
+
/**
|
|
675
|
+
* The number a field's text means, if it means one.
|
|
676
|
+
*
|
|
677
|
+
* @param text - What is in the field.
|
|
678
|
+
* @returns The number, or `null` for empty, partial (`-`, `1e`) or non-numeric text.
|
|
679
|
+
*/
|
|
680
|
+
export declare function parseNumber(text: string): number | null;
|
|
681
|
+
//#endregion
|
|
496
682
|
//#region src/components/ui/Panel.d.ts
|
|
497
683
|
/**
|
|
498
684
|
* A bordered surface with an optional header (a title and actions) above a padded body.
|
|
@@ -587,6 +773,49 @@ export declare function ReadoutStrip({ items, className }: {
|
|
|
587
773
|
className?: string | undefined;
|
|
588
774
|
}): import("react").JSX.Element | null;
|
|
589
775
|
//#endregion
|
|
776
|
+
//#region src/components/ui/Popover.d.ts
|
|
777
|
+
/** Props of `Popover`. */
|
|
778
|
+
interface PopoverProps {
|
|
779
|
+
/**
|
|
780
|
+
* The element that opens it: one focusable element that accepts a ref (Radix `asChild`).
|
|
781
|
+
* It carries `aria-expanded` and `data-state` (`open` / `closed`).
|
|
782
|
+
*/
|
|
783
|
+
trigger: ReactNode;
|
|
784
|
+
/** The content. */
|
|
785
|
+
children: ReactNode;
|
|
786
|
+
/** Controlled open state. */
|
|
787
|
+
open?: boolean | undefined;
|
|
788
|
+
/** Initial open state when uncontrolled. */
|
|
789
|
+
defaultOpen?: boolean | undefined;
|
|
790
|
+
/** Called when it opens or closes. */
|
|
791
|
+
onOpenChange?: ((open: boolean) => void) | undefined;
|
|
792
|
+
/** The trigger's side it opens on. Defaults to `bottom`. */
|
|
793
|
+
side?: "top" | "right" | "bottom" | "left" | undefined;
|
|
794
|
+
/** Its alignment along that side. Defaults to `start`. */
|
|
795
|
+
align?: "start" | "center" | "end" | undefined;
|
|
796
|
+
/** Names the content (`aria-label`), when nothing inside it does. */
|
|
797
|
+
"aria-label"?: string | undefined;
|
|
798
|
+
/** Merged with the content's own classes through `cn`. */
|
|
799
|
+
className?: string | undefined;
|
|
800
|
+
}
|
|
801
|
+
/**
|
|
802
|
+
* Floating content anchored to `trigger`, on the `overlay` surface with a shadow (floating
|
|
803
|
+
* layers are the only ones that cast one).
|
|
804
|
+
*
|
|
805
|
+
* Controlled (`open` / `onOpenChange`) or not (`defaultOpen`). Focus moves into the content
|
|
806
|
+
* when it opens and back to the trigger when it closes. Escape and a press outside close it.
|
|
807
|
+
* The content carries `data-state` and `data-side`.
|
|
808
|
+
*/
|
|
809
|
+
export declare function Popover({ trigger, children, open, defaultOpen, onOpenChange, side, align, "aria-label": ariaLabel, className }: PopoverProps): import("react").JSX.Element;
|
|
810
|
+
/**
|
|
811
|
+
* Closes the surrounding `Popover` when its child is activated. Wraps one element (Radix
|
|
812
|
+
* `asChild`).
|
|
813
|
+
*/
|
|
814
|
+
export declare function PopoverClose({ children }: {
|
|
815
|
+
/** The one element that closes the popover. */
|
|
816
|
+
children: ReactNode;
|
|
817
|
+
}): import("react").JSX.Element;
|
|
818
|
+
//#endregion
|
|
590
819
|
//#region src/components/ui/PoseInput.d.ts
|
|
591
820
|
/** Three numbers: a translation `[tx, ty, tz]`, or Euler angles. */
|
|
592
821
|
type Vec3 = readonly [number, number, number];
|
|
@@ -1043,8 +1272,8 @@ interface VectorInputProps {
|
|
|
1043
1272
|
* A row of number fields editing one small vector, with the axis labels before the fields
|
|
1044
1273
|
* and the unit once after them.
|
|
1045
1274
|
*
|
|
1046
|
-
* Controlled. A `role="group"` named by `aria-label
|
|
1047
|
-
* described by the unit. While a field has focus it shows what is typed; on blur or Enter it
|
|
1275
|
+
* Controlled. A `role="group"` named by `aria-label`. Each field is named by the group and its
|
|
1276
|
+
* label ("Translation x"), so two vectors on one screen stay apart, and is described by the unit. While a field has focus it shows what is typed; on blur or Enter it
|
|
1048
1277
|
* shows the value at `precision`; Escape restores the value it had on focus. With `readOnly`
|
|
1049
1278
|
* it renders a `ReadoutStrip` (`x 0.100 m · y …`) instead. The row carries `data-readonly`
|
|
1050
1279
|
* and `data-disabled`.
|
|
@@ -1090,5 +1319,5 @@ export declare function Tabs<Id extends string>({ items, active, onSelect, label
|
|
|
1090
1319
|
className?: string | undefined;
|
|
1091
1320
|
}): import("react").JSX.Element;
|
|
1092
1321
|
//#endregion
|
|
1093
|
-
export type { BackLink, ButtonSize, ButtonVariant, CalloutTone, Column, Density, MeasureTone, NumberInputProps, PoseInputProps, PoseValue, Quaternion, ReadoutItem, RotationView, SelectOption, TabItem, ThemeChoice, ToastOptions, ToastRecord, ToastStore, ToastTone, ToasterProps, Tone, Vec3, VectorInputProps };
|
|
1322
|
+
export type { BackLink, ButtonSize, ButtonVariant, CalloutTone, Column, Density, DropdownMenuProps, ListboxOption, ListboxOptionState, ListboxProps, MeasureTone, MenuCheckboxItemProps, MenuItemProps, NumberInputProps, PopoverProps, PoseInputProps, PoseValue, Quaternion, ReadoutItem, RotationView, SelectOption, TabItem, ThemeChoice, ToastOptions, ToastRecord, ToastStore, ToastTone, ToasterProps, Tone, Vec3, VectorInputProps };
|
|
1094
1323
|
//# sourceMappingURL=index.d.ts.map
|