@dirstack/ui 1.0.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/LICENSE +21 -0
- package/README.md +67 -0
- package/dist/components/animated-number.d.ts +18 -0
- package/dist/components/animated-number.d.ts.map +1 -0
- package/dist/components/animated-number.js +29 -0
- package/dist/components/animated-number.js.map +1 -0
- package/dist/components/avatar.d.ts +8 -0
- package/dist/components/avatar.d.ts.map +1 -0
- package/dist/components/avatar.js +27 -0
- package/dist/components/avatar.js.map +1 -0
- package/dist/components/badge.d.ts +58 -0
- package/dist/components/badge.d.ts.map +1 -0
- package/dist/components/badge.js +51 -0
- package/dist/components/badge.js.map +1 -0
- package/dist/components/button.d.ts +63 -0
- package/dist/components/button.d.ts.map +1 -0
- package/dist/components/button.js +66 -0
- package/dist/components/button.js.map +1 -0
- package/dist/components/callout.d.ts +41 -0
- package/dist/components/callout.d.ts.map +1 -0
- package/dist/components/callout.js +49 -0
- package/dist/components/callout.js.map +1 -0
- package/dist/components/card.d.ts +61 -0
- package/dist/components/card.d.ts.map +1 -0
- package/dist/components/card.js +67 -0
- package/dist/components/card.js.map +1 -0
- package/dist/components/chart.d.ts +32 -0
- package/dist/components/chart.d.ts.map +1 -0
- package/dist/components/chart.js +121 -0
- package/dist/components/chart.js.map +1 -0
- package/dist/components/copy-button.d.ts +22 -0
- package/dist/components/copy-button.d.ts.map +1 -0
- package/dist/components/copy-button.js +50 -0
- package/dist/components/copy-button.js.map +1 -0
- package/dist/components/copy-input.d.ts +13 -0
- package/dist/components/copy-input.d.ts.map +1 -0
- package/dist/components/copy-input.js +28 -0
- package/dist/components/copy-input.js.map +1 -0
- package/dist/components/detail-row.d.ts +93 -0
- package/dist/components/detail-row.d.ts.map +1 -0
- package/dist/components/detail-row.js +69 -0
- package/dist/components/detail-row.js.map +1 -0
- package/dist/components/dialog.d.ts +173 -0
- package/dist/components/dialog.d.ts.map +1 -0
- package/dist/components/dialog.js +139 -0
- package/dist/components/dialog.js.map +1 -0
- package/dist/components/empty-state.d.ts +96 -0
- package/dist/components/empty-state.d.ts.map +1 -0
- package/dist/components/empty-state.js +69 -0
- package/dist/components/empty-state.js.map +1 -0
- package/dist/components/entity-avatar.d.ts +77 -0
- package/dist/components/entity-avatar.d.ts.map +1 -0
- package/dist/components/entity-avatar.js +48 -0
- package/dist/components/entity-avatar.js.map +1 -0
- package/dist/components/form-row.d.ts +35 -0
- package/dist/components/form-row.d.ts.map +1 -0
- package/dist/components/form-row.js +46 -0
- package/dist/components/form-row.js.map +1 -0
- package/dist/components/form-section.d.ts +24 -0
- package/dist/components/form-section.d.ts.map +1 -0
- package/dist/components/form-section.js +39 -0
- package/dist/components/form-section.js.map +1 -0
- package/dist/components/form.d.ts +28 -0
- package/dist/components/form.d.ts.map +1 -0
- package/dist/components/form.js +88 -0
- package/dist/components/form.js.map +1 -0
- package/dist/components/heading.d.ts +44 -0
- package/dist/components/heading.d.ts.map +1 -0
- package/dist/components/heading.js +45 -0
- package/dist/components/heading.js.map +1 -0
- package/dist/components/input.d.ts +55 -0
- package/dist/components/input.d.ts.map +1 -0
- package/dist/components/input.js +33 -0
- package/dist/components/input.js.map +1 -0
- package/dist/components/kbd.d.ts +28 -0
- package/dist/components/kbd.d.ts.map +1 -0
- package/dist/components/kbd.js +31 -0
- package/dist/components/kbd.js.map +1 -0
- package/dist/components/label.d.ts +21 -0
- package/dist/components/label.d.ts.map +1 -0
- package/dist/components/label.js +21 -0
- package/dist/components/label.js.map +1 -0
- package/dist/components/menu.d.ts +22 -0
- package/dist/components/menu.d.ts.map +1 -0
- package/dist/components/menu.js +73 -0
- package/dist/components/menu.js.map +1 -0
- package/dist/components/nav-button.d.ts +34 -0
- package/dist/components/nav-button.d.ts.map +1 -0
- package/dist/components/nav-button.js +70 -0
- package/dist/components/nav-button.js.map +1 -0
- package/dist/components/nav.d.ts +44 -0
- package/dist/components/nav.d.ts.map +1 -0
- package/dist/components/nav.js +53 -0
- package/dist/components/nav.js.map +1 -0
- package/dist/components/number-input.d.ts +18 -0
- package/dist/components/number-input.d.ts.map +1 -0
- package/dist/components/number-input.js +25 -0
- package/dist/components/number-input.js.map +1 -0
- package/dist/components/page.d.ts +24 -0
- package/dist/components/page.d.ts.map +1 -0
- package/dist/components/page.js +24 -0
- package/dist/components/page.js.map +1 -0
- package/dist/components/pagination.d.ts +17 -0
- package/dist/components/pagination.d.ts.map +1 -0
- package/dist/components/pagination.js +63 -0
- package/dist/components/pagination.js.map +1 -0
- package/dist/components/popover.d.ts +8 -0
- package/dist/components/popover.d.ts.map +1 -0
- package/dist/components/popover.js +24 -0
- package/dist/components/popover.js.map +1 -0
- package/dist/components/search-input.d.ts +14 -0
- package/dist/components/search-input.d.ts.map +1 -0
- package/dist/components/search-input.js +36 -0
- package/dist/components/search-input.js.map +1 -0
- package/dist/components/section-header.d.ts +107 -0
- package/dist/components/section-header.d.ts.map +1 -0
- package/dist/components/section-header.js +147 -0
- package/dist/components/section-header.js.map +1 -0
- package/dist/components/select.d.ts +17 -0
- package/dist/components/select.d.ts.map +1 -0
- package/dist/components/select.js +94 -0
- package/dist/components/select.js.map +1 -0
- package/dist/components/skeleton.d.ts +5 -0
- package/dist/components/skeleton.d.ts.map +1 -0
- package/dist/components/skeleton.js +13 -0
- package/dist/components/skeleton.js.map +1 -0
- package/dist/components/stack.d.ts +54 -0
- package/dist/components/stack.d.ts.map +1 -0
- package/dist/components/stack.js +46 -0
- package/dist/components/stack.js.map +1 -0
- package/dist/components/stat-strip.d.ts +38 -0
- package/dist/components/stat-strip.d.ts.map +1 -0
- package/dist/components/stat-strip.js +57 -0
- package/dist/components/stat-strip.js.map +1 -0
- package/dist/components/steps.d.ts +19 -0
- package/dist/components/steps.d.ts.map +1 -0
- package/dist/components/steps.js +29 -0
- package/dist/components/steps.js.map +1 -0
- package/dist/components/switch.d.ts +6 -0
- package/dist/components/switch.d.ts.map +1 -0
- package/dist/components/switch.js +17 -0
- package/dist/components/switch.js.map +1 -0
- package/dist/components/tabs.d.ts +62 -0
- package/dist/components/tabs.d.ts.map +1 -0
- package/dist/components/tabs.js +64 -0
- package/dist/components/tabs.js.map +1 -0
- package/dist/components/textarea.d.ts +9 -0
- package/dist/components/textarea.d.ts.map +1 -0
- package/dist/components/textarea.js +18 -0
- package/dist/components/textarea.js.map +1 -0
- package/dist/components/toaster.d.ts +6 -0
- package/dist/components/toaster.d.ts.map +1 -0
- package/dist/components/toaster.js +37 -0
- package/dist/components/toaster.js.map +1 -0
- package/dist/components/tooltip.d.ts +15 -0
- package/dist/components/tooltip.d.ts.map +1 -0
- package/dist/components/tooltip.js +41 -0
- package/dist/components/tooltip.js.map +1 -0
- package/dist/lib/animation.d.ts +12 -0
- package/dist/lib/animation.d.ts.map +1 -0
- package/dist/lib/animation.js +14 -0
- package/dist/lib/animation.js.map +1 -0
- package/dist/lib/classes.d.ts +29 -0
- package/dist/lib/classes.d.ts.map +1 -0
- package/dist/lib/classes.js +39 -0
- package/dist/lib/classes.js.map +1 -0
- package/dist/lib/icons.d.ts +21 -0
- package/dist/lib/icons.d.ts.map +1 -0
- package/dist/lib/icons.js +43 -0
- package/dist/lib/icons.js.map +1 -0
- package/dist/lib/interactive.d.ts +41 -0
- package/dist/lib/interactive.d.ts.map +1 -0
- package/dist/lib/interactive.js +30 -0
- package/dist/lib/interactive.js.map +1 -0
- package/dist/lib/slot.d.ts +12 -0
- package/dist/lib/slot.d.ts.map +1 -0
- package/dist/lib/slot.js +19 -0
- package/dist/lib/slot.js.map +1 -0
- package/dist/lib/variants.d.ts +3 -0
- package/dist/lib/variants.js +3 -0
- package/dist/styles.css +169 -0
- package/package.json +112 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { cn } from "../lib/variants.js";
|
|
2
|
+
import { SearchIcon, XIcon } from "../lib/icons.js";
|
|
3
|
+
import { Button } from "./button.js";
|
|
4
|
+
import { Input } from "./input.js";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
//#region src/components/search-input.tsx
|
|
7
|
+
/**
|
|
8
|
+
* Text input with a leading search icon and a clear button once it holds a value. Labels and
|
|
9
|
+
* placeholders come from the caller.
|
|
10
|
+
*/
|
|
11
|
+
function SearchInput({ value, onValueChange, className, ...props }) {
|
|
12
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
13
|
+
className: cn("relative", className),
|
|
14
|
+
children: [
|
|
15
|
+
/* @__PURE__ */ jsx(SearchIcon, { className: "pointer-events-none absolute top-1/2 left-3 size-4 -translate-y-1/2 text-muted-foreground" }),
|
|
16
|
+
/* @__PURE__ */ jsx(Input, {
|
|
17
|
+
value,
|
|
18
|
+
className: "px-9",
|
|
19
|
+
onChange: (event) => onValueChange(event.target.value),
|
|
20
|
+
...props
|
|
21
|
+
}),
|
|
22
|
+
value.length > 0 && /* @__PURE__ */ jsx(Button, {
|
|
23
|
+
variant: "ghost",
|
|
24
|
+
size: "sm",
|
|
25
|
+
"aria-label": "Clear search",
|
|
26
|
+
prefix: /* @__PURE__ */ jsx(XIcon, {}),
|
|
27
|
+
className: "absolute top-1/2 right-1 -translate-y-1/2",
|
|
28
|
+
onClick: () => onValueChange("")
|
|
29
|
+
})
|
|
30
|
+
]
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
//#endregion
|
|
34
|
+
export { SearchInput };
|
|
35
|
+
|
|
36
|
+
//# sourceMappingURL=search-input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-input.js","names":[],"sources":["../../src/components/search-input.tsx"],"sourcesContent":["import type { ComponentProps } from \"react\"\nimport { Button } from \"~/components/button\"\nimport { Input } from \"~/components/input\"\nimport { SearchIcon, XIcon } from \"~/lib/icons\"\nimport { cn } from \"~/lib/variants\"\n\ntype SearchInputProps = Omit<ComponentProps<typeof Input>, \"value\" | \"onChange\"> & {\n value: string\n onValueChange: (value: string) => void\n}\n\n/**\n * Text input with a leading search icon and a clear button once it holds a value. Labels and\n * placeholders come from the caller.\n */\nexport function SearchInput({ value, onValueChange, className, ...props }: SearchInputProps) {\n return (\n <div className={cn(\"relative\", className)}>\n <SearchIcon className=\"pointer-events-none absolute top-1/2 left-3 size-4 -translate-y-1/2 text-muted-foreground\" />\n\n <Input\n value={value}\n className=\"px-9\"\n onChange={event => onValueChange(event.target.value)}\n {...props}\n />\n\n {value.length > 0 && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n aria-label=\"Clear search\"\n prefix={<XIcon />}\n className=\"absolute top-1/2 right-1 -translate-y-1/2\"\n onClick={() => onValueChange(\"\")}\n />\n )}\n </div>\n )\n}\n"],"mappings":";;;;;;;;;;AAeA,SAAgB,YAAY,EAAE,OAAO,eAAe,WAAW,GAAG,SAA2B;CAC3F,OACE,qBAAC,OAAD;EAAK,WAAW,GAAG,YAAY,SAAS;EAAxC,UAAA;GACE,oBAAC,YAAD,EAAY,WAAU,4FAA6F,CAAA;GAEnH,oBAAC,OAAD;IACS;IACP,WAAU;IACV,WAAU,UAAS,cAAc,MAAM,OAAO,KAAK;IACnD,GAAI;GACL,CAAA;GAEA,MAAM,SAAS,KACd,oBAAC,QAAD;IACE,SAAQ;IACR,MAAK;IACL,cAAW;IACX,QAAQ,oBAAC,OAAD,CAAQ,CAAA;IAChB,WAAU;IACV,eAAe,cAAc,EAAE;GAChC,CAAA;EAEA;;AAET"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { VariantProps } from "../lib/variants.js";
|
|
2
|
+
import { Stack } from "./stack.js";
|
|
3
|
+
import { HeadingProps } from "./heading.js";
|
|
4
|
+
import { useRender } from "@base-ui/react/use-render";
|
|
5
|
+
import { ComponentProps, ReactNode } from "react";
|
|
6
|
+
//#region src/components/section-header.d.ts
|
|
7
|
+
declare const sectionHeaderVariants: import("tailwind-variants").TVReturnType<{
|
|
8
|
+
alignment: {
|
|
9
|
+
left: "justify-between text-start";
|
|
10
|
+
center: "justify-center text-center";
|
|
11
|
+
};
|
|
12
|
+
size: {
|
|
13
|
+
page: "gap-y-3 gap-x-6 lg:gap-x-12";
|
|
14
|
+
card: "gap-y-2 gap-x-6";
|
|
15
|
+
panel: "gap-y-2 gap-x-6";
|
|
16
|
+
hero: "gap-y-3 gap-x-6 lg:gap-x-12";
|
|
17
|
+
};
|
|
18
|
+
wrap: {
|
|
19
|
+
true: "flex-wrap";
|
|
20
|
+
false: "flex-nowrap";
|
|
21
|
+
};
|
|
22
|
+
}, undefined, "flex items-center w-full min-w-0", {
|
|
23
|
+
alignment: {
|
|
24
|
+
left: "justify-between text-start";
|
|
25
|
+
center: "justify-center text-center";
|
|
26
|
+
};
|
|
27
|
+
size: {
|
|
28
|
+
page: "gap-y-3 gap-x-6 lg:gap-x-12";
|
|
29
|
+
card: "gap-y-2 gap-x-6";
|
|
30
|
+
panel: "gap-y-2 gap-x-6";
|
|
31
|
+
hero: "gap-y-3 gap-x-6 lg:gap-x-12";
|
|
32
|
+
};
|
|
33
|
+
wrap: {
|
|
34
|
+
true: "flex-wrap";
|
|
35
|
+
false: "flex-nowrap";
|
|
36
|
+
};
|
|
37
|
+
}, undefined, import("tailwind-variants").TVReturnTypeLike<{
|
|
38
|
+
alignment: {
|
|
39
|
+
left: "justify-between text-start";
|
|
40
|
+
center: "justify-center text-center";
|
|
41
|
+
};
|
|
42
|
+
size: {
|
|
43
|
+
page: "gap-y-3 gap-x-6 lg:gap-x-12";
|
|
44
|
+
card: "gap-y-2 gap-x-6";
|
|
45
|
+
panel: "gap-y-2 gap-x-6";
|
|
46
|
+
hero: "gap-y-3 gap-x-6 lg:gap-x-12";
|
|
47
|
+
};
|
|
48
|
+
wrap: {
|
|
49
|
+
true: "flex-wrap";
|
|
50
|
+
false: "flex-nowrap";
|
|
51
|
+
};
|
|
52
|
+
}, undefined>>;
|
|
53
|
+
type SectionHeaderProps = Omit<useRender.ComponentProps<"div">, "title"> & Omit<VariantProps<typeof sectionHeaderVariants>, "wrap"> & {
|
|
54
|
+
/**
|
|
55
|
+
* Keep the title block and the actions on one line instead of wrapping them.
|
|
56
|
+
*/
|
|
57
|
+
wrap?: boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Title block. Given any of `title`/`description`/`leading`/`actions`, the header renders
|
|
60
|
+
* its own `SectionHeaderBody` (empty if there is nothing but actions, so they still sit right);
|
|
61
|
+
* leave them all out to compose the body by hand, e.g. an entity header with dot-joined
|
|
62
|
+
* meta or the dashboard greeting.
|
|
63
|
+
*/
|
|
64
|
+
title?: ReactNode;
|
|
65
|
+
description?: ReactNode;
|
|
66
|
+
actions?: ReactNode;
|
|
67
|
+
/**
|
|
68
|
+
* Leading visual beside the title, e.g. an entity avatar.
|
|
69
|
+
*/
|
|
70
|
+
leading?: ReactNode;
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* The one header for every surface in the app: pages, cards, list panels, dialogs and settings
|
|
74
|
+
* sections. Pass `title`/`description`/`actions` for the standard block, or compose
|
|
75
|
+
* `SectionHeaderBody` + `SectionHeaderActions` as children when the content is bespoke.
|
|
76
|
+
*/
|
|
77
|
+
declare function SectionHeader({ className, alignment, size, wrap, title, description, actions, leading, children, render, ...props }: SectionHeaderProps): import("react").JSX.Element;
|
|
78
|
+
/**
|
|
79
|
+
* The page title. Its visual size and semantic level both follow the header's `size`, so a
|
|
80
|
+
* page heading stays the route's single `<h1>` while cards and panels render `<h2>`s. Pass
|
|
81
|
+
* `size`/`as` to override either one on its own.
|
|
82
|
+
*/
|
|
83
|
+
declare function SectionHeaderTitle({ size, as, ...props }: HeadingProps): import("react").JSX.Element;
|
|
84
|
+
type SectionHeaderBodyProps = ComponentProps<"div"> & {
|
|
85
|
+
/**
|
|
86
|
+
* Leading visual, e.g. an entity avatar.
|
|
87
|
+
*/
|
|
88
|
+
leading?: ReactNode;
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* The one title block for every header in the app (pages, cards, dialogs, settings sections):
|
|
92
|
+
* an optional leading visual beside a column of `SectionHeaderTitle` + `SectionHeaderDescription`. Change the
|
|
93
|
+
* spacing here and it changes everywhere.
|
|
94
|
+
*/
|
|
95
|
+
declare function SectionHeaderBody({ leading, children, className, ...props }: SectionHeaderBodyProps): import("react").JSX.Element;
|
|
96
|
+
/**
|
|
97
|
+
* The muted line under a title. Wraps by default; pass `truncate` for one-line entity meta.
|
|
98
|
+
*/
|
|
99
|
+
declare function SectionHeaderDescription({ className, ...props }: ComponentProps<"p">): import("react").JSX.Element;
|
|
100
|
+
/**
|
|
101
|
+
* Right-aligned actions. Stops shrinking when the header is `wrap={false}`, so a long title
|
|
102
|
+
* truncates instead of squeezing the buttons.
|
|
103
|
+
*/
|
|
104
|
+
declare function SectionHeaderActions({ className, ...props }: ComponentProps<typeof Stack>): import("react").JSX.Element;
|
|
105
|
+
//#endregion
|
|
106
|
+
export { SectionHeader, SectionHeaderActions, SectionHeaderBody, SectionHeaderDescription, SectionHeaderTitle };
|
|
107
|
+
//# sourceMappingURL=section-header.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"section-header.d.ts","names":[],"sources":["../../src/components/section-header.tsx"],"mappings":";;;;;;cAOM,mDAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA8CtB,qBAAqB,KAAK,UAAU,kCACvC,KAAK,oBAAoB;;;;EAIvB;;;;;;;EAOA,QAAQ;EACR,cAAc;EACd,UAAU;;;;EAIV,UAAU;;;;;;;iBAQL,gBACP,WACA,WACA,MACA,MACA,OACA,aACA,SACA,SACA,UACA,WACG,SACF,qCAAkB,IAAA;;;;;;iBAmCZ,qBAAqB,MAAM,OAAO,SAAS,+BAAY,IAAA;KAM3D,yBAAyB;;;;EAI5B,UAAU;;;;;;;iBAQH,oBAAoB,SAAS,UAAU,cAAc,SAAS,yCAAsB,IAAA;;;;iBAYpF,2BAA2B,cAAc,SAAS,sCAAmB,IAAA;;;;;iBAQrE,uBAAuB,cAAc,SAAS,sBAAsB,yBAAM,IAAA"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { cn, variants } from "../lib/variants.js";
|
|
2
|
+
import { Stack } from "./stack.js";
|
|
3
|
+
import { Heading } from "./heading.js";
|
|
4
|
+
import { descriptionClasses } from "../lib/classes.js";
|
|
5
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import { useRender } from "@base-ui/react/use-render";
|
|
7
|
+
import { createContext, use } from "react";
|
|
8
|
+
//#region src/components/section-header.tsx
|
|
9
|
+
const sectionHeaderVariants = variants({
|
|
10
|
+
base: "flex items-center w-full min-w-0",
|
|
11
|
+
variants: {
|
|
12
|
+
alignment: {
|
|
13
|
+
left: "justify-between text-start",
|
|
14
|
+
center: "justify-center text-center"
|
|
15
|
+
},
|
|
16
|
+
size: {
|
|
17
|
+
page: "gap-y-3 gap-x-6 lg:gap-x-12",
|
|
18
|
+
card: "gap-y-2 gap-x-6",
|
|
19
|
+
panel: "gap-y-2 gap-x-6",
|
|
20
|
+
hero: "gap-y-3 gap-x-6 lg:gap-x-12"
|
|
21
|
+
},
|
|
22
|
+
wrap: {
|
|
23
|
+
true: "flex-wrap",
|
|
24
|
+
false: "flex-nowrap"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
defaultVariants: {
|
|
28
|
+
alignment: "left",
|
|
29
|
+
wrap: true
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
/**
|
|
33
|
+
* The title each header scale gets, alongside the spacing the variant above gives it: `page`
|
|
34
|
+
* for a route heading, `card` for a standalone card, `panel` for a dashboard or list panel,
|
|
35
|
+
* `hero` for the centered auth and callback screens. The `as` entry keeps the heading outline
|
|
36
|
+
* intact — one `<h1>` per route, `<h2>` for everything nested inside it.
|
|
37
|
+
*/
|
|
38
|
+
const sectionHeaderTitles = {
|
|
39
|
+
page: {
|
|
40
|
+
size: "h3",
|
|
41
|
+
as: "h1"
|
|
42
|
+
},
|
|
43
|
+
card: {
|
|
44
|
+
size: "h4",
|
|
45
|
+
as: "h2"
|
|
46
|
+
},
|
|
47
|
+
panel: {
|
|
48
|
+
size: "h5",
|
|
49
|
+
as: "h2"
|
|
50
|
+
},
|
|
51
|
+
hero: {
|
|
52
|
+
size: "h2",
|
|
53
|
+
as: "h1"
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
const SectionHeaderContext = createContext({
|
|
57
|
+
size: "page",
|
|
58
|
+
wrap: true
|
|
59
|
+
});
|
|
60
|
+
/**
|
|
61
|
+
* The one header for every surface in the app: pages, cards, list panels, dialogs and settings
|
|
62
|
+
* sections. Pass `title`/`description`/`actions` for the standard block, or compose
|
|
63
|
+
* `SectionHeaderBody` + `SectionHeaderActions` as children when the content is bespoke.
|
|
64
|
+
*/
|
|
65
|
+
function SectionHeader({ className, alignment = "left", size = "page", wrap = true, title, description, actions, leading, children, render, ...props }) {
|
|
66
|
+
const element = useRender({
|
|
67
|
+
render,
|
|
68
|
+
defaultTagName: "div",
|
|
69
|
+
props: {
|
|
70
|
+
className: cn(sectionHeaderVariants({
|
|
71
|
+
alignment,
|
|
72
|
+
size,
|
|
73
|
+
wrap,
|
|
74
|
+
className
|
|
75
|
+
})),
|
|
76
|
+
children: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
77
|
+
(title || description || leading || actions) && /* @__PURE__ */ jsxs(SectionHeaderBody, {
|
|
78
|
+
leading,
|
|
79
|
+
className: cn(alignment === "center" && "justify-center"),
|
|
80
|
+
children: [title && /* @__PURE__ */ jsx(SectionHeaderTitle, { children: title }), description && /* @__PURE__ */ jsx(SectionHeaderDescription, { children: description })]
|
|
81
|
+
}),
|
|
82
|
+
actions && /* @__PURE__ */ jsx(SectionHeaderActions, { children: actions }),
|
|
83
|
+
children
|
|
84
|
+
] }),
|
|
85
|
+
...props
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
return /* @__PURE__ */ jsx(SectionHeaderContext, {
|
|
89
|
+
value: {
|
|
90
|
+
size,
|
|
91
|
+
wrap
|
|
92
|
+
},
|
|
93
|
+
children: element
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* The page title. Its visual size and semantic level both follow the header's `size`, so a
|
|
98
|
+
* page heading stays the route's single `<h1>` while cards and panels render `<h2>`s. Pass
|
|
99
|
+
* `size`/`as` to override either one on its own.
|
|
100
|
+
*/
|
|
101
|
+
function SectionHeaderTitle({ size, as, ...props }) {
|
|
102
|
+
const preset = sectionHeaderTitles[use(SectionHeaderContext).size];
|
|
103
|
+
return /* @__PURE__ */ jsx(Heading, {
|
|
104
|
+
size: size ?? preset.size,
|
|
105
|
+
as: as ?? preset.as,
|
|
106
|
+
...props
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* The one title block for every header in the app (pages, cards, dialogs, settings sections):
|
|
111
|
+
* an optional leading visual beside a column of `SectionHeaderTitle` + `SectionHeaderDescription`. Change the
|
|
112
|
+
* spacing here and it changes everywhere.
|
|
113
|
+
*/
|
|
114
|
+
function SectionHeaderBody({ leading, children, className, ...props }) {
|
|
115
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
116
|
+
className: cn("flex min-w-0 flex-1 items-center gap-3", className),
|
|
117
|
+
...props,
|
|
118
|
+
children: [leading, /* @__PURE__ */ jsx("div", {
|
|
119
|
+
className: "flex min-w-0 flex-col gap-1.5",
|
|
120
|
+
children
|
|
121
|
+
})]
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* The muted line under a title. Wraps by default; pass `truncate` for one-line entity meta.
|
|
126
|
+
*/
|
|
127
|
+
function SectionHeaderDescription({ className, ...props }) {
|
|
128
|
+
return /* @__PURE__ */ jsx("p", {
|
|
129
|
+
className: cn(descriptionClasses, className),
|
|
130
|
+
...props
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Right-aligned actions. Stops shrinking when the header is `wrap={false}`, so a long title
|
|
135
|
+
* truncates instead of squeezing the buttons.
|
|
136
|
+
*/
|
|
137
|
+
function SectionHeaderActions({ className, ...props }) {
|
|
138
|
+
const { wrap } = use(SectionHeaderContext);
|
|
139
|
+
return /* @__PURE__ */ jsx(Stack, {
|
|
140
|
+
className: cn("-my-0.5", !wrap && "shrink-0", className),
|
|
141
|
+
...props
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
//#endregion
|
|
145
|
+
export { SectionHeader, SectionHeaderActions, SectionHeaderBody, SectionHeaderDescription, SectionHeaderTitle };
|
|
146
|
+
|
|
147
|
+
//# sourceMappingURL=section-header.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"section-header.js","names":[],"sources":["../../src/components/section-header.tsx"],"sourcesContent":["import { useRender } from \"@base-ui/react/use-render\"\nimport { type ComponentProps, createContext, type ReactNode, use } from \"react\"\nimport { Heading, type HeadingProps } from \"~/components/heading\"\nimport { Stack } from \"~/components/stack\"\nimport { descriptionClasses } from \"~/lib/classes\"\nimport { variants, cn, type VariantProps } from \"~/lib/variants\"\n\nconst sectionHeaderVariants = variants({\n base: \"flex items-center w-full min-w-0\",\n\n variants: {\n alignment: {\n left: \"justify-between text-start\",\n center: \"justify-center text-center\",\n },\n size: {\n page: \"gap-y-3 gap-x-6 lg:gap-x-12\",\n card: \"gap-y-2 gap-x-6\",\n panel: \"gap-y-2 gap-x-6\",\n hero: \"gap-y-3 gap-x-6 lg:gap-x-12\",\n },\n wrap: {\n true: \"flex-wrap\",\n false: \"flex-nowrap\",\n },\n },\n\n defaultVariants: {\n alignment: \"left\",\n wrap: true,\n },\n})\n\ntype SectionHeaderSize = NonNullable<VariantProps<typeof sectionHeaderVariants>[\"size\"]>\n\n/**\n * The title each header scale gets, alongside the spacing the variant above gives it: `page`\n * for a route heading, `card` for a standalone card, `panel` for a dashboard or list panel,\n * `hero` for the centered auth and callback screens. The `as` entry keeps the heading outline\n * intact — one `<h1>` per route, `<h2>` for everything nested inside it.\n */\nconst sectionHeaderTitles = {\n page: { size: \"h3\", as: \"h1\" },\n card: { size: \"h4\", as: \"h2\" },\n panel: { size: \"h5\", as: \"h2\" },\n hero: { size: \"h2\", as: \"h1\" },\n} as const satisfies Record<SectionHeaderSize, { size: HeadingProps[\"size\"]; as: string }>\n\nconst SectionHeaderContext = createContext<{ size: SectionHeaderSize; wrap: boolean }>({\n size: \"page\",\n wrap: true,\n})\n\ntype SectionHeaderProps = Omit<useRender.ComponentProps<\"div\">, \"title\"> &\n Omit<VariantProps<typeof sectionHeaderVariants>, \"wrap\"> & {\n /**\n * Keep the title block and the actions on one line instead of wrapping them.\n */\n wrap?: boolean\n /**\n * Title block. Given any of `title`/`description`/`leading`/`actions`, the header renders\n * its own `SectionHeaderBody` (empty if there is nothing but actions, so they still sit right);\n * leave them all out to compose the body by hand, e.g. an entity header with dot-joined\n * meta or the dashboard greeting.\n */\n title?: ReactNode\n description?: ReactNode\n actions?: ReactNode\n /**\n * Leading visual beside the title, e.g. an entity avatar.\n */\n leading?: ReactNode\n }\n\n/**\n * The one header for every surface in the app: pages, cards, list panels, dialogs and settings\n * sections. Pass `title`/`description`/`actions` for the standard block, or compose\n * `SectionHeaderBody` + `SectionHeaderActions` as children when the content is bespoke.\n */\nfunction SectionHeader({\n className,\n alignment = \"left\",\n size = \"page\",\n wrap = true,\n title,\n description,\n actions,\n leading,\n children,\n render,\n ...props\n}: SectionHeaderProps) {\n const element = useRender({\n render,\n defaultTagName: \"div\",\n props: {\n className: cn(sectionHeaderVariants({ alignment, size, wrap, className })),\n children: (\n <>\n {(title || description || leading || actions) && (\n <SectionHeaderBody\n leading={leading}\n className={cn(alignment === \"center\" && \"justify-center\")}\n >\n {title && <SectionHeaderTitle>{title}</SectionHeaderTitle>}\n {description && <SectionHeaderDescription>{description}</SectionHeaderDescription>}\n </SectionHeaderBody>\n )}\n\n {actions && <SectionHeaderActions>{actions}</SectionHeaderActions>}\n\n {children}\n </>\n ),\n ...props,\n },\n })\n\n return <SectionHeaderContext value={{ size, wrap }}>{element}</SectionHeaderContext>\n}\n\n/**\n * The page title. Its visual size and semantic level both follow the header's `size`, so a\n * page heading stays the route's single `<h1>` while cards and panels render `<h2>`s. Pass\n * `size`/`as` to override either one on its own.\n */\nfunction SectionHeaderTitle({ size, as, ...props }: HeadingProps) {\n const preset = sectionHeaderTitles[use(SectionHeaderContext).size]\n\n return <Heading size={size ?? preset.size} as={as ?? preset.as} {...props} />\n}\n\ntype SectionHeaderBodyProps = ComponentProps<\"div\"> & {\n /**\n * Leading visual, e.g. an entity avatar.\n */\n leading?: ReactNode\n}\n\n/**\n * The one title block for every header in the app (pages, cards, dialogs, settings sections):\n * an optional leading visual beside a column of `SectionHeaderTitle` + `SectionHeaderDescription`. Change the\n * spacing here and it changes everywhere.\n */\nfunction SectionHeaderBody({ leading, children, className, ...props }: SectionHeaderBodyProps) {\n return (\n <div className={cn(\"flex min-w-0 flex-1 items-center gap-3\", className)} {...props}>\n {leading}\n <div className=\"flex min-w-0 flex-col gap-1.5\">{children}</div>\n </div>\n )\n}\n\n/**\n * The muted line under a title. Wraps by default; pass `truncate` for one-line entity meta.\n */\nfunction SectionHeaderDescription({ className, ...props }: ComponentProps<\"p\">) {\n return <p className={cn(descriptionClasses, className)} {...props} />\n}\n\n/**\n * Right-aligned actions. Stops shrinking when the header is `wrap={false}`, so a long title\n * truncates instead of squeezing the buttons.\n */\nfunction SectionHeaderActions({ className, ...props }: ComponentProps<typeof Stack>) {\n const { wrap } = use(SectionHeaderContext)\n\n return <Stack className={cn(\"-my-0.5\", !wrap && \"shrink-0\", className)} {...props} />\n}\n\nexport {\n SectionHeader,\n SectionHeaderTitle,\n SectionHeaderBody,\n SectionHeaderDescription,\n SectionHeaderActions,\n}\n"],"mappings":";;;;;;;;AAOA,MAAM,wBAAwB,SAAS;CACrC,MAAM;CAEN,UAAU;EACR,WAAW;GACT,MAAM;GACN,QAAQ;EACV;EACA,MAAM;GACJ,MAAM;GACN,MAAM;GACN,OAAO;GACP,MAAM;EACR;EACA,MAAM;GACJ,MAAM;GACN,OAAO;EACT;CACF;CAEA,iBAAiB;EACf,WAAW;EACX,MAAM;CACR;AACF,CAAC;;;;;;;AAUD,MAAM,sBAAsB;CAC1B,MAAM;EAAE,MAAM;EAAM,IAAI;CAAK;CAC7B,MAAM;EAAE,MAAM;EAAM,IAAI;CAAK;CAC7B,OAAO;EAAE,MAAM;EAAM,IAAI;CAAK;CAC9B,MAAM;EAAE,MAAM;EAAM,IAAI;CAAK;AAC/B;AAEA,MAAM,uBAAuB,cAA0D;CACrF,MAAM;CACN,MAAM;AACR,CAAC;;;;;;AA4BD,SAAS,cAAc,EACrB,WACA,YAAY,QACZ,OAAO,QACP,OAAO,MACP,OACA,aACA,SACA,SACA,UACA,QACA,GAAG,SACkB;CACrB,MAAM,UAAU,UAAU;EACxB;EACA,gBAAgB;EAChB,OAAO;GACL,WAAW,GAAG,sBAAsB;IAAE;IAAW;IAAM;IAAM;GAAU,CAAC,CAAC;GACzE,UACE,qBAAA,UAAA,EAAA,UAAA;KACI,SAAS,eAAe,WAAW,YACnC,qBAAC,mBAAD;KACW;KACT,WAAW,GAAG,cAAc,YAAY,gBAAgB;KAF1D,UAAA,CAIG,SAAS,oBAAC,oBAAD,EAAA,UAAqB,MAA0B,CAAA,GACxD,eAAe,oBAAC,0BAAD,EAAA,UAA2B,YAAsC,CAAA,CAChE;;IAGpB,WAAW,oBAAC,sBAAD,EAAA,UAAuB,QAA8B,CAAA;IAEhE;GACD,EAAA,CAAA;GAEJ,GAAG;EACL;CACF,CAAC;CAED,OAAO,oBAAC,sBAAD;EAAsB,OAAO;GAAE;GAAM;EAAK;EAAI,UAAA;CAA8B,CAAA;AACrF;;;;;;AAOA,SAAS,mBAAmB,EAAE,MAAM,IAAI,GAAG,SAAuB;CAChE,MAAM,SAAS,oBAAoB,IAAI,oBAAoB,CAAC,CAAC;CAE7D,OAAO,oBAAC,SAAD;EAAS,MAAM,QAAQ,OAAO;EAAM,IAAI,MAAM,OAAO;EAAI,GAAI;CAAQ,CAAA;AAC9E;;;;;;AAcA,SAAS,kBAAkB,EAAE,SAAS,UAAU,WAAW,GAAG,SAAiC;CAC7F,OACE,qBAAC,OAAD;EAAK,WAAW,GAAG,0CAA0C,SAAS;EAAG,GAAI;EAA7E,UAAA,CACG,SACD,oBAAC,OAAD;GAAK,WAAU;GAAiC;EAAc,CAAA,CAC3D;;AAET;;;;AAKA,SAAS,yBAAyB,EAAE,WAAW,GAAG,SAA8B;CAC9E,OAAO,oBAAC,KAAD;EAAG,WAAW,GAAG,oBAAoB,SAAS;EAAG,GAAI;CAAQ,CAAA;AACtE;;;;;AAMA,SAAS,qBAAqB,EAAE,WAAW,GAAG,SAAuC;CACnF,MAAM,EAAE,SAAS,IAAI,oBAAoB;CAEzC,OAAO,oBAAC,OAAD;EAAO,WAAW,GAAG,WAAW,CAAC,QAAQ,YAAY,SAAS;EAAG,GAAI;CAAQ,CAAA;AACtF"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { VariantProps } from "../lib/variants.js";
|
|
2
|
+
import { inputVariants } from "./input.js";
|
|
3
|
+
import { Select as Select$1 } from "@base-ui/react/select";
|
|
4
|
+
//#region src/components/select.d.ts
|
|
5
|
+
declare const Select: typeof Select$1.Root;
|
|
6
|
+
declare const SelectGroup: import("react").ForwardRefExoticComponent<Omit<import("@base-ui/react").SelectGroupProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
|
|
7
|
+
declare const SelectValue: import("react").ForwardRefExoticComponent<Omit<import("@base-ui/react").SelectValueProps, "ref"> & import("react").RefAttributes<HTMLSpanElement>>;
|
|
8
|
+
declare function SelectTrigger({ children, className, hover, focus, size, ...props }: Select$1.Trigger.Props & VariantProps<typeof inputVariants>): import("react").JSX.Element;
|
|
9
|
+
declare function SelectScrollUpButton({ className, ...props }: Select$1.ScrollUpArrow.Props): import("react").JSX.Element;
|
|
10
|
+
declare function SelectScrollDownButton({ className, ...props }: Select$1.ScrollDownArrow.Props): import("react").JSX.Element;
|
|
11
|
+
declare function SelectContent({ className, children, align, side, sideOffset, alignItemWithTrigger, ...props }: Select$1.Popup.Props & Pick<Select$1.Positioner.Props, "align" | "side" | "sideOffset" | "alignItemWithTrigger">): import("react").JSX.Element;
|
|
12
|
+
declare function SelectLabel({ className, ...props }: Select$1.GroupLabel.Props): import("react").JSX.Element;
|
|
13
|
+
declare function SelectItem({ className, children, label, ...props }: Select$1.Item.Props): import("react").JSX.Element;
|
|
14
|
+
declare function SelectSeparator({ className, ...props }: Select$1.Separator.Props): import("react").JSX.Element;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue };
|
|
17
|
+
//# sourceMappingURL=select.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"select.d.ts","names":[],"sources":["../../src/components/select.tsx"],"mappings":";;;;cAQM,eAAM,SAAA;cACN,6BAAW,0BAAA,8BAAA,2CAAA,cAAA;cACX,6BAAW,0BAAA,8BAAA,2CAAA,cAAA;iBAER,gBACP,UACA,WACA,OACA,OACA,SACG,SACF,SAAgB,QAAQ,QAAQ,oBAAoB,iCAAc,IAAA;iBAmB5D,uBAAuB,cAAc,SAAS,SAAgB,cAAc,wBAAK,IAAA;iBAWjF,yBAAyB,cAAc,SAAS,SAAgB,gBAAgB,wBAAK,IAAA;iBAqBrF,gBACP,WACA,UACA,OACA,MACA,YACA,yBACG,SACF,SAAgB,MAAM,QACvB,KACE,SAAgB,WAAW,mFAE5B,IAAA;iBA2BM,cAAc,cAAc,SAAS,SAAgB,WAAW,wBAAK,IAAA;iBASrE,aAAa,WAAW,UAAU,UAAU,SAAS,SAAgB,KAAK,wBAAK,IAAA;iBAoB/E,kBAAkB,cAAc,SAAS,SAAgB,UAAU,wBAAK,IAAA"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn, variants } from "../lib/variants.js";
|
|
3
|
+
import { CheckIcon, ChevronDownIcon, ChevronUpIcon, ChevronsUpDownIcon } from "../lib/icons.js";
|
|
4
|
+
import { popoverAnimationClasses } from "../lib/classes.js";
|
|
5
|
+
import { inputVariants } from "./input.js";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { Select as Select$1 } from "@base-ui/react/select";
|
|
8
|
+
//#region src/components/select.tsx
|
|
9
|
+
const Select = Select$1.Root;
|
|
10
|
+
const SelectGroup = Select$1.Group;
|
|
11
|
+
const SelectValue = Select$1.Value;
|
|
12
|
+
function SelectTrigger({ children, className, hover = true, focus = true, size, ...props }) {
|
|
13
|
+
return /* @__PURE__ */ jsxs(Select$1.Trigger, {
|
|
14
|
+
className: cn(inputVariants({
|
|
15
|
+
hover,
|
|
16
|
+
focus,
|
|
17
|
+
size
|
|
18
|
+
}), "flex items-center justify-between", className),
|
|
19
|
+
...props,
|
|
20
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
21
|
+
className: "truncate",
|
|
22
|
+
children
|
|
23
|
+
}), /* @__PURE__ */ jsx(Select$1.Icon, { render: /* @__PURE__ */ jsx(ChevronsUpDownIcon, { className: "ml-1 size-4 shrink-0 opacity-50" }) })]
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
function SelectScrollUpButton({ className, ...props }) {
|
|
27
|
+
return /* @__PURE__ */ jsx(Select$1.ScrollUpArrow, {
|
|
28
|
+
className: cn("flex cursor-pointer items-center justify-center py-1", className),
|
|
29
|
+
...props,
|
|
30
|
+
children: /* @__PURE__ */ jsx(ChevronUpIcon, {})
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
function SelectScrollDownButton({ className, ...props }) {
|
|
34
|
+
return /* @__PURE__ */ jsx(Select$1.ScrollDownArrow, {
|
|
35
|
+
className: cn("flex cursor-pointer items-center justify-center py-1", className),
|
|
36
|
+
...props,
|
|
37
|
+
children: /* @__PURE__ */ jsx(ChevronDownIcon, {})
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
const selectScrollButtonVariants = variants({
|
|
41
|
+
base: "absolute inset-x-0 z-10 bg-background animate-in fade-in-0 duration-300",
|
|
42
|
+
variants: { position: {
|
|
43
|
+
top: "top-0 mask-b-from-0",
|
|
44
|
+
bottom: "bottom-0 mask-t-from-0"
|
|
45
|
+
} }
|
|
46
|
+
});
|
|
47
|
+
function SelectContent({ className, children, align, side, sideOffset = 4, alignItemWithTrigger = false, ...props }) {
|
|
48
|
+
return /* @__PURE__ */ jsx(Select$1.Portal, { children: /* @__PURE__ */ jsx(Select$1.Positioner, {
|
|
49
|
+
sideOffset,
|
|
50
|
+
align,
|
|
51
|
+
side,
|
|
52
|
+
alignItemWithTrigger,
|
|
53
|
+
className: "isolate z-50",
|
|
54
|
+
children: /* @__PURE__ */ jsxs(Select$1.Popup, {
|
|
55
|
+
className: cn("relative z-50 isolate max-h-(--available-height) min-w-(--anchor-width) overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md backdrop-blur-xs", !alignItemWithTrigger && popoverAnimationClasses, className),
|
|
56
|
+
...props,
|
|
57
|
+
children: [
|
|
58
|
+
/* @__PURE__ */ jsx(SelectScrollUpButton, { className: selectScrollButtonVariants({ position: "top" }) }),
|
|
59
|
+
/* @__PURE__ */ jsx(Select$1.List, {
|
|
60
|
+
className: "p-1",
|
|
61
|
+
children
|
|
62
|
+
}),
|
|
63
|
+
/* @__PURE__ */ jsx(SelectScrollDownButton, { className: selectScrollButtonVariants({ position: "bottom" }) })
|
|
64
|
+
]
|
|
65
|
+
})
|
|
66
|
+
}) });
|
|
67
|
+
}
|
|
68
|
+
function SelectLabel({ className, ...props }) {
|
|
69
|
+
return /* @__PURE__ */ jsx(Select$1.GroupLabel, {
|
|
70
|
+
className: cn("px-2 py-1.5 text-sm font-medium", className),
|
|
71
|
+
...props
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
function SelectItem({ className, children, label, ...props }) {
|
|
75
|
+
return /* @__PURE__ */ jsxs(Select$1.Item, {
|
|
76
|
+
label: label ?? (typeof children === "string" ? children : void 0),
|
|
77
|
+
className: cn("relative flex w-full cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-control text-secondary-foreground outline-none focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50", className),
|
|
78
|
+
...props,
|
|
79
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
80
|
+
className: "absolute left-2 flex size-3.5 items-center justify-center",
|
|
81
|
+
children: /* @__PURE__ */ jsx(Select$1.ItemIndicator, { children: /* @__PURE__ */ jsx(CheckIcon, { className: "size-4" }) })
|
|
82
|
+
}), /* @__PURE__ */ jsx(Select$1.ItemText, { children })]
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
function SelectSeparator({ className, ...props }) {
|
|
86
|
+
return /* @__PURE__ */ jsx(Select$1.Separator, {
|
|
87
|
+
className: cn("-mx-1 my-1 h-px bg-border", className),
|
|
88
|
+
...props
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
//#endregion
|
|
92
|
+
export { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue };
|
|
93
|
+
|
|
94
|
+
//# sourceMappingURL=select.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"select.js","names":["SelectPrimitive"],"sources":["../../src/components/select.tsx"],"sourcesContent":["\"use client\"\n\nimport { Select as SelectPrimitive } from \"@base-ui/react/select\"\nimport { inputVariants } from \"~/components/input\"\nimport { popoverAnimationClasses } from \"~/lib/classes\"\nimport { CheckIcon, ChevronDownIcon, ChevronUpIcon, ChevronsUpDownIcon } from \"~/lib/icons\"\nimport { variants, cn, type VariantProps } from \"~/lib/variants\"\n\nconst Select = SelectPrimitive.Root\nconst SelectGroup = SelectPrimitive.Group\nconst SelectValue = SelectPrimitive.Value\n\nfunction SelectTrigger({\n children,\n className,\n hover = true,\n focus = true,\n size,\n ...props\n}: SelectPrimitive.Trigger.Props & VariantProps<typeof inputVariants>) {\n return (\n <SelectPrimitive.Trigger\n className={cn(\n inputVariants({ hover, focus, size }),\n \"flex items-center justify-between\",\n className,\n )}\n {...props}\n >\n <span className=\"truncate\">{children}</span>\n\n <SelectPrimitive.Icon\n render={<ChevronsUpDownIcon className=\"ml-1 size-4 shrink-0 opacity-50\" />}\n />\n </SelectPrimitive.Trigger>\n )\n}\n\nfunction SelectScrollUpButton({ className, ...props }: SelectPrimitive.ScrollUpArrow.Props) {\n return (\n <SelectPrimitive.ScrollUpArrow\n className={cn(\"flex cursor-pointer items-center justify-center py-1\", className)}\n {...props}\n >\n <ChevronUpIcon />\n </SelectPrimitive.ScrollUpArrow>\n )\n}\n\nfunction SelectScrollDownButton({ className, ...props }: SelectPrimitive.ScrollDownArrow.Props) {\n return (\n <SelectPrimitive.ScrollDownArrow\n className={cn(\"flex cursor-pointer items-center justify-center py-1\", className)}\n {...props}\n >\n <ChevronDownIcon />\n </SelectPrimitive.ScrollDownArrow>\n )\n}\n\nconst selectScrollButtonVariants = variants({\n base: \"absolute inset-x-0 z-10 bg-background animate-in fade-in-0 duration-300\",\n variants: {\n position: {\n top: \"top-0 mask-b-from-0\",\n bottom: \"bottom-0 mask-t-from-0\",\n },\n },\n})\n\nfunction SelectContent({\n className,\n children,\n align,\n side,\n sideOffset = 4,\n alignItemWithTrigger = false,\n ...props\n}: SelectPrimitive.Popup.Props &\n Pick<\n SelectPrimitive.Positioner.Props,\n \"align\" | \"side\" | \"sideOffset\" | \"alignItemWithTrigger\"\n >) {\n return (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Positioner\n sideOffset={sideOffset}\n align={align}\n side={side}\n alignItemWithTrigger={alignItemWithTrigger}\n className=\"isolate z-50\"\n >\n <SelectPrimitive.Popup\n className={cn(\n \"relative z-50 isolate max-h-(--available-height) min-w-(--anchor-width) overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md backdrop-blur-xs\",\n !alignItemWithTrigger && popoverAnimationClasses,\n className,\n )}\n {...props}\n >\n <SelectScrollUpButton className={selectScrollButtonVariants({ position: \"top\" })} />\n <SelectPrimitive.List className=\"p-1\">{children}</SelectPrimitive.List>\n <SelectScrollDownButton className={selectScrollButtonVariants({ position: \"bottom\" })} />\n </SelectPrimitive.Popup>\n </SelectPrimitive.Positioner>\n </SelectPrimitive.Portal>\n )\n}\n\nfunction SelectLabel({ className, ...props }: SelectPrimitive.GroupLabel.Props) {\n return (\n <SelectPrimitive.GroupLabel\n className={cn(\"px-2 py-1.5 text-sm font-medium\", className)}\n {...props}\n />\n )\n}\n\nfunction SelectItem({ className, children, label, ...props }: SelectPrimitive.Item.Props) {\n return (\n <SelectPrimitive.Item\n label={label ?? (typeof children === \"string\" ? children : undefined)}\n className={cn(\n \"relative flex w-full cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-control text-secondary-foreground outline-none focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50\",\n className,\n )}\n {...props}\n >\n <span className=\"absolute left-2 flex size-3.5 items-center justify-center\">\n <SelectPrimitive.ItemIndicator>\n <CheckIcon className=\"size-4\" />\n </SelectPrimitive.ItemIndicator>\n </span>\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n </SelectPrimitive.Item>\n )\n}\n\nfunction SelectSeparator({ className, ...props }: SelectPrimitive.Separator.Props) {\n return (\n <SelectPrimitive.Separator className={cn(\"-mx-1 my-1 h-px bg-border\", className)} {...props} />\n )\n}\n\nexport {\n Select,\n SelectGroup,\n SelectValue,\n SelectTrigger,\n SelectContent,\n SelectLabel,\n SelectItem,\n SelectSeparator,\n SelectScrollUpButton,\n SelectScrollDownButton,\n}\n"],"mappings":";;;;;;;;AAQA,MAAM,SAASA,SAAgB;AAC/B,MAAM,cAAcA,SAAgB;AACpC,MAAM,cAAcA,SAAgB;AAEpC,SAAS,cAAc,EACrB,UACA,WACA,QAAQ,MACR,QAAQ,MACR,MACA,GAAG,SACkE;CACrE,OACE,qBAACA,SAAgB,SAAjB;EACE,WAAW,GACT,cAAc;GAAE;GAAO;GAAO;EAAK,CAAC,GACpC,qCACA,SACF;EACA,GAAI;EANN,UAAA,CAQE,oBAAC,QAAD;GAAM,WAAU;GAAY;EAAe,CAAA,GAE3C,oBAACA,SAAgB,MAAjB,EACE,QAAQ,oBAAC,oBAAD,EAAoB,WAAU,kCAAmC,CAAA,EAC1E,CAAA,CACsB;;AAE7B;AAEA,SAAS,qBAAqB,EAAE,WAAW,GAAG,SAA8C;CAC1F,OACE,oBAACA,SAAgB,eAAjB;EACE,WAAW,GAAG,wDAAwD,SAAS;EAC/E,GAAI;EAEJ,UAAA,oBAAC,eAAD,CAAgB,CAAA;CACa,CAAA;AAEnC;AAEA,SAAS,uBAAuB,EAAE,WAAW,GAAG,SAAgD;CAC9F,OACE,oBAACA,SAAgB,iBAAjB;EACE,WAAW,GAAG,wDAAwD,SAAS;EAC/E,GAAI;EAEJ,UAAA,oBAAC,iBAAD,CAAkB,CAAA;CACa,CAAA;AAErC;AAEA,MAAM,6BAA6B,SAAS;CAC1C,MAAM;CACN,UAAU,EACR,UAAU;EACR,KAAK;EACL,QAAQ;CACV,EACF;AACF,CAAC;AAED,SAAS,cAAc,EACrB,WACA,UACA,OACA,MACA,aAAa,GACb,uBAAuB,OACvB,GAAG,SAKA;CACH,OACE,oBAACA,SAAgB,QAAjB,EAAA,UACE,oBAACA,SAAgB,YAAjB;EACc;EACL;EACD;EACgB;EACtB,WAAU;EAEV,UAAA,qBAACA,SAAgB,OAAjB;GACE,WAAW,GACT,2KACA,CAAC,wBAAwB,yBACzB,SACF;GACA,GAAI;GANN,UAAA;IAQE,oBAAC,sBAAD,EAAsB,WAAW,2BAA2B,EAAE,UAAU,MAAM,CAAC,EAAI,CAAA;IACnF,oBAACA,SAAgB,MAAjB;KAAsB,WAAU;KAAO;IAA+B,CAAA;IACtE,oBAAC,wBAAD,EAAwB,WAAW,2BAA2B,EAAE,UAAU,SAAS,CAAC,EAAI,CAAA;GACnE;;CACG,CAAA,EACN,CAAA;AAE5B;AAEA,SAAS,YAAY,EAAE,WAAW,GAAG,SAA2C;CAC9E,OACE,oBAACA,SAAgB,YAAjB;EACE,WAAW,GAAG,mCAAmC,SAAS;EAC1D,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,WAAW,EAAE,WAAW,UAAU,OAAO,GAAG,SAAqC;CACxF,OACE,qBAACA,SAAgB,MAAjB;EACE,OAAO,UAAU,OAAO,aAAa,WAAW,WAAW,KAAA;EAC3D,WAAW,GACT,wPACA,SACF;EACA,GAAI;EANN,UAAA,CAQE,oBAAC,QAAD;GAAM,WAAU;GACd,UAAA,oBAACA,SAAgB,eAAjB,EAAA,UACE,oBAAC,WAAD,EAAW,WAAU,SAAU,CAAA,EACF,CAAA;EAC3B,CAAA,GACN,oBAACA,SAAgB,UAAjB,EAA2B,SAAmC,CAAA,CAC1C;;AAE1B;AAEA,SAAS,gBAAgB,EAAE,WAAW,GAAG,SAA0C;CACjF,OACE,oBAACA,SAAgB,WAAjB;EAA2B,WAAW,GAAG,6BAA6B,SAAS;EAAG,GAAI;CAAQ,CAAA;AAElG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skeleton.d.ts","names":[],"sources":["../../src/components/skeleton.tsx"],"mappings":";;wBAGgB,WAAW,cAAc,SAAS,wCAAqB,IAAA"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { cn } from "../lib/variants.js";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
//#region src/components/skeleton.tsx
|
|
4
|
+
function Skeleton({ className, ...props }) {
|
|
5
|
+
return /* @__PURE__ */ jsx("div", {
|
|
6
|
+
className: cn("animate-pulse rounded-md bg-foreground/10", className),
|
|
7
|
+
...props
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
//#endregion
|
|
11
|
+
export { Skeleton };
|
|
12
|
+
|
|
13
|
+
//# sourceMappingURL=skeleton.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skeleton.js","names":[],"sources":["../../src/components/skeleton.tsx"],"sourcesContent":["import type { ComponentProps } from \"react\"\nimport { cn } from \"~/lib/variants\"\n\nexport function Skeleton({ className, ...props }: ComponentProps<\"div\">) {\n return <div className={cn(\"animate-pulse rounded-md bg-foreground/10\", className)} {...props} />\n}\n"],"mappings":";;;AAGA,SAAgB,SAAS,EAAE,WAAW,GAAG,SAAgC;CACvE,OAAO,oBAAC,OAAD;EAAK,WAAW,GAAG,6CAA6C,SAAS;EAAG,GAAI;CAAQ,CAAA;AACjG"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { VariantProps } from "../lib/variants.js";
|
|
2
|
+
import { useRender } from "@base-ui/react/use-render";
|
|
3
|
+
//#region src/components/stack.d.ts
|
|
4
|
+
declare const stackVariants: import("tailwind-variants").TVReturnType<{
|
|
5
|
+
size: {
|
|
6
|
+
xs: "gap-1";
|
|
7
|
+
sm: "gap-x-2 gap-y-1";
|
|
8
|
+
md: "gap-x-3 gap-y-2";
|
|
9
|
+
lg: "gap-x-4 gap-y-3";
|
|
10
|
+
};
|
|
11
|
+
direction: {
|
|
12
|
+
row: "flex-row items-center place-content-start";
|
|
13
|
+
column: "flex-col items-start";
|
|
14
|
+
};
|
|
15
|
+
wrap: {
|
|
16
|
+
true: "flex-wrap";
|
|
17
|
+
false: "";
|
|
18
|
+
};
|
|
19
|
+
}, undefined, "flex", {
|
|
20
|
+
size: {
|
|
21
|
+
xs: "gap-1";
|
|
22
|
+
sm: "gap-x-2 gap-y-1";
|
|
23
|
+
md: "gap-x-3 gap-y-2";
|
|
24
|
+
lg: "gap-x-4 gap-y-3";
|
|
25
|
+
};
|
|
26
|
+
direction: {
|
|
27
|
+
row: "flex-row items-center place-content-start";
|
|
28
|
+
column: "flex-col items-start";
|
|
29
|
+
};
|
|
30
|
+
wrap: {
|
|
31
|
+
true: "flex-wrap";
|
|
32
|
+
false: "";
|
|
33
|
+
};
|
|
34
|
+
}, undefined, import("tailwind-variants").TVReturnTypeLike<{
|
|
35
|
+
size: {
|
|
36
|
+
xs: "gap-1";
|
|
37
|
+
sm: "gap-x-2 gap-y-1";
|
|
38
|
+
md: "gap-x-3 gap-y-2";
|
|
39
|
+
lg: "gap-x-4 gap-y-3";
|
|
40
|
+
};
|
|
41
|
+
direction: {
|
|
42
|
+
row: "flex-row items-center place-content-start";
|
|
43
|
+
column: "flex-col items-start";
|
|
44
|
+
};
|
|
45
|
+
wrap: {
|
|
46
|
+
true: "flex-wrap";
|
|
47
|
+
false: "";
|
|
48
|
+
};
|
|
49
|
+
}, undefined>>;
|
|
50
|
+
type StackProps = useRender.ComponentProps<"div"> & VariantProps<typeof stackVariants>;
|
|
51
|
+
declare function Stack({ className, render, size, direction, wrap, ...props }: StackProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
52
|
+
//#endregion
|
|
53
|
+
export { Stack };
|
|
54
|
+
//# sourceMappingURL=stack.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stack.d.ts","names":[],"sources":["../../src/components/stack.tsx"],"mappings":";;;cAGM,2CAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA2Bd,aAAa,UAAU,wBAAwB,oBAAoB;iBAE/D,QAAQ,WAAW,QAAQ,MAAM,WAAW,SAAS,SAAS,6BAAU,+CAAA"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { cn, variants } from "../lib/variants.js";
|
|
2
|
+
import { useRender } from "@base-ui/react/use-render";
|
|
3
|
+
//#region src/components/stack.tsx
|
|
4
|
+
const stackVariants = variants({
|
|
5
|
+
base: "flex",
|
|
6
|
+
variants: {
|
|
7
|
+
size: {
|
|
8
|
+
xs: "gap-1",
|
|
9
|
+
sm: "gap-x-2 gap-y-1",
|
|
10
|
+
md: "gap-x-3 gap-y-2",
|
|
11
|
+
lg: "gap-x-4 gap-y-3"
|
|
12
|
+
},
|
|
13
|
+
direction: {
|
|
14
|
+
row: "flex-row items-center place-content-start",
|
|
15
|
+
column: "flex-col items-start"
|
|
16
|
+
},
|
|
17
|
+
wrap: {
|
|
18
|
+
true: "flex-wrap",
|
|
19
|
+
false: ""
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
defaultVariants: {
|
|
23
|
+
size: "md",
|
|
24
|
+
direction: "row",
|
|
25
|
+
wrap: true
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
function Stack({ className, render, size, direction, wrap, ...props }) {
|
|
29
|
+
return useRender({
|
|
30
|
+
render,
|
|
31
|
+
defaultTagName: "div",
|
|
32
|
+
props: {
|
|
33
|
+
className: cn(stackVariants({
|
|
34
|
+
size,
|
|
35
|
+
direction,
|
|
36
|
+
wrap,
|
|
37
|
+
className
|
|
38
|
+
})),
|
|
39
|
+
...props
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
//#endregion
|
|
44
|
+
export { Stack };
|
|
45
|
+
|
|
46
|
+
//# sourceMappingURL=stack.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stack.js","names":[],"sources":["../../src/components/stack.tsx"],"sourcesContent":["import { useRender } from \"@base-ui/react/use-render\"\nimport { variants, cn, type VariantProps } from \"~/lib/variants\"\n\nconst stackVariants = variants({\n base: \"flex\",\n\n variants: {\n size: {\n xs: \"gap-1\",\n sm: \"gap-x-2 gap-y-1\",\n md: \"gap-x-3 gap-y-2\",\n lg: \"gap-x-4 gap-y-3\",\n },\n direction: {\n row: \"flex-row items-center place-content-start\",\n column: \"flex-col items-start\",\n },\n wrap: {\n true: \"flex-wrap\",\n false: \"\",\n },\n },\n\n defaultVariants: {\n size: \"md\",\n direction: \"row\",\n wrap: true,\n },\n})\n\ntype StackProps = useRender.ComponentProps<\"div\"> & VariantProps<typeof stackVariants>\n\nfunction Stack({ className, render, size, direction, wrap, ...props }: StackProps) {\n return useRender({\n render,\n defaultTagName: \"div\",\n props: { className: cn(stackVariants({ size, direction, wrap, className })), ...props },\n })\n}\n\nexport { Stack }\n"],"mappings":";;;AAGA,MAAM,gBAAgB,SAAS;CAC7B,MAAM;CAEN,UAAU;EACR,MAAM;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;EACN;EACA,WAAW;GACT,KAAK;GACL,QAAQ;EACV;EACA,MAAM;GACJ,MAAM;GACN,OAAO;EACT;CACF;CAEA,iBAAiB;EACf,MAAM;EACN,WAAW;EACX,MAAM;CACR;AACF,CAAC;AAID,SAAS,MAAM,EAAE,WAAW,QAAQ,MAAM,WAAW,MAAM,GAAG,SAAqB;CACjF,OAAO,UAAU;EACf;EACA,gBAAgB;EAChB,OAAO;GAAE,WAAW,GAAG,cAAc;IAAE;IAAM;IAAW;IAAM;GAAU,CAAC,CAAC;GAAG,GAAG;EAAM;CACxF,CAAC;AACH"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { VariantProps } from "../lib/variants.js";
|
|
2
|
+
import { Format } from "@number-flow/react";
|
|
3
|
+
import { useRender } from "@base-ui/react/use-render";
|
|
4
|
+
import { ComponentProps } from "react";
|
|
5
|
+
//#region src/components/stat-strip.d.ts
|
|
6
|
+
declare const stripVariants: import("tailwind-variants").TVReturnType<{
|
|
7
|
+
variant: {
|
|
8
|
+
plain: "overflow-clip rounded-xl border bg-card shadow-xs";
|
|
9
|
+
track: "rounded-xl bg-background p-1.5 sm:gap-x-[13px]";
|
|
10
|
+
};
|
|
11
|
+
}, undefined, "group/strip grid grid-cols-2 gap-y-1 max-sm:[&>*:last-child:nth-child(odd)]:col-span-2 sm:flex sm:flex-wrap sm:gap-y-0", {
|
|
12
|
+
variant: {
|
|
13
|
+
plain: "overflow-clip rounded-xl border bg-card shadow-xs";
|
|
14
|
+
track: "rounded-xl bg-background p-1.5 sm:gap-x-[13px]";
|
|
15
|
+
};
|
|
16
|
+
}, undefined, import("tailwind-variants").TVReturnTypeLike<{
|
|
17
|
+
variant: {
|
|
18
|
+
plain: "overflow-clip rounded-xl border bg-card shadow-xs";
|
|
19
|
+
track: "rounded-xl bg-background p-1.5 sm:gap-x-[13px]";
|
|
20
|
+
};
|
|
21
|
+
}, undefined>>;
|
|
22
|
+
type StatStripProps = ComponentProps<"div"> & VariantProps<typeof stripVariants>;
|
|
23
|
+
declare function StatStrip({ className, variant, ...props }: StatStripProps): import("react").JSX.Element;
|
|
24
|
+
type StatStripItemProps = Omit<useRender.ComponentProps<"div">, "children"> & {
|
|
25
|
+
label: string;
|
|
26
|
+
value: string | number;
|
|
27
|
+
format?: Format;
|
|
28
|
+
hint?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Marks the item as the one driving the panel beside it. Pass `render={<button ... />}`
|
|
31
|
+
* to make it selectable.
|
|
32
|
+
*/
|
|
33
|
+
selected?: boolean;
|
|
34
|
+
};
|
|
35
|
+
declare function StatStripItem({ label, value, format, hint, selected, render, className, ...props }: StatStripItemProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
36
|
+
//#endregion
|
|
37
|
+
export { StatStrip, StatStripItem };
|
|
38
|
+
//# sourceMappingURL=stat-strip.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stat-strip.d.ts","names":[],"sources":["../../src/components/stat-strip.tsx"],"mappings":";;;;;cAOM,2CAAa;;;;;;;;;;;;;;;;KAmBd,iBAAiB,wBAAwB,oBAAoB;iBAEzD,YAAY,WAAW,YAAY,SAAS,iCAAc,IAAA;KAU9D,qBAAqB,KAAK,UAAU;EACvC;EACA;EACA,SAAS;EACT;;;;;EAKA;;iBAGO,gBACP,OACA,OACA,QACA,MACA,UACA,QACA,cACG,SACF,qCAAkB,+CAAA"}
|