@inkorange/space-ui 1.0.4 → 1.1.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 CHANGED
@@ -3,8 +3,8 @@
3
3
  <!-- badges:start -->
4
4
 
5
5
  [![npm](https://img.shields.io/npm/v/@inkorange/space-ui)](https://www.npmjs.com/package/@inkorange/space-ui)
6
- ![coverage](https://img.shields.io/badge/coverage-83%25-green)
7
- ![minzip](https://img.shields.io/badge/minzip-22.1%20kB-blue)
6
+ ![coverage](https://img.shields.io/badge/coverage-82%25-green)
7
+ ![minzip](https://img.shields.io/badge/minzip-21.7%20kB-blue)
8
8
  ![dependencies](https://img.shields.io/badge/dependencies-0-blue)
9
9
  [![docs](https://img.shields.io/badge/docs-live%20gallery-0b7dd6)](https://space-components.vercel.app)
10
10
 
@@ -75,14 +75,11 @@ screen at once — the kind of interface where someone is adjusting values and
75
75
  watching something respond.
76
76
 
77
77
  ```tsx
78
- <Select.Root value={star} onValueChange={setStar}>
79
- <Select.Trigger />
80
- <Select.Content>
81
- {types.map((t) => (
82
- <Select.Item key={t} value={t}>{t}-type star</Select.Item>
83
- ))}
84
- </Select.Content>
85
- </Select.Root>
78
+ <Select value={star} onValueChange={setStar}>
79
+ {types.map((t) => (
80
+ <Select.Item key={t} value={t}>{t}-type star</Select.Item>
81
+ ))}
82
+ </Select>
86
83
  ```
87
84
 
88
85
  The small things are handled so you never have to notice them. That Select
@@ -1,8 +1,17 @@
1
- import { Trigger as DialogTrigger, Close as DialogClose, Content as DialogContent, Title as DialogTitle, Description as DialogDescription } from "./Dialog";
2
- export declare const Root: ({ open, onOpenChange, children }: import("./Dialog").RootProps) => import("react").JSX.Element;
3
- export declare const Trigger: typeof DialogTrigger;
4
- export declare const Content: typeof DialogContent;
5
- export declare const Title: typeof DialogTitle;
6
- export declare const Description: typeof DialogDescription;
7
- export declare const Cancel: typeof DialogClose;
8
- export declare const Action: typeof DialogClose;
1
+ import { Trigger, Close, Content, Title, Description, type DialogProps } from "./Dialog";
2
+ export type { DialogProps as AlertDialogProps };
3
+ /**
4
+ * A modal that interrupts to confirm something consequential.
5
+ *
6
+ * Unlike a Dialog it has no backdrop dismissal, because dismissing an alert
7
+ * by missing it is not a decision. Put `Cancel` before `Action` so the safe
8
+ * choice takes focus when it opens.
9
+ */
10
+ export declare const AlertDialog: (({ open, onOpenChange, children }: DialogProps) => import("react").JSX.Element) & {
11
+ Trigger: typeof Trigger;
12
+ Content: typeof Content;
13
+ Title: typeof Title;
14
+ Description: typeof Description;
15
+ Cancel: typeof Close;
16
+ Action: typeof Close;
17
+ };
@@ -14,26 +14,19 @@ export interface DialogCtx {
14
14
  setHasDesc: (v: boolean) => void;
15
15
  }
16
16
  export declare const useDialog: () => DialogCtx;
17
- export interface RootProps {
17
+ export interface DialogProps {
18
18
  /** Controls the dialog. Omit both this and onOpenChange to let the dialog
19
19
  * manage its own state. */
20
20
  open?: boolean;
21
21
  /** Called whenever the dialog opens or closes, including via Escape or a
22
22
  * backdrop click. */
23
23
  onOpenChange?: (o: boolean) => void;
24
- /** A Trigger and a Content. */
24
+ /** A `Trigger` and a `Content`, in any arrangement — this renders
25
+ * nothing itself, so they can sit anywhere beneath it. */
25
26
  children?: ReactNode;
26
27
  }
27
- /** Shared by Dialog.Root and AlertDialog.Root (alert flag differs). */
28
- export declare function makeRoot(alert: boolean): ({ open, onOpenChange, children }: RootProps) => React.JSX.Element;
29
- /**
30
- * Owns a dialog's open state. Works controlled via `open`/`onOpenChange`, or
31
- * uncontrolled if you pass neither.
32
- *
33
- * Renders nothing itself — it only provides context, so Trigger and Content
34
- * can sit anywhere beneath it in the tree.
35
- */
36
- export declare const Root: ({ open, onOpenChange, children }: RootProps) => React.JSX.Element;
28
+ /** Shared by Dialog and AlertDialog; only the alert flag differs. */
29
+ export declare function makeRoot(alert: boolean): ({ open, onOpenChange, children }: DialogProps) => React.JSX.Element;
37
30
  /**
38
31
  * Opens the dialog. Chains onto its child's existing click handler rather
39
32
  * than replacing it, and renders no element of its own — so the child stays
@@ -79,3 +72,10 @@ export declare function Title({ className, ...rest }: HeadingProps): React.JSX.E
79
72
  * description. Optional, and only announced when present.
80
73
  */
81
74
  export declare function Description(props: TextProps): React.JSX.Element;
75
+ export declare const Dialog: (({ open, onOpenChange, children }: DialogProps) => React.JSX.Element) & {
76
+ Trigger: typeof Trigger;
77
+ Close: typeof Close;
78
+ Content: typeof Content;
79
+ Title: typeof Title;
80
+ Description: typeof Description;
81
+ };
@@ -1,42 +1,38 @@
1
1
  import type * as React from "react";
2
2
  import { type ReactNode } from "react";
3
- /**
4
- * Owns a menu's open state and closes it on an outside click or Escape.
5
- * Renders nothing of its own.
6
- */
7
- export declare function Root({ children, }: {
8
- /** A Trigger and a Content. */
9
- children?: ReactNode;
10
- }): React.JSX.Element;
11
- /**
12
- * The control that opens the menu, and the element the menu is positioned
13
- * against. Wraps its child rather than rendering a button of its own.
14
- */
15
- export declare function Trigger({ children, }: {
16
- /** The control that opens the menu, and what the menu anchors to. */
17
- children?: ReactNode;
18
- }): React.ReactElement<Record<string, unknown>, string | React.JSXElementConstructor<any>> | null;
19
- /**
20
- * The menu surface, anchored to the trigger and aligned to its start or end
21
- * edge. Owns the keyboard model: arrows move between items, Escape closes and
22
- * returns focus to the trigger.
23
- */
24
- export declare function Content({ align, children, }: {
3
+ import { type ButtonProps } from "./Button";
4
+ export interface DropdownMenuProps extends Omit<ButtonProps, "children"> {
5
+ /** The trigger's content. The trigger is always a Button, so this is what
6
+ * goes inside it — text, or an icon with `iconOnly`. */
7
+ label: ReactNode;
25
8
  /** Which edge of the trigger the menu lines up with. Use `end` when the
26
9
  * trigger sits near the right edge and the menu would overflow. */
27
10
  align?: "start" | "end";
28
- /** Items, Labels and Separators. */
11
+ /** `DropdownMenu.Item`, `.Separator` and `.Label`, in any order. */
29
12
  children?: ReactNode;
30
- }): React.JSX.Element;
13
+ }
14
+ /**
15
+ * A menu of actions hung off a button.
16
+ *
17
+ * The trigger is built in and is always a Button — a dropdown whose trigger
18
+ * looked like anything else was never a shape worth supporting, and making it
19
+ * arbitrary cost a `cloneElement` that had to graft aria wiring and a click
20
+ * handler onto someone else's element.
21
+ *
22
+ * The menu rides the platform's top layer via `popover`, so click-outside
23
+ * dismissal and stacking come from the browser rather than an approximation.
24
+ * Arrows move between items, Escape closes and returns focus to the trigger.
25
+ */
26
+ declare function DropdownMenuRoot({ label, align, children, ...buttonProps }: DropdownMenuProps): React.JSX.Element;
31
27
  /**
32
28
  * A non-interactive heading for a group of items. Skipped by arrow-key
33
29
  * navigation, since there is nothing to activate.
34
30
  */
35
- export declare function Label({ children, }: {
31
+ declare function Label({ children, }: {
36
32
  /** Heading text for the group beneath it. Not focusable. */
37
33
  children?: ReactNode;
38
34
  }): React.JSX.Element;
39
- export interface ItemProps {
35
+ export interface DropdownMenuItemProps {
40
36
  /** Render the child element instead of the default item — for a link that
41
37
  * should stay an anchor rather than becoming a button. */
42
38
  asChild?: boolean;
@@ -54,9 +50,15 @@ export interface ItemProps {
54
50
  * Pass `color="danger"` for a destructive action so it reads differently from
55
51
  * its neighbours before it is chosen, not after.
56
52
  */
57
- export declare function Item({ asChild, color, onSelect, children }: ItemProps): React.JSX.Element;
53
+ declare function Item({ asChild, color, onSelect, children }: DropdownMenuItemProps): React.JSX.Element;
58
54
  /**
59
55
  * A rule between groups of items — for separating a destructive action from
60
56
  * routine ones, so the two are not adjacent to a moving cursor.
61
57
  */
62
- export declare function Separator(): React.JSX.Element;
58
+ declare function Separator(): React.JSX.Element;
59
+ export declare const DropdownMenu: typeof DropdownMenuRoot & {
60
+ Item: typeof Item;
61
+ Separator: typeof Separator;
62
+ Label: typeof Label;
63
+ };
64
+ export {};
@@ -1,6 +1,6 @@
1
1
  import type * as React from "react";
2
2
  import { type ReactNode } from "react";
3
- export interface RootProps {
3
+ export interface RadioGroupProps {
4
4
  /** The selected item's value. Fully controlled. */
5
5
  value: string;
6
6
  /** Called with the newly selected value. */
@@ -9,15 +9,15 @@ export interface RootProps {
9
9
  disabled?: boolean;
10
10
  /** Merged onto the group wrapper. */
11
11
  className?: string;
12
- /** The Items. */
12
+ /** One or more `RadioGroup.Item`. */
13
13
  children?: ReactNode;
14
14
  }
15
15
  /**
16
16
  * A single-choice control for short lists, where seeing every option at once
17
17
  * matters more than saving space. Reach for Select when it does not.
18
18
  */
19
- export declare function Root({ value, onValueChange, disabled, className, children }: RootProps): React.JSX.Element;
20
- export interface ItemProps {
19
+ declare function RadioGroupRoot({ value, onValueChange, disabled, className, children }: RadioGroupProps): React.JSX.Element;
20
+ export interface RadioGroupItemProps {
21
21
  /** Reported to the group's onValueChange when chosen. */
22
22
  value: string;
23
23
  /** Disables this option only. */
@@ -25,8 +25,16 @@ export interface ItemProps {
25
25
  /** The option's label. Part of the click target, not merely beside it. */
26
26
  children?: ReactNode;
27
27
  }
28
- /** With children: self-labeling (<label> wraps input+orb+children) — the
29
- * SaveShareDialog pattern. Without children: emits a bare span so an
30
- * OUTER label (ConfigurationPanel's <Text as="label">) owns association —
31
- * nesting labels would be invalid HTML. */
32
- export declare function Item({ value, disabled, children }: ItemProps): React.JSX.Element;
28
+ /**
29
+ * One option.
30
+ *
31
+ * With children it labels itself: a <label> wraps the input, the orb and the
32
+ * children, so the text is part of the click target. Without children it
33
+ * emits a bare span instead, so an OUTER label can own the association —
34
+ * nesting one label inside another is invalid HTML.
35
+ */
36
+ declare function Item({ value, disabled, children }: RadioGroupItemProps): React.JSX.Element;
37
+ export declare const RadioGroup: typeof RadioGroupRoot & {
38
+ Item: typeof Item;
39
+ };
40
+ export {};
@@ -1,70 +1,53 @@
1
1
  import type * as React from "react";
2
2
  import { type ReactNode } from "react";
3
- export interface RootProps {
3
+ export interface SelectProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "value" | "children" | "onChange"> {
4
4
  /** The selected item's value. Fully controlled. */
5
5
  value: string;
6
6
  /** Called with the newly selected value. */
7
7
  onValueChange: (v: string) => void;
8
8
  /** Blocks the trigger and removes it from the tab order. */
9
9
  disabled?: boolean;
10
- /** A Trigger and a Content. */
11
- children?: ReactNode;
12
- }
13
- /**
14
- * A single-choice menu for lists too long to show inline. Fully controlled.
15
- *
16
- * Reads its options at render time rather than through effects, so the
17
- * trigger shows the right label on first paint and under SSR.
18
- */
19
- export declare function Root({ value, onValueChange, disabled, children }: RootProps): React.JSX.Element;
20
- export interface TriggerProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "value"> {
21
- /** Shown when nothing is selected. Counts toward the trigger's width,
22
- * so selecting an option never resizes it.
23
- */
10
+ /** Shown when nothing is selected. Counts toward the control's width, so
11
+ * selecting an option never resizes it. */
24
12
  placeholder?: string;
25
- /** Ambient motion: the lit arc orbiting the rim. The glass skin itself
26
- * is always applied. Default true. */
13
+ /** Ambient motion: the lit arc orbiting the rim. The glass skin itself is
14
+ * always applied. Default true. */
27
15
  animated?: boolean;
16
+ /** One or more `Select.Item`. Anything else is ignored for selection but
17
+ * still rendered in the panel. */
18
+ children?: ReactNode;
28
19
  }
29
20
  /**
30
- * The closed state of the Select, showing the selected item's own content.
21
+ * A single-choice menu for lists too long to show inline. Fully controlled.
31
22
  *
32
- * Sizes itself to its widest option, so it never changes width as you select
33
- * — capped by `--sp-select-trigger-max-width`, past which the label
23
+ * The control sizes itself to its widest option, so it never changes width as
24
+ * you select — capped by `--sp-select-trigger-max-width`, past which the label
34
25
  * ellipsizes.
35
- */
36
- export declare function Trigger({ placeholder, animated, className, ...rest }: TriggerProps): React.JSX.Element;
37
- export interface ContentProps {
38
- /** Merged with the panel's own classes. */
39
- className?: string;
40
- /** Accepted for Radix call-site compatibility ("popper" everywhere);
41
- * our listbox is always trigger-anchored. */
42
- position?: string;
43
- /** Ambient motion on the panel rim. Default true. */
44
- animated?: boolean;
45
- /** The Items. */
46
- children?: ReactNode;
47
- }
48
- /**
49
- * The option panel. Always mounted but hidden while closed, so the trigger
50
- * can read its labels for sizing.
51
26
  *
52
- * Never narrower than the trigger, and grows to fit the longest option so
53
- * labels only wrap when they truly must.
27
+ * Reads its options at render time rather than through effects, so the right
28
+ * label shows on first paint and under SSR.
29
+ *
30
+ * Every prop other than the ones listed lands on the trigger button, which is
31
+ * the focusable control — so `aria-label`, `id`, `name` and `onBlur` go where
32
+ * you would expect.
54
33
  */
55
- export declare function Content({ className, position: _position, animated, children }: ContentProps): React.JSX.Element;
56
- export interface ItemProps {
34
+ declare function SelectRoot({ value, onValueChange, disabled, placeholder, animated, className, children, ...rest }: SelectProps): React.JSX.Element;
35
+ export interface SelectItemProps {
57
36
  /** Reported to onValueChange when chosen. */
58
37
  value: string;
59
- /** Skipped by keyboard navigation and not selectable. Still contributes
60
- * its width to the trigger's sizing. */
38
+ /** Skipped by keyboard navigation and not selectable. Still contributes its
39
+ * width to the control's sizing. */
61
40
  disabled?: boolean;
62
- /** Shown in the panel and, once selected, in the trigger — so it has to
63
- * read correctly in both places. */
41
+ /** Shown in the panel and, once selected, in the closed control — so it has
42
+ * to read correctly in both places. */
64
43
  children?: ReactNode;
65
44
  }
66
45
  /**
67
- * One option. Its children are what the trigger displays once selected, so
68
- * anything rendered here has to read correctly in both places.
46
+ * One option. Its children are what the closed control displays once
47
+ * selected, so anything rendered here has to read correctly in both places.
69
48
  */
70
- export declare function Item({ value, disabled, children }: ItemProps): React.JSX.Element;
49
+ declare function Item({ value, disabled, children }: SelectItemProps): React.JSX.Element;
50
+ export declare const Select: typeof SelectRoot & {
51
+ Item: typeof Item;
52
+ };
53
+ export {};
@@ -1,23 +1,24 @@
1
1
  import type * as React from "react";
2
2
  import { type ReactNode } from "react";
3
- /**
4
- * Wraps a tab set and owns which tab is showing. Fully controlled — pass
5
- * `value` and `onValueChange`; there is no uncontrolled mode.
6
- *
7
- * Renders a plain div, so it imposes no layout of its own. It also mints the
8
- * id that pairs each Trigger with its Content, which is why every part has to
9
- * sit inside a Root rather than being usable on its own.
10
- */
11
- export declare function Root({ value, onValueChange, className, children }: {
3
+ export interface TabsProps {
12
4
  /** The selected tab's value. Fully controlled — there is no default. */
13
5
  value: string;
14
6
  /** Called with the newly selected tab's value. */
15
7
  onValueChange: (v: string) => void;
16
8
  /** Merged onto the wrapper div, which is otherwise unstyled. */
17
9
  className?: string;
18
- /** A List and the Contents it switches between. */
10
+ /** A `Tabs.List` and the `Tabs.Content`s it switches between. */
19
11
  children?: ReactNode;
20
- }): React.JSX.Element;
12
+ }
13
+ /**
14
+ * Wraps a tab set and owns which tab is showing. Fully controlled — pass
15
+ * `value` and `onValueChange`; there is no uncontrolled mode.
16
+ *
17
+ * Renders a plain div, so it imposes no layout of its own. It also mints the
18
+ * id that pairs each Trigger with its Content, which is why every part has to
19
+ * sit inside it rather than being usable on its own.
20
+ */
21
+ declare function TabsRoot({ value, onValueChange, className, children }: TabsProps): React.JSX.Element;
21
22
  /**
22
23
  * The row of triggers, and the keyboard model for the set: arrow keys move
23
24
  * between tabs, Home and End jump to the ends, each moving focus and
@@ -26,7 +27,7 @@ export declare function Root({ value, onValueChange, className, children }: {
26
27
  * Bottom-aligns its children, so an active tab that grows taller rises above
27
28
  * its neighbours instead of pushing the row down — the folder-tab effect.
28
29
  */
29
- export declare function List({ children, }: {
30
+ declare function List({ children, }: {
30
31
  /** The Triggers. Their order is the tab order. */
31
32
  children?: ReactNode;
32
33
  }): React.JSX.Element;
@@ -37,7 +38,7 @@ export declare function List({ children, }: {
37
38
  * Emits `data-state="active" | "inactive"`, which is the hook the active
38
39
  * styling keys off — useful if you are restyling tabs from outside.
39
40
  */
40
- export declare function Trigger({ value, className, children, ...rest }: {
41
+ declare function Trigger({ value, className, children, ...rest }: {
41
42
  /** Selects this value. Must match the Content it reveals. */
42
43
  value: string;
43
44
  /** Merged with the tab's own classes rather than replacing them. */
@@ -53,9 +54,15 @@ export declare function Trigger({ value, className, children, ...rest }: {
53
54
  * Carries no styling: the surface a tab set seats onto is the consumer's, and
54
55
  * should match `--sp-tabs-surface-color` so the active tab connects to it.
55
56
  */
56
- export declare function Content({ value, children, }: {
57
+ declare function Content({ value, children, }: {
57
58
  /** Shown while this matches the Root's value. Must match a Trigger. */
58
59
  value: string;
59
60
  /** Panel contents. Unmounted while another tab is selected. */
60
61
  children?: ReactNode;
61
62
  }): React.JSX.Element | null;
63
+ export declare const Tabs: typeof TabsRoot & {
64
+ List: typeof List;
65
+ Trigger: typeof Trigger;
66
+ Content: typeof Content;
67
+ };
68
+ export {};
@@ -1,6 +1,6 @@
1
1
  import type * as React from "react";
2
2
  import { type ReactNode } from "react";
3
- export interface RootProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "className" | "style"> {
3
+ export interface TextFieldProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "className" | "style"> {
4
4
  /** Merged onto the field wrapper, not the inner input. */
5
5
  className?: string;
6
6
  /** Ambient motion on the rim. The glass skin is always applied.
@@ -11,20 +11,16 @@ export interface RootProps extends Omit<React.InputHTMLAttributes<HTMLInputEleme
11
11
  /** Slots rendered inside the field, alongside the input. */
12
12
  children?: ReactNode;
13
13
  }
14
- /**
15
- * Single-line text entry. Composed as a Root so slots can sit alongside the
16
- * input inside the same field surface.
17
- *
18
- * Props land on the inner input, so `value`, `onChange` and the rest behave
19
- * as they would on a bare input.
20
- */
21
- export declare const Root: React.ForwardRefExoticComponent<RootProps & React.RefAttributes<HTMLInputElement>>;
22
14
  /**
23
15
  * A fixed element inside the field, before or after the input — an icon, a
24
16
  * unit, a short affordance. Sits within the field's surface rather than
25
17
  * beside it, and does not shrink as the input fills.
26
18
  */
27
- export declare function Slot({ children, }: {
19
+ declare function Slot({ children, }: {
28
20
  /** The slot's contents — an icon, a unit, a short affordance. */
29
21
  children?: ReactNode;
30
22
  }): React.JSX.Element;
23
+ export declare const TextField: React.ForwardRefExoticComponent<TextFieldProps & React.RefAttributes<HTMLInputElement>> & {
24
+ Slot: typeof Slot;
25
+ };
26
+ export {};