panelui-web 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/button-group/index.d.ts +28 -16
- package/dist/components/button-group/index.js +53 -15
- package/dist/components/choice-cards/index.d.ts +167 -0
- package/dist/components/choice-cards/index.js +132 -0
- package/dist/components/inspector/index.d.ts +242 -0
- package/dist/components/inspector/index.js +230 -0
- package/dist/components/sheet/index.d.ts +16 -5
- package/dist/components/sheet/index.js +72 -15
- package/dist/components/slider/index.d.ts +293 -0
- package/dist/components/slider/index.js +342 -0
- package/dist/components/timeline/index.d.ts +328 -0
- package/dist/components/timeline/index.js +613 -0
- package/dist/components/toolbar/index.d.ts +185 -0
- package/dist/components/toolbar/index.js +270 -0
- package/dist/components/workbench/index.d.ts +224 -0
- package/dist/components/workbench/index.js +306 -0
- package/dist/components/xy-pad/index.d.ts +180 -0
- package/dist/components/xy-pad/index.js +278 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +7 -0
- package/package.json +1 -1
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import { Tabs } from '@base-ui/react/tabs';
|
|
2
|
+
import { type ComponentProps, type ReactNode } from 'react';
|
|
3
|
+
declare const inspectorVariants: import("tailwind-variants").TVReturnType<{
|
|
4
|
+
[key: string]: {
|
|
5
|
+
[key: string]: import("tailwind-merge").ClassNameValue | {
|
|
6
|
+
root?: import("tailwind-merge").ClassNameValue;
|
|
7
|
+
section?: import("tailwind-merge").ClassNameValue;
|
|
8
|
+
marker?: import("tailwind-merge").ClassNameValue;
|
|
9
|
+
content?: import("tailwind-merge").ClassNameValue;
|
|
10
|
+
scrollbar?: import("tailwind-merge").ClassNameValue;
|
|
11
|
+
separator?: import("tailwind-merge").ClassNameValue;
|
|
12
|
+
tab?: import("tailwind-merge").ClassNameValue;
|
|
13
|
+
tooltip?: import("tailwind-merge").ClassNameValue;
|
|
14
|
+
page?: import("tailwind-merge").ClassNameValue;
|
|
15
|
+
viewport?: import("tailwind-merge").ClassNameValue;
|
|
16
|
+
panel?: import("tailwind-merge").ClassNameValue;
|
|
17
|
+
thumb?: import("tailwind-merge").ClassNameValue;
|
|
18
|
+
chevron?: import("tailwind-merge").ClassNameValue;
|
|
19
|
+
sectionTitle?: import("tailwind-merge").ClassNameValue;
|
|
20
|
+
railSeparator?: import("tailwind-merge").ClassNameValue;
|
|
21
|
+
sectionAction?: import("tailwind-merge").ClassNameValue;
|
|
22
|
+
rail?: import("tailwind-merge").ClassNameValue;
|
|
23
|
+
sectionContent?: import("tailwind-merge").ClassNameValue;
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
} | {
|
|
27
|
+
[x: string]: {
|
|
28
|
+
[x: string]: import("tailwind-merge").ClassNameValue | {
|
|
29
|
+
root?: import("tailwind-merge").ClassNameValue;
|
|
30
|
+
section?: import("tailwind-merge").ClassNameValue;
|
|
31
|
+
marker?: import("tailwind-merge").ClassNameValue;
|
|
32
|
+
content?: import("tailwind-merge").ClassNameValue;
|
|
33
|
+
scrollbar?: import("tailwind-merge").ClassNameValue;
|
|
34
|
+
separator?: import("tailwind-merge").ClassNameValue;
|
|
35
|
+
tab?: import("tailwind-merge").ClassNameValue;
|
|
36
|
+
tooltip?: import("tailwind-merge").ClassNameValue;
|
|
37
|
+
page?: import("tailwind-merge").ClassNameValue;
|
|
38
|
+
viewport?: import("tailwind-merge").ClassNameValue;
|
|
39
|
+
panel?: import("tailwind-merge").ClassNameValue;
|
|
40
|
+
thumb?: import("tailwind-merge").ClassNameValue;
|
|
41
|
+
chevron?: import("tailwind-merge").ClassNameValue;
|
|
42
|
+
sectionTitle?: import("tailwind-merge").ClassNameValue;
|
|
43
|
+
railSeparator?: import("tailwind-merge").ClassNameValue;
|
|
44
|
+
sectionAction?: import("tailwind-merge").ClassNameValue;
|
|
45
|
+
rail?: import("tailwind-merge").ClassNameValue;
|
|
46
|
+
sectionContent?: import("tailwind-merge").ClassNameValue;
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
} | {}, {
|
|
50
|
+
root: string;
|
|
51
|
+
rail: string[];
|
|
52
|
+
marker: string[];
|
|
53
|
+
tab: string[];
|
|
54
|
+
railSeparator: string;
|
|
55
|
+
tooltip: string[];
|
|
56
|
+
panel: string[];
|
|
57
|
+
page: string[];
|
|
58
|
+
viewport: string;
|
|
59
|
+
content: string;
|
|
60
|
+
scrollbar: string;
|
|
61
|
+
thumb: string;
|
|
62
|
+
section: string;
|
|
63
|
+
sectionTitle: string[];
|
|
64
|
+
chevron: string[];
|
|
65
|
+
sectionAction: string;
|
|
66
|
+
sectionContent: string[];
|
|
67
|
+
separator: string;
|
|
68
|
+
}, undefined, {
|
|
69
|
+
[key: string]: {
|
|
70
|
+
[key: string]: import("tailwind-merge").ClassNameValue | {
|
|
71
|
+
root?: import("tailwind-merge").ClassNameValue;
|
|
72
|
+
section?: import("tailwind-merge").ClassNameValue;
|
|
73
|
+
marker?: import("tailwind-merge").ClassNameValue;
|
|
74
|
+
content?: import("tailwind-merge").ClassNameValue;
|
|
75
|
+
scrollbar?: import("tailwind-merge").ClassNameValue;
|
|
76
|
+
separator?: import("tailwind-merge").ClassNameValue;
|
|
77
|
+
tab?: import("tailwind-merge").ClassNameValue;
|
|
78
|
+
tooltip?: import("tailwind-merge").ClassNameValue;
|
|
79
|
+
page?: import("tailwind-merge").ClassNameValue;
|
|
80
|
+
viewport?: import("tailwind-merge").ClassNameValue;
|
|
81
|
+
panel?: import("tailwind-merge").ClassNameValue;
|
|
82
|
+
thumb?: import("tailwind-merge").ClassNameValue;
|
|
83
|
+
chevron?: import("tailwind-merge").ClassNameValue;
|
|
84
|
+
sectionTitle?: import("tailwind-merge").ClassNameValue;
|
|
85
|
+
railSeparator?: import("tailwind-merge").ClassNameValue;
|
|
86
|
+
sectionAction?: import("tailwind-merge").ClassNameValue;
|
|
87
|
+
rail?: import("tailwind-merge").ClassNameValue;
|
|
88
|
+
sectionContent?: import("tailwind-merge").ClassNameValue;
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
} | {}, {
|
|
92
|
+
root: string;
|
|
93
|
+
rail: string[];
|
|
94
|
+
marker: string[];
|
|
95
|
+
tab: string[];
|
|
96
|
+
railSeparator: string;
|
|
97
|
+
tooltip: string[];
|
|
98
|
+
panel: string[];
|
|
99
|
+
page: string[];
|
|
100
|
+
viewport: string;
|
|
101
|
+
content: string;
|
|
102
|
+
scrollbar: string;
|
|
103
|
+
thumb: string;
|
|
104
|
+
section: string;
|
|
105
|
+
sectionTitle: string[];
|
|
106
|
+
chevron: string[];
|
|
107
|
+
sectionAction: string;
|
|
108
|
+
sectionContent: string[];
|
|
109
|
+
separator: string;
|
|
110
|
+
}, import("tailwind-variants").TVReturnType<unknown, {
|
|
111
|
+
root: string;
|
|
112
|
+
rail: string[];
|
|
113
|
+
marker: string[];
|
|
114
|
+
tab: string[];
|
|
115
|
+
railSeparator: string;
|
|
116
|
+
tooltip: string[];
|
|
117
|
+
panel: string[];
|
|
118
|
+
page: string[];
|
|
119
|
+
viewport: string;
|
|
120
|
+
content: string;
|
|
121
|
+
scrollbar: string;
|
|
122
|
+
thumb: string;
|
|
123
|
+
section: string;
|
|
124
|
+
sectionTitle: string[];
|
|
125
|
+
chevron: string[];
|
|
126
|
+
sectionAction: string;
|
|
127
|
+
sectionContent: string[];
|
|
128
|
+
separator: string;
|
|
129
|
+
}, undefined, unknown, unknown, undefined>>;
|
|
130
|
+
export interface InspectorProps extends Omit<Tabs.Root.Props, 'className' | 'orientation'> {
|
|
131
|
+
className?: string;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* The rail and the panel side by side. `defaultValue`, or `value` with
|
|
135
|
+
* `onValueChange`, names the page that is open.
|
|
136
|
+
*/
|
|
137
|
+
declare function InspectorRoot({ className, ...props }: InspectorProps): import("react").JSX.Element;
|
|
138
|
+
declare namespace InspectorRoot {
|
|
139
|
+
var displayName: string;
|
|
140
|
+
}
|
|
141
|
+
export interface InspectorRailProps extends Omit<Tabs.List.Props, 'className'> {
|
|
142
|
+
className?: string;
|
|
143
|
+
}
|
|
144
|
+
/** The column of page icons, in a pill of its own beside the panel. */
|
|
145
|
+
declare function InspectorRail({ className, children, ...props }: InspectorRailProps): import("react").JSX.Element;
|
|
146
|
+
declare namespace InspectorRail {
|
|
147
|
+
var displayName: string;
|
|
148
|
+
}
|
|
149
|
+
export interface InspectorTabProps extends Omit<Tabs.Tab.Props, 'className' | 'children'> {
|
|
150
|
+
/** What the page is called: the tab's tooltip and its name for a screen reader. */
|
|
151
|
+
label: string;
|
|
152
|
+
/** The icon. */
|
|
153
|
+
children?: ReactNode;
|
|
154
|
+
className?: string;
|
|
155
|
+
}
|
|
156
|
+
/** One page's icon on the rail. */
|
|
157
|
+
declare function InspectorTab({ label, className, children, ...props }: InspectorTabProps): import("react").JSX.Element;
|
|
158
|
+
declare namespace InspectorTab {
|
|
159
|
+
var displayName: string;
|
|
160
|
+
}
|
|
161
|
+
export interface InspectorRailSeparatorProps extends ComponentProps<'span'> {
|
|
162
|
+
}
|
|
163
|
+
/** A short line between groups of pages on the rail. */
|
|
164
|
+
declare function InspectorRailSeparator({ className, ...props }: InspectorRailSeparatorProps): import("react").JSX.Element;
|
|
165
|
+
declare namespace InspectorRailSeparator {
|
|
166
|
+
var displayName: string;
|
|
167
|
+
}
|
|
168
|
+
export interface InspectorPanelProps extends ComponentProps<'div'> {
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* The card the pages open in. Give it a height, such as `h-[32rem]`, and a
|
|
172
|
+
* page longer than that scrolls inside it. Without pages, its children are
|
|
173
|
+
* one page of sections.
|
|
174
|
+
*/
|
|
175
|
+
declare function InspectorPanel({ className, children, ...props }: InspectorPanelProps): import("react").JSX.Element;
|
|
176
|
+
declare namespace InspectorPanel {
|
|
177
|
+
var displayName: string;
|
|
178
|
+
}
|
|
179
|
+
export interface InspectorPageProps extends Omit<Tabs.Panel.Props, 'className'> {
|
|
180
|
+
className?: string;
|
|
181
|
+
}
|
|
182
|
+
/** What one tab opens: a column of sections that scrolls inside the panel. */
|
|
183
|
+
declare function InspectorPage({ className, children, ...props }: InspectorPageProps): import("react").JSX.Element;
|
|
184
|
+
declare namespace InspectorPage {
|
|
185
|
+
var displayName: string;
|
|
186
|
+
}
|
|
187
|
+
export interface InspectorSectionProps extends Omit<ComponentProps<'div'>, 'onChange'> {
|
|
188
|
+
/** Fold the section away by its title. Its content then shows only while it is open. */
|
|
189
|
+
collapsible?: boolean;
|
|
190
|
+
/** Whether a collapsible section starts open. Default true. */
|
|
191
|
+
defaultOpen?: boolean;
|
|
192
|
+
/** Whether a collapsible section is open, when the caller holds it. */
|
|
193
|
+
open?: boolean;
|
|
194
|
+
/** Called when a collapsible section opens or closes. */
|
|
195
|
+
onOpenChange?: (open: boolean) => void;
|
|
196
|
+
}
|
|
197
|
+
/** A titled group of settings: a title, an action on its line, and the controls under them. */
|
|
198
|
+
declare function InspectorSection({ collapsible, defaultOpen, open, onOpenChange, className, children, ...props }: InspectorSectionProps): import("react").JSX.Element;
|
|
199
|
+
declare namespace InspectorSection {
|
|
200
|
+
var displayName: string;
|
|
201
|
+
}
|
|
202
|
+
export interface InspectorSectionTitleProps extends ComponentProps<'h3'> {
|
|
203
|
+
}
|
|
204
|
+
/** The section's name. In a collapsible section it is the button that folds it, with a chevron. */
|
|
205
|
+
declare function InspectorSectionTitle({ className, children, ...props }: InspectorSectionTitleProps): import("react").JSX.Element;
|
|
206
|
+
declare namespace InspectorSectionTitle {
|
|
207
|
+
var displayName: string;
|
|
208
|
+
}
|
|
209
|
+
export interface InspectorSectionActionProps extends ComponentProps<'div'> {
|
|
210
|
+
}
|
|
211
|
+
/** What sits at the end of the title's line: the switch for the whole section, or a Reset. */
|
|
212
|
+
declare function InspectorSectionAction({ className, ...props }: InspectorSectionActionProps): import("react").JSX.Element;
|
|
213
|
+
declare namespace InspectorSectionAction {
|
|
214
|
+
var displayName: string;
|
|
215
|
+
}
|
|
216
|
+
export interface InspectorSectionContentProps extends ComponentProps<'div'> {
|
|
217
|
+
}
|
|
218
|
+
/** The controls under the title, stacked with an even gap. */
|
|
219
|
+
declare function InspectorSectionContent({ className, children, ...props }: InspectorSectionContentProps): import("react").JSX.Element;
|
|
220
|
+
declare namespace InspectorSectionContent {
|
|
221
|
+
var displayName: string;
|
|
222
|
+
}
|
|
223
|
+
export interface InspectorSeparatorProps extends ComponentProps<'div'> {
|
|
224
|
+
}
|
|
225
|
+
/** A hairline between sections that belong to different things. */
|
|
226
|
+
declare function InspectorSeparator({ className, ...props }: InspectorSeparatorProps): import("react").JSX.Element;
|
|
227
|
+
declare namespace InspectorSeparator {
|
|
228
|
+
var displayName: string;
|
|
229
|
+
}
|
|
230
|
+
export declare const Inspector: typeof InspectorRoot & {
|
|
231
|
+
Rail: typeof InspectorRail;
|
|
232
|
+
Tab: typeof InspectorTab;
|
|
233
|
+
RailSeparator: typeof InspectorRailSeparator;
|
|
234
|
+
Panel: typeof InspectorPanel;
|
|
235
|
+
Page: typeof InspectorPage;
|
|
236
|
+
Section: typeof InspectorSection;
|
|
237
|
+
SectionTitle: typeof InspectorSectionTitle;
|
|
238
|
+
SectionAction: typeof InspectorSectionAction;
|
|
239
|
+
SectionContent: typeof InspectorSectionContent;
|
|
240
|
+
Separator: typeof InspectorSeparator;
|
|
241
|
+
};
|
|
242
|
+
export { InspectorRail, InspectorTab, InspectorRailSeparator, InspectorPanel, InspectorPage, InspectorSection, InspectorSectionTitle, InspectorSectionAction, InspectorSectionContent, InspectorSeparator, inspectorVariants, };
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* Inspector — the settings panel beside an editor's canvas: a rail of
|
|
5
|
+
* icons, each opening a page of titled sections.
|
|
6
|
+
*
|
|
7
|
+
* ```tsx
|
|
8
|
+
* <Inspector defaultValue="pointer">
|
|
9
|
+
* <Inspector.Rail>
|
|
10
|
+
* <Inspector.Tab value="pointer" label="Pointer"><MousePointer2Icon /></Inspector.Tab>
|
|
11
|
+
* <Inspector.Tab value="audio" label="Audio"><Volume2Icon /></Inspector.Tab>
|
|
12
|
+
* </Inspector.Rail>
|
|
13
|
+
* <Inspector.Panel>
|
|
14
|
+
* <Inspector.Page value="pointer">
|
|
15
|
+
* <Inspector.Section>
|
|
16
|
+
* <Inspector.SectionTitle>Click sound</Inspector.SectionTitle>
|
|
17
|
+
* <Inspector.SectionAction><Switch label="Click sound" /></Inspector.SectionAction>
|
|
18
|
+
* <Inspector.SectionContent>…</Inspector.SectionContent>
|
|
19
|
+
* </Inspector.Section>
|
|
20
|
+
* </Inspector.Page>
|
|
21
|
+
* </Inspector.Panel>
|
|
22
|
+
* </Inspector>
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* ## The rail stands apart
|
|
26
|
+
*
|
|
27
|
+
* The rail is a pill of its own beside the panel, not a strip inside it.
|
|
28
|
+
* It is navigation, and the panel is the thing being navigated; drawn
|
|
29
|
+
* apart, the eye knows which of the two it is looking at. A filled marker
|
|
30
|
+
* slides along the rail to the chosen page, and the page arrives from the
|
|
31
|
+
* direction the marker went.
|
|
32
|
+
*
|
|
33
|
+
* ## Sections carry their own switch
|
|
34
|
+
*
|
|
35
|
+
* A section's title sits on one line with its action: the switch that turns
|
|
36
|
+
* the whole section on, or a Reset that puts its values back. The controls
|
|
37
|
+
* under it are what that switch or reset applies to, so the relation never
|
|
38
|
+
* has to be explained. A section can fold away with `collapsible`.
|
|
39
|
+
*/
|
|
40
|
+
import { Collapsible } from '@base-ui/react/collapsible';
|
|
41
|
+
import { ScrollArea } from '@base-ui/react/scroll-area';
|
|
42
|
+
import { Tabs } from '@base-ui/react/tabs';
|
|
43
|
+
import { Tooltip } from '@base-ui/react/tooltip';
|
|
44
|
+
import { createContext, useContext } from 'react';
|
|
45
|
+
import { tv } from 'tailwind-variants';
|
|
46
|
+
const EASE = 'ease-[cubic-bezier(0.3,1.2,0.4,1)]';
|
|
47
|
+
const inspectorVariants = tv({
|
|
48
|
+
slots: {
|
|
49
|
+
root: 'group/inspector flex items-start gap-2 data-[orientation=vertical]:flex-row',
|
|
50
|
+
rail: [
|
|
51
|
+
'relative isolate flex shrink-0 flex-col items-center gap-1 rounded-[20px] bg-popover p-1.5 text-popover-foreground',
|
|
52
|
+
'shadow-[0_10px_30px_-12px_rgb(0_0_0/0.3)] ring-1 ring-foreground/[0.06] dark:ring-foreground/10',
|
|
53
|
+
],
|
|
54
|
+
marker: [
|
|
55
|
+
'absolute -z-10 rounded-[14px] bg-primary shadow-[0_1px_2px_rgb(0_0_0/0.18),inset_0_1px_0_rgb(255_255_255/0.18)]',
|
|
56
|
+
'top-(--active-tab-top) left-(--active-tab-left) h-(--active-tab-height) w-(--active-tab-width)',
|
|
57
|
+
`transition-[top,height] duration-[380ms] ${EASE} motion-reduce:transition-none`,
|
|
58
|
+
],
|
|
59
|
+
tab: [
|
|
60
|
+
'relative z-10 inline-flex size-10 shrink-0 cursor-pointer items-center justify-center rounded-[14px] outline-none select-none',
|
|
61
|
+
'text-muted-foreground transition-[color,background-color,scale] duration-150',
|
|
62
|
+
'hover:bg-foreground/[0.06] hover:text-foreground active:scale-[0.94]',
|
|
63
|
+
'data-active:bg-transparent data-active:text-primary-foreground data-active:hover:bg-transparent',
|
|
64
|
+
'focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset',
|
|
65
|
+
'data-disabled:pointer-events-none data-disabled:opacity-40',
|
|
66
|
+
'[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*=size-])]:size-[1.125rem]',
|
|
67
|
+
],
|
|
68
|
+
railSeparator: 'my-1 h-px w-5 shrink-0 rounded-full bg-foreground/15',
|
|
69
|
+
tooltip: [
|
|
70
|
+
'origin-(--transform-origin) rounded-lg bg-foreground px-2 py-1 text-xs font-medium text-background shadow-md',
|
|
71
|
+
'transition-[opacity,scale] duration-150 data-starting-style:scale-95 data-starting-style:opacity-0 data-ending-style:opacity-0',
|
|
72
|
+
'data-instant:duration-0 motion-reduce:transition-none',
|
|
73
|
+
],
|
|
74
|
+
panel: [
|
|
75
|
+
'relative flex w-72 min-w-0 flex-col overflow-hidden rounded-[22px] bg-popover text-popover-foreground',
|
|
76
|
+
'shadow-[0_10px_30px_-12px_rgb(0_0_0/0.3)] ring-1 ring-foreground/[0.06] dark:ring-foreground/10',
|
|
77
|
+
],
|
|
78
|
+
page: [
|
|
79
|
+
'flex min-h-0 flex-1 flex-col outline-none',
|
|
80
|
+
`transition-[opacity,translate] duration-300 ${EASE} motion-reduce:transition-none`,
|
|
81
|
+
'data-starting-style:opacity-0',
|
|
82
|
+
'data-[activation-direction=down]:data-starting-style:translate-y-3 data-[activation-direction=up]:data-starting-style:-translate-y-3',
|
|
83
|
+
'data-ending-style:hidden',
|
|
84
|
+
],
|
|
85
|
+
viewport: 'min-h-0 flex-1 overscroll-contain outline-none',
|
|
86
|
+
content: 'flex flex-col gap-1 p-3.5',
|
|
87
|
+
scrollbar: 'my-3 me-1 flex w-1.5 opacity-0 transition-opacity delay-300 data-hovering:opacity-100 data-hovering:delay-0 data-scrolling:opacity-100 data-scrolling:delay-0',
|
|
88
|
+
thumb: 'relative flex-1 rounded-full bg-foreground/20',
|
|
89
|
+
section: 'grid grid-cols-[minmax(0,1fr)_auto] items-center gap-x-3 py-1.5',
|
|
90
|
+
sectionTitle: [
|
|
91
|
+
'col-start-1 row-start-1 flex min-h-8 items-center text-left text-[13px] font-medium text-foreground',
|
|
92
|
+
// A section that folds: its title is the button, with a chevron that turns.
|
|
93
|
+
'data-[slot=inspector-section-trigger]:-mx-1.5 data-[slot=inspector-section-trigger]:cursor-pointer data-[slot=inspector-section-trigger]:gap-1.5 data-[slot=inspector-section-trigger]:rounded-lg data-[slot=inspector-section-trigger]:px-1.5',
|
|
94
|
+
'data-[slot=inspector-section-trigger]:outline-none data-[slot=inspector-section-trigger]:hover:bg-foreground/[0.04] data-[slot=inspector-section-trigger]:focus-visible:ring-2 data-[slot=inspector-section-trigger]:focus-visible:ring-ring',
|
|
95
|
+
],
|
|
96
|
+
// Right after the title: up while the section is open, down while it is folded.
|
|
97
|
+
chevron: [
|
|
98
|
+
'size-3.5 shrink-0 rotate-180 text-muted-foreground transition-transform duration-200',
|
|
99
|
+
'in-data-panel-open:rotate-0 motion-reduce:transition-none',
|
|
100
|
+
],
|
|
101
|
+
sectionAction: 'col-start-2 row-start-1 flex items-center gap-1.5',
|
|
102
|
+
sectionContent: [
|
|
103
|
+
'col-span-2 flex flex-col gap-2 pt-2',
|
|
104
|
+
// Folding: the height follows the content, from and to nothing.
|
|
105
|
+
'data-[slot=inspector-section-panel]:h-(--collapsible-panel-height) data-[slot=inspector-section-panel]:overflow-hidden',
|
|
106
|
+
'data-[slot=inspector-section-panel]:transition-[height,opacity] data-[slot=inspector-section-panel]:duration-300',
|
|
107
|
+
'data-[slot=inspector-section-panel]:ease-[cubic-bezier(0.3,1.2,0.4,1)]',
|
|
108
|
+
'data-starting-style:h-0 data-starting-style:opacity-0 data-ending-style:h-0 data-ending-style:opacity-0 motion-reduce:transition-none',
|
|
109
|
+
],
|
|
110
|
+
separator: 'my-2 h-px shrink-0 bg-foreground/[0.08]',
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
const SectionContext = createContext(null);
|
|
114
|
+
/**
|
|
115
|
+
* The rail and the panel side by side. `defaultValue`, or `value` with
|
|
116
|
+
* `onValueChange`, names the page that is open.
|
|
117
|
+
*/
|
|
118
|
+
function InspectorRoot({ className, ...props }) {
|
|
119
|
+
const slots = inspectorVariants();
|
|
120
|
+
return (_jsx(Tooltip.Provider, { delay: 500, closeDelay: 0, children: _jsx(Tabs.Root, { "data-slot": "inspector", orientation: "vertical", className: slots.root({ className }), ...props }) }));
|
|
121
|
+
}
|
|
122
|
+
InspectorRoot.displayName = 'Inspector';
|
|
123
|
+
/** The column of page icons, in a pill of its own beside the panel. */
|
|
124
|
+
function InspectorRail({ className, children, ...props }) {
|
|
125
|
+
const slots = inspectorVariants();
|
|
126
|
+
return (_jsxs(Tabs.List, { "data-slot": "inspector-rail", className: slots.rail({ className }), ...props, children: [children, _jsx(Tabs.Indicator, { "data-slot": "inspector-marker", className: slots.marker(), renderBeforeHydration: true })] }));
|
|
127
|
+
}
|
|
128
|
+
InspectorRail.displayName = 'Inspector.Rail';
|
|
129
|
+
/** One page's icon on the rail. */
|
|
130
|
+
function InspectorTab({ label, className, children, ...props }) {
|
|
131
|
+
const slots = inspectorVariants();
|
|
132
|
+
return (_jsxs(Tooltip.Root, { children: [_jsx(Tooltip.Trigger, { render: _jsx(Tabs.Tab, { "data-slot": "inspector-tab", "aria-label": label, className: slots.tab({ className }), ...props, children: children }) }), _jsx(Tooltip.Portal, { children: _jsx(Tooltip.Positioner, { side: "left", sideOffset: 10, className: "z-50", children: _jsx(Tooltip.Popup, { className: slots.tooltip(), children: label }) }) })] }));
|
|
133
|
+
}
|
|
134
|
+
InspectorTab.displayName = 'Inspector.Tab';
|
|
135
|
+
/** A short line between groups of pages on the rail. */
|
|
136
|
+
function InspectorRailSeparator({ className, ...props }) {
|
|
137
|
+
const slots = inspectorVariants();
|
|
138
|
+
return _jsx("span", { "aria-hidden": true, "data-slot": "inspector-rail-separator", className: slots.railSeparator({ className }), ...props });
|
|
139
|
+
}
|
|
140
|
+
InspectorRailSeparator.displayName = 'Inspector.RailSeparator';
|
|
141
|
+
/**
|
|
142
|
+
* The card the pages open in. Give it a height, such as `h-[32rem]`, and a
|
|
143
|
+
* page longer than that scrolls inside it. Without pages, its children are
|
|
144
|
+
* one page of sections.
|
|
145
|
+
*/
|
|
146
|
+
function InspectorPanel({ className, children, ...props }) {
|
|
147
|
+
const slots = inspectorVariants();
|
|
148
|
+
return (_jsx("div", { "data-slot": "inspector-panel", className: slots.panel({ className }), ...props, children: hasPages(children) ? children : _jsx(Scroll, { children: children }) }));
|
|
149
|
+
}
|
|
150
|
+
InspectorPanel.displayName = 'Inspector.Panel';
|
|
151
|
+
/** Whether the panel's children are pages, rather than sections written straight into it. */
|
|
152
|
+
function hasPages(children) {
|
|
153
|
+
const list = Array.isArray(children) ? children : [children];
|
|
154
|
+
return list.some((child) => typeof child === 'object' &&
|
|
155
|
+
child !== null &&
|
|
156
|
+
'type' in child &&
|
|
157
|
+
child.type === InspectorPage);
|
|
158
|
+
}
|
|
159
|
+
/** The scrolling column of a page, with a thin bar that shows while it moves. */
|
|
160
|
+
function Scroll({ children }) {
|
|
161
|
+
const slots = inspectorVariants();
|
|
162
|
+
return (_jsxs(ScrollArea.Root, { className: "relative flex min-h-0 flex-1 flex-col", children: [_jsx(ScrollArea.Viewport, { className: slots.viewport(), children: _jsx(ScrollArea.Content, { className: slots.content(), children: children }) }), _jsx(ScrollArea.Scrollbar, { orientation: "vertical", className: slots.scrollbar(), children: _jsx(ScrollArea.Thumb, { className: slots.thumb() }) })] }));
|
|
163
|
+
}
|
|
164
|
+
/** What one tab opens: a column of sections that scrolls inside the panel. */
|
|
165
|
+
function InspectorPage({ className, children, ...props }) {
|
|
166
|
+
const slots = inspectorVariants();
|
|
167
|
+
return (_jsx(Tabs.Panel, { "data-slot": "inspector-page", className: slots.page({ className }), ...props, children: _jsx(Scroll, { children: children }) }));
|
|
168
|
+
}
|
|
169
|
+
InspectorPage.displayName = 'Inspector.Page';
|
|
170
|
+
/** A titled group of settings: a title, an action on its line, and the controls under them. */
|
|
171
|
+
function InspectorSection({ collapsible = false, defaultOpen = true, open, onOpenChange, className, children, ...props }) {
|
|
172
|
+
const slots = inspectorVariants();
|
|
173
|
+
if (!collapsible) {
|
|
174
|
+
return (_jsx(SectionContext.Provider, { value: { collapsible: false }, children: _jsx("div", { "data-slot": "inspector-section", className: slots.section({ className }), ...props, children: children }) }));
|
|
175
|
+
}
|
|
176
|
+
return (_jsx(SectionContext.Provider, { value: { collapsible: true }, children: _jsx(Collapsible.Root, { "data-slot": "inspector-section", defaultOpen: defaultOpen, open: open, onOpenChange: onOpenChange ? (next) => onOpenChange(next) : undefined, className: slots.section({ className }), ...props, children: children }) }));
|
|
177
|
+
}
|
|
178
|
+
InspectorSection.displayName = 'Inspector.Section';
|
|
179
|
+
function useSection(part) {
|
|
180
|
+
const section = useContext(SectionContext);
|
|
181
|
+
if (!section)
|
|
182
|
+
throw new Error(`${part} must be used inside an <Inspector.Section>.`);
|
|
183
|
+
return section;
|
|
184
|
+
}
|
|
185
|
+
/** The section's name. In a collapsible section it is the button that folds it, with a chevron. */
|
|
186
|
+
function InspectorSectionTitle({ className, children, ...props }) {
|
|
187
|
+
const { collapsible } = useSection('Inspector.SectionTitle');
|
|
188
|
+
const slots = inspectorVariants();
|
|
189
|
+
if (!collapsible) {
|
|
190
|
+
return (_jsx("h3", { "data-slot": "inspector-section-title", className: slots.sectionTitle({ className }), ...props, children: children }));
|
|
191
|
+
}
|
|
192
|
+
return (_jsx("h3", { className: "col-start-1 row-start-1 m-0", children: _jsxs(Collapsible.Trigger, { "data-slot": "inspector-section-trigger", className: slots.sectionTitle({ className: ['w-full', className] }), children: [children, _jsx("svg", { viewBox: "0 0 16 16", "aria-hidden": true, className: slots.chevron(), fill: "none", stroke: "currentColor", strokeWidth: 1.8, strokeLinecap: "round", strokeLinejoin: "round", children: _jsx("path", { d: "m4 10 4-4 4 4" }) })] }) }));
|
|
193
|
+
}
|
|
194
|
+
InspectorSectionTitle.displayName = 'Inspector.SectionTitle';
|
|
195
|
+
/** What sits at the end of the title's line: the switch for the whole section, or a Reset. */
|
|
196
|
+
function InspectorSectionAction({ className, ...props }) {
|
|
197
|
+
useSection('Inspector.SectionAction');
|
|
198
|
+
const slots = inspectorVariants();
|
|
199
|
+
return _jsx("div", { "data-slot": "inspector-section-action", className: slots.sectionAction({ className }), ...props });
|
|
200
|
+
}
|
|
201
|
+
InspectorSectionAction.displayName = 'Inspector.SectionAction';
|
|
202
|
+
/** The controls under the title, stacked with an even gap. */
|
|
203
|
+
function InspectorSectionContent({ className, children, ...props }) {
|
|
204
|
+
const { collapsible } = useSection('Inspector.SectionContent');
|
|
205
|
+
const slots = inspectorVariants();
|
|
206
|
+
if (!collapsible) {
|
|
207
|
+
return (_jsx("div", { "data-slot": "inspector-section-content", className: slots.sectionContent({ className }), ...props, children: children }));
|
|
208
|
+
}
|
|
209
|
+
return (_jsx(Collapsible.Panel, { "data-slot": "inspector-section-panel", className: slots.sectionContent({ className }), style: props.style, children: children }));
|
|
210
|
+
}
|
|
211
|
+
InspectorSectionContent.displayName = 'Inspector.SectionContent';
|
|
212
|
+
/** A hairline between sections that belong to different things. */
|
|
213
|
+
function InspectorSeparator({ className, ...props }) {
|
|
214
|
+
const slots = inspectorVariants();
|
|
215
|
+
return _jsx("div", { role: "separator", "data-slot": "inspector-separator", className: slots.separator({ className }), ...props });
|
|
216
|
+
}
|
|
217
|
+
InspectorSeparator.displayName = 'Inspector.Separator';
|
|
218
|
+
export const Inspector = Object.assign(InspectorRoot, {
|
|
219
|
+
Rail: InspectorRail,
|
|
220
|
+
Tab: InspectorTab,
|
|
221
|
+
RailSeparator: InspectorRailSeparator,
|
|
222
|
+
Panel: InspectorPanel,
|
|
223
|
+
Page: InspectorPage,
|
|
224
|
+
Section: InspectorSection,
|
|
225
|
+
SectionTitle: InspectorSectionTitle,
|
|
226
|
+
SectionAction: InspectorSectionAction,
|
|
227
|
+
SectionContent: InspectorSectionContent,
|
|
228
|
+
Separator: InspectorSeparator,
|
|
229
|
+
});
|
|
230
|
+
export { InspectorRail, InspectorTab, InspectorRailSeparator, InspectorPanel, InspectorPage, InspectorSection, InspectorSectionTitle, InspectorSectionAction, InspectorSectionContent, InspectorSeparator, inspectorVariants, };
|
|
@@ -84,9 +84,16 @@ export interface SheetContentProps extends Omit<ComponentProps<'div'>, 'children
|
|
|
84
84
|
* `full` take that share of the screen, and `full` meets the edges.
|
|
85
85
|
*/
|
|
86
86
|
size?: 'auto' | 'half' | 'full';
|
|
87
|
-
/**
|
|
87
|
+
/**
|
|
88
|
+
* Show the grabber. On by default for a top or bottom sheet that a swipe
|
|
89
|
+
* can close, and off when `dismissible` is.
|
|
90
|
+
*/
|
|
88
91
|
showGrabber?: boolean;
|
|
89
|
-
/**
|
|
92
|
+
/**
|
|
93
|
+
* Show the round close button in the top trailing corner. Default true.
|
|
94
|
+
* Write a bare `<Sheet.Close />` into the sheet to place it somewhere else,
|
|
95
|
+
* or set this to `false` for a sheet with no close button at all.
|
|
96
|
+
*/
|
|
90
97
|
showClose?: boolean;
|
|
91
98
|
/** Frost the page behind the sheet instead of only dimming it. */
|
|
92
99
|
blur?: boolean;
|
|
@@ -150,13 +157,17 @@ declare namespace SheetFooter {
|
|
|
150
157
|
export interface SheetCloseProps extends ComponentProps<'button'> {
|
|
151
158
|
/**
|
|
152
159
|
* Your own element to close the sheet with, such as a Cancel button.
|
|
153
|
-
* Without it, and without children, this is the round close button
|
|
160
|
+
* Without it, and without children, this is the round close button, drawn
|
|
161
|
+
* where it is written in place of the one in the corner.
|
|
154
162
|
*/
|
|
155
163
|
render?: ReactElement;
|
|
156
|
-
/** Draw the
|
|
164
|
+
/** Draw the round close button. A `Sheet.Close` with nothing inside it already is one. */
|
|
157
165
|
icon?: boolean;
|
|
158
166
|
}
|
|
159
|
-
/**
|
|
167
|
+
/**
|
|
168
|
+
* Closes the sheet. Works even when `dismissible` is off. Written bare, it is
|
|
169
|
+
* the round close button, and the sheet stops drawing its own in the corner.
|
|
170
|
+
*/
|
|
160
171
|
declare function SheetClose({ render, icon, children, ...props }: SheetCloseProps): import("react").JSX.Element;
|
|
161
172
|
declare namespace SheetClose {
|
|
162
173
|
var displayName: string;
|