@vitavision/ui 0.7.0 → 0.9.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 +18 -2
- package/dist/index.d.ts +220 -9
- package/dist/index.js +463 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/ui/Input.tsx +67 -10
- package/src/components/ui/PoseInput.tsx +181 -0
- package/src/components/ui/Toaster.tsx +148 -0
- package/src/components/ui/VectorInput.tsx +183 -0
- package/src/components/ui/index.ts +20 -0
- package/src/components/ui/numberText.ts +36 -0
- package/src/components/ui/toastStore.ts +128 -0
- package/src/styles.css +19 -2
package/README.md
CHANGED
|
@@ -124,11 +124,27 @@ keep independent preferences.
|
|
|
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
126
|
`DialogClose` · `Disclosure` · `Callout`, `Empty`, `ErrorBox`, `ProgressBar`, `Skeleton`,
|
|
127
|
-
`SkeletonRows` · `Field` · `Input`, `NumberInput
|
|
127
|
+
`SkeletonRows` · `Field` · `Input`, `NumberInput` (with an optional `unit` written in the
|
|
128
|
+
field), `Textarea` · `VectorInput`, `PoseInput` · `PageHeader`, `Panel`,
|
|
128
129
|
`ReadoutStrip`, `Section` · `SegmentedControl` · `Select` · `Slider` · `Table` ·
|
|
129
|
-
`Checkbox`, `Switch` · `ToggleChip` · `
|
|
130
|
+
`Checkbox`, `Switch` · `ToggleChip` · `Toaster`, `toast()` (notifications from anywhere; mount one `<Toaster />` near the root) ·
|
|
131
|
+
`InfoHint`, `Tooltip`, `TooltipProvider` ·
|
|
130
132
|
`ThemeToggle` · plus `cn`, `focusRing`, `focusRingInset`.
|
|
131
133
|
|
|
134
|
+
`PoseInput` edits an SE(3) pose in the wire form `{ rotation: [qx, qy, qz, qw], translation:
|
|
135
|
+
[tx, ty, tz] }` as a translation and roll/pitch/yaw in degrees, but does no rotation
|
|
136
|
+
mathematics: the quaternion ↔ angles conversion — and so what "roll, pitch, yaw" means — is
|
|
137
|
+
passed in as a `RotationView` by the package that owns the frame conventions:
|
|
138
|
+
|
|
139
|
+
```tsx
|
|
140
|
+
<PoseInput
|
|
141
|
+
value={camera.world_se3_self}
|
|
142
|
+
onValueChange={setPose}
|
|
143
|
+
rotationView={{ toEuler: quatToRpy, fromEuler: rpyToQuat }}
|
|
144
|
+
translationUnit="mm"
|
|
145
|
+
/>
|
|
146
|
+
```
|
|
147
|
+
|
|
132
148
|
### Density
|
|
133
149
|
|
|
134
150
|
Every primitive with two spacings reads `useDensity()`. The default, `comfortable`, is what
|
package/dist/index.d.ts
CHANGED
|
@@ -460,18 +460,33 @@ export declare function useControlHeight(): string;
|
|
|
460
460
|
* is described by the field's description and error.
|
|
461
461
|
*/
|
|
462
462
|
export declare function Input({ className, "aria-describedby": describedBy, ...rest }: ComponentProps<"input">): import("react").JSX.Element;
|
|
463
|
-
/**
|
|
464
|
-
|
|
465
|
-
*
|
|
466
|
-
* `font-mono` because these are read as quantities and compared down a column. Takes every
|
|
467
|
-
* `<input>` prop, `ref` included (`type` is always `number`).
|
|
468
|
-
*/
|
|
469
|
-
export declare function NumberInput({ className, "aria-describedby": describedBy, ...rest }: Omit<ComponentProps<"input">, "min" | "max"> & {
|
|
463
|
+
/** Props of `NumberInput`: every `<input>` prop, `ref` included, with numeric bounds and a `unit`. */
|
|
464
|
+
type NumberInputProps = Omit<ComponentProps<"input">, "min" | "max"> & {
|
|
470
465
|
/** The smallest accepted value. */
|
|
471
466
|
min?: number | undefined;
|
|
472
467
|
/** The largest accepted value. */
|
|
473
468
|
max?: number | undefined;
|
|
474
|
-
|
|
469
|
+
/**
|
|
470
|
+
* The quantity's unit (`mm`, `m`, `°`, `px`), written inside the field after the number, in
|
|
471
|
+
* mono and muted. It is not part of the value. It is announced as the field's description
|
|
472
|
+
* (`aria-describedby`): after the caller's own `aria-describedby`, before a surrounding
|
|
473
|
+
* `Field`'s description and error.
|
|
474
|
+
*/
|
|
475
|
+
unit?: string | undefined;
|
|
476
|
+
};
|
|
477
|
+
/**
|
|
478
|
+
* A number, with the schema's own bounds attached and, optionally, its unit written in the
|
|
479
|
+
* field.
|
|
480
|
+
*
|
|
481
|
+
* `font-mono` because these are read as quantities and compared down a column. Takes every
|
|
482
|
+
* `<input>` prop, `ref` included (`type` is always `number`); `className`, `style` and `ref`
|
|
483
|
+
* always go to the `<input>`.
|
|
484
|
+
*
|
|
485
|
+
* With a `unit`, the input sits in a `relative` full-width wrapper carrying `data-unit`, keeps
|
|
486
|
+
* room on its right for the unit, and is described by it; size such a field through its
|
|
487
|
+
* container. Without one — or with `""` — the markup is exactly the plain input.
|
|
488
|
+
*/
|
|
489
|
+
export declare function NumberInput({ unit, ...props }: NumberInputProps): import("react").JSX.Element;
|
|
475
490
|
/**
|
|
476
491
|
* Multi-line text — set in mono, for JSON and lists. Takes every `<textarea>` prop, `ref`
|
|
477
492
|
* included.
|
|
@@ -572,6 +587,71 @@ export declare function ReadoutStrip({ items, className }: {
|
|
|
572
587
|
className?: string | undefined;
|
|
573
588
|
}): import("react").JSX.Element | null;
|
|
574
589
|
//#endregion
|
|
590
|
+
//#region src/components/ui/PoseInput.d.ts
|
|
591
|
+
/** Three numbers: a translation `[tx, ty, tz]`, or Euler angles. */
|
|
592
|
+
type Vec3 = readonly [number, number, number];
|
|
593
|
+
/** A unit quaternion in the wire order `[qx, qy, qz, qw]` (scalar last). */
|
|
594
|
+
type Quaternion = readonly [number, number, number, number];
|
|
595
|
+
/**
|
|
596
|
+
* An SE(3) pose in the wire form (`a_se3_b` as nalgebra's `Isometry3` serialises it):
|
|
597
|
+
* translation in metres, rotation as a unit quaternion `[qx, qy, qz, qw]`.
|
|
598
|
+
*/
|
|
599
|
+
interface PoseValue {
|
|
600
|
+
/** The rotation, `[qx, qy, qz, qw]`. */
|
|
601
|
+
rotation: Quaternion;
|
|
602
|
+
/** The translation `[tx, ty, tz]`, in metres. */
|
|
603
|
+
translation: Vec3;
|
|
604
|
+
}
|
|
605
|
+
/**
|
|
606
|
+
* How a rotation is shown as three angles: the conversion both ways, and the angles' names.
|
|
607
|
+
* Supplied by the package that owns the frame conventions; `PoseInput` only calls it.
|
|
608
|
+
*/
|
|
609
|
+
interface RotationView {
|
|
610
|
+
/** The quaternion as three angles, in radians, in the order of `labels`. */
|
|
611
|
+
toEuler: (rotation: Quaternion) => Vec3;
|
|
612
|
+
/** Three angles in radians, in the order of `labels`, as a unit quaternion `[qx, qy, qz, qw]`. */
|
|
613
|
+
fromEuler: (angles: Vec3) => Quaternion;
|
|
614
|
+
/** The angles' names, shown before each field. Defaults to roll, pitch, yaw. */
|
|
615
|
+
labels?: readonly [string, string, string] | undefined;
|
|
616
|
+
}
|
|
617
|
+
/** Props of `PoseInput`. */
|
|
618
|
+
interface PoseInputProps {
|
|
619
|
+
/** The pose, in the wire form. */
|
|
620
|
+
value: PoseValue;
|
|
621
|
+
/** Called with a new pose (new arrays) whenever a component changes. */
|
|
622
|
+
onValueChange?: ((value: PoseValue) => void) | undefined;
|
|
623
|
+
/** The quaternion ↔ angles conversion and the angles' names. Required: see `RotationView`. */
|
|
624
|
+
rotationView: RotationView;
|
|
625
|
+
/** Show and edit the translation in metres (the default) or millimetres. The value is always metres. */
|
|
626
|
+
translationUnit?: "m" | "mm" | undefined;
|
|
627
|
+
/** Decimals of the translation. Defaults to 4 for m, 1 for mm. */
|
|
628
|
+
translationPrecision?: number | undefined;
|
|
629
|
+
/** Decimals of the angles, in degrees. Defaults to 2. */
|
|
630
|
+
rotationPrecision?: number | undefined;
|
|
631
|
+
/** Show a compact mono readout instead of fields. */
|
|
632
|
+
readOnly?: boolean | undefined;
|
|
633
|
+
/** Blocks every field. */
|
|
634
|
+
disabled?: boolean | undefined;
|
|
635
|
+
/** Names the pose (`role="group"`). Defaults to "Pose". */
|
|
636
|
+
"aria-label"?: string | undefined;
|
|
637
|
+
/** Merged with the component's own classes through `cn`. */
|
|
638
|
+
className?: string | undefined;
|
|
639
|
+
}
|
|
640
|
+
/**
|
|
641
|
+
* An SE(3) pose shown and edited as a translation (m or mm) and three angles in degrees,
|
|
642
|
+
* reading and writing the wire form `{ rotation: [qx, qy, qz, qw], translation: [tx, ty, tz] }`.
|
|
643
|
+
*
|
|
644
|
+
* The angles come from `rotationView.toEuler` and go back through `rotationView.fromEuler`.
|
|
645
|
+
* The angles as typed are kept while the pose they produced is the one shown, so a yaw of
|
|
646
|
+
* 190° is not redisplayed as −170° and a gimbal-locked pitch does not scramble the other two
|
|
647
|
+
* angles mid-edit.
|
|
648
|
+
*
|
|
649
|
+
* A `role="group"` named by `aria-label`, holding two `VectorInput` groups ("Translation",
|
|
650
|
+
* "Rotation"). With `readOnly` it renders a `ReadoutStrip` instead
|
|
651
|
+
* (`t 0.1000 0.2000 0.3000 m · rpy 0.00 90.00 0.00 °`). The root carries `data-readonly`.
|
|
652
|
+
*/
|
|
653
|
+
export declare function PoseInput({ value, onValueChange, rotationView, translationUnit, translationPrecision, rotationPrecision, readOnly, disabled, "aria-label": ariaLabel, className }: PoseInputProps): import("react").JSX.Element;
|
|
654
|
+
//#endregion
|
|
575
655
|
//#region src/components/ui/SegmentedControl.d.ts
|
|
576
656
|
/**
|
|
577
657
|
* A choice among two or three, shown as a strip of segments (native radios in one group, so
|
|
@@ -800,6 +880,97 @@ export declare function ToggleChip({ checked, onCheckedChange, children, swatch,
|
|
|
800
880
|
className?: string | undefined;
|
|
801
881
|
}): import("react").JSX.Element;
|
|
802
882
|
//#endregion
|
|
883
|
+
//#region src/components/ui/toastStore.d.ts
|
|
884
|
+
/** A toast's kind: a fact (`info`), a completed action (`success`), a caveat (`warn`), a failure (`error`). */
|
|
885
|
+
type ToastTone = "info" | "success" | "warn" | "error";
|
|
886
|
+
/** What `toast()` takes. */
|
|
887
|
+
interface ToastOptions {
|
|
888
|
+
/** One line: what happened. */
|
|
889
|
+
title: string;
|
|
890
|
+
/** More detail, and what to do about it. */
|
|
891
|
+
description?: string | undefined;
|
|
892
|
+
/** Defaults to `info`. */
|
|
893
|
+
tone?: ToastTone | undefined;
|
|
894
|
+
/**
|
|
895
|
+
* How long it stays, in milliseconds, while not hovered or focused. Defaults to 5000
|
|
896
|
+
* (8000 for `error`); `Infinity` keeps it until dismissed.
|
|
897
|
+
*/
|
|
898
|
+
duration?: number | undefined;
|
|
899
|
+
/** Replace the toast with this id instead of adding one — for progress that updates in place. */
|
|
900
|
+
id?: string | undefined;
|
|
901
|
+
}
|
|
902
|
+
/** A toast in the store. */
|
|
903
|
+
interface ToastRecord {
|
|
904
|
+
/** Identifies the toast to `dismiss` and to `id` replacement. */
|
|
905
|
+
id: string;
|
|
906
|
+
/** One line: what happened. */
|
|
907
|
+
title: string;
|
|
908
|
+
/** More detail, if any. */
|
|
909
|
+
description: string | undefined;
|
|
910
|
+
/** Its kind. */
|
|
911
|
+
tone: ToastTone;
|
|
912
|
+
/** Milliseconds before it dismisses itself (`Infinity`: never). */
|
|
913
|
+
duration: number;
|
|
914
|
+
}
|
|
915
|
+
/**
|
|
916
|
+
* A toast store: what `toast()` writes to and `<Toaster />` reads. Every member may be called
|
|
917
|
+
* detached.
|
|
918
|
+
*/
|
|
919
|
+
interface ToastStore {
|
|
920
|
+
/** Add a toast (or replace the one with `options.id`), returning its id. */
|
|
921
|
+
readonly toast: (options: ToastOptions) => string;
|
|
922
|
+
/** Remove one toast, or every toast when `id` is omitted. */
|
|
923
|
+
readonly dismiss: (id?: string) => void;
|
|
924
|
+
/** The toasts, oldest first. The same array until the store changes. */
|
|
925
|
+
readonly getSnapshot: () => readonly ToastRecord[];
|
|
926
|
+
/** Be told when the toasts change; returns the unsubscribe function. */
|
|
927
|
+
readonly subscribe: (listener: () => void) => () => void;
|
|
928
|
+
}
|
|
929
|
+
/**
|
|
930
|
+
* A new, empty toast store. The package keeps one (behind `toast()` and the default
|
|
931
|
+
* `<Toaster />`); create another only to isolate a region or a test.
|
|
932
|
+
*
|
|
933
|
+
* @returns The store.
|
|
934
|
+
*/
|
|
935
|
+
export declare function createToastStore(): ToastStore;
|
|
936
|
+
/** The store behind `toast()` and a `<Toaster />` given no `store`. */
|
|
937
|
+
export declare const defaultToastStore: ToastStore;
|
|
938
|
+
/**
|
|
939
|
+
* Raise a notification, from anywhere — shown by the mounted `<Toaster />`.
|
|
940
|
+
*
|
|
941
|
+
* `toast({ title: "Scenario loaded", tone: "success" })`. Pass `id` to update a toast in
|
|
942
|
+
* place (a progress message that becomes a result). `toast.dismiss(id)` removes one early,
|
|
943
|
+
* `toast.dismiss()` all of them.
|
|
944
|
+
*
|
|
945
|
+
* @param options - The message, its tone and its duration.
|
|
946
|
+
* @returns The toast's id.
|
|
947
|
+
*/
|
|
948
|
+
export declare const toast: ((options: ToastOptions) => string) & {
|
|
949
|
+
/** Remove one toast, or every toast when `id` is omitted. */
|
|
950
|
+
dismiss: (id?: string) => void;
|
|
951
|
+
};
|
|
952
|
+
//#endregion
|
|
953
|
+
//#region src/components/ui/Toaster.d.ts
|
|
954
|
+
/** Props of `Toaster`. */
|
|
955
|
+
interface ToasterProps {
|
|
956
|
+
/** The store to show. Defaults to the one behind `toast()`. */
|
|
957
|
+
store?: ToastStore | undefined;
|
|
958
|
+
/** How many toasts are shown at once; older ones wait. Defaults to 5. */
|
|
959
|
+
limit?: number | undefined;
|
|
960
|
+
/** Merged with the stack's own classes through `cn` (it is fixed to the bottom-right corner). */
|
|
961
|
+
className?: string | undefined;
|
|
962
|
+
}
|
|
963
|
+
/**
|
|
964
|
+
* The stack of notifications raised with `toast()`. Mount it once, near the root.
|
|
965
|
+
*
|
|
966
|
+
* Fixed to the bottom-right corner, newest at the bottom. Each toast dismisses itself after
|
|
967
|
+
* its `duration`; the countdown pauses while the pointer is over the stack or focus is inside
|
|
968
|
+
* it. A `section` landmark ("Notifications") holding a polite live region, so new toasts are
|
|
969
|
+
* announced; an `error` toast is a `role="alert"`, announced at once. Each toast carries
|
|
970
|
+
* `data-tone` and a "Dismiss" button.
|
|
971
|
+
*/
|
|
972
|
+
export declare function Toaster({ store, limit, className }: ToasterProps): import("react").JSX.Element;
|
|
973
|
+
//#endregion
|
|
803
974
|
//#region src/components/ui/Tooltip.d.ts
|
|
804
975
|
/**
|
|
805
976
|
* Shares one open delay (200 ms) across the tooltips below it. Mount it once near the root:
|
|
@@ -840,6 +1011,46 @@ export declare function InfoHint({ children, label, icon: Icon }: {
|
|
|
840
1011
|
icon?: LucideIcon | undefined;
|
|
841
1012
|
}): import("react").JSX.Element;
|
|
842
1013
|
//#endregion
|
|
1014
|
+
//#region src/components/ui/VectorInput.d.ts
|
|
1015
|
+
/** Props of `VectorInput`. */
|
|
1016
|
+
interface VectorInputProps {
|
|
1017
|
+
/** The components. Its length is the number of fields. */
|
|
1018
|
+
value: readonly number[];
|
|
1019
|
+
/** Called with the whole vector (a new array) whenever one component changes to a valid number. */
|
|
1020
|
+
onValueChange?: ((value: number[]) => void) | undefined;
|
|
1021
|
+
/** Each component's label, shown before its field and naming it. Defaults to x, y, z, w. */
|
|
1022
|
+
labels?: readonly string[] | undefined;
|
|
1023
|
+
/** The unit of every component, shown once after the row (`m`, `mm`, `°`). */
|
|
1024
|
+
unit?: string | undefined;
|
|
1025
|
+
/** The arrow-key step. Defaults to `any` (the browser then steps by 1). */
|
|
1026
|
+
step?: number | undefined;
|
|
1027
|
+
/** Decimals shown when a field is not being edited. Defaults to 3. */
|
|
1028
|
+
precision?: number | undefined;
|
|
1029
|
+
/** The smallest accepted component. */
|
|
1030
|
+
min?: number | undefined;
|
|
1031
|
+
/** The largest accepted component. */
|
|
1032
|
+
max?: number | undefined;
|
|
1033
|
+
/** Show the values as a compact mono readout instead of fields. */
|
|
1034
|
+
readOnly?: boolean | undefined;
|
|
1035
|
+
/** Blocks every field. */
|
|
1036
|
+
disabled?: boolean | undefined;
|
|
1037
|
+
/** Names the group (`role="group"`). */
|
|
1038
|
+
"aria-label": string;
|
|
1039
|
+
/** Merged with the row's own classes through `cn`. */
|
|
1040
|
+
className?: string | undefined;
|
|
1041
|
+
}
|
|
1042
|
+
/**
|
|
1043
|
+
* A row of number fields editing one small vector, with the axis labels before the fields
|
|
1044
|
+
* and the unit once after them.
|
|
1045
|
+
*
|
|
1046
|
+
* Controlled. A `role="group"` named by `aria-label`, each field named by its label and
|
|
1047
|
+
* described by the unit. While a field has focus it shows what is typed; on blur or Enter it
|
|
1048
|
+
* shows the value at `precision`; Escape restores the value it had on focus. With `readOnly`
|
|
1049
|
+
* it renders a `ReadoutStrip` (`x 0.100 m · y …`) instead. The row carries `data-readonly`
|
|
1050
|
+
* and `data-disabled`.
|
|
1051
|
+
*/
|
|
1052
|
+
export declare function VectorInput({ value, onValueChange, labels, unit, step, precision, min, max, readOnly, disabled, "aria-label": ariaLabel, className }: VectorInputProps): import("react").JSX.Element;
|
|
1053
|
+
//#endregion
|
|
843
1054
|
//#region src/components/Tabs.d.ts
|
|
844
1055
|
/** One tab of a `Tabs` strip. */
|
|
845
1056
|
interface TabItem<Id extends string> {
|
|
@@ -879,5 +1090,5 @@ export declare function Tabs<Id extends string>({ items, active, onSelect, label
|
|
|
879
1090
|
className?: string | undefined;
|
|
880
1091
|
}): import("react").JSX.Element;
|
|
881
1092
|
//#endregion
|
|
882
|
-
export type { BackLink, ButtonSize, ButtonVariant, CalloutTone, Column, Density, MeasureTone, ReadoutItem, SelectOption, TabItem, ThemeChoice, Tone };
|
|
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 };
|
|
883
1094
|
//# sourceMappingURL=index.d.ts.map
|