@rebasepro/ui 0.23.0 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,6 +4,11 @@ export type BooleanSwitchProps = {
4
4
  className?: string;
5
5
  disabled?: boolean;
6
6
  size?: "smallest" | "small" | "medium" | "large";
7
+ /** Names the switch when no visible label is tied to it. */
8
+ "aria-label"?: string;
9
+ /** The id of the element whose text names the switch. */
10
+ "aria-labelledby"?: string;
11
+ id?: string;
7
12
  } & ({
8
13
  allowIndeterminate: true;
9
14
  onValueChange?: (newValue: boolean | null) => void;
@@ -14,4 +14,4 @@ export type BooleanSwitchWithLabelProps = BooleanSwitchProps & {
14
14
  * Simple boolean switch.
15
15
  *
16
16
  */
17
- export declare const BooleanSwitchWithLabel: ({ value, position, size, invisible, onValueChange, error, label, autoFocus, disabled, className, fullWidth, inputClassName, ...props }: BooleanSwitchWithLabelProps) => React.JSX.Element;
17
+ export declare const BooleanSwitchWithLabel: ({ value, position, size, invisible, onValueChange, error, label, autoFocus, disabled, className, fullWidth, inputClassName, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, ...props }: BooleanSwitchWithLabelProps) => React.JSX.Element;
@@ -1,6 +1,6 @@
1
1
  import React from "react";
2
2
  import { type ButtonSize } from "../styles.js";
3
- export type ButtonProps<C extends React.ElementType = "button"> = {
3
+ type ButtonOwnProps<C extends React.ElementType> = {
4
4
  children?: React.ReactNode;
5
5
  variant?: "filled" | "outlined" | "text";
6
6
  disabled?: boolean;
@@ -11,5 +11,13 @@ export type ButtonProps<C extends React.ElementType = "button"> = {
11
11
  className?: string;
12
12
  component?: C;
13
13
  onClick?: React.MouseEventHandler<HTMLElement>;
14
- } & React.ComponentPropsWithoutRef<C>;
15
- export declare const Button: React.FC<ButtonProps<React.ElementType>>;
14
+ };
15
+ /**
16
+ * The kit's own props, plus those of the element it renders (`button`, or
17
+ * `component`). It used to intersect with `ComponentPropsWithoutRef` of a bare
18
+ * `ElementType`, which is as good as `any`: any misspelt or invented prop on
19
+ * the most-used control in the product compiled, and landed on the DOM.
20
+ */
21
+ export type ButtonProps<C extends React.ElementType = "button"> = ButtonOwnProps<C> & Omit<React.ComponentPropsWithoutRef<C>, keyof ButtonOwnProps<C>>;
22
+ export declare const Button: <C extends React.ElementType = "button">(props: ButtonProps<C> & React.RefAttributes<HTMLButtonElement>) => React.ReactElement | null;
23
+ export {};
@@ -12,11 +12,32 @@ export type DialogProps = {
12
12
  maxWidth?: keyof typeof widthClasses;
13
13
  modal?: boolean;
14
14
  onOpenAutoFocus?: (e: Event) => void;
15
+ /**
16
+ * Called when focus is about to return after the dialog closes. By default
17
+ * it goes back to the element that had it when the dialog opened; call
18
+ * `preventDefault()` to put it somewhere else.
19
+ */
20
+ onCloseAutoFocus?: (e: Event) => void;
15
21
  onEscapeKeyDown?: (e: KeyboardEvent) => void;
16
22
  onPointerDownOutside?: (e: Event) => void;
17
23
  onInteractOutside?: (e: Event) => void;
18
24
  /**
19
- * If `true`, the dialog will not focus the first focusable element when opened.
25
+ * Whether a click on the dimmed backdrop closes the dialog. Off by default:
26
+ * a record or a form dialog holds work that one stray click must not throw
27
+ * away. Turn it on for a picker, where closing loses nothing. Escape closes
28
+ * either kind.
29
+ */
30
+ dismissOnBackdrop?: boolean;
31
+ /**
32
+ * The element to focus when the dialog opens, for a dialog whose purpose is
33
+ * one field. Without it the dialog focuses itself, so a screen reader
34
+ * announces it by its title and a phone does not raise its keyboard.
35
+ */
36
+ initialFocus?: React.RefObject<HTMLElement | null>;
37
+ /**
38
+ * If `true` (the default), the dialog will not focus the first focusable
39
+ * element when opened: it focuses its own container instead. `false` lets
40
+ * the first focusable element take focus.
20
41
  */
21
42
  disableInitialFocus?: boolean;
22
43
  portalContainer?: HTMLElement | null;
@@ -36,5 +57,5 @@ declare const widthClasses: {
36
57
  "7xl": string;
37
58
  full: string;
38
59
  };
39
- export declare const Dialog: ({ open, onOpenChange, children, className, containerClassName, fullWidth, fullHeight, fullScreen, scrollable, maxWidth, modal, onOpenAutoFocus, onEscapeKeyDown, onPointerDownOutside, onInteractOutside, disableInitialFocus, portalContainer, "aria-describedby": ariaDescribedby }: DialogProps) => React.JSX.Element;
60
+ export declare const Dialog: ({ open, onOpenChange, children, className, containerClassName, fullWidth, fullHeight, fullScreen, scrollable, maxWidth, modal, onOpenAutoFocus, onCloseAutoFocus, onEscapeKeyDown, onPointerDownOutside, onInteractOutside, dismissOnBackdrop, initialFocus, disableInitialFocus, portalContainer, "aria-describedby": ariaDescribedby }: DialogProps) => React.JSX.Element;
40
61
  export {};
@@ -1,12 +1,23 @@
1
1
  import React from "react";
2
- export type IconButtonProps<C extends React.ElementType> = Omit<(C extends "button" ? React.ButtonHTMLAttributes<HTMLButtonElement> : React.ComponentProps<C>), "onClick"> & {
2
+ type IconButtonOwnProps<C extends React.ElementType> = {
3
3
  size?: "medium" | "small" | "smallest" | "large";
4
4
  variant?: "ghost" | "filled";
5
5
  shape?: "circular" | "square";
6
6
  disabled?: boolean;
7
7
  toggled?: boolean;
8
8
  component?: C;
9
- onClick?: React.MouseEventHandler<any>;
9
+ onClick?: React.MouseEventHandler<HTMLElement>;
10
+ className?: string;
11
+ children?: React.ReactNode;
10
12
  "aria-label"?: string;
11
13
  };
12
- export declare const IconButton: React.ComponentType<IconButtonProps<any>>;
14
+ /**
15
+ * The kit's own props, plus those of the element it renders (`button`, or
16
+ * `component`). Typed against that element rather than `any`: a misspelt or
17
+ * invented prop is a compile error, not an attribute on the DOM. `color` is
18
+ * left out — it is an obsolete HTML attribute that does nothing, and callers
19
+ * wrote `color="primary"` expecting the accent icon `Button`'s `color` gives.
20
+ */
21
+ export type IconButtonProps<C extends React.ElementType = "button"> = IconButtonOwnProps<C> & Omit<React.ComponentPropsWithoutRef<C>, keyof IconButtonOwnProps<C> | "color">;
22
+ export declare const IconButton: <C extends React.ElementType = "button">(props: IconButtonProps<C> & React.RefAttributes<HTMLButtonElement>) => React.ReactElement | null;
23
+ export {};
@@ -1,7 +1,7 @@
1
1
  import React from "react";
2
2
  import { ButtonProps } from "./Button.js";
3
- export type LoadingButtonProps<P extends React.ElementType> = ButtonProps<P> & {
3
+ export type LoadingButtonProps<P extends React.ElementType = "button"> = ButtonProps<P> & {
4
4
  startIcon?: React.ReactNode;
5
5
  loading?: boolean;
6
6
  };
7
- export declare function LoadingButton<P extends React.ElementType = "button">({ children, loading, disabled, onClick, startIcon, ...props }: LoadingButtonProps<P>): React.JSX.Element;
7
+ export declare function LoadingButton<P extends React.ElementType = "button">({ children, loading, startIcon, ...props }: LoadingButtonProps<P>): React.JSX.Element;
@@ -45,6 +45,13 @@ interface MultiSelectProps<T extends MultiSelectValue = string> {
45
45
  * the cell that clips it, and the list belongs under what can be seen.
46
46
  */
47
47
  anchorRef?: React.RefObject<HTMLElement | null>;
48
+ /**
49
+ * Replaces everything the trigger draws — the values, the box, its
50
+ * padding, its height and the chevron — with this node. For a caller that
51
+ * frames the select itself: a table cell passes the preview it shows at
52
+ * rest, so selecting the cell moves nothing.
53
+ */
54
+ triggerContent?: React.ReactNode;
48
55
  children: React.ReactNode;
49
56
  renderValues?: (values: T[]) => React.ReactNode;
50
57
  portalContainer?: HTMLElement | null;
@@ -28,6 +28,13 @@ export type SelectProps<T extends SelectValue = string> = {
28
28
  * the cell draws one opener for every kind of editor, in the same place.
29
29
  */
30
30
  chevron?: boolean;
31
+ /**
32
+ * Replaces everything the trigger draws — the value, the box, its padding,
33
+ * its height and the chevron — with this node. For a caller that frames
34
+ * the select itself: a table cell passes the preview it shows at rest, so
35
+ * selecting the cell moves nothing.
36
+ */
37
+ triggerContent?: React.ReactNode;
31
38
  children?: React.ReactNode;
32
39
  dataType?: "string" | "number" | "boolean";
33
40
  portalContainer?: HTMLElement | null;
@@ -11,6 +11,19 @@ interface SheetProps {
11
11
  onOpenChange?: (open: boolean) => void;
12
12
  onPointerDownOutside?: (e: Event) => void;
13
13
  onInteractOutside?: (e: Event) => void;
14
+ /**
15
+ * The element to focus when the sheet opens. Without it the sheet focuses
16
+ * itself, so a screen reader announces it by its title and a phone does
17
+ * not raise its keyboard.
18
+ */
19
+ initialFocus?: React.RefObject<HTMLElement | null>;
20
+ /** Called as the sheet opens, before focus moves into it. `preventDefault()` keeps focus where it is. */
21
+ onOpenAutoFocus?: (e: Event) => void;
22
+ /**
23
+ * Called when focus is about to return after the sheet closes. By default
24
+ * it goes back to the element that had it when the sheet opened.
25
+ */
26
+ onCloseAutoFocus?: (e: Event) => void;
14
27
  className?: string;
15
28
  style?: React.CSSProperties;
16
29
  overlayClassName?: string;
@@ -0,0 +1,51 @@
1
+ import React from "react";
2
+ export type ModalFocusOptions = {
3
+ /** Whether the modal is open. Focus is recorded on the closed → open edge. */
4
+ open: boolean;
5
+ /**
6
+ * The element to focus when the modal opens. Without it the modal focuses
7
+ * itself (see {@link useModalFocus}).
8
+ */
9
+ initialFocus?: React.RefObject<HTMLElement | null>;
10
+ /**
11
+ * `false` hands the choice back to Radix: the first focusable element
12
+ * inside the modal takes focus. `true` (the default) focuses the modal's
13
+ * own container.
14
+ */
15
+ focusContainer?: boolean;
16
+ onOpenAutoFocus?: (event: Event) => void;
17
+ onCloseAutoFocus?: (event: Event) => void;
18
+ };
19
+ /**
20
+ * Where focus goes when a kit modal (`Dialog`, `Sheet`) opens and closes.
21
+ *
22
+ * Both used to cancel Radix's open-focus and do nothing else, so focus stayed
23
+ * on the trigger behind the modal — which Radix had just hidden from assistive
24
+ * technology with `aria-hidden`. A screen reader announced nothing, and Enter
25
+ * pressed again fired the trigger a second time underneath the open modal.
26
+ *
27
+ * On open, focus moves into the modal: to `initialFocus` when the caller names
28
+ * an element, otherwise to the modal's own container (it carries
29
+ * `tabIndex=-1`). The container rather than the first field, because the first
30
+ * field on a phone raises the keyboard over a form the user has not started,
31
+ * and because the container is what a screen reader announces by its title.
32
+ * The first Tab then lands on the first control.
33
+ *
34
+ * On close, focus goes back to whatever had it when the modal opened. Radix
35
+ * only returns it to a `Dialog.Trigger`, and the kit's modals are controlled —
36
+ * there is no trigger — so focus used to fall to `<body>` and the next Tab
37
+ * started from the top of the page.
38
+ *
39
+ * The origin is read while rendering the open edge, not from the open-focus
40
+ * event: a field with `autoFocus` inside the modal has taken focus by the time
41
+ * any effect runs, and Radix then skips the event altogether. When the origin
42
+ * is an item in a menu, the menu's trigger is recorded instead: the item is
43
+ * gone a moment later, and the menu does not take focus back to its trigger
44
+ * once the modal has it.
45
+ *
46
+ * Internal to the kit's modals — not exported.
47
+ */
48
+ export declare function useModalFocus({ open, initialFocus, focusContainer, onOpenAutoFocus, onCloseAutoFocus }: ModalFocusOptions): {
49
+ onOpenAutoFocus: (event: Event) => void;
50
+ onCloseAutoFocus: (event: Event) => void;
51
+ };
package/dist/index.d.ts CHANGED
@@ -15,4 +15,5 @@ export { useInjectStyles } from "./hooks/useInjectStyles.js";
15
15
  export { PortalContainerProvider, usePortalContainer } from "./hooks/PortalContainerContext.js";
16
16
  export type { PortalContainerContextType, PortalContainerProviderProps } from "./hooks/PortalContainerContext.js";
17
17
  export { debounce } from "./util/debounce.js";
18
+ export { isKeyHandled } from "./util/keys.js";
18
19
  export type { Cancelable } from "./util/debounce.js";