@claralight-design/react 0.0.1
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/index.d.ts +12 -0
- package/dist/index.js +12 -0
- package/dist/lib/anchored.d.ts +152 -0
- package/dist/lib/anchored.js +821 -0
- package/dist/lib/anchored.js.map +1 -0
- package/dist/lib/morph.js +484 -0
- package/dist/lib/morph.js.map +1 -0
- package/dist/lib/squircle.d.ts +95 -0
- package/dist/lib/squircle.js +220 -0
- package/dist/lib/squircle.js.map +1 -0
- package/dist/lib/utils.d.ts +30 -0
- package/dist/lib/utils.js +76 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/ui/button.d.ts +40 -0
- package/dist/ui/button.js +104 -0
- package/dist/ui/button.js.map +1 -0
- package/dist/ui/card.d.ts +54 -0
- package/dist/ui/card.js +82 -0
- package/dist/ui/card.js.map +1 -0
- package/dist/ui/dialog.d.ts +82 -0
- package/dist/ui/dialog.js +129 -0
- package/dist/ui/dialog.js.map +1 -0
- package/dist/ui/input.d.ts +34 -0
- package/dist/ui/input.js +60 -0
- package/dist/ui/input.js.map +1 -0
- package/dist/ui/popover.d.ts +67 -0
- package/dist/ui/popover.js +93 -0
- package/dist/ui/popover.js.map +1 -0
- package/dist/ui/scroll-area.d.ts +110 -0
- package/dist/ui/scroll-area.js +125 -0
- package/dist/ui/scroll-area.js.map +1 -0
- package/dist/ui/select.d.ts +113 -0
- package/dist/ui/select.js +213 -0
- package/dist/ui/select.js.map +1 -0
- package/dist/ui/tooltip.d.ts +108 -0
- package/dist/ui/tooltip.js +142 -0
- package/dist/ui/tooltip.js.map +1 -0
- package/package.json +72 -0
- package/styles/anchored.css +115 -0
- package/styles/base.css +309 -0
- package/styles/fonts/README.md +63 -0
- package/styles/index.css +28 -0
- package/styles/scroll-area.css +299 -0
- package/styles/theme.css +540 -0
- package/styles/tooltip.css +156 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { AnchoredSide } from "../lib/anchored.js";
|
|
2
|
+
import { ComponentProps, ReactNode } from "react";
|
|
3
|
+
import { Popover } from "@base-ui/react/popover";
|
|
4
|
+
//#region src/ui/popover.d.ts
|
|
5
|
+
declare const Popover$1: typeof Popover.Root;
|
|
6
|
+
/** Re-exported unstyled, for building something other than the default content. */
|
|
7
|
+
export declare const PopoverPortal: typeof Popover.Portal;
|
|
8
|
+
export declare const PopoverPositioner: typeof Popover.Positioner;
|
|
9
|
+
export declare const PopoverPopup: typeof Popover.Popup;
|
|
10
|
+
export declare const PopoverArrow: typeof Popover.Arrow;
|
|
11
|
+
export declare const PopoverBackdrop: typeof Popover.Backdrop;
|
|
12
|
+
export type PopoverTriggerProps = Omit<ComponentProps<typeof Popover.Trigger>, "className"> & {
|
|
13
|
+
className?: string;
|
|
14
|
+
};
|
|
15
|
+
export declare function PopoverTrigger({ className, ...props }: PopoverTriggerProps): import("react").JSX.Element;
|
|
16
|
+
export type PopoverContentProps = Omit<ComponentProps<typeof Popover.Popup>, "className"> & {
|
|
17
|
+
/** Applied to the clipped element: the frost, padding and text. */
|
|
18
|
+
className?: string;
|
|
19
|
+
/** Applied to the wrapper, which is what is positioned and animated. */
|
|
20
|
+
wrapperClassName?: string;
|
|
21
|
+
/** Preferred side of the trigger. Base UI flips when there is not enough room. */
|
|
22
|
+
side?: AnchoredSide;
|
|
23
|
+
align?: ComponentProps<typeof Popover.Positioner>["align"];
|
|
24
|
+
/** Gap between the trigger and the surface, in px. Measured from the arrow's tip. */
|
|
25
|
+
sideOffset?: number;
|
|
26
|
+
/** Space kept clear of the viewport edge, in px. */
|
|
27
|
+
collisionPadding?: number;
|
|
28
|
+
/** Whether the surface points at its trigger. */
|
|
29
|
+
arrow?: boolean;
|
|
30
|
+
children?: ReactNode;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Portal, positioner and the pointing frosted surface, in the composition
|
|
34
|
+
* everyone actually wants.
|
|
35
|
+
*
|
|
36
|
+
* `top` is the default side because that is ClaraLight's, not Base UI's — a
|
|
37
|
+
* popover belongs above the control that opened it, so the control stays
|
|
38
|
+
* visible under the reader's hand on touch.
|
|
39
|
+
*
|
|
40
|
+
* The arrow is part of the surface rather than an element beside it, so the
|
|
41
|
+
* `Arrow` rendered here paints nothing: Floating UI solves and clamps its
|
|
42
|
+
* position, and `AnchoredSurface` reads that back to splice the tail into the
|
|
43
|
+
* surface's own path. See `src/lib/anchored.tsx`.
|
|
44
|
+
*
|
|
45
|
+
* The entrance grows the surface out of its own tail rather than from Base UI's
|
|
46
|
+
* `--transform-origin`, which is the anchor's edge and therefore sits in the
|
|
47
|
+
* gap *outside* the surface. `AnchoredSurface` sets the origin from the tail it
|
|
48
|
+
* measured, and carries `.cl-anchored-root`, whose scale starts at zero instead
|
|
49
|
+
* of at a dialog's 95% nudge. `sticky` keeps the surface on screen once its
|
|
50
|
+
* trigger has been scrolled out of view, instead of letting it leave with it.
|
|
51
|
+
*/
|
|
52
|
+
export declare function PopoverContent({ className, wrapperClassName, side, align, sideOffset, collisionPadding, arrow, children, ...props }: PopoverContentProps): import("react").JSX.Element;
|
|
53
|
+
export type PopoverTitleProps = Omit<ComponentProps<typeof Popover.Title>, "className"> & {
|
|
54
|
+
className?: string;
|
|
55
|
+
};
|
|
56
|
+
export declare function PopoverTitle({ className, ...props }: PopoverTitleProps): import("react").JSX.Element;
|
|
57
|
+
export type PopoverDescriptionProps = Omit<ComponentProps<typeof Popover.Description>, "className"> & {
|
|
58
|
+
className?: string;
|
|
59
|
+
};
|
|
60
|
+
export declare function PopoverDescription({ className, ...props }: PopoverDescriptionProps): import("react").JSX.Element;
|
|
61
|
+
export type PopoverCloseProps = Omit<ComponentProps<typeof Popover.Close>, "className"> & {
|
|
62
|
+
className?: string;
|
|
63
|
+
};
|
|
64
|
+
export declare function PopoverClose({ className, ...props }: PopoverCloseProps): import("react").JSX.Element;
|
|
65
|
+
//#endregion
|
|
66
|
+
export { Popover$1 as Popover };
|
|
67
|
+
//# sourceMappingURL=popover.d.ts.map
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../lib/utils.js";
|
|
3
|
+
import { AnchoredSurface, themedNumber, useThemedNumber } from "../lib/anchored.js";
|
|
4
|
+
import { useRef } from "react";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import { Popover } from "@base-ui/react/popover";
|
|
7
|
+
//#region src/ui/popover.tsx
|
|
8
|
+
const Popover$1 = Popover.Root;
|
|
9
|
+
/** Re-exported unstyled, for building something other than the default content. */
|
|
10
|
+
const PopoverPortal = Popover.Portal;
|
|
11
|
+
const PopoverPositioner = Popover.Positioner;
|
|
12
|
+
const PopoverPopup = Popover.Popup;
|
|
13
|
+
const PopoverArrow = Popover.Arrow;
|
|
14
|
+
const PopoverBackdrop = Popover.Backdrop;
|
|
15
|
+
function PopoverTrigger({ className, ...props }) {
|
|
16
|
+
return /* @__PURE__ */ jsx(Popover.Trigger, {
|
|
17
|
+
className,
|
|
18
|
+
...props
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Portal, positioner and the pointing frosted surface, in the composition
|
|
23
|
+
* everyone actually wants.
|
|
24
|
+
*
|
|
25
|
+
* `top` is the default side because that is ClaraLight's, not Base UI's — a
|
|
26
|
+
* popover belongs above the control that opened it, so the control stays
|
|
27
|
+
* visible under the reader's hand on touch.
|
|
28
|
+
*
|
|
29
|
+
* The arrow is part of the surface rather than an element beside it, so the
|
|
30
|
+
* `Arrow` rendered here paints nothing: Floating UI solves and clamps its
|
|
31
|
+
* position, and `AnchoredSurface` reads that back to splice the tail into the
|
|
32
|
+
* surface's own path. See `src/lib/anchored.tsx`.
|
|
33
|
+
*
|
|
34
|
+
* The entrance grows the surface out of its own tail rather than from Base UI's
|
|
35
|
+
* `--transform-origin`, which is the anchor's edge and therefore sits in the
|
|
36
|
+
* gap *outside* the surface. `AnchoredSurface` sets the origin from the tail it
|
|
37
|
+
* measured, and carries `.cl-anchored-root`, whose scale starts at zero instead
|
|
38
|
+
* of at a dialog's 95% nudge. `sticky` keeps the surface on screen once its
|
|
39
|
+
* trigger has been scrolled out of view, instead of letting it leave with it.
|
|
40
|
+
*/
|
|
41
|
+
function PopoverContent({ className, wrapperClassName, side = "top", align = "center", sideOffset, collisionPadding, arrow = true, children, ...props }) {
|
|
42
|
+
const positionerRef = useRef(null);
|
|
43
|
+
const margin = useThemedNumber(positionerRef, "--cl-anchor-margin");
|
|
44
|
+
return /* @__PURE__ */ jsx(Popover.Portal, { children: /* @__PURE__ */ jsx(Popover.Positioner, {
|
|
45
|
+
ref: positionerRef,
|
|
46
|
+
side,
|
|
47
|
+
align,
|
|
48
|
+
sideOffset: sideOffset ?? (() => themedNumber(positionerRef.current, "--cl-anchor-gap") ?? 0),
|
|
49
|
+
collisionPadding: collisionPadding ?? margin,
|
|
50
|
+
sticky: true,
|
|
51
|
+
className: "z-50 outline-none",
|
|
52
|
+
children: /* @__PURE__ */ jsx(AnchoredSurface, {
|
|
53
|
+
asChild: true,
|
|
54
|
+
radius: "panel",
|
|
55
|
+
side,
|
|
56
|
+
arrow,
|
|
57
|
+
wrapperClassName: cn("w-fit", wrapperClassName),
|
|
58
|
+
children: /* @__PURE__ */ jsxs(Popover.Popup, {
|
|
59
|
+
"data-cl-slot": "popover-content",
|
|
60
|
+
className: cn("cl-exit-sentinel cl-frost shadow-none font-sans text-foreground", "[--cl-anchored-padding-x:var(--cl-popover-padding)]", "[--cl-anchored-padding-y:var(--cl-popover-padding)]", className),
|
|
61
|
+
...props,
|
|
62
|
+
children: [children, arrow ? /* @__PURE__ */ jsx(Popover.Arrow, {
|
|
63
|
+
"data-cl-anchor-probe": "",
|
|
64
|
+
className: "cl-anchor-probe"
|
|
65
|
+
}) : null]
|
|
66
|
+
})
|
|
67
|
+
})
|
|
68
|
+
}) });
|
|
69
|
+
}
|
|
70
|
+
function PopoverTitle({ className, ...props }) {
|
|
71
|
+
return /* @__PURE__ */ jsx(Popover.Title, {
|
|
72
|
+
"data-cl-slot": "popover-title",
|
|
73
|
+
className: cn("text-callout text-foreground", className),
|
|
74
|
+
...props
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
function PopoverDescription({ className, ...props }) {
|
|
78
|
+
return /* @__PURE__ */ jsx(Popover.Description, {
|
|
79
|
+
"data-cl-slot": "popover-description",
|
|
80
|
+
className: cn("text-caption text-foreground-tertiary", className),
|
|
81
|
+
...props
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
function PopoverClose({ className, ...props }) {
|
|
85
|
+
return /* @__PURE__ */ jsx(Popover.Close, {
|
|
86
|
+
className,
|
|
87
|
+
...props
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
//#endregion
|
|
91
|
+
export { Popover$1 as Popover, PopoverArrow, PopoverBackdrop, PopoverClose, PopoverContent, PopoverDescription, PopoverPopup, PopoverPortal, PopoverPositioner, PopoverTitle, PopoverTrigger };
|
|
92
|
+
|
|
93
|
+
//# sourceMappingURL=popover.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"popover.js","names":["Popover","BasePopover"],"sources":["../../src/ui/popover.tsx"],"sourcesContent":["\"use client\";\n\nimport { Popover as BasePopover } from \"@base-ui/react/popover\";\nimport { type ComponentProps, type ReactNode, useRef } from \"react\";\nimport { type AnchoredSide, AnchoredSurface, themedNumber, useThemedNumber } from \"@/lib/anchored\";\nimport { cn } from \"@/lib/utils\";\n\nexport const Popover: typeof BasePopover.Root = BasePopover.Root;\n\n/** Re-exported unstyled, for building something other than the default content. */\nexport const PopoverPortal: typeof BasePopover.Portal = BasePopover.Portal;\nexport const PopoverPositioner: typeof BasePopover.Positioner = BasePopover.Positioner;\nexport const PopoverPopup: typeof BasePopover.Popup = BasePopover.Popup;\nexport const PopoverArrow: typeof BasePopover.Arrow = BasePopover.Arrow;\nexport const PopoverBackdrop: typeof BasePopover.Backdrop = BasePopover.Backdrop;\n\nexport type PopoverTriggerProps = Omit<ComponentProps<typeof BasePopover.Trigger>, \"className\"> & {\n className?: string;\n};\n\nexport function PopoverTrigger({ className, ...props }: PopoverTriggerProps) {\n return <BasePopover.Trigger className={className} {...props} />;\n}\n\nexport type PopoverContentProps = Omit<ComponentProps<typeof BasePopover.Popup>, \"className\"> & {\n /** Applied to the clipped element: the frost, padding and text. */\n className?: string;\n /** Applied to the wrapper, which is what is positioned and animated. */\n wrapperClassName?: string;\n /** Preferred side of the trigger. Base UI flips when there is not enough room. */\n side?: AnchoredSide;\n align?: ComponentProps<typeof BasePopover.Positioner>[\"align\"];\n /** Gap between the trigger and the surface, in px. Measured from the arrow's tip. */\n sideOffset?: number;\n /** Space kept clear of the viewport edge, in px. */\n collisionPadding?: number;\n /** Whether the surface points at its trigger. */\n arrow?: boolean;\n children?: ReactNode;\n};\n\n/**\n * Portal, positioner and the pointing frosted surface, in the composition\n * everyone actually wants.\n *\n * `top` is the default side because that is ClaraLight's, not Base UI's — a\n * popover belongs above the control that opened it, so the control stays\n * visible under the reader's hand on touch.\n *\n * The arrow is part of the surface rather than an element beside it, so the\n * `Arrow` rendered here paints nothing: Floating UI solves and clamps its\n * position, and `AnchoredSurface` reads that back to splice the tail into the\n * surface's own path. See `src/lib/anchored.tsx`.\n *\n * The entrance grows the surface out of its own tail rather than from Base UI's\n * `--transform-origin`, which is the anchor's edge and therefore sits in the\n * gap *outside* the surface. `AnchoredSurface` sets the origin from the tail it\n * measured, and carries `.cl-anchored-root`, whose scale starts at zero instead\n * of at a dialog's 95% nudge. `sticky` keeps the surface on screen once its\n * trigger has been scrolled out of view, instead of letting it leave with it.\n */\nexport function PopoverContent({\n className,\n wrapperClassName,\n side = \"top\",\n align = \"center\",\n sideOffset,\n collisionPadding,\n arrow = true,\n children,\n ...props\n}: PopoverContentProps) {\n const positionerRef = useRef<HTMLDivElement>(null);\n const margin = useThemedNumber(positionerRef, \"--cl-anchor-margin\");\n\n return (\n <BasePopover.Portal>\n <BasePopover.Positioner\n ref={positionerRef}\n side={side}\n align={align}\n sideOffset={\n sideOffset ?? (() => themedNumber(positionerRef.current, \"--cl-anchor-gap\") ?? 0)\n }\n collisionPadding={collisionPadding ?? margin}\n sticky\n className=\"z-50 outline-none\"\n >\n <AnchoredSurface\n asChild\n radius=\"panel\"\n side={side}\n arrow={arrow}\n wrapperClassName={cn(\"w-fit\", wrapperClassName)}\n >\n <BasePopover.Popup\n data-cl-slot=\"popover-content\"\n className={cn(\n \"cl-exit-sentinel cl-frost shadow-none font-sans text-foreground\",\n \"[--cl-anchored-padding-x:var(--cl-popover-padding)]\",\n \"[--cl-anchored-padding-y:var(--cl-popover-padding)]\",\n className,\n )}\n {...props}\n >\n {children}\n {arrow ? (\n <BasePopover.Arrow data-cl-anchor-probe=\"\" className=\"cl-anchor-probe\" />\n ) : null}\n </BasePopover.Popup>\n </AnchoredSurface>\n </BasePopover.Positioner>\n </BasePopover.Portal>\n );\n}\n\nexport type PopoverTitleProps = Omit<ComponentProps<typeof BasePopover.Title>, \"className\"> & {\n className?: string;\n};\n\nexport function PopoverTitle({ className, ...props }: PopoverTitleProps) {\n return (\n <BasePopover.Title\n data-cl-slot=\"popover-title\"\n className={cn(\"text-callout text-foreground\", className)}\n {...props}\n />\n );\n}\n\nexport type PopoverDescriptionProps = Omit<\n ComponentProps<typeof BasePopover.Description>,\n \"className\"\n> & { className?: string };\n\nexport function PopoverDescription({ className, ...props }: PopoverDescriptionProps) {\n return (\n <BasePopover.Description\n data-cl-slot=\"popover-description\"\n className={cn(\"text-caption text-foreground-tertiary\", className)}\n {...props}\n />\n );\n}\n\nexport type PopoverCloseProps = Omit<ComponentProps<typeof BasePopover.Close>, \"className\"> & {\n className?: string;\n};\n\nexport function PopoverClose({ className, ...props }: PopoverCloseProps) {\n return <BasePopover.Close className={className} {...props} />;\n}\n"],"mappings":";;;;;;;AAOA,MAAaA,YAAmCC,QAAY;;AAG5D,MAAa,gBAA2CA,QAAY;AACpE,MAAa,oBAAmDA,QAAY;AAC5E,MAAa,eAAyCA,QAAY;AAClE,MAAa,eAAyCA,QAAY;AAClE,MAAa,kBAA+CA,QAAY;AAMxE,SAAgB,eAAe,EAAE,WAAW,GAAG,SAA8B;CAC3E,OAAO,oBAACA,QAAY,SAAb;EAAgC;EAAW,GAAI;CAAQ,CAAA;AAChE;;;;;;;;;;;;;;;;;;;;;AAuCA,SAAgB,eAAe,EAC7B,WACA,kBACA,OAAO,OACP,QAAQ,UACR,YACA,kBACA,QAAQ,MACR,UACA,GAAG,SACmB;CACtB,MAAM,gBAAgB,OAAuB,IAAI;CACjD,MAAM,SAAS,gBAAgB,eAAe,oBAAoB;CAElE,OACE,oBAACA,QAAY,QAAb,EAAA,UACE,oBAACA,QAAY,YAAb;EACE,KAAK;EACC;EACC;EACP,YACE,qBAAqB,aAAa,cAAc,SAAS,iBAAiB,KAAK;EAEjF,kBAAkB,oBAAoB;EACtC,QAAA;EACA,WAAU;EAEV,UAAA,oBAAC,iBAAD;GACE,SAAA;GACA,QAAO;GACD;GACC;GACP,kBAAkB,GAAG,SAAS,gBAAgB;GAE9C,UAAA,qBAACA,QAAY,OAAb;IACE,gBAAa;IACb,WAAW,GACT,mEACA,uDACA,uDACA,SACF;IACA,GAAI;IARN,UAAA,CAUG,UACA,QACC,oBAACA,QAAY,OAAb;KAAmB,wBAAqB;KAAG,WAAU;IAAmB,CAAA,IACtE,IACa;;EACJ,CAAA;CACK,CAAA,EACN,CAAA;AAExB;AAMA,SAAgB,aAAa,EAAE,WAAW,GAAG,SAA4B;CACvE,OACE,oBAACA,QAAY,OAAb;EACE,gBAAa;EACb,WAAW,GAAG,gCAAgC,SAAS;EACvD,GAAI;CACL,CAAA;AAEL;AAOA,SAAgB,mBAAmB,EAAE,WAAW,GAAG,SAAkC;CACnF,OACE,oBAACA,QAAY,aAAb;EACE,gBAAa;EACb,WAAW,GAAG,yCAAyC,SAAS;EAChE,GAAI;CACL,CAAA;AAEL;AAMA,SAAgB,aAAa,EAAE,WAAW,GAAG,SAA4B;CACvE,OAAO,oBAACA,QAAY,OAAb;EAA8B;EAAW,GAAI;CAAQ,CAAA;AAC9D"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { RadiusToken } from "../lib/squircle.js";
|
|
2
|
+
import { ComponentProps, ReactNode, Ref } from "react";
|
|
3
|
+
import { ScrollArea } from "@base-ui/react/scroll-area";
|
|
4
|
+
//#region src/ui/scroll-area.d.ts
|
|
5
|
+
/** Axes the content can move in. */
|
|
6
|
+
export type ScrollAreaOrientation = "vertical" | "horizontal" | "both";
|
|
7
|
+
/** Visibility policy for one scrollbar. */
|
|
8
|
+
export type ScrollbarVisibility = "auto" | "always" | "hidden";
|
|
9
|
+
/**
|
|
10
|
+
* How a side announces that there is more content behind it.
|
|
11
|
+
*
|
|
12
|
+
* `blur` is the full treatment: the content fades out *and* smears into the
|
|
13
|
+
* edge. **It needs an opaque fill** — `bg-panel` or `bg-background`, not
|
|
14
|
+
* `bg-control`, `bg-track` or `cl-frost`. The smooth-corner clip makes the
|
|
15
|
+
* surface its own backdrop root, so the blur can only see the surface's own
|
|
16
|
+
* fill and the scrolled content; over a translucent fill there is barely any
|
|
17
|
+
* colour there to blur and the engine lifts it into a white halo instead. See
|
|
18
|
+
* `scroll-area.css` for the measurements and why nothing else can be done
|
|
19
|
+
* about it.
|
|
20
|
+
*
|
|
21
|
+
* `mask` keeps only the fade. It has none of that coupling — it is a
|
|
22
|
+
* compositor-only effect that works over any fill — and it is the right choice
|
|
23
|
+
* for a translucent surface, or for a scroll area already inside something
|
|
24
|
+
* expensive. `none` leaves the edges hard.
|
|
25
|
+
*/
|
|
26
|
+
export type ScrollAreaEdge = "blur" | "mask" | "none";
|
|
27
|
+
/** Re-exported unstyled, for building something other than the default area. */
|
|
28
|
+
export declare const ScrollAreaRoot: typeof ScrollArea.Root;
|
|
29
|
+
export declare const ScrollAreaViewport: typeof ScrollArea.Viewport;
|
|
30
|
+
export declare const ScrollAreaContent: typeof ScrollArea.Content;
|
|
31
|
+
export declare const ScrollAreaScrollbar: typeof ScrollArea.Scrollbar;
|
|
32
|
+
export declare const ScrollAreaThumb: typeof ScrollArea.Thumb;
|
|
33
|
+
export declare const ScrollAreaCorner: typeof ScrollArea.Corner;
|
|
34
|
+
export interface ScrollAreaProps extends Omit<ComponentProps<typeof ScrollArea.Root>, "className" | "children"> {
|
|
35
|
+
/**
|
|
36
|
+
* Applied to the clipped element: fill, border, and **the area's size**.
|
|
37
|
+
*
|
|
38
|
+
* The size has to be here and it has to be definite. The viewport fills the
|
|
39
|
+
* surface absolutely, so a surface left to size itself to its content has no
|
|
40
|
+
* height at all — `className="h-64"`, not a bare `<ScrollArea>`.
|
|
41
|
+
*/
|
|
42
|
+
className?: string;
|
|
43
|
+
/**
|
|
44
|
+
* Applied to the layout wrapper, which is the element the caller's grid or
|
|
45
|
+
* flex lays out. Placement goes here — `col-span-2`, `flex-1` — and when the
|
|
46
|
+
* placement is what decides the height, pair it with `className="h-full"` so
|
|
47
|
+
* the surface inside still resolves to something definite.
|
|
48
|
+
*/
|
|
49
|
+
wrapperClassName?: string;
|
|
50
|
+
/** Applied to the scrolling element itself. */
|
|
51
|
+
viewportClassName?: string;
|
|
52
|
+
/**
|
|
53
|
+
* Applied to the box that moves. This is where padding belongs: put it on
|
|
54
|
+
* the surface instead and it stays pinned over the scrolling content, with
|
|
55
|
+
* the edge effects fading a gap rather than the content.
|
|
56
|
+
*/
|
|
57
|
+
contentClassName?: string;
|
|
58
|
+
/**
|
|
59
|
+
* Axes the content can move in.
|
|
60
|
+
*
|
|
61
|
+
* `both` matches the Flutter widget and leaves the content unconstrained on
|
|
62
|
+
* each enabled axis, which is why the content box is `max-content` wide
|
|
63
|
+
* whenever the inline axis can scroll: a horizontally scrollable child has to
|
|
64
|
+
* be allowed to exceed the viewport before it has anything to scroll. Lock
|
|
65
|
+
* the axis with `vertical` and the box is pinned to the viewport instead, so
|
|
66
|
+
* the content wraps rather than running off an edge it cannot scroll to.
|
|
67
|
+
*/
|
|
68
|
+
orientation?: ScrollAreaOrientation;
|
|
69
|
+
/** How the sides announce content behind them. */
|
|
70
|
+
edge?: ScrollAreaEdge;
|
|
71
|
+
/** One policy for both bars, or one per axis. */
|
|
72
|
+
scrollbars?: ScrollbarVisibility | {
|
|
73
|
+
x?: ScrollbarVisibility;
|
|
74
|
+
y?: ScrollbarVisibility;
|
|
75
|
+
};
|
|
76
|
+
/** Which `--radius-*` token shapes the corners. */
|
|
77
|
+
radius?: RadiusToken;
|
|
78
|
+
/** Figma's `xi`; see `Squircle`. */
|
|
79
|
+
smoothing?: number;
|
|
80
|
+
/**
|
|
81
|
+
* The scrolling element. This is the web's scroll controller — `scrollTo`,
|
|
82
|
+
* `scrollTop` and `scrollIntoView` on a child all work through it — so there
|
|
83
|
+
* is no separate controller object and no per-axis pairing to keep distinct.
|
|
84
|
+
*/
|
|
85
|
+
viewportRef?: Ref<HTMLDivElement>;
|
|
86
|
+
children?: ReactNode;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* A ClaraLight viewport: content that scrolls, sides that dissolve into the
|
|
90
|
+
* frame as more of it comes into range, and scrollbars that surface while you
|
|
91
|
+
* are using them.
|
|
92
|
+
*
|
|
93
|
+
* Almost nothing here runs in React. Base UI reports the four overflow edges
|
|
94
|
+
* both as booleans and as live pixel distances, and `scroll-area.css` drives
|
|
95
|
+
* the mask straight off the distances — so the fade tracks the scroll position
|
|
96
|
+
* exactly, with no animation, no timer and no re-render between the wheel and
|
|
97
|
+
* the pixels. Scrolling only re-renders when an edge is genuinely crossed.
|
|
98
|
+
*
|
|
99
|
+
* Everything dimensional is a CSS variable rather than a prop, which is how the
|
|
100
|
+
* per-side control the design asks for costs no API surface:
|
|
101
|
+
*
|
|
102
|
+
* <ScrollArea className="[--cl-scroll-edge-block-end:0px]" />
|
|
103
|
+
*
|
|
104
|
+
* turns the bottom edge off, and scoping `--cl-scroll-blur` to one `[data-edge]`
|
|
105
|
+
* gives that side its own sigma.
|
|
106
|
+
*/
|
|
107
|
+
declare function ScrollArea$1({ className, wrapperClassName, viewportClassName, contentClassName, orientation, edge, scrollbars, radius, smoothing, viewportRef, children, ...props }: ScrollAreaProps): import("react").JSX.Element;
|
|
108
|
+
//#endregion
|
|
109
|
+
export { ScrollArea$1 as ScrollArea };
|
|
110
|
+
//# sourceMappingURL=scroll-area.d.ts.map
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../lib/utils.js";
|
|
3
|
+
import { Squircle } from "../lib/squircle.js";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
import { ScrollArea } from "@base-ui/react/scroll-area";
|
|
6
|
+
//#region src/ui/scroll-area.tsx
|
|
7
|
+
/** Re-exported unstyled, for building something other than the default area. */
|
|
8
|
+
const ScrollAreaRoot = ScrollArea.Root;
|
|
9
|
+
const ScrollAreaViewport = ScrollArea.Viewport;
|
|
10
|
+
const ScrollAreaContent = ScrollArea.Content;
|
|
11
|
+
const ScrollAreaScrollbar = ScrollArea.Scrollbar;
|
|
12
|
+
const ScrollAreaThumb = ScrollArea.Thumb;
|
|
13
|
+
const ScrollAreaCorner = ScrollArea.Corner;
|
|
14
|
+
const EDGES = {
|
|
15
|
+
vertical: ["block-start", "block-end"],
|
|
16
|
+
horizontal: ["inline-start", "inline-end"]
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Three layers per edge, because a single `backdrop-filter` has one sigma for
|
|
20
|
+
* its whole box and the effect needs sigma to fall off across the band. The
|
|
21
|
+
* masks and the sigma ramp live in `scroll-area.css`; the count is here because
|
|
22
|
+
* it is the one part the CSS cannot express on its own.
|
|
23
|
+
*/
|
|
24
|
+
function ScrollEdge({ edge }) {
|
|
25
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
26
|
+
"data-cl-slot": "scroll-area-edge",
|
|
27
|
+
"data-edge": edge,
|
|
28
|
+
className: "cl-scroll-edge",
|
|
29
|
+
"aria-hidden": true,
|
|
30
|
+
children: [
|
|
31
|
+
/* @__PURE__ */ jsx("div", { className: "cl-scroll-edge-layer" }),
|
|
32
|
+
/* @__PURE__ */ jsx("div", { className: "cl-scroll-edge-layer" }),
|
|
33
|
+
/* @__PURE__ */ jsx("div", { className: "cl-scroll-edge-layer" })
|
|
34
|
+
]
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
function resolveScrollbars(value) {
|
|
38
|
+
if (value === void 0) return {
|
|
39
|
+
x: "auto",
|
|
40
|
+
y: "auto"
|
|
41
|
+
};
|
|
42
|
+
if (typeof value === "string") return {
|
|
43
|
+
x: value,
|
|
44
|
+
y: value
|
|
45
|
+
};
|
|
46
|
+
return {
|
|
47
|
+
x: value.x ?? "auto",
|
|
48
|
+
y: value.y ?? "auto"
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* A ClaraLight viewport: content that scrolls, sides that dissolve into the
|
|
53
|
+
* frame as more of it comes into range, and scrollbars that surface while you
|
|
54
|
+
* are using them.
|
|
55
|
+
*
|
|
56
|
+
* Almost nothing here runs in React. Base UI reports the four overflow edges
|
|
57
|
+
* both as booleans and as live pixel distances, and `scroll-area.css` drives
|
|
58
|
+
* the mask straight off the distances — so the fade tracks the scroll position
|
|
59
|
+
* exactly, with no animation, no timer and no re-render between the wheel and
|
|
60
|
+
* the pixels. Scrolling only re-renders when an edge is genuinely crossed.
|
|
61
|
+
*
|
|
62
|
+
* Everything dimensional is a CSS variable rather than a prop, which is how the
|
|
63
|
+
* per-side control the design asks for costs no API surface:
|
|
64
|
+
*
|
|
65
|
+
* <ScrollArea className="[--cl-scroll-edge-block-end:0px]" />
|
|
66
|
+
*
|
|
67
|
+
* turns the bottom edge off, and scoping `--cl-scroll-blur` to one `[data-edge]`
|
|
68
|
+
* gives that side its own sigma.
|
|
69
|
+
*/
|
|
70
|
+
function ScrollArea$1({ className, wrapperClassName, viewportClassName, contentClassName, orientation = "both", edge = "blur", scrollbars, radius = "medium", smoothing, viewportRef, children, ...props }) {
|
|
71
|
+
const visibility = resolveScrollbars(scrollbars);
|
|
72
|
+
const vertical = orientation !== "horizontal";
|
|
73
|
+
const horizontal = orientation !== "vertical";
|
|
74
|
+
const activeEdges = edge === "blur" ? [...vertical ? EDGES.vertical : [], ...horizontal ? EDGES.horizontal : []] : [];
|
|
75
|
+
return /* @__PURE__ */ jsx(Squircle, {
|
|
76
|
+
asChild: true,
|
|
77
|
+
radius,
|
|
78
|
+
smoothing,
|
|
79
|
+
wrapperClassName,
|
|
80
|
+
children: /* @__PURE__ */ jsxs(ScrollArea.Root, {
|
|
81
|
+
"data-cl-slot": "scroll-area",
|
|
82
|
+
className: cn("cl-scroll-area", className),
|
|
83
|
+
...props,
|
|
84
|
+
children: [
|
|
85
|
+
/* @__PURE__ */ jsx(ScrollArea.Viewport, {
|
|
86
|
+
ref: viewportRef,
|
|
87
|
+
"data-cl-slot": "scroll-area-viewport",
|
|
88
|
+
className: cn("size-full overscroll-contain", edge !== "none" && "cl-scroll-viewport", viewportClassName),
|
|
89
|
+
style: vertical && horizontal ? void 0 : vertical ? { overflowX: "hidden" } : { overflowY: "hidden" },
|
|
90
|
+
children: /* @__PURE__ */ jsx(ScrollArea.Content, {
|
|
91
|
+
"data-cl-slot": "scroll-area-content",
|
|
92
|
+
className: contentClassName,
|
|
93
|
+
style: { minWidth: horizontal ? "max-content" : 0 },
|
|
94
|
+
children
|
|
95
|
+
})
|
|
96
|
+
}),
|
|
97
|
+
activeEdges.map((side) => /* @__PURE__ */ jsx(ScrollEdge, { edge: side }, side)),
|
|
98
|
+
vertical && visibility.y !== "hidden" && /* @__PURE__ */ jsx(ScrollArea.Scrollbar, {
|
|
99
|
+
orientation: "vertical",
|
|
100
|
+
"data-cl-slot": "scroll-area-scrollbar",
|
|
101
|
+
"data-cl-visibility": visibility.y,
|
|
102
|
+
className: "cl-scrollbar",
|
|
103
|
+
children: /* @__PURE__ */ jsx(ScrollArea.Thumb, {
|
|
104
|
+
"data-cl-slot": "scroll-area-thumb",
|
|
105
|
+
className: "cl-scroll-thumb"
|
|
106
|
+
})
|
|
107
|
+
}),
|
|
108
|
+
horizontal && visibility.x !== "hidden" && /* @__PURE__ */ jsx(ScrollArea.Scrollbar, {
|
|
109
|
+
orientation: "horizontal",
|
|
110
|
+
"data-cl-slot": "scroll-area-scrollbar",
|
|
111
|
+
"data-cl-visibility": visibility.x,
|
|
112
|
+
className: "cl-scrollbar",
|
|
113
|
+
children: /* @__PURE__ */ jsx(ScrollArea.Thumb, {
|
|
114
|
+
"data-cl-slot": "scroll-area-thumb",
|
|
115
|
+
className: "cl-scroll-thumb"
|
|
116
|
+
})
|
|
117
|
+
})
|
|
118
|
+
]
|
|
119
|
+
})
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
//#endregion
|
|
123
|
+
export { ScrollArea$1 as ScrollArea, ScrollAreaContent, ScrollAreaCorner, ScrollAreaRoot, ScrollAreaScrollbar, ScrollAreaThumb, ScrollAreaViewport };
|
|
124
|
+
|
|
125
|
+
//# sourceMappingURL=scroll-area.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scroll-area.js","names":["BaseScrollArea","ScrollArea"],"sources":["../../src/ui/scroll-area.tsx"],"sourcesContent":["\"use client\";\n\nimport { ScrollArea as BaseScrollArea } from \"@base-ui/react/scroll-area\";\nimport type { ComponentProps, ReactNode, Ref } from \"react\";\nimport { type RadiusToken, Squircle } from \"@/lib/squircle\";\nimport { cn } from \"@/lib/utils\";\n\n/** Axes the content can move in. */\nexport type ScrollAreaOrientation = \"vertical\" | \"horizontal\" | \"both\";\n\n/** Visibility policy for one scrollbar. */\nexport type ScrollbarVisibility = \"auto\" | \"always\" | \"hidden\";\n\n/**\n * How a side announces that there is more content behind it.\n *\n * `blur` is the full treatment: the content fades out *and* smears into the\n * edge. **It needs an opaque fill** — `bg-panel` or `bg-background`, not\n * `bg-control`, `bg-track` or `cl-frost`. The smooth-corner clip makes the\n * surface its own backdrop root, so the blur can only see the surface's own\n * fill and the scrolled content; over a translucent fill there is barely any\n * colour there to blur and the engine lifts it into a white halo instead. See\n * `scroll-area.css` for the measurements and why nothing else can be done\n * about it.\n *\n * `mask` keeps only the fade. It has none of that coupling — it is a\n * compositor-only effect that works over any fill — and it is the right choice\n * for a translucent surface, or for a scroll area already inside something\n * expensive. `none` leaves the edges hard.\n */\nexport type ScrollAreaEdge = \"blur\" | \"mask\" | \"none\";\n\n/** Re-exported unstyled, for building something other than the default area. */\nexport const ScrollAreaRoot: typeof BaseScrollArea.Root = BaseScrollArea.Root;\nexport const ScrollAreaViewport: typeof BaseScrollArea.Viewport = BaseScrollArea.Viewport;\nexport const ScrollAreaContent: typeof BaseScrollArea.Content = BaseScrollArea.Content;\nexport const ScrollAreaScrollbar: typeof BaseScrollArea.Scrollbar = BaseScrollArea.Scrollbar;\nexport const ScrollAreaThumb: typeof BaseScrollArea.Thumb = BaseScrollArea.Thumb;\nexport const ScrollAreaCorner: typeof BaseScrollArea.Corner = BaseScrollArea.Corner;\n\nconst EDGES = {\n vertical: [\"block-start\", \"block-end\"],\n horizontal: [\"inline-start\", \"inline-end\"],\n} as const;\n\n/**\n * Three layers per edge, because a single `backdrop-filter` has one sigma for\n * its whole box and the effect needs sigma to fall off across the band. The\n * masks and the sigma ramp live in `scroll-area.css`; the count is here because\n * it is the one part the CSS cannot express on its own.\n */\nfunction ScrollEdge({ edge }: { edge: (typeof EDGES)[keyof typeof EDGES][number] }) {\n return (\n <div data-cl-slot=\"scroll-area-edge\" data-edge={edge} className=\"cl-scroll-edge\" aria-hidden>\n <div className=\"cl-scroll-edge-layer\" />\n <div className=\"cl-scroll-edge-layer\" />\n <div className=\"cl-scroll-edge-layer\" />\n </div>\n );\n}\n\nexport interface ScrollAreaProps\n extends Omit<ComponentProps<typeof BaseScrollArea.Root>, \"className\" | \"children\"> {\n /**\n * Applied to the clipped element: fill, border, and **the area's size**.\n *\n * The size has to be here and it has to be definite. The viewport fills the\n * surface absolutely, so a surface left to size itself to its content has no\n * height at all — `className=\"h-64\"`, not a bare `<ScrollArea>`.\n */\n className?: string;\n /**\n * Applied to the layout wrapper, which is the element the caller's grid or\n * flex lays out. Placement goes here — `col-span-2`, `flex-1` — and when the\n * placement is what decides the height, pair it with `className=\"h-full\"` so\n * the surface inside still resolves to something definite.\n */\n wrapperClassName?: string;\n /** Applied to the scrolling element itself. */\n viewportClassName?: string;\n /**\n * Applied to the box that moves. This is where padding belongs: put it on\n * the surface instead and it stays pinned over the scrolling content, with\n * the edge effects fading a gap rather than the content.\n */\n contentClassName?: string;\n /**\n * Axes the content can move in.\n *\n * `both` matches the Flutter widget and leaves the content unconstrained on\n * each enabled axis, which is why the content box is `max-content` wide\n * whenever the inline axis can scroll: a horizontally scrollable child has to\n * be allowed to exceed the viewport before it has anything to scroll. Lock\n * the axis with `vertical` and the box is pinned to the viewport instead, so\n * the content wraps rather than running off an edge it cannot scroll to.\n */\n orientation?: ScrollAreaOrientation;\n /** How the sides announce content behind them. */\n edge?: ScrollAreaEdge;\n /** One policy for both bars, or one per axis. */\n scrollbars?: ScrollbarVisibility | { x?: ScrollbarVisibility; y?: ScrollbarVisibility };\n /** Which `--radius-*` token shapes the corners. */\n radius?: RadiusToken;\n /** Figma's `xi`; see `Squircle`. */\n smoothing?: number;\n /**\n * The scrolling element. This is the web's scroll controller — `scrollTo`,\n * `scrollTop` and `scrollIntoView` on a child all work through it — so there\n * is no separate controller object and no per-axis pairing to keep distinct.\n */\n viewportRef?: Ref<HTMLDivElement>;\n children?: ReactNode;\n}\n\nfunction resolveScrollbars(value: ScrollAreaProps[\"scrollbars\"]) {\n if (value === undefined) return { x: \"auto\", y: \"auto\" } as const;\n if (typeof value === \"string\") return { x: value, y: value };\n return { x: value.x ?? \"auto\", y: value.y ?? \"auto\" };\n}\n\n/**\n * A ClaraLight viewport: content that scrolls, sides that dissolve into the\n * frame as more of it comes into range, and scrollbars that surface while you\n * are using them.\n *\n * Almost nothing here runs in React. Base UI reports the four overflow edges\n * both as booleans and as live pixel distances, and `scroll-area.css` drives\n * the mask straight off the distances — so the fade tracks the scroll position\n * exactly, with no animation, no timer and no re-render between the wheel and\n * the pixels. Scrolling only re-renders when an edge is genuinely crossed.\n *\n * Everything dimensional is a CSS variable rather than a prop, which is how the\n * per-side control the design asks for costs no API surface:\n *\n * <ScrollArea className=\"[--cl-scroll-edge-block-end:0px]\" />\n *\n * turns the bottom edge off, and scoping `--cl-scroll-blur` to one `[data-edge]`\n * gives that side its own sigma.\n */\nexport function ScrollArea({\n className,\n wrapperClassName,\n viewportClassName,\n contentClassName,\n orientation = \"both\",\n edge = \"blur\",\n scrollbars,\n radius = \"medium\",\n smoothing,\n viewportRef,\n children,\n ...props\n}: ScrollAreaProps) {\n const visibility = resolveScrollbars(scrollbars);\n const vertical = orientation !== \"horizontal\";\n const horizontal = orientation !== \"vertical\";\n\n const activeEdges =\n edge === \"blur\"\n ? [...(vertical ? EDGES.vertical : []), ...(horizontal ? EDGES.horizontal : [])]\n : [];\n\n return (\n <Squircle asChild radius={radius} smoothing={smoothing} wrapperClassName={wrapperClassName}>\n <BaseScrollArea.Root\n data-cl-slot=\"scroll-area\"\n className={cn(\"cl-scroll-area\", className)}\n {...props}\n >\n <BaseScrollArea.Viewport\n ref={viewportRef}\n data-cl-slot=\"scroll-area-viewport\"\n // `size-full` is load-bearing, not cosmetic. Base UI gives the\n // viewport `overflow: scroll` and nothing else, so left to itself it\n // is an auto-height block that grows to its content and therefore\n // never overflows: the area looks right, because the surface clips\n // it, and scrolls nowhere. The height has to come from the surface.\n className={cn(\n \"size-full overscroll-contain\",\n edge !== \"none\" && \"cl-scroll-viewport\",\n viewportClassName,\n )}\n // Base UI writes `overflow: scroll`; a locked axis is layered on top\n // of it rather than replacing it, so the element stays a scroller and\n // keeps reporting the other axis' overflow.\n style={\n vertical && horizontal\n ? undefined\n : vertical\n ? { overflowX: \"hidden\" }\n : { overflowY: \"hidden\" }\n }\n >\n <BaseScrollArea.Content\n data-cl-slot=\"scroll-area-content\"\n className={contentClassName}\n // Base UI writes `min-width: fit-content` here inline, which no\n // class can outrank — and inside a scroll container that keyword\n // measures the content rather than the scrollport, so it is wrong\n // in both directions: a scrollable axis is still capped at the\n // viewport, and a locked axis is widened past it, where nothing can\n // reach it. Each axis wants the opposite.\n style={{ minWidth: horizontal ? \"max-content\" : 0 }}\n >\n {children}\n </BaseScrollArea.Content>\n </BaseScrollArea.Viewport>\n\n {activeEdges.map((side) => (\n <ScrollEdge key={side} edge={side} />\n ))}\n\n {vertical && visibility.y !== \"hidden\" && (\n <BaseScrollArea.Scrollbar\n orientation=\"vertical\"\n data-cl-slot=\"scroll-area-scrollbar\"\n data-cl-visibility={visibility.y}\n className=\"cl-scrollbar\"\n >\n <BaseScrollArea.Thumb data-cl-slot=\"scroll-area-thumb\" className=\"cl-scroll-thumb\" />\n </BaseScrollArea.Scrollbar>\n )}\n\n {horizontal && visibility.x !== \"hidden\" && (\n <BaseScrollArea.Scrollbar\n orientation=\"horizontal\"\n data-cl-slot=\"scroll-area-scrollbar\"\n data-cl-visibility={visibility.x}\n className=\"cl-scrollbar\"\n >\n <BaseScrollArea.Thumb data-cl-slot=\"scroll-area-thumb\" className=\"cl-scroll-thumb\" />\n </BaseScrollArea.Scrollbar>\n )}\n </BaseScrollArea.Root>\n </Squircle>\n );\n}\n"],"mappings":";;;;;;;AAiCA,MAAa,iBAA6CA,WAAe;AACzE,MAAa,qBAAqDA,WAAe;AACjF,MAAa,oBAAmDA,WAAe;AAC/E,MAAa,sBAAuDA,WAAe;AACnF,MAAa,kBAA+CA,WAAe;AAC3E,MAAa,mBAAiDA,WAAe;AAE7E,MAAM,QAAQ;CACZ,UAAU,CAAC,eAAe,WAAW;CACrC,YAAY,CAAC,gBAAgB,YAAY;AAC3C;;;;;;;AAQA,SAAS,WAAW,EAAE,QAA8D;CAClF,OACE,qBAAC,OAAD;EAAK,gBAAa;EAAmB,aAAW;EAAM,WAAU;EAAiB,eAAA;EAAjF,UAAA;GACE,oBAAC,OAAD,EAAK,WAAU,uBAAwB,CAAA;GACvC,oBAAC,OAAD,EAAK,WAAU,uBAAwB,CAAA;GACvC,oBAAC,OAAD,EAAK,WAAU,uBAAwB,CAAA;EACpC;;AAET;AAuDA,SAAS,kBAAkB,OAAsC;CAC/D,IAAI,UAAU,KAAA,GAAW,OAAO;EAAE,GAAG;EAAQ,GAAG;CAAO;CACvD,IAAI,OAAO,UAAU,UAAU,OAAO;EAAE,GAAG;EAAO,GAAG;CAAM;CAC3D,OAAO;EAAE,GAAG,MAAM,KAAK;EAAQ,GAAG,MAAM,KAAK;CAAO;AACtD;;;;;;;;;;;;;;;;;;;;AAqBA,SAAgBC,aAAW,EACzB,WACA,kBACA,mBACA,kBACA,cAAc,QACd,OAAO,QACP,YACA,SAAS,UACT,WACA,aACA,UACA,GAAG,SACe;CAClB,MAAM,aAAa,kBAAkB,UAAU;CAC/C,MAAM,WAAW,gBAAgB;CACjC,MAAM,aAAa,gBAAgB;CAEnC,MAAM,cACJ,SAAS,SACL,CAAC,GAAI,WAAW,MAAM,WAAW,CAAC,GAAI,GAAI,aAAa,MAAM,aAAa,CAAC,CAAE,IAC7E,CAAC;CAEP,OACE,oBAAC,UAAD;EAAU,SAAA;EAAgB;EAAmB;EAA6B;EACxE,UAAA,qBAACD,WAAe,MAAhB;GACE,gBAAa;GACb,WAAW,GAAG,kBAAkB,SAAS;GACzC,GAAI;GAHN,UAAA;IAKE,oBAACA,WAAe,UAAhB;KACE,KAAK;KACL,gBAAa;KAMb,WAAW,GACT,gCACA,SAAS,UAAU,sBACnB,iBACF;KAIA,OACE,YAAY,aACR,KAAA,IACA,WACE,EAAE,WAAW,SAAS,IACtB,EAAE,WAAW,SAAS;KAG9B,UAAA,oBAACA,WAAe,SAAhB;MACE,gBAAa;MACb,WAAW;MAOX,OAAO,EAAE,UAAU,aAAa,gBAAgB,EAAE;MAEjD;KACqB,CAAA;IACD,CAAA;IAExB,YAAY,KAAK,SAChB,oBAAC,YAAD,EAAuB,MAAM,KAAO,GAAnB,IAAmB,CACrC;IAEA,YAAY,WAAW,MAAM,YAC5B,oBAACA,WAAe,WAAhB;KACE,aAAY;KACZ,gBAAa;KACb,sBAAoB,WAAW;KAC/B,WAAU;KAEV,UAAA,oBAACA,WAAe,OAAhB;MAAsB,gBAAa;MAAoB,WAAU;KAAmB,CAAA;IAC5D,CAAA;IAG3B,cAAc,WAAW,MAAM,YAC9B,oBAACA,WAAe,WAAhB;KACE,aAAY;KACZ,gBAAa;KACb,sBAAoB,WAAW;KAC/B,WAAU;KAEV,UAAA,oBAACA,WAAe,OAAhB;MAAsB,gBAAa;MAAoB,WAAU;KAAmB,CAAA;IAC5D,CAAA;GAET;;CACb,CAAA;AAEd"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { ComponentProps } from "react";
|
|
2
|
+
import { Select } from "@base-ui/react/select";
|
|
3
|
+
//#region src/ui/select.d.ts
|
|
4
|
+
declare const Select$1: typeof Select.Root;
|
|
5
|
+
/** Re-exported unstyled, for building something other than the default content. */
|
|
6
|
+
export declare const SelectPortal: typeof Select.Portal;
|
|
7
|
+
export declare const SelectPositioner: typeof Select.Positioner;
|
|
8
|
+
export declare const SelectPopup: typeof Select.Popup;
|
|
9
|
+
export declare const SelectList: typeof Select.List;
|
|
10
|
+
export type SelectTriggerProps = Omit<ComponentProps<typeof Select.Trigger>, "className"> & {
|
|
11
|
+
className?: string;
|
|
12
|
+
/** Applied to the wrapper, which is what a caller's layout sizes. */
|
|
13
|
+
wrapperClassName?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Shared control-height tokens. Defaults to `md` rather than
|
|
16
|
+
* the button's `lg`, because a select is usually one control among several in
|
|
17
|
+
* a dense row.
|
|
18
|
+
*/
|
|
19
|
+
size?: "sm" | "md" | "lg";
|
|
20
|
+
};
|
|
21
|
+
export declare function SelectTrigger({ className, wrapperClassName, size, ...props }: SelectTriggerProps): import("react").JSX.Element;
|
|
22
|
+
export type SelectValueProps = Omit<ComponentProps<typeof Select.Value>, "className"> & {
|
|
23
|
+
className?: string;
|
|
24
|
+
};
|
|
25
|
+
export declare function SelectValue({ className, ...props }: SelectValueProps): import("react").JSX.Element;
|
|
26
|
+
export type SelectIconProps = Omit<ComponentProps<typeof Select.Icon>, "className"> & {
|
|
27
|
+
className?: string;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Flips with the popup and is `aria-hidden` because Base UI already exposes the
|
|
31
|
+
* expanded state; the glyph is decoration, not information.
|
|
32
|
+
*/
|
|
33
|
+
export declare function SelectIcon({ className, ...props }: SelectIconProps): import("react").JSX.Element;
|
|
34
|
+
export type SelectContentProps = Omit<ComponentProps<typeof Select.Popup>, "className"> & {
|
|
35
|
+
/** Applied to the clipped element: the frost, padding and text. */
|
|
36
|
+
className?: string;
|
|
37
|
+
/** Applied to the wrapper, which is what is positioned and animated. */
|
|
38
|
+
wrapperClassName?: string;
|
|
39
|
+
/** Gap between the trigger and the popup, in px. */
|
|
40
|
+
sideOffset?: number;
|
|
41
|
+
/** Preferred side; Base UI flips when there is not enough room. */
|
|
42
|
+
side?: ComponentProps<typeof Select.Positioner>["side"];
|
|
43
|
+
align?: ComponentProps<typeof Select.Positioner>["align"];
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Portal, positioner and popup in the composition everyone actually wants.
|
|
47
|
+
*
|
|
48
|
+
* Two details come straight from Base UI:
|
|
49
|
+
*
|
|
50
|
+
* - `origin-[var(--transform-origin)]` — the positioner computes where the
|
|
51
|
+
* popup should *appear to grow from* based on the trigger's position, so the
|
|
52
|
+
* scale-in reads as the trigger unfolding rather than a box fading in.
|
|
53
|
+
* - `--available-height` / `--anchor-width` — measured space, so the list never
|
|
54
|
+
* spills past the viewport and the popup can match the trigger's width.
|
|
55
|
+
*/
|
|
56
|
+
export declare function SelectContent({ className, wrapperClassName, children, sideOffset, side, align, ...props }: SelectContentProps): import("react").JSX.Element;
|
|
57
|
+
export type SelectItemProps = Omit<ComponentProps<typeof Select.Item>, "className"> & {
|
|
58
|
+
className?: string;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* The item radius has its own token so nested corners remain comfortable
|
|
62
|
+
* inside the medium-radius popup.
|
|
63
|
+
*/
|
|
64
|
+
export declare function SelectItem({ className, ...props }: SelectItemProps): import("react").JSX.Element;
|
|
65
|
+
export type SelectItemIndicatorProps = Omit<ComponentProps<typeof Select.ItemIndicator>, "className"> & {
|
|
66
|
+
className?: string;
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* The selected mark, on the **trailing** edge of its item.
|
|
70
|
+
*
|
|
71
|
+
* The row is `[leading] [label] [gap] [check]`, which is the design's own — the
|
|
72
|
+
* check belongs after the value, where the eye already is, and it is what keeps
|
|
73
|
+
* the row honest in two ways that are easy to lose by reordering the JSX:
|
|
74
|
+
*
|
|
75
|
+
* - every row's label starts in the same column, because an unselected row has no
|
|
76
|
+
* indicator at all and a leading one would indent only the selected row;
|
|
77
|
+
* - Base UI aligns the popup so the selected item's *text* sits over the
|
|
78
|
+
* trigger's value text (native `<select>`, and the design's own overlap). A
|
|
79
|
+
* leading indicator makes that text column 24px wider than the trigger's, so the
|
|
80
|
+
* whole popup lands that far to the left of its anchor.
|
|
81
|
+
*
|
|
82
|
+
* `ml-auto` states the position in the indicator rather than relying on a sibling
|
|
83
|
+
* growing, so a row without a label still keeps its mark on the trailing edge.
|
|
84
|
+
*/
|
|
85
|
+
export declare function SelectItemIndicator({ className, ...props }: SelectItemIndicatorProps): import("react").JSX.Element;
|
|
86
|
+
export type SelectItemTextProps = Omit<ComponentProps<typeof Select.ItemText>, "className"> & {
|
|
87
|
+
className?: string;
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* The label, which takes the row's free space so the trailing indicator is pushed
|
|
91
|
+
* against the far edge — the `Expanded` of the Flutter row, and what lets a long
|
|
92
|
+
* label truncate instead of moving the check out of the popup.
|
|
93
|
+
*/
|
|
94
|
+
export declare function SelectItemText({ className, ...props }: SelectItemTextProps): import("react").JSX.Element;
|
|
95
|
+
export type SelectGroupProps = Omit<ComponentProps<typeof Select.Group>, "className"> & {
|
|
96
|
+
className?: string;
|
|
97
|
+
};
|
|
98
|
+
export declare function SelectGroup({ className, ...props }: SelectGroupProps): import("react").JSX.Element;
|
|
99
|
+
export type SelectGroupLabelProps = Omit<ComponentProps<typeof Select.GroupLabel>, "className"> & {
|
|
100
|
+
className?: string;
|
|
101
|
+
};
|
|
102
|
+
export declare function SelectGroupLabel({ className, ...props }: SelectGroupLabelProps): import("react").JSX.Element;
|
|
103
|
+
export type SelectSeparatorProps = Omit<ComponentProps<typeof Select.Separator>, "className"> & {
|
|
104
|
+
className?: string;
|
|
105
|
+
};
|
|
106
|
+
export declare function SelectSeparator({ className, ...props }: SelectSeparatorProps): import("react").JSX.Element;
|
|
107
|
+
export type SelectLabelProps = Omit<ComponentProps<typeof Select.Label>, "className"> & {
|
|
108
|
+
className?: string;
|
|
109
|
+
};
|
|
110
|
+
export declare function SelectLabel({ className, ...props }: SelectLabelProps): import("react").JSX.Element;
|
|
111
|
+
//#endregion
|
|
112
|
+
export { Select$1 as Select };
|
|
113
|
+
//# sourceMappingURL=select.d.ts.map
|