@qeetrix/react 0.0.0-stage → 0.0.2
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/CHANGELOG.md +181 -0
- package/README.md +167 -2
- package/dist/accordion/accordion.d.ts +42 -0
- package/dist/accordion/accordion.js +72 -0
- package/dist/accordion/index.d.ts +2 -0
- package/dist/accordion/index.js +1 -0
- package/dist/avatar/avatar.d.ts +21 -0
- package/dist/avatar/avatar.js +43 -0
- package/dist/avatar/index.d.ts +2 -0
- package/dist/avatar/index.js +1 -0
- package/dist/badge/badge.d.ts +14 -0
- package/dist/badge/badge.js +25 -0
- package/dist/badge/index.d.ts +2 -0
- package/dist/badge/index.js +1 -0
- package/dist/box/box.d.ts +27 -0
- package/dist/box/box.js +21 -0
- package/dist/box/index.d.ts +2 -0
- package/dist/box/index.js +1 -0
- package/dist/button/button.d.ts +46 -0
- package/dist/button/button.js +74 -0
- package/dist/button/index.d.ts +2 -0
- package/dist/button/index.js +1 -0
- package/dist/card/card.d.ts +30 -0
- package/dist/card/card.js +56 -0
- package/dist/card/index.d.ts +2 -0
- package/dist/card/index.js +1 -0
- package/dist/checkbox/checkbox.d.ts +33 -0
- package/dist/checkbox/checkbox.js +61 -0
- package/dist/checkbox/index.d.ts +2 -0
- package/dist/checkbox/index.js +1 -0
- package/dist/css/accordion.css +73 -0
- package/dist/css/avatar.css +44 -0
- package/dist/css/badge.css +53 -0
- package/dist/css/base.css +5 -0
- package/dist/css/box.css +163 -0
- package/dist/css/button.css +168 -0
- package/dist/css/card.css +75 -0
- package/dist/css/checkbox.css +58 -0
- package/dist/css/dialog.css +121 -0
- package/dist/css/drawer.css +123 -0
- package/dist/css/field.css +121 -0
- package/dist/css/fieldset.css +37 -0
- package/dist/css/grid.css +86 -0
- package/dist/css/heading.css +93 -0
- package/dist/css/inline.css +85 -0
- package/dist/css/input.css +98 -0
- package/dist/css/link.css +45 -0
- package/dist/css/menu.css +149 -0
- package/dist/css/popover.css +72 -0
- package/dist/css/progress.css +88 -0
- package/dist/css/radio.css +54 -0
- package/dist/css/scroll-area.css +63 -0
- package/dist/css/select.css +173 -0
- package/dist/css/separator.css +28 -0
- package/dist/css/skeleton.css +33 -0
- package/dist/css/skip-link.css +33 -0
- package/dist/css/slider.css +86 -0
- package/dist/css/spinner.css +55 -0
- package/dist/css/stack.css +76 -0
- package/dist/css/switch.css +79 -0
- package/dist/css/table.css +68 -0
- package/dist/css/tabs.css +112 -0
- package/dist/css/text-field.css +4 -0
- package/dist/css/text.css +106 -0
- package/dist/css/toast.css +108 -0
- package/dist/css/toggle.css +112 -0
- package/dist/css/tooltip.css +41 -0
- package/dist/css/visually-hidden.css +15 -0
- package/dist/dialog/dialog.d.ts +51 -0
- package/dist/dialog/dialog.js +120 -0
- package/dist/dialog/index.d.ts +2 -0
- package/dist/dialog/index.js +1 -0
- package/dist/drawer/drawer.d.ts +46 -0
- package/dist/drawer/drawer.js +101 -0
- package/dist/drawer/index.d.ts +2 -0
- package/dist/drawer/index.js +1 -0
- package/dist/field/choice.d.ts +21 -0
- package/dist/field/choice.js +67 -0
- package/dist/field/field.d.ts +28 -0
- package/dist/field/field.js +77 -0
- package/dist/field/index.d.ts +3 -0
- package/dist/field/index.js +1 -0
- package/dist/fieldset/fieldset.d.ts +19 -0
- package/dist/fieldset/fieldset.js +29 -0
- package/dist/fieldset/index.d.ts +2 -0
- package/dist/fieldset/index.js +1 -0
- package/dist/grid/grid.d.ts +30 -0
- package/dist/grid/grid.js +36 -0
- package/dist/grid/index.d.ts +2 -0
- package/dist/grid/index.js +1 -0
- package/dist/heading/heading.d.ts +23 -0
- package/dist/heading/heading.js +30 -0
- package/dist/heading/index.d.ts +2 -0
- package/dist/heading/index.js +1 -0
- package/dist/index.d.ts +80 -0
- package/dist/index.js +38 -0
- package/dist/inline/index.d.ts +2 -0
- package/dist/inline/index.js +1 -0
- package/dist/inline/inline.d.ts +19 -0
- package/dist/inline/inline.js +16 -0
- package/dist/input/index.d.ts +2 -0
- package/dist/input/index.js +1 -0
- package/dist/input/input.d.ts +37 -0
- package/dist/input/input.js +63 -0
- package/dist/internal/control.d.ts +9 -0
- package/dist/internal/control.js +4 -0
- package/dist/internal/cx.js +7 -0
- package/dist/internal/messages.js +22 -0
- package/dist/internal/refs.js +23 -0
- package/dist/internal/render.d.ts +6 -0
- package/dist/internal/render.js +22 -0
- package/dist/internal/space.d.ts +9 -0
- package/dist/internal/text.d.ts +5 -0
- package/dist/internal/text.js +18 -0
- package/dist/link/index.d.ts +2 -0
- package/dist/link/index.js +1 -0
- package/dist/link/link.d.ts +13 -0
- package/dist/link/link.js +31 -0
- package/dist/menu/index.d.ts +2 -0
- package/dist/menu/index.js +1 -0
- package/dist/menu/menu.d.ts +76 -0
- package/dist/menu/menu.js +172 -0
- package/dist/popover/index.d.ts +2 -0
- package/dist/popover/index.js +1 -0
- package/dist/popover/popover.d.ts +33 -0
- package/dist/popover/popover.js +48 -0
- package/dist/progress/index.d.ts +2 -0
- package/dist/progress/index.js +1 -0
- package/dist/progress/progress.d.ts +26 -0
- package/dist/progress/progress.js +57 -0
- package/dist/radio/index.d.ts +2 -0
- package/dist/radio/index.js +1 -0
- package/dist/radio/radio.d.ts +31 -0
- package/dist/radio/radio.js +47 -0
- package/dist/scroll-area/index.d.ts +2 -0
- package/dist/scroll-area/index.js +1 -0
- package/dist/scroll-area/scroll-area.d.ts +18 -0
- package/dist/scroll-area/scroll-area.js +39 -0
- package/dist/select/index.d.ts +2 -0
- package/dist/select/index.js +1 -0
- package/dist/select/select.d.ts +36 -0
- package/dist/select/select.js +82 -0
- package/dist/separator/index.d.ts +2 -0
- package/dist/separator/index.js +1 -0
- package/dist/separator/separator.d.ts +16 -0
- package/dist/separator/separator.js +16 -0
- package/dist/skeleton/index.d.ts +2 -0
- package/dist/skeleton/index.js +1 -0
- package/dist/skeleton/skeleton.d.ts +12 -0
- package/dist/skeleton/skeleton.js +18 -0
- package/dist/skip-link/index.d.ts +2 -0
- package/dist/skip-link/index.js +1 -0
- package/dist/skip-link/skip-link.d.ts +13 -0
- package/dist/skip-link/skip-link.js +18 -0
- package/dist/slider/index.d.ts +2 -0
- package/dist/slider/index.js +1 -0
- package/dist/slider/slider.d.ts +17 -0
- package/dist/slider/slider.js +51 -0
- package/dist/spinner/index.d.ts +2 -0
- package/dist/spinner/index.js +1 -0
- package/dist/spinner/spinner.d.ts +15 -0
- package/dist/spinner/spinner.js +19 -0
- package/dist/stack/index.d.ts +2 -0
- package/dist/stack/index.js +1 -0
- package/dist/stack/stack.d.ts +17 -0
- package/dist/stack/stack.js +15 -0
- package/dist/styles.css +2960 -0
- package/dist/switch/index.d.ts +2 -0
- package/dist/switch/index.js +1 -0
- package/dist/switch/switch.d.ts +18 -0
- package/dist/switch/switch.js +31 -0
- package/dist/table/index.d.ts +2 -0
- package/dist/table/index.js +1 -0
- package/dist/table/table.d.ts +36 -0
- package/dist/table/table.js +69 -0
- package/dist/tabs/index.d.ts +2 -0
- package/dist/tabs/index.js +1 -0
- package/dist/tabs/tabs.d.ts +43 -0
- package/dist/tabs/tabs.js +66 -0
- package/dist/text/index.d.ts +3 -0
- package/dist/text/index.js +1 -0
- package/dist/text/text.d.ts +24 -0
- package/dist/text/text.js +24 -0
- package/dist/text-field/index.d.ts +2 -0
- package/dist/text-field/index.js +1 -0
- package/dist/text-field/text-field.d.ts +15 -0
- package/dist/text-field/text-field.js +41 -0
- package/dist/toast/index.d.ts +2 -0
- package/dist/toast/index.js +1 -0
- package/dist/toast/toast.d.ts +54 -0
- package/dist/toast/toast.js +123 -0
- package/dist/toggle/index.d.ts +2 -0
- package/dist/toggle/index.js +1 -0
- package/dist/toggle/toggle.d.ts +48 -0
- package/dist/toggle/toggle.js +54 -0
- package/dist/tooltip/index.d.ts +2 -0
- package/dist/tooltip/index.js +1 -0
- package/dist/tooltip/tooltip.d.ts +26 -0
- package/dist/tooltip/tooltip.js +39 -0
- package/dist/visually-hidden/index.d.ts +2 -0
- package/dist/visually-hidden/index.js +1 -0
- package/dist/visually-hidden/visually-hidden.d.ts +8 -0
- package/dist/visually-hidden/visually-hidden.js +12 -0
- package/package.json +219 -4
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cx } from "../internal/cx.js";
|
|
3
|
+
import { messages } from "../internal/messages.js";
|
|
4
|
+
import { IconButton } from "../button/button.js";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import { createContext, use } from "react";
|
|
7
|
+
import { AlertDialog } from "@base-ui/react/alert-dialog";
|
|
8
|
+
import { Dialog } from "@base-ui/react/dialog";
|
|
9
|
+
import { XIcon } from "@qeetrix/icons/icons/x";
|
|
10
|
+
// src/dialog/dialog.tsx
|
|
11
|
+
/** The ways a user dismisses a dialog, as opposed to choosing one of its actions. */
|
|
12
|
+
const DISMISSALS = /* @__PURE__ */ new Set([
|
|
13
|
+
"escape-key",
|
|
14
|
+
"outside-press",
|
|
15
|
+
"focus-out"
|
|
16
|
+
]);
|
|
17
|
+
const DialogContext = createContext({
|
|
18
|
+
intent: "standard",
|
|
19
|
+
dismissible: true
|
|
20
|
+
});
|
|
21
|
+
/** Holds a dialog's open state: `open` / `defaultOpen` / `onOpenChange(open, details)`. */
|
|
22
|
+
function Dialog$1({ intent = "standard", dismissible = intent !== "danger", modal, onOpenChange, children, ...props }) {
|
|
23
|
+
const handleOpenChange = (open, details) => {
|
|
24
|
+
if (!open && !dismissible && DISMISSALS.has(details.reason)) {
|
|
25
|
+
details.cancel();
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
onOpenChange?.(open, details);
|
|
29
|
+
};
|
|
30
|
+
return /* @__PURE__ */ jsx(DialogContext, {
|
|
31
|
+
value: {
|
|
32
|
+
intent,
|
|
33
|
+
dismissible
|
|
34
|
+
},
|
|
35
|
+
children: intent === "standard" ? /* @__PURE__ */ jsx(Dialog.Root, {
|
|
36
|
+
...props,
|
|
37
|
+
modal,
|
|
38
|
+
disablePointerDismissal: !dismissible,
|
|
39
|
+
onOpenChange: handleOpenChange,
|
|
40
|
+
children
|
|
41
|
+
}) : /* @__PURE__ */ jsx(AlertDialog.Root, {
|
|
42
|
+
...props,
|
|
43
|
+
onOpenChange: handleOpenChange,
|
|
44
|
+
children
|
|
45
|
+
})
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
/** Opens the dialog. Render your own control: `render={<Button tone="danger">Revoke</Button>}`. */
|
|
49
|
+
function DialogTrigger(props) {
|
|
50
|
+
const { intent } = use(DialogContext);
|
|
51
|
+
return intent === "standard" ? /* @__PURE__ */ jsx(Dialog.Trigger, { ...props }) : /* @__PURE__ */ jsx(AlertDialog.Trigger, { ...props });
|
|
52
|
+
}
|
|
53
|
+
/** Closes the dialog, e.g. Cancel: `render={<Button variant="ghost">Cancel</Button>}`. */
|
|
54
|
+
function DialogClose(props) {
|
|
55
|
+
return /* @__PURE__ */ jsx(Dialog.Close, { ...props });
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* The dialog (06-component-specs.md §6): over a scrim, with the intent line, the header, then your
|
|
59
|
+
* body and footer. The close button comes last in the DOM, so initial focus lands on the first field
|
|
60
|
+
* or else the footer's first (least destructive) action.
|
|
61
|
+
*/
|
|
62
|
+
function DialogContent({ title, description, size = "md", className, children, ...props }) {
|
|
63
|
+
const { intent, dismissible } = use(DialogContext);
|
|
64
|
+
return /* @__PURE__ */ jsxs(Dialog.Portal, { children: [/* @__PURE__ */ jsx(Dialog.Backdrop, {
|
|
65
|
+
className: "qx-dialog-backdrop",
|
|
66
|
+
"data-slot": "dialog-backdrop"
|
|
67
|
+
}), /* @__PURE__ */ jsx(Dialog.Viewport, {
|
|
68
|
+
className: "qx-dialog-viewport",
|
|
69
|
+
children: /* @__PURE__ */ jsxs(Dialog.Popup, {
|
|
70
|
+
...props,
|
|
71
|
+
className: cx("qx-dialog", className),
|
|
72
|
+
"data-slot": "dialog-popup",
|
|
73
|
+
"data-intent": intent,
|
|
74
|
+
"data-size": size,
|
|
75
|
+
"data-dismissible": dismissible ? "" : void 0,
|
|
76
|
+
children: [
|
|
77
|
+
/* @__PURE__ */ jsxs("div", {
|
|
78
|
+
className: "qx-dialog-header",
|
|
79
|
+
"data-slot": "dialog-header",
|
|
80
|
+
children: [/* @__PURE__ */ jsx(Dialog.Title, {
|
|
81
|
+
className: "qx-dialog-title",
|
|
82
|
+
"data-slot": "dialog-title",
|
|
83
|
+
children: title
|
|
84
|
+
}), description != null && /* @__PURE__ */ jsx(Dialog.Description, {
|
|
85
|
+
className: "qx-dialog-description",
|
|
86
|
+
"data-slot": "dialog-description",
|
|
87
|
+
children: description
|
|
88
|
+
})]
|
|
89
|
+
}),
|
|
90
|
+
children,
|
|
91
|
+
dismissible && /* @__PURE__ */ jsx("div", {
|
|
92
|
+
className: "qx-dialog-close",
|
|
93
|
+
"data-slot": "dialog-close",
|
|
94
|
+
children: /* @__PURE__ */ jsx(Dialog.Close, { render: /* @__PURE__ */ jsx(IconButton, {
|
|
95
|
+
icon: XIcon,
|
|
96
|
+
"aria-label": messages.overlay.close,
|
|
97
|
+
size: "sm"
|
|
98
|
+
}) })
|
|
99
|
+
})
|
|
100
|
+
]
|
|
101
|
+
})
|
|
102
|
+
})] });
|
|
103
|
+
}
|
|
104
|
+
/** The dialog's content; it scrolls when the dialog reaches its maximum height. */
|
|
105
|
+
function DialogBody({ className, ...props }) {
|
|
106
|
+
return /* @__PURE__ */ jsx("div", {
|
|
107
|
+
...props,
|
|
108
|
+
className: cx("qx-dialog-body", className),
|
|
109
|
+
"data-slot": "dialog-body"
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
/** The actions, end-aligned: tertiary first, then the primary or destructive action. */
|
|
113
|
+
function DialogFooter({ className, ...props }) {
|
|
114
|
+
return /* @__PURE__ */ jsx("div", {
|
|
115
|
+
...props,
|
|
116
|
+
className: cx("qx-dialog-footer", className),
|
|
117
|
+
"data-slot": "dialog-footer"
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
export { Dialog$1 as Dialog, DialogBody, DialogClose, DialogContent, DialogFooter, DialogTrigger };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { Dialog, DialogBody, DialogBodyProps, DialogClose, DialogCloseProps, DialogContent, DialogContentProps, DialogFooter, DialogFooterProps, DialogIntent, DialogProps, DialogSize, DialogTrigger, DialogTriggerProps } from "./dialog.js";
|
|
2
|
+
export { Dialog, DialogBody, type DialogBodyProps, DialogClose, type DialogCloseProps, DialogContent, type DialogContentProps, DialogFooter, type DialogFooterProps, type DialogIntent, type DialogProps, type DialogSize, DialogTrigger, type DialogTriggerProps };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Dialog, DialogBody, DialogClose, DialogContent, DialogFooter, DialogTrigger } from "./dialog.js";
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { CSSProperties, ComponentProps, ReactElement, ReactNode } from "react";
|
|
2
|
+
import { Drawer } from "@base-ui/react/drawer";
|
|
3
|
+
/** The edge a drawer opens from, in the text direction: `end` is the right edge in English. */
|
|
4
|
+
export type DrawerSide = "start" | "end";
|
|
5
|
+
export type DrawerSize = "sm" | "md" | "lg";
|
|
6
|
+
export interface DrawerProps extends Omit<Drawer.Root.Props, "swipeDirection"> {
|
|
7
|
+
/** Default `end`. Right-to-left layouts need Base UI's DirectionProvider, as its keyboard does. */
|
|
8
|
+
side?: DrawerSide;
|
|
9
|
+
}
|
|
10
|
+
export type DrawerTriggerProps = Drawer.Trigger.Props;
|
|
11
|
+
export type DrawerCloseProps = Drawer.Close.Props;
|
|
12
|
+
export interface DrawerContentProps extends Omit<Drawer.Popup.Props, "className" | "style" | "title" | "children"> {
|
|
13
|
+
/** The title; it labels the drawer. */
|
|
14
|
+
title: ReactNode;
|
|
15
|
+
/** A line under the title; it describes the drawer. */
|
|
16
|
+
description?: ReactNode;
|
|
17
|
+
/** Width: `sm` 400, `md` 560 (default) or `lg` 800px. */
|
|
18
|
+
size?: DrawerSize;
|
|
19
|
+
/** Placement only. */
|
|
20
|
+
className?: string;
|
|
21
|
+
style?: CSSProperties;
|
|
22
|
+
/** DrawerBody and DrawerFooter. */
|
|
23
|
+
children?: ReactNode;
|
|
24
|
+
}
|
|
25
|
+
export interface DrawerBodyProps extends Omit<Drawer.Content.Props, "className"> {
|
|
26
|
+
className?: string;
|
|
27
|
+
}
|
|
28
|
+
export interface DrawerFooterProps extends ComponentProps<"div"> {}
|
|
29
|
+
/** Holds a drawer's open state: `open` / `defaultOpen` / `onOpenChange(open, details)`. */
|
|
30
|
+
declare function Drawer$1({ side, ...props }: DrawerProps): ReactElement;
|
|
31
|
+
/** Opens the drawer. Render your own control: `render={<Button>Edit</Button>}`. */
|
|
32
|
+
export declare function DrawerTrigger(props: DrawerTriggerProps): ReactElement;
|
|
33
|
+
/** Closes the drawer, e.g. Cancel: `render={<Button variant="ghost">Cancel</Button>}`. */
|
|
34
|
+
export declare function DrawerClose(props: DrawerCloseProps): ReactElement;
|
|
35
|
+
/**
|
|
36
|
+
* A full-height side panel (06-component-specs.md, increment 4) with a ruled header, a scrolling
|
|
37
|
+
* body and a ruled footer. Escape, an outside click and a swipe toward its edge close it. On open,
|
|
38
|
+
* focus goes to the first focusable element in the body, as in a dialog; on touch it goes to the
|
|
39
|
+
* drawer itself, so a phone's keyboard doesn't open over it.
|
|
40
|
+
*/
|
|
41
|
+
export declare function DrawerContent({ title, description, size, initialFocus, ref, className, children, ...props }: DrawerContentProps): ReactElement;
|
|
42
|
+
/** The drawer's content; it scrolls, and text in it can be selected without starting a swipe. */
|
|
43
|
+
export declare function DrawerBody({ className, ...props }: DrawerBodyProps): ReactElement;
|
|
44
|
+
/** The actions, end-aligned under a rule: tertiary first, then the primary action. */
|
|
45
|
+
export declare function DrawerFooter({ className, ...props }: DrawerFooterProps): ReactElement;
|
|
46
|
+
export { Drawer$1 as Drawer };
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cx } from "../internal/cx.js";
|
|
3
|
+
import { messages } from "../internal/messages.js";
|
|
4
|
+
import { IconButton } from "../button/button.js";
|
|
5
|
+
import { mergeRefs } from "../internal/refs.js";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { createContext, use, useRef } from "react";
|
|
8
|
+
import { XIcon } from "@qeetrix/icons/icons/x";
|
|
9
|
+
import { useDirection } from "@base-ui/react/direction-provider";
|
|
10
|
+
import { Drawer } from "@base-ui/react/drawer";
|
|
11
|
+
// src/drawer/drawer.tsx
|
|
12
|
+
const SideContext = createContext("end");
|
|
13
|
+
const FOCUSABLE = "input:not([type=\"hidden\"], :disabled), textarea:not(:disabled), select:not(:disabled), button:not(:disabled), [href], [tabindex]:not([tabindex=\"-1\"])";
|
|
14
|
+
/** Holds a drawer's open state: `open` / `defaultOpen` / `onOpenChange(open, details)`. */
|
|
15
|
+
function Drawer$1({ side = "end", ...props }) {
|
|
16
|
+
const rtl = useDirection() === "rtl";
|
|
17
|
+
const swipeDirection = side === "end" === rtl ? "left" : "right";
|
|
18
|
+
return /* @__PURE__ */ jsx(SideContext, {
|
|
19
|
+
value: side,
|
|
20
|
+
children: /* @__PURE__ */ jsx(Drawer.Root, {
|
|
21
|
+
...props,
|
|
22
|
+
swipeDirection
|
|
23
|
+
})
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
/** Opens the drawer. Render your own control: `render={<Button>Edit</Button>}`. */
|
|
27
|
+
function DrawerTrigger(props) {
|
|
28
|
+
return /* @__PURE__ */ jsx(Drawer.Trigger, { ...props });
|
|
29
|
+
}
|
|
30
|
+
/** Closes the drawer, e.g. Cancel: `render={<Button variant="ghost">Cancel</Button>}`. */
|
|
31
|
+
function DrawerClose(props) {
|
|
32
|
+
return /* @__PURE__ */ jsx(Drawer.Close, { ...props });
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* A full-height side panel (06-component-specs.md, increment 4) with a ruled header, a scrolling
|
|
36
|
+
* body and a ruled footer. Escape, an outside click and a swipe toward its edge close it. On open,
|
|
37
|
+
* focus goes to the first focusable element in the body, as in a dialog; on touch it goes to the
|
|
38
|
+
* drawer itself, so a phone's keyboard doesn't open over it.
|
|
39
|
+
*/
|
|
40
|
+
function DrawerContent({ title, description, size = "md", initialFocus, ref, className, children, ...props }) {
|
|
41
|
+
const side = use(SideContext);
|
|
42
|
+
const popup = useRef(null);
|
|
43
|
+
const firstInBody = (type) => type === "touch" || (popup.current?.querySelector(`[data-slot="drawer-body"] :is(${FOCUSABLE})`) ?? true);
|
|
44
|
+
return /* @__PURE__ */ jsxs(Drawer.Portal, { children: [/* @__PURE__ */ jsx(Drawer.Backdrop, {
|
|
45
|
+
className: "qx-drawer-backdrop",
|
|
46
|
+
"data-slot": "drawer-backdrop"
|
|
47
|
+
}), /* @__PURE__ */ jsx(Drawer.Viewport, {
|
|
48
|
+
className: "qx-drawer-viewport",
|
|
49
|
+
"data-side": side,
|
|
50
|
+
children: /* @__PURE__ */ jsxs(Drawer.Popup, {
|
|
51
|
+
...props,
|
|
52
|
+
ref: mergeRefs(ref, popup),
|
|
53
|
+
initialFocus: initialFocus ?? firstInBody,
|
|
54
|
+
className: cx("qx-drawer", className),
|
|
55
|
+
"data-slot": "drawer-popup",
|
|
56
|
+
"data-size": size,
|
|
57
|
+
children: [
|
|
58
|
+
/* @__PURE__ */ jsxs("div", {
|
|
59
|
+
className: "qx-drawer-header",
|
|
60
|
+
"data-slot": "drawer-header",
|
|
61
|
+
children: [/* @__PURE__ */ jsx(Drawer.Title, {
|
|
62
|
+
className: "qx-drawer-title",
|
|
63
|
+
"data-slot": "drawer-title",
|
|
64
|
+
children: title
|
|
65
|
+
}), description != null && /* @__PURE__ */ jsx(Drawer.Description, {
|
|
66
|
+
className: "qx-drawer-description",
|
|
67
|
+
"data-slot": "drawer-description",
|
|
68
|
+
children: description
|
|
69
|
+
})]
|
|
70
|
+
}),
|
|
71
|
+
children,
|
|
72
|
+
/* @__PURE__ */ jsx("div", {
|
|
73
|
+
className: "qx-drawer-close",
|
|
74
|
+
"data-slot": "drawer-close",
|
|
75
|
+
children: /* @__PURE__ */ jsx(Drawer.Close, { render: /* @__PURE__ */ jsx(IconButton, {
|
|
76
|
+
icon: XIcon,
|
|
77
|
+
"aria-label": messages.overlay.close,
|
|
78
|
+
size: "sm"
|
|
79
|
+
}) })
|
|
80
|
+
})
|
|
81
|
+
]
|
|
82
|
+
})
|
|
83
|
+
})] });
|
|
84
|
+
}
|
|
85
|
+
/** The drawer's content; it scrolls, and text in it can be selected without starting a swipe. */
|
|
86
|
+
function DrawerBody({ className, ...props }) {
|
|
87
|
+
return /* @__PURE__ */ jsx(Drawer.Content, {
|
|
88
|
+
...props,
|
|
89
|
+
className: cx("qx-drawer-body", className),
|
|
90
|
+
"data-slot": "drawer-body"
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
/** The actions, end-aligned under a rule: tertiary first, then the primary action. */
|
|
94
|
+
function DrawerFooter({ className, ...props }) {
|
|
95
|
+
return /* @__PURE__ */ jsx("div", {
|
|
96
|
+
...props,
|
|
97
|
+
className: cx("qx-drawer-footer", className),
|
|
98
|
+
"data-slot": "drawer-footer"
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
export { Drawer$1 as Drawer, DrawerBody, DrawerClose, DrawerContent, DrawerFooter, DrawerTrigger };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { Drawer, DrawerBody, DrawerBodyProps, DrawerClose, DrawerCloseProps, DrawerContent, DrawerContentProps, DrawerFooter, DrawerFooterProps, DrawerProps, DrawerSide, DrawerSize, DrawerTrigger, DrawerTriggerProps } from "./drawer.js";
|
|
2
|
+
export { Drawer, DrawerBody, type DrawerBodyProps, DrawerClose, type DrawerCloseProps, DrawerContent, type DrawerContentProps, DrawerFooter, type DrawerFooterProps, type DrawerProps, type DrawerSide, type DrawerSize, DrawerTrigger, type DrawerTriggerProps };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Drawer, DrawerBody, DrawerClose, DrawerContent, DrawerFooter, DrawerTrigger } from "./drawer.js";
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import "./field.js";
|
|
2
|
+
import { CSSProperties, ReactElement, ReactNode } from "react";
|
|
3
|
+
/**
|
|
4
|
+
* How a checkbox, radio or switch is named: by its visible `label`, or — with no visible label, as
|
|
5
|
+
* in a table row — by `aria-label` or `aria-labelledby`, which the type then requires.
|
|
6
|
+
*/
|
|
7
|
+
export type ChoiceLabelProps = {
|
|
8
|
+
label: ReactNode;
|
|
9
|
+
"aria-label"?: string;
|
|
10
|
+
"aria-labelledby"?: string;
|
|
11
|
+
} | {
|
|
12
|
+
label?: undefined;
|
|
13
|
+
"aria-label": string;
|
|
14
|
+
"aria-labelledby"?: string;
|
|
15
|
+
} | {
|
|
16
|
+
label?: undefined;
|
|
17
|
+
"aria-label"?: string;
|
|
18
|
+
"aria-labelledby": string;
|
|
19
|
+
};
|
|
20
|
+
/** Options stacked (`vertical`) or in a wrapping row (`horizontal`, for short options). */
|
|
21
|
+
export type ChoiceOrientation = "vertical" | "horizontal";
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cx } from "../internal/cx.js";
|
|
3
|
+
import { FieldMessages, InFieldContext } from "./field.js";
|
|
4
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
import { use } from "react";
|
|
6
|
+
import { Field } from "@base-ui/react/field";
|
|
7
|
+
import { Fieldset } from "@base-ui/react/fieldset";
|
|
8
|
+
// src/field/choice.tsx
|
|
9
|
+
/**
|
|
10
|
+
* One option: the control and its text inside a label (the whole row is the click target), then an
|
|
11
|
+
* optional description, both linked to the control by Base UI. Inside a group or a Field the row is
|
|
12
|
+
* a Field.Item; on its own it is a Field.Root. With no visible label, the control renders alone.
|
|
13
|
+
*/
|
|
14
|
+
function ChoiceRow({ kind, label, description, disabled, className, style, children }) {
|
|
15
|
+
const inField = use(InFieldContext);
|
|
16
|
+
if (label == null) return children;
|
|
17
|
+
const row = {
|
|
18
|
+
disabled,
|
|
19
|
+
className: cx("qx-choice", className),
|
|
20
|
+
style,
|
|
21
|
+
"data-slot": kind,
|
|
22
|
+
children: /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs(Field.Label, {
|
|
23
|
+
className: "qx-choice-label",
|
|
24
|
+
"data-slot": `${kind}-label`,
|
|
25
|
+
children: [children, /* @__PURE__ */ jsx("span", {
|
|
26
|
+
className: "qx-choice-text",
|
|
27
|
+
children: label
|
|
28
|
+
})]
|
|
29
|
+
}), description != null && /* @__PURE__ */ jsx(Field.Description, {
|
|
30
|
+
className: "qx-choice-description",
|
|
31
|
+
"data-slot": `${kind}-description`,
|
|
32
|
+
children: description
|
|
33
|
+
})] })
|
|
34
|
+
};
|
|
35
|
+
return inField ? /* @__PURE__ */ jsx(Field.Item, { ...row }) : /* @__PURE__ */ jsx(Field.Root, { ...row });
|
|
36
|
+
}
|
|
37
|
+
/** A question with options: Field › Fieldset rendered as the group › legend, options, messages. */
|
|
38
|
+
function ChoiceGroup({ kind, label, description, error, name, disabled, orientation, className, style, group, children }) {
|
|
39
|
+
return /* @__PURE__ */ jsxs(Field.Root, {
|
|
40
|
+
name,
|
|
41
|
+
disabled,
|
|
42
|
+
invalid: error != null ? true : void 0,
|
|
43
|
+
className: cx("qx-field qx-choice-group", className),
|
|
44
|
+
style,
|
|
45
|
+
"data-slot": `${kind}-group`,
|
|
46
|
+
"data-orientation": orientation,
|
|
47
|
+
children: [/* @__PURE__ */ jsxs(Fieldset.Root, {
|
|
48
|
+
render: group,
|
|
49
|
+
className: "qx-choice-group-set",
|
|
50
|
+
children: [/* @__PURE__ */ jsx(Fieldset.Legend, {
|
|
51
|
+
className: "qx-field-label",
|
|
52
|
+
"data-slot": `${kind}-group-legend`,
|
|
53
|
+
children: label
|
|
54
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
55
|
+
className: "qx-choice-group-options",
|
|
56
|
+
children: /* @__PURE__ */ jsx(InFieldContext, {
|
|
57
|
+
value: true,
|
|
58
|
+
children
|
|
59
|
+
})
|
|
60
|
+
})]
|
|
61
|
+
}), /* @__PURE__ */ jsx(FieldMessages, {
|
|
62
|
+
description,
|
|
63
|
+
error
|
|
64
|
+
})]
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
export { ChoiceGroup, ChoiceRow };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { CSSProperties, ReactElement, ReactNode } from "react";
|
|
2
|
+
import { Field } from "@base-ui/react/field";
|
|
3
|
+
/** The help text and error every labelled field shares. */
|
|
4
|
+
export interface FieldMessageProps {
|
|
5
|
+
/** Help text under the control, e.g. a format ("15 characters"). Hidden while an error shows. */
|
|
6
|
+
description?: ReactNode;
|
|
7
|
+
/**
|
|
8
|
+
* An error to show now, e.g. from the server; it also marks the field invalid. Without it, the
|
|
9
|
+
* browser's or `validate`'s message shows whenever the field is invalid.
|
|
10
|
+
*/
|
|
11
|
+
error?: ReactNode;
|
|
12
|
+
}
|
|
13
|
+
export interface FieldProps extends Omit<Field.Root.Props, "className" | "style" | "render" | "children">, FieldMessageProps {
|
|
14
|
+
/** The label. Required: a placeholder is never a label. */
|
|
15
|
+
label: ReactNode;
|
|
16
|
+
/** Appends "(optional)". Qeetrix marks optional fields, never required ones. */
|
|
17
|
+
optional?: boolean;
|
|
18
|
+
/** Hides the label visually and keeps it for assistive technology. Only for a toolbar search. */
|
|
19
|
+
hideLabel?: boolean;
|
|
20
|
+
/** Placement only (margin, width, grid placement). */
|
|
21
|
+
className?: string;
|
|
22
|
+
style?: CSSProperties;
|
|
23
|
+
/** The control: an Input, a Textarea, or any Base UI form control. */
|
|
24
|
+
children?: ReactNode;
|
|
25
|
+
}
|
|
26
|
+
/** The label, help text and error for one control (06-component-specs.md §2). */
|
|
27
|
+
declare function Field$1({ label, description, error, optional, hideLabel, invalid, className, children, ...props }: FieldProps): ReactElement;
|
|
28
|
+
export { Field$1 as Field };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cx } from "../internal/cx.js";
|
|
3
|
+
import { messages } from "../internal/messages.js";
|
|
4
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
import { createContext } from "react";
|
|
6
|
+
import { Field } from "@base-ui/react/field";
|
|
7
|
+
import { CircleAlertIcon } from "@qeetrix/icons/icons/circle-alert";
|
|
8
|
+
// src/field/field.tsx
|
|
9
|
+
/**
|
|
10
|
+
* True inside a Field or a choice group. A checkbox, radio or switch there is an item of that field
|
|
11
|
+
* (Base UI Field.Item); on its own it is a field of its own (Field.Root).
|
|
12
|
+
*/
|
|
13
|
+
const InFieldContext = createContext(false);
|
|
14
|
+
function ErrorRow({ children, ...props }) {
|
|
15
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
16
|
+
...props,
|
|
17
|
+
children: [/* @__PURE__ */ jsx(CircleAlertIcon, {
|
|
18
|
+
shape: "sharp",
|
|
19
|
+
size: 16,
|
|
20
|
+
"aria-hidden": true,
|
|
21
|
+
className: "qx-field-error-icon"
|
|
22
|
+
}), /* @__PURE__ */ jsx("span", { children })]
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
/** The description and error under a control; Base UI links both to it with aria-describedby. */
|
|
26
|
+
function FieldMessages({ description, error }) {
|
|
27
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [description != null && /* @__PURE__ */ jsx(Field.Description, {
|
|
28
|
+
className: "qx-field-description",
|
|
29
|
+
"data-slot": "field-description",
|
|
30
|
+
children: description
|
|
31
|
+
}), /* @__PURE__ */ jsx(Field.Error, {
|
|
32
|
+
className: "qx-field-error",
|
|
33
|
+
"data-slot": "field-error",
|
|
34
|
+
match: error != null ? true : void 0,
|
|
35
|
+
render: /* @__PURE__ */ jsx(ErrorRow, {}),
|
|
36
|
+
...error != null ? { children: error } : {}
|
|
37
|
+
})] });
|
|
38
|
+
}
|
|
39
|
+
/** The label text, with "(optional)" when the field may be left empty. */
|
|
40
|
+
function labelText(label, optional) {
|
|
41
|
+
if (!optional) return label;
|
|
42
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
43
|
+
label,
|
|
44
|
+
" ",
|
|
45
|
+
/* @__PURE__ */ jsx("span", {
|
|
46
|
+
className: "qx-field-optional",
|
|
47
|
+
"data-slot": "field-optional",
|
|
48
|
+
children: messages.field.optional
|
|
49
|
+
})
|
|
50
|
+
] });
|
|
51
|
+
}
|
|
52
|
+
/** The label, help text and error for one control (06-component-specs.md §2). */
|
|
53
|
+
function Field$1({ label, description, error, optional, hideLabel, invalid, className, children, ...props }) {
|
|
54
|
+
return /* @__PURE__ */ jsxs(Field.Root, {
|
|
55
|
+
...props,
|
|
56
|
+
invalid: invalid ?? (error != null ? true : void 0),
|
|
57
|
+
className: cx("qx-field", className),
|
|
58
|
+
"data-slot": "field",
|
|
59
|
+
children: [
|
|
60
|
+
/* @__PURE__ */ jsx(Field.Label, {
|
|
61
|
+
className: "qx-field-label",
|
|
62
|
+
"data-slot": "field-label",
|
|
63
|
+
"data-hidden": hideLabel ? "" : void 0,
|
|
64
|
+
children: labelText(label, optional)
|
|
65
|
+
}),
|
|
66
|
+
/* @__PURE__ */ jsx(InFieldContext, {
|
|
67
|
+
value: true,
|
|
68
|
+
children
|
|
69
|
+
}),
|
|
70
|
+
/* @__PURE__ */ jsx(FieldMessages, {
|
|
71
|
+
description,
|
|
72
|
+
error
|
|
73
|
+
})
|
|
74
|
+
]
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
export { Field$1 as Field, FieldMessages, InFieldContext, labelText };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Field } from "./field.js";
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { CSSProperties, ReactElement, ReactNode } from "react";
|
|
2
|
+
import { Fieldset } from "@base-ui/react/fieldset";
|
|
3
|
+
export interface FieldsetProps extends Omit<Fieldset.Root.Props, "className" | "style" | "children"> {
|
|
4
|
+
/** The section's heading, e.g. "Billing address". */
|
|
5
|
+
legend: ReactNode;
|
|
6
|
+
/** A line under the legend. */
|
|
7
|
+
description?: ReactNode;
|
|
8
|
+
/** Placement only (margin, width, grid placement). */
|
|
9
|
+
className?: string;
|
|
10
|
+
style?: CSSProperties;
|
|
11
|
+
/** The fields, stacked with the density's form gap. */
|
|
12
|
+
children?: ReactNode;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* A section of fields under a heading. `disabled` disables every field inside. A choice question is
|
|
16
|
+
* a CheckboxGroup or RadioGroup, not a Fieldset.
|
|
17
|
+
*/
|
|
18
|
+
declare function Fieldset$1({ legend, description, className, children, ...props }: FieldsetProps): ReactElement;
|
|
19
|
+
export { Fieldset$1 as Fieldset };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cx } from "../internal/cx.js";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
import { Fieldset } from "@base-ui/react/fieldset";
|
|
5
|
+
// src/fieldset/fieldset.tsx
|
|
6
|
+
/**
|
|
7
|
+
* A section of fields under a heading. `disabled` disables every field inside. A choice question is
|
|
8
|
+
* a CheckboxGroup or RadioGroup, not a Fieldset.
|
|
9
|
+
*/
|
|
10
|
+
function Fieldset$1({ legend, description, className, children, ...props }) {
|
|
11
|
+
return /* @__PURE__ */ jsxs(Fieldset.Root, {
|
|
12
|
+
...props,
|
|
13
|
+
className: cx("qx-fieldset", className),
|
|
14
|
+
"data-slot": "fieldset",
|
|
15
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
16
|
+
className: "qx-fieldset-header",
|
|
17
|
+
children: [/* @__PURE__ */ jsx(Fieldset.Legend, {
|
|
18
|
+
className: "qx-fieldset-legend",
|
|
19
|
+
"data-slot": "fieldset-legend",
|
|
20
|
+
children: legend
|
|
21
|
+
}), description != null && /* @__PURE__ */ jsx("p", {
|
|
22
|
+
className: "qx-fieldset-description",
|
|
23
|
+
"data-slot": "fieldset-description",
|
|
24
|
+
children: description
|
|
25
|
+
})]
|
|
26
|
+
}), children]
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
export { Fieldset$1 as Fieldset };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Fieldset } from "./fieldset.js";
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { RenderProp } from "../internal/render.js";
|
|
2
|
+
import { Space } from "../internal/space.js";
|
|
3
|
+
import { ComponentProps, ReactElement } from "react";
|
|
4
|
+
export type GridColumnCount = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
|
|
5
|
+
/** Columns per window size class. Each class inherits the nearest smaller one that is set. */
|
|
6
|
+
export interface GridColumns {
|
|
7
|
+
/** Below 600px, and the starting point for the others. */
|
|
8
|
+
base?: GridColumnCount;
|
|
9
|
+
/** From 600px. */
|
|
10
|
+
medium?: GridColumnCount;
|
|
11
|
+
/** From 840px. */
|
|
12
|
+
expanded?: GridColumnCount;
|
|
13
|
+
/** From 1200px. */
|
|
14
|
+
large?: GridColumnCount;
|
|
15
|
+
/** From 1600px. */
|
|
16
|
+
xlarge?: GridColumnCount;
|
|
17
|
+
}
|
|
18
|
+
export type GridAlign = "start" | "center" | "end" | "stretch";
|
|
19
|
+
export interface GridProps extends ComponentProps<"div"> {
|
|
20
|
+
/** Equal columns: one count, or one per window size class. Default 1. */
|
|
21
|
+
columns?: GridColumnCount | GridColumns;
|
|
22
|
+
/** Space between cells, from the space scale. Default `md` (12px). */
|
|
23
|
+
gap?: Space;
|
|
24
|
+
/** Vertical alignment of cells in a row. Default `stretch`. */
|
|
25
|
+
align?: GridAlign;
|
|
26
|
+
/** Render a different element, e.g. `<ul />`. */
|
|
27
|
+
render?: RenderProp;
|
|
28
|
+
}
|
|
29
|
+
/** Responsive equal columns on the window size classes, with token gaps. */
|
|
30
|
+
export declare function Grid({ columns, gap, align, render, className, style, ...props }: GridProps): ReactElement;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { cx } from "../internal/cx.js";
|
|
2
|
+
import { renderElement } from "../internal/render.js";
|
|
3
|
+
// src/grid/grid.tsx
|
|
4
|
+
const SIZE_CLASSES = [
|
|
5
|
+
"base",
|
|
6
|
+
"medium",
|
|
7
|
+
"expanded",
|
|
8
|
+
"large",
|
|
9
|
+
"xlarge"
|
|
10
|
+
];
|
|
11
|
+
/** A whole number from 1 to 12; the value becomes a CSS variable, so it is never trusted as-is. */
|
|
12
|
+
const count = (value) => Math.min(12, Math.max(1, Math.trunc(value) || 1));
|
|
13
|
+
function columnVariables(columns) {
|
|
14
|
+
const perClass = typeof columns === "number" ? { base: columns } : columns;
|
|
15
|
+
const variables = {};
|
|
16
|
+
for (const sizeClass of SIZE_CLASSES) {
|
|
17
|
+
const value = perClass[sizeClass];
|
|
18
|
+
if (value !== void 0) variables[`--qx-grid-${sizeClass}`] = count(value);
|
|
19
|
+
}
|
|
20
|
+
return variables;
|
|
21
|
+
}
|
|
22
|
+
/** Responsive equal columns on the window size classes, with token gaps. */
|
|
23
|
+
function Grid({ columns = 1, gap = "md", align, render, className, style, ...props }) {
|
|
24
|
+
return renderElement("div", render, {
|
|
25
|
+
...props,
|
|
26
|
+
className: cx("qx-grid", className),
|
|
27
|
+
style: {
|
|
28
|
+
...columnVariables(columns),
|
|
29
|
+
...style
|
|
30
|
+
},
|
|
31
|
+
"data-slot": "grid",
|
|
32
|
+
"data-gap": gap,
|
|
33
|
+
"data-align": align
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
export { Grid };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Grid } from "./grid.js";
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { RenderProp } from "../internal/render.js";
|
|
2
|
+
import { TextAlign } from "../internal/space.js";
|
|
3
|
+
import { Truncate } from "../internal/text.js";
|
|
4
|
+
import { ComponentProps, ReactElement } from "react";
|
|
5
|
+
export type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;
|
|
6
|
+
export type HeadingSize = "display-lg" | "display-md" | "display-sm" | "heading-lg" | "heading-md" | "heading-sm" | "title-lg" | "title-md" | "title-sm";
|
|
7
|
+
export type HeadingTone = "default" | "subtle" | "inverse";
|
|
8
|
+
export interface HeadingProps extends ComponentProps<"h2"> {
|
|
9
|
+
/** The document level: renders `<h1>`…`<h6>`. Required, so the outline is always intended. */
|
|
10
|
+
level: HeadingLevel;
|
|
11
|
+
/** The look. Default by level: 1 heading-lg, 2 heading-md, 3 heading-sm, 4 title-lg, 5 title-md, 6 title-sm. */
|
|
12
|
+
size?: HeadingSize;
|
|
13
|
+
/** `default`, `subtle` or `inverse`. */
|
|
14
|
+
tone?: HeadingTone;
|
|
15
|
+
/** `true` for one line with an ellipsis, or a number of lines. */
|
|
16
|
+
truncate?: Truncate;
|
|
17
|
+
/** Logical alignment. */
|
|
18
|
+
align?: TextAlign;
|
|
19
|
+
/** Render a different element. Prefer `level`; use this for a link that looks like a heading. */
|
|
20
|
+
render?: RenderProp;
|
|
21
|
+
}
|
|
22
|
+
/** A section heading: the level sets the element, the size sets the look. */
|
|
23
|
+
export declare function Heading({ level, size, tone, truncate, align, render, className, style, ...props }: HeadingProps): ReactElement;
|