@ploykit/ui 0.1.1 → 0.4.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/README.md +183 -23
- package/dist/AppProviders.d.ts +15 -0
- package/dist/AppProviders.js +15 -0
- package/dist/components/ConfirmDialog.js +8 -2
- package/dist/components/CronInput.js +2 -2
- package/dist/components/DataTable.d.ts +12 -3
- package/dist/components/DataTable.js +7 -3
- package/dist/components/ErrorBoundary.js +1 -1
- package/dist/components/ImpersonationBanner.js +1 -1
- package/dist/components/NotificationBell.js +5 -5
- package/dist/components/OnboardingChecklist.js +3 -3
- package/dist/components/Page.js +1 -1
- package/dist/components/ReauthDialog.d.ts +15 -0
- package/dist/components/ReauthDialog.js +42 -0
- package/dist/components/SecretModal.d.ts +8 -1
- package/dist/components/SecretModal.js +6 -3
- package/dist/components/SettingsCard.js +2 -2
- package/dist/components/SiteBannerLayer.js +1 -1
- package/dist/components/StatusBadge.d.ts +4 -0
- package/dist/components/StatusBadge.js +7 -0
- package/dist/components/UserMenu.js +2 -2
- package/dist/components/WorkspaceSwitcher.js +4 -4
- package/dist/components/ui/alert-dialog.d.ts +2 -2
- package/dist/components/ui/alert-dialog.js +10 -9
- package/dist/components/ui/avatar.js +3 -2
- package/dist/components/ui/badge.d.ts +7 -0
- package/dist/components/ui/badge.js +33 -0
- package/dist/components/ui/breadcrumb.js +7 -7
- package/dist/components/ui/button.d.ts +8 -0
- package/dist/components/ui/button.js +34 -0
- package/dist/components/ui/card.d.ts +2 -4
- package/dist/components/ui/card.js +7 -7
- package/dist/components/ui/checkbox.js +3 -2
- package/dist/components/ui/dialog.d.ts +22 -14
- package/dist/components/ui/dialog.js +40 -25
- package/dist/components/ui/dropdown-menu.js +50 -0
- package/dist/components/ui/empty.d.ts +7 -9
- package/dist/components/ui/empty.js +6 -9
- package/dist/components/ui/field.js +10 -9
- package/dist/components/ui/input.d.ts +3 -0
- package/dist/components/ui/input.js +7 -0
- package/dist/components/ui/popover.js +3 -2
- package/dist/components/ui/progress.js +2 -1
- package/dist/components/ui/select.d.ts +20 -1
- package/dist/components/ui/select.js +28 -7
- package/dist/components/ui/separator.js +1 -0
- package/dist/components/ui/sheet.d.ts +9 -1
- package/dist/components/ui/sheet.js +11 -4
- package/dist/components/ui/sidebar.d.ts +2 -2
- package/dist/components/ui/sidebar.js +25 -34
- package/dist/components/ui/skeleton.d.ts +1 -2
- package/dist/components/ui/switch.js +1 -1
- package/dist/components/ui/tabs.js +3 -3
- package/dist/components/ui/textarea.d.ts +9 -0
- package/dist/components/ui/textarea.js +12 -0
- package/dist/components/ui/tooltip.js +1 -1
- package/dist/index.d.ts +10 -40
- package/dist/index.js +10 -26
- package/dist/layouts/AppShell.d.ts +1 -1
- package/dist/layouts/AppShell.js +23 -1
- package/dist/layouts/SettingsShell.d.ts +1 -1
- package/dist/layouts/SettingsShell.js +3 -3
- package/dist/pages/LandingPage.js +1 -1
- package/dist/pages/LoginPage.js +7 -7
- package/dist/pages/account/NotificationPreferencesPage.js +2 -2
- package/dist/pages/account/ProfileSettingsPage.js +7 -7
- package/dist/pages/account/SecuritySettingsPage.js +8 -8
- package/dist/pages/account/TokensPage.js +4 -4
- package/dist/pages/admin/AdminSettingsPage.js +5 -5
- package/dist/pages/admin/AdminShell.js +2 -2
- package/dist/pages/admin/AuditPage.js +3 -3
- package/dist/pages/admin/OrdersPage.js +4 -3
- package/dist/pages/admin/OverviewPage.js +4 -4
- package/dist/pages/admin/SSOPage.js +3 -3
- package/dist/pages/admin/UserDetailPage.js +6 -5
- package/dist/pages/admin/UsersPage.js +7 -6
- package/dist/pages/admin/WebhookDeliveriesPage.js +4 -3
- package/dist/pages/admin/WorkspaceDetailPage.js +5 -5
- package/dist/pages/admin/WorkspacesPage.js +4 -4
- package/dist/pages/admin/shared.js +1 -1
- package/dist/pages/auth/ForgotPasswordPage.js +3 -3
- package/dist/pages/auth/InviteAcceptPage.js +4 -4
- package/dist/pages/auth/RegisterPage.js +6 -6
- package/dist/pages/auth/ResetPasswordPage.js +4 -4
- package/dist/pages/auth/VerifyEmailPage.js +4 -4
- package/dist/pages/workspace/BillingPage.js +8 -7
- package/dist/pages/workspace/BillingSuccessPage.js +3 -3
- package/dist/pages/workspace/MembersPage.js +7 -6
- package/dist/pages/workspace/RolePermissionsPage.d.ts +3 -0
- package/dist/pages/workspace/RolePermissionsPage.js +118 -0
- package/dist/pages/workspace/SchedulesPage.js +5 -5
- package/dist/pages/workspace/UsagePage.d.ts +1 -1
- package/dist/pages/workspace/UsagePage.js +2 -2
- package/dist/pages/workspace/WebhooksPage.js +9 -9
- package/dist/pages/workspace/WorkspaceAuditPage.js +3 -3
- package/dist/pages/workspace/WorkspaceGeneralPage.js +7 -7
- package/package.json +9 -5
- package/dist/components/ui/Badge.d.ts +0 -13
- package/dist/components/ui/Badge.js +0 -21
- package/dist/components/ui/Button.d.ts +0 -10
- package/dist/components/ui/Button.js +0 -33
- package/dist/components/ui/Input.d.ts +0 -3
- package/dist/components/ui/Input.js +0 -10
- package/dist/components/ui/menu.js +0 -50
- package/dist/hooks/useApi.d.ts +0 -10
- package/dist/hooks/useApi.js +0 -11
- package/dist/hooks/useAudit.d.ts +0 -39
- package/dist/hooks/useAudit.js +0 -55
- package/dist/hooks/useAuth.d.ts +0 -1
- package/dist/hooks/useAuth.js +0 -4
- package/dist/hooks/useBilling.d.ts +0 -44
- package/dist/hooks/useBilling.js +0 -64
- package/dist/hooks/useLogin.d.ts +0 -10
- package/dist/hooks/useLogin.js +0 -39
- package/dist/hooks/useMembers.d.ts +0 -125
- package/dist/hooks/useMembers.js +0 -127
- package/dist/hooks/useNotificationPrefs.d.ts +0 -20
- package/dist/hooks/useNotificationPrefs.js +0 -42
- package/dist/hooks/usePasswordReset.d.ts +0 -5
- package/dist/hooks/usePasswordReset.js +0 -12
- package/dist/hooks/useSEO.d.ts +0 -6
- package/dist/hooks/useSEO.js +0 -14
- package/dist/hooks/useSessions.d.ts +0 -20
- package/dist/hooks/useSessions.js +0 -38
- package/dist/hooks/useSiteConfig.d.ts +0 -12
- package/dist/hooks/useSiteConfig.js +0 -11
- package/dist/hooks/useTokens.d.ts +0 -36
- package/dist/hooks/useTokens.js +0 -35
- package/dist/hooks/useUsage.d.ts +0 -20
- package/dist/hooks/useUsage.js +0 -21
- package/dist/hooks/useWorkspace.d.ts +0 -26
- package/dist/hooks/useWorkspace.js +0 -32
- package/dist/hooks/useZodForm.d.ts +0 -6
- package/dist/hooks/useZodForm.js +0 -6
- package/dist/hooks/ws.d.ts +0 -4
- package/dist/hooks/ws.js +0 -21
- package/dist/lib/perm.d.ts +0 -2
- package/dist/lib/perm.js +0 -7
- package/dist/lib/ws-query-bridge.d.ts +0 -7
- package/dist/lib/ws-query-bridge.js +0 -35
- package/dist/provider/PloykitProvider.d.ts +0 -50
- package/dist/provider/PloykitProvider.js +0 -240
- package/dist/realtime.d.ts +0 -3
- package/dist/realtime.js +0 -11
- /package/dist/components/ui/{menu.d.ts → dropdown-menu.d.ts} +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use client";
|
|
1
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
3
|
import { useMemo } from "react";
|
|
3
4
|
import { cva } from "class-variance-authority";
|
|
@@ -5,15 +6,15 @@ import { cn } from "../../lib/utils";
|
|
|
5
6
|
import { Label } from "./label";
|
|
6
7
|
import { Separator } from "./separator";
|
|
7
8
|
function FieldSet({ className, ...props }) {
|
|
8
|
-
return (_jsx("fieldset", { "data-slot": "field-set", className: cn("flex flex-col gap-
|
|
9
|
+
return (_jsx("fieldset", { "data-slot": "field-set", className: cn("flex flex-col gap-4 has-[>[data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3", className), ...props }));
|
|
9
10
|
}
|
|
10
11
|
function FieldLegend({ className, variant = "legend", ...props }) {
|
|
11
|
-
return (_jsx("legend", { "data-slot": "field-legend", "data-variant": variant, className: cn("mb-
|
|
12
|
+
return (_jsx("legend", { "data-slot": "field-legend", "data-variant": variant, className: cn("mb-1.5 font-medium data-[variant=label]:text-sm data-[variant=legend]:text-base", className), ...props }));
|
|
12
13
|
}
|
|
13
14
|
function FieldGroup({ className, ...props }) {
|
|
14
|
-
return (_jsx("div", { "data-slot": "field-group", className: cn("group/field-group @container/field-group flex w-full flex-col gap-
|
|
15
|
+
return (_jsx("div", { "data-slot": "field-group", className: cn("group/field-group @container/field-group flex w-full flex-col gap-5 data-[slot=checkbox-group]:gap-3 *:data-[slot=field-group]:gap-4", className), ...props }));
|
|
15
16
|
}
|
|
16
|
-
const fieldVariants = cva("group/field flex w-full gap-
|
|
17
|
+
const fieldVariants = cva("group/field flex w-full gap-2 data-[invalid=true]:text-destructive", {
|
|
17
18
|
variants: {
|
|
18
19
|
orientation: {
|
|
19
20
|
vertical: "flex-col *:w-full [&>.sr-only]:w-auto",
|
|
@@ -29,16 +30,16 @@ function Field({ className, orientation = "vertical", ...props }) {
|
|
|
29
30
|
return (_jsx("div", { role: "group", "data-slot": "field", "data-orientation": orientation, className: cn(fieldVariants({ orientation }), className), ...props }));
|
|
30
31
|
}
|
|
31
32
|
function FieldContent({ className, ...props }) {
|
|
32
|
-
return (_jsx("div", { "data-slot": "field-content", className: cn("group/field-content flex flex-1 flex-col gap-
|
|
33
|
+
return (_jsx("div", { "data-slot": "field-content", className: cn("group/field-content flex flex-1 flex-col gap-0.5 leading-snug", className), ...props }));
|
|
33
34
|
}
|
|
34
35
|
function FieldLabel({ className, ...props }) {
|
|
35
|
-
return (_jsx(Label, { "data-slot": "field-label", className: cn("group/field-label peer/field-label flex w-fit gap-2 leading-snug group-data-[disabled=true]/field:opacity-50
|
|
36
|
+
return (_jsx(Label, { "data-slot": "field-label", className: cn("group/field-label peer/field-label flex w-fit gap-2 leading-snug group-data-[disabled=true]/field:opacity-50 has-data-checked:border-primary/30 has-data-checked:bg-primary/5 has-[>[data-slot=field]]:rounded-lg has-[>[data-slot=field]]:border has-[>[data-slot=field]]:not-has-[:disabled,[data-disabled]]:hover:bg-muted/50 has-[>[data-slot=field]]:has-[:focus-visible]:border-ring has-[>[data-slot=field]]:has-[:focus-visible]:ring-3 has-[>[data-slot=field]]:has-[:focus-visible]:ring-ring/50 *:data-[slot=field]:p-2.5 dark:has-data-checked:border-primary/20 dark:has-data-checked:bg-primary/10", "has-[>[data-slot=field]]:w-full has-[>[data-slot=field]]:flex-col", className), ...props }));
|
|
36
37
|
}
|
|
37
38
|
function FieldTitle({ className, ...props }) {
|
|
38
|
-
return (_jsx("div", { "data-slot": "field-label", className: cn("flex w-fit items-center gap-2 text-sm
|
|
39
|
+
return (_jsx("div", { "data-slot": "field-label", className: cn("flex w-fit items-center gap-2 text-sm font-medium group-data-[disabled=true]/field:opacity-50", className), ...props }));
|
|
39
40
|
}
|
|
40
41
|
function FieldDescription({ className, ...props }) {
|
|
41
|
-
return (_jsx("p", { "data-slot": "field-description", className: cn("text-
|
|
42
|
+
return (_jsx("p", { "data-slot": "field-description", className: cn("text-left text-sm leading-normal font-normal text-muted-foreground group-has-data-horizontal/field:text-balance [[data-variant=legend]+&]:-mt-1.5", "last:mt-0 nth-last-2:-mt-1", "[&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary", className), ...props }));
|
|
42
43
|
}
|
|
43
44
|
function FieldSeparator({ children, className, ...props }) {
|
|
44
45
|
return (_jsxs("div", { "data-slot": "field-separator", "data-content": !!children, className: cn("relative -my-2 h-5 text-sm group-data-[variant=outline]/field-group:-mb-2", className), ...props, children: [_jsx(Separator, { className: "absolute inset-0 top-1/2" }), children && (_jsx("span", { className: "relative mx-auto block w-fit bg-background px-2 text-muted-foreground", "data-slot": "field-separator-content", children: children }))] }));
|
|
@@ -62,6 +63,6 @@ function FieldError({ className, children, errors, ...props }) {
|
|
|
62
63
|
if (!content) {
|
|
63
64
|
return null;
|
|
64
65
|
}
|
|
65
|
-
return (_jsx("div", { role: "alert", "data-slot": "field-error", className: cn("text-
|
|
66
|
+
return (_jsx("div", { role: "alert", "data-slot": "field-error", className: cn("text-sm font-normal text-destructive", className), ...props, children: content }));
|
|
66
67
|
}
|
|
67
68
|
export { Field, FieldLabel, FieldDescription, FieldError, FieldGroup, FieldLegend, FieldSeparator, FieldSet, FieldContent, FieldTitle, };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Input as InputPrimitive } from "@base-ui/react/input";
|
|
3
|
+
import { cn } from "../../lib/utils";
|
|
4
|
+
function Input({ className, type, ...props }) {
|
|
5
|
+
return (_jsx(InputPrimitive, { type: type, "data-slot": "input", className: cn("h-8 w-full min-w-0 rounded-lg border border-input bg-transparent px-2.5 py-1 text-base transition-colors outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40", className), ...props }));
|
|
6
|
+
}
|
|
7
|
+
export { Input };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use client";
|
|
1
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
3
|
import { Popover as PopoverPrimitive } from "@base-ui/react/popover";
|
|
3
4
|
import { cn } from "../../lib/utils";
|
|
@@ -8,10 +9,10 @@ function PopoverTrigger({ ...props }) {
|
|
|
8
9
|
return _jsx(PopoverPrimitive.Trigger, { "data-slot": "popover-trigger", ...props });
|
|
9
10
|
}
|
|
10
11
|
function PopoverContent({ className, align = "center", alignOffset = 0, side = "bottom", sideOffset = 4, ...props }) {
|
|
11
|
-
return (_jsx(PopoverPrimitive.Portal, { children: _jsx(PopoverPrimitive.Positioner, { align: align, alignOffset: alignOffset, side: side, sideOffset: sideOffset, className: "isolate z-50", children: _jsx(PopoverPrimitive.Popup, { "data-slot": "popover-content", className: cn("z-50 flex w-72 origin-(--transform-origin) flex-col gap-
|
|
12
|
+
return (_jsx(PopoverPrimitive.Portal, { children: _jsx(PopoverPrimitive.Positioner, { align: align, alignOffset: alignOffset, side: side, sideOffset: sideOffset, className: "isolate z-50", children: _jsx(PopoverPrimitive.Popup, { "data-slot": "popover-content", className: cn("z-50 flex w-72 origin-(--transform-origin) flex-col gap-2.5 rounded-lg bg-popover p-2.5 text-sm text-popover-foreground shadow-md ring-1 ring-foreground/10 outline-hidden duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", className), ...props }) }) }));
|
|
12
13
|
}
|
|
13
14
|
function PopoverHeader({ className, ...props }) {
|
|
14
|
-
return (_jsx("div", { "data-slot": "popover-header", className: cn("flex flex-col gap-
|
|
15
|
+
return (_jsx("div", { "data-slot": "popover-header", className: cn("flex flex-col gap-0.5 text-sm", className), ...props }));
|
|
15
16
|
}
|
|
16
17
|
function PopoverTitle({ className, ...props }) {
|
|
17
18
|
return (_jsx(PopoverPrimitive.Title, { "data-slot": "popover-title", className: cn("font-medium", className), ...props }));
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use client";
|
|
1
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
3
|
import { Progress as ProgressPrimitive } from "@base-ui/react/progress";
|
|
3
4
|
import { cn } from "../../lib/utils";
|
|
@@ -5,7 +6,7 @@ function Progress({ className, children, value, ...props }) {
|
|
|
5
6
|
return (_jsxs(ProgressPrimitive.Root, { value: value, "data-slot": "progress", className: cn("flex flex-wrap gap-3", className), ...props, children: [children, _jsx(ProgressTrack, { children: _jsx(ProgressIndicator, {}) })] }));
|
|
6
7
|
}
|
|
7
8
|
function ProgressTrack({ className, ...props }) {
|
|
8
|
-
return (_jsx(ProgressPrimitive.Track, { className: cn("relative flex h-1
|
|
9
|
+
return (_jsx(ProgressPrimitive.Track, { className: cn("relative flex h-1 w-full items-center overflow-x-hidden rounded-full bg-muted", className), "data-slot": "progress-track", ...props }));
|
|
9
10
|
}
|
|
10
11
|
function ProgressIndicator({ className, ...props }) {
|
|
11
12
|
return (_jsx(ProgressPrimitive.Indicator, { "data-slot": "progress-indicator", className: cn("h-full bg-primary transition-all", className), ...props }));
|
|
@@ -1,8 +1,27 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { Select as SelectPrimitive } from "@base-ui/react/select";
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Select 根组件:base-ui Select Root 的 string 契约包装。
|
|
5
|
+
*
|
|
6
|
+
* 契约:onValueChange 永远收到 string——base-ui 原生回调的 value 可为 null
|
|
7
|
+
* (清空/取消选择时),包装层统一归一为空串(''),产品侧无需再写
|
|
8
|
+
* `v ?? ''` 卫语句。受控 value 仍允许 null、类型不收窄(与 base-ui 一致);
|
|
9
|
+
* 其余 props(items/defaultValue/children 等)原样透传。
|
|
10
|
+
* 泛型保留(默认 string):个别历史调用点用数值 item(如 days),此时
|
|
11
|
+
* 回调运行时收到的是原始数值——签名仍标为 string,属已知偏差。
|
|
12
|
+
* 多选(multiple)不在本契约内;如需多选请直接使用
|
|
13
|
+
* `@base-ui/react/select` 的 Root 原语。
|
|
14
|
+
*/
|
|
15
|
+
declare function Select<Value = string>({ onValueChange, ...props }: Omit<SelectPrimitive.Root.Props<Value, false>, "onValueChange" | "multiple"> & {
|
|
16
|
+
onValueChange?: (value: string) => void;
|
|
17
|
+
}): React.JSX.Element;
|
|
4
18
|
declare function SelectGroup({ className, ...props }: SelectPrimitive.Group.Props): React.JSX.Element;
|
|
5
19
|
declare function SelectValue({ className, ...props }: SelectPrimitive.Value.Props): React.JSX.Element;
|
|
20
|
+
/**
|
|
21
|
+
* SelectTrigger 触发按钮。size 控制高度档位(经 data-size 落到 Tailwind
|
|
22
|
+
* data-[size=*] 变体):'default' = h-8(表单默认高度);'sm' = h-7 +
|
|
23
|
+
* 更小圆角(工具栏/紧凑筛选条)。默认 'default'。
|
|
24
|
+
*/
|
|
6
25
|
declare function SelectTrigger({ className, size, children, ...props }: SelectPrimitive.Trigger.Props & {
|
|
7
26
|
size?: "sm" | "default";
|
|
8
27
|
}): React.JSX.Element;
|
|
@@ -1,25 +1,46 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Select as SelectPrimitive } from "@base-ui/react/select";
|
|
3
|
-
import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react";
|
|
4
3
|
import { cn } from "../../lib/utils";
|
|
5
|
-
|
|
4
|
+
import { ChevronDownIcon, CheckIcon, ChevronUpIcon } from "lucide-react";
|
|
5
|
+
/**
|
|
6
|
+
* Select 根组件:base-ui Select Root 的 string 契约包装。
|
|
7
|
+
*
|
|
8
|
+
* 契约:onValueChange 永远收到 string——base-ui 原生回调的 value 可为 null
|
|
9
|
+
* (清空/取消选择时),包装层统一归一为空串(''),产品侧无需再写
|
|
10
|
+
* `v ?? ''` 卫语句。受控 value 仍允许 null、类型不收窄(与 base-ui 一致);
|
|
11
|
+
* 其余 props(items/defaultValue/children 等)原样透传。
|
|
12
|
+
* 泛型保留(默认 string):个别历史调用点用数值 item(如 days),此时
|
|
13
|
+
* 回调运行时收到的是原始数值——签名仍标为 string,属已知偏差。
|
|
14
|
+
* 多选(multiple)不在本契约内;如需多选请直接使用
|
|
15
|
+
* `@base-ui/react/select` 的 Root 原语。
|
|
16
|
+
*/
|
|
17
|
+
function Select({ onValueChange, ...props }) {
|
|
18
|
+
return (_jsx(SelectPrimitive.Root, { ...props, onValueChange: onValueChange
|
|
19
|
+
? (value) => onValueChange(value == null ? "" : value)
|
|
20
|
+
: undefined }));
|
|
21
|
+
}
|
|
6
22
|
function SelectGroup({ className, ...props }) {
|
|
7
23
|
return (_jsx(SelectPrimitive.Group, { "data-slot": "select-group", className: cn("scroll-my-1 p-1", className), ...props }));
|
|
8
24
|
}
|
|
9
25
|
function SelectValue({ className, ...props }) {
|
|
10
|
-
return (_jsx(SelectPrimitive.Value, { "data-slot": "select-value", className: cn("flex flex-1 text-left
|
|
26
|
+
return (_jsx(SelectPrimitive.Value, { "data-slot": "select-value", className: cn("flex flex-1 text-left", className), ...props }));
|
|
11
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* SelectTrigger 触发按钮。size 控制高度档位(经 data-size 落到 Tailwind
|
|
30
|
+
* data-[size=*] 变体):'default' = h-8(表单默认高度);'sm' = h-7 +
|
|
31
|
+
* 更小圆角(工具栏/紧凑筛选条)。默认 'default'。
|
|
32
|
+
*/
|
|
12
33
|
function SelectTrigger({ className, size = "default", children, ...props }) {
|
|
13
|
-
return (_jsxs(SelectPrimitive.Trigger, { "data-slot": "select-trigger", "data-size": size, className: cn("flex w-fit items-center justify-between gap-1.5
|
|
34
|
+
return (_jsxs(SelectPrimitive.Trigger, { "data-slot": "select-trigger", "data-size": size, className: cn("flex w-fit items-center justify-between gap-1.5 rounded-lg border border-input bg-transparent py-2 pr-2 pl-2.5 text-sm whitespace-nowrap transition-colors outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-placeholder:text-muted-foreground data-[size=default]:h-8 data-[size=sm]:h-7 data-[size=sm]:rounded-[min(var(--radius-md),10px)] *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className), ...props, children: [children, _jsx(SelectPrimitive.Icon, { render: _jsx(ChevronDownIcon, { className: "pointer-events-none size-4 text-muted-foreground" }) })] }));
|
|
14
35
|
}
|
|
15
36
|
function SelectContent({ className, children, side = "bottom", sideOffset = 4, align = "center", alignOffset = 0, alignItemWithTrigger = true, ...props }) {
|
|
16
|
-
return (_jsx(SelectPrimitive.Portal, { children: _jsx(SelectPrimitive.Positioner, { side: side, sideOffset: sideOffset, align: align, alignOffset: alignOffset, alignItemWithTrigger: alignItemWithTrigger, className: "isolate z-50", children: _jsxs(SelectPrimitive.Popup, { "data-slot": "select-content", "data-align-trigger": alignItemWithTrigger, className: cn("relative isolate z-50 max-h-(--available-height)
|
|
37
|
+
return (_jsx(SelectPrimitive.Portal, { children: _jsx(SelectPrimitive.Positioner, { side: side, sideOffset: sideOffset, align: align, alignOffset: alignOffset, alignItemWithTrigger: alignItemWithTrigger, className: "isolate z-50", children: _jsxs(SelectPrimitive.Popup, { "data-slot": "select-content", "data-align-trigger": alignItemWithTrigger, className: cn("relative isolate z-50 max-h-(--available-height) w-(--anchor-width) min-w-36 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[align-trigger=true]:animate-none data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", className), ...props, children: [_jsx(SelectScrollUpButton, {}), _jsx(SelectPrimitive.List, { children: children }), _jsx(SelectScrollDownButton, {})] }) }) }));
|
|
17
38
|
}
|
|
18
39
|
function SelectLabel({ className, ...props }) {
|
|
19
|
-
return (_jsx(SelectPrimitive.GroupLabel, { "data-slot": "select-label", className: cn("px-
|
|
40
|
+
return (_jsx(SelectPrimitive.GroupLabel, { "data-slot": "select-label", className: cn("px-1.5 py-1 text-xs text-muted-foreground", className), ...props }));
|
|
20
41
|
}
|
|
21
42
|
function SelectItem({ className, children, ...props }) {
|
|
22
|
-
return (_jsxs(SelectPrimitive.Item, { "data-slot": "select-item", className: cn("relative flex w-full cursor-default items-center gap-
|
|
43
|
+
return (_jsxs(SelectPrimitive.Item, { "data-slot": "select-item", className: cn("relative flex w-full cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2", className), ...props, children: [_jsx(SelectPrimitive.ItemText, { className: "flex flex-1 shrink-0 gap-2 whitespace-nowrap", children: children }), _jsx(SelectPrimitive.ItemIndicator, { render: _jsx("span", { className: "pointer-events-none absolute right-2 flex size-4 items-center justify-center" }), children: _jsx(CheckIcon, { className: "pointer-events-none" }) })] }));
|
|
23
44
|
}
|
|
24
45
|
function SelectSeparator({ className, ...props }) {
|
|
25
46
|
return (_jsx(SelectPrimitive.Separator, { "data-slot": "select-separator", className: cn("pointer-events-none -mx-1 my-1 h-px bg-border", className), ...props }));
|
|
@@ -3,8 +3,16 @@ import { Dialog as SheetPrimitive } from "@base-ui/react/dialog";
|
|
|
3
3
|
declare function Sheet({ ...props }: SheetPrimitive.Root.Props): React.JSX.Element;
|
|
4
4
|
declare function SheetTrigger({ ...props }: SheetPrimitive.Trigger.Props): React.JSX.Element;
|
|
5
5
|
declare function SheetClose({ ...props }: SheetPrimitive.Close.Props): React.JSX.Element;
|
|
6
|
-
|
|
6
|
+
/**
|
|
7
|
+
* SheetContent 内容面板。size 控制尺寸档位(经 data-size 落到 Tailwind
|
|
8
|
+
* data-[size=*] 变体):left/right 侧约束最大宽度(sm=sm:max-w-sm /
|
|
9
|
+
* md=sm:max-w-lg / lg=sm:max-w-2xl),top/bottom 侧约束最大高度
|
|
10
|
+
* (sm=40vh / md=60vh / lg=80vh)。默认 'sm',与历史视觉一致。
|
|
11
|
+
* 基础类自带 overflow-y-auto,长表单可滚动不被裁剪。
|
|
12
|
+
*/
|
|
13
|
+
declare function SheetContent({ className, children, side, size, showCloseButton, ...props }: SheetPrimitive.Popup.Props & {
|
|
7
14
|
side?: "top" | "right" | "bottom" | "left";
|
|
15
|
+
size?: "sm" | "md" | "lg";
|
|
8
16
|
showCloseButton?: boolean;
|
|
9
17
|
}): React.JSX.Element;
|
|
10
18
|
declare function SheetHeader({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Dialog as SheetPrimitive } from "@base-ui/react/dialog";
|
|
3
3
|
import { cn } from "../../lib/utils";
|
|
4
|
-
import { Button } from "./
|
|
4
|
+
import { Button } from "./button";
|
|
5
5
|
import { XIcon } from "lucide-react";
|
|
6
6
|
function Sheet({ ...props }) {
|
|
7
7
|
return _jsx(SheetPrimitive.Root, { "data-slot": "sheet", ...props });
|
|
@@ -18,8 +18,15 @@ function SheetPortal({ ...props }) {
|
|
|
18
18
|
function SheetOverlay({ className, ...props }) {
|
|
19
19
|
return (_jsx(SheetPrimitive.Backdrop, { "data-slot": "sheet-overlay", className: cn("fixed inset-0 z-50 bg-black/10 transition-opacity duration-150 data-ending-style:opacity-0 data-starting-style:opacity-0 supports-backdrop-filter:backdrop-blur-xs", className), ...props }));
|
|
20
20
|
}
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
/**
|
|
22
|
+
* SheetContent 内容面板。size 控制尺寸档位(经 data-size 落到 Tailwind
|
|
23
|
+
* data-[size=*] 变体):left/right 侧约束最大宽度(sm=sm:max-w-sm /
|
|
24
|
+
* md=sm:max-w-lg / lg=sm:max-w-2xl),top/bottom 侧约束最大高度
|
|
25
|
+
* (sm=40vh / md=60vh / lg=80vh)。默认 'sm',与历史视觉一致。
|
|
26
|
+
* 基础类自带 overflow-y-auto,长表单可滚动不被裁剪。
|
|
27
|
+
*/
|
|
28
|
+
function SheetContent({ className, children, side = "right", size = "sm", showCloseButton = true, ...props }) {
|
|
29
|
+
return (_jsxs(SheetPortal, { children: [_jsx(SheetOverlay, {}), _jsxs(SheetPrimitive.Popup, { "data-slot": "sheet-content", "data-side": side, "data-size": size, className: cn("fixed z-50 flex flex-col gap-4 overflow-y-auto bg-popover bg-clip-padding text-sm text-popover-foreground shadow-lg transition duration-200 ease-in-out data-ending-style:opacity-0 data-starting-style:opacity-0 data-[side=bottom]:inset-x-0 data-[side=bottom]:bottom-0 data-[side=bottom]:h-auto data-[side=bottom]:border-t data-[side=bottom]:data-ending-style:translate-y-[2.5rem] data-[side=bottom]:data-starting-style:translate-y-[2.5rem] data-[side=left]:inset-y-0 data-[side=left]:left-0 data-[side=left]:h-full data-[side=left]:w-3/4 data-[side=left]:border-r data-[side=left]:data-ending-style:translate-x-[-2.5rem] data-[side=left]:data-starting-style:translate-x-[-2.5rem] data-[side=right]:inset-y-0 data-[side=right]:right-0 data-[side=right]:h-full data-[side=right]:w-3/4 data-[side=right]:border-l data-[side=right]:data-ending-style:translate-x-[2.5rem] data-[side=right]:data-starting-style:translate-x-[2.5rem] data-[side=top]:inset-x-0 data-[side=top]:top-0 data-[side=top]:h-auto data-[side=top]:border-b data-[side=top]:data-ending-style:translate-y-[-2.5rem] data-[side=top]:data-starting-style:translate-y-[-2.5rem] data-[side=left]:sm:max-w-sm data-[side=right]:sm:max-w-sm data-[side=left]:data-[size=md]:sm:max-w-lg data-[side=right]:data-[size=md]:sm:max-w-lg data-[side=left]:data-[size=lg]:sm:max-w-2xl data-[side=right]:data-[size=lg]:sm:max-w-2xl data-[side=top]:data-[size=sm]:max-h-[40vh] data-[side=bottom]:data-[size=sm]:max-h-[40vh] data-[side=top]:data-[size=md]:max-h-[60vh] data-[side=bottom]:data-[size=md]:max-h-[60vh] data-[side=top]:data-[size=lg]:max-h-[80vh] data-[side=bottom]:data-[size=lg]:max-h-[80vh]", className), ...props, children: [children, showCloseButton && (_jsxs(SheetPrimitive.Close, { "data-slot": "sheet-close", render: _jsx(Button, { variant: "ghost", className: "absolute top-3 right-3", size: "icon-sm" }), children: [_jsx(XIcon, {}), _jsx("span", { className: "sr-only", children: "Close" })] }))] })] }));
|
|
23
30
|
}
|
|
24
31
|
function SheetHeader({ className, ...props }) {
|
|
25
32
|
return (_jsx("div", { "data-slot": "sheet-header", className: cn("flex flex-col gap-0.5 p-4", className), ...props }));
|
|
@@ -28,7 +35,7 @@ function SheetFooter({ className, ...props }) {
|
|
|
28
35
|
return (_jsx("div", { "data-slot": "sheet-footer", className: cn("mt-auto flex flex-col gap-2 p-4", className), ...props }));
|
|
29
36
|
}
|
|
30
37
|
function SheetTitle({ className, ...props }) {
|
|
31
|
-
return (_jsx(SheetPrimitive.Title, { "data-slot": "sheet-title", className: cn("
|
|
38
|
+
return (_jsx(SheetPrimitive.Title, { "data-slot": "sheet-title", className: cn("text-base font-medium text-foreground", className), ...props }));
|
|
32
39
|
}
|
|
33
40
|
function SheetDescription({ className, ...props }) {
|
|
34
41
|
return (_jsx(SheetPrimitive.Description, { "data-slot": "sheet-description", className: cn("text-sm text-muted-foreground", className), ...props }));
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { useRender } from "@base-ui/react/use-render";
|
|
3
3
|
import { type VariantProps } from "class-variance-authority";
|
|
4
|
-
import { Button } from "./
|
|
5
|
-
import { Input } from "./
|
|
4
|
+
import { Button } from "./button";
|
|
5
|
+
import { Input } from "./input";
|
|
6
6
|
import { Separator } from "./separator";
|
|
7
7
|
import { TooltipContent } from "./tooltip";
|
|
8
8
|
type SidebarContextProps = {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use client";
|
|
1
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
3
|
import * as React from "react";
|
|
3
4
|
import { mergeProps } from "@base-ui/react/merge-props";
|
|
@@ -5,8 +6,8 @@ import { useRender } from "@base-ui/react/use-render";
|
|
|
5
6
|
import { cva } from "class-variance-authority";
|
|
6
7
|
import { cn } from "../../lib/utils";
|
|
7
8
|
import { useIsMobile } from "../../hooks/use-mobile";
|
|
8
|
-
import { Button } from "./
|
|
9
|
-
import { Input } from "./
|
|
9
|
+
import { Button } from "./button";
|
|
10
|
+
import { Input } from "./input";
|
|
10
11
|
import { Separator } from "./separator";
|
|
11
12
|
import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, } from "./sheet";
|
|
12
13
|
import { Skeleton } from "./skeleton";
|
|
@@ -18,16 +19,6 @@ const SIDEBAR_WIDTH = "16rem";
|
|
|
18
19
|
const SIDEBAR_WIDTH_MOBILE = "18rem";
|
|
19
20
|
const SIDEBAR_WIDTH_ICON = "3rem";
|
|
20
21
|
const SIDEBAR_KEYBOARD_SHORTCUT = "b";
|
|
21
|
-
function readSidebarCookie() {
|
|
22
|
-
if (typeof document === "undefined")
|
|
23
|
-
return undefined;
|
|
24
|
-
const match = document.cookie
|
|
25
|
-
.split("; ")
|
|
26
|
-
.find((row) => row.startsWith(`${SIDEBAR_COOKIE_NAME}=`));
|
|
27
|
-
if (!match)
|
|
28
|
-
return undefined;
|
|
29
|
-
return match.split("=")[1] === "false" ? false : true;
|
|
30
|
-
}
|
|
31
22
|
const SidebarContext = React.createContext(null);
|
|
32
23
|
function useSidebar() {
|
|
33
24
|
const context = React.useContext(SidebarContext);
|
|
@@ -36,14 +27,12 @@ function useSidebar() {
|
|
|
36
27
|
}
|
|
37
28
|
return context;
|
|
38
29
|
}
|
|
39
|
-
function SidebarProvider({ defaultOpen, open: openProp, onOpenChange: setOpenProp, className, style, children, ...props }) {
|
|
30
|
+
function SidebarProvider({ defaultOpen = true, open: openProp, onOpenChange: setOpenProp, className, style, children, ...props }) {
|
|
40
31
|
const isMobile = useIsMobile();
|
|
41
32
|
const [openMobile, setOpenMobile] = React.useState(false);
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
return readSidebarCookie() ?? true;
|
|
46
|
-
});
|
|
33
|
+
// This is the internal state of the sidebar.
|
|
34
|
+
// We use openProp and setOpenProp for control from outside the component.
|
|
35
|
+
const [_open, _setOpen] = React.useState(defaultOpen);
|
|
47
36
|
const open = openProp ?? _open;
|
|
48
37
|
const setOpen = React.useCallback((value) => {
|
|
49
38
|
const openState = typeof value === "function" ? value(open) : value;
|
|
@@ -53,21 +42,18 @@ function SidebarProvider({ defaultOpen, open: openProp, onOpenChange: setOpenPro
|
|
|
53
42
|
else {
|
|
54
43
|
_setOpen(openState);
|
|
55
44
|
}
|
|
45
|
+
// This sets the cookie to keep the sidebar state.
|
|
56
46
|
document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`;
|
|
57
47
|
}, [setOpenProp, open]);
|
|
48
|
+
// Helper to toggle the sidebar.
|
|
58
49
|
const toggleSidebar = React.useCallback(() => {
|
|
59
50
|
return isMobile ? setOpenMobile((open) => !open) : setOpen((open) => !open);
|
|
60
51
|
}, [isMobile, setOpen, setOpenMobile]);
|
|
52
|
+
// Adds a keyboard shortcut to toggle the sidebar.
|
|
61
53
|
React.useEffect(() => {
|
|
62
54
|
const handleKeyDown = (event) => {
|
|
63
55
|
if (event.key === SIDEBAR_KEYBOARD_SHORTCUT &&
|
|
64
56
|
(event.metaKey || event.ctrlKey)) {
|
|
65
|
-
const target = event.target;
|
|
66
|
-
if (target?.isContentEditable ||
|
|
67
|
-
(target && typeof target.matches === "function" &&
|
|
68
|
-
target.matches("input, textarea, select"))) {
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
57
|
event.preventDefault();
|
|
72
58
|
toggleSidebar();
|
|
73
59
|
}
|
|
@@ -75,6 +61,8 @@ function SidebarProvider({ defaultOpen, open: openProp, onOpenChange: setOpenPro
|
|
|
75
61
|
window.addEventListener("keydown", handleKeyDown);
|
|
76
62
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
77
63
|
}, [toggleSidebar]);
|
|
64
|
+
// We add a state so that we can do data-state="expanded" or "collapsed".
|
|
65
|
+
// This makes it easier to style the sidebar with Tailwind classes.
|
|
78
66
|
const state = open ? "expanded" : "collapsed";
|
|
79
67
|
const contextValue = React.useMemo(() => ({
|
|
80
68
|
state,
|
|
@@ -101,25 +89,27 @@ function Sidebar({ side = "left", variant = "sidebar", collapsible = "offcanvas"
|
|
|
101
89
|
"--sidebar-width": SIDEBAR_WIDTH_MOBILE,
|
|
102
90
|
}, side: side, children: [_jsxs(SheetHeader, { className: "sr-only", children: [_jsx(SheetTitle, { children: "Sidebar" }), _jsx(SheetDescription, { children: "Displays the mobile sidebar." })] }), _jsx("div", { className: "flex h-full w-full flex-col", children: children })] }) }));
|
|
103
91
|
}
|
|
104
|
-
return (_jsxs("div", { className: "group peer hidden text-sidebar-foreground md:block", "data-collapsible": state === "collapsed" ? collapsible : "", "data-variant": variant, "data-side": side, "data-slot": "sidebar", children: [_jsx("div", { "data-slot": "sidebar-gap", className: cn("relative w-(--sidebar-width) bg-transparent transition-[width] duration-200 ease-linear", "group-data-[collapsible=offcanvas]:w-0", "group-data-[side=right]:rotate-180", variant === "floating" || variant === "inset"
|
|
92
|
+
return (_jsxs("div", { className: "group peer hidden text-sidebar-foreground md:block", "data-state": state, "data-collapsible": state === "collapsed" ? collapsible : "", "data-variant": variant, "data-side": side, "data-slot": "sidebar", children: [_jsx("div", { "data-slot": "sidebar-gap", className: cn("relative w-(--sidebar-width) bg-transparent transition-[width] duration-200 ease-linear", "group-data-[collapsible=offcanvas]:w-0", "group-data-[side=right]:rotate-180", variant === "floating" || variant === "inset"
|
|
105
93
|
? "group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]"
|
|
106
|
-
: "group-data-[collapsible=icon]:w-(--sidebar-width-icon)") }), _jsx("div", { "data-slot": "sidebar-container", "data-side": side, className: cn("fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear data-[side=left]:left-0 data-[side=left]:group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)] data-[side=right]:right-0 data-[side=right]:group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)] md:flex",
|
|
94
|
+
: "group-data-[collapsible=icon]:w-(--sidebar-width-icon)") }), _jsx("div", { "data-slot": "sidebar-container", "data-side": side, className: cn("fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear data-[side=left]:left-0 data-[side=left]:group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)] data-[side=right]:right-0 data-[side=right]:group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)] md:flex",
|
|
95
|
+
// Adjust the padding for floating and inset variants.
|
|
96
|
+
variant === "floating" || variant === "inset"
|
|
107
97
|
? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]"
|
|
108
98
|
: "group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l", className), ...props, children: _jsx("div", { "data-sidebar": "sidebar", "data-slot": "sidebar-inner", className: "flex size-full flex-col bg-sidebar group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:shadow-sm group-data-[variant=floating]:ring-1 group-data-[variant=floating]:ring-sidebar-border", children: children }) })] }));
|
|
109
99
|
}
|
|
110
100
|
function SidebarTrigger({ className, onClick, ...props }) {
|
|
111
101
|
const { toggleSidebar } = useSidebar();
|
|
112
|
-
return (_jsxs(Button, { "data-sidebar": "trigger", "data-slot": "sidebar-trigger", variant: "ghost", size: "
|
|
102
|
+
return (_jsxs(Button, { "data-sidebar": "trigger", "data-slot": "sidebar-trigger", variant: "ghost", size: "icon-sm", className: cn(className), onClick: (event) => {
|
|
113
103
|
onClick?.(event);
|
|
114
104
|
toggleSidebar();
|
|
115
105
|
}, ...props, children: [_jsx(PanelLeftIcon, {}), _jsx("span", { className: "sr-only", children: "Toggle Sidebar" })] }));
|
|
116
106
|
}
|
|
117
107
|
function SidebarRail({ className, ...props }) {
|
|
118
108
|
const { toggleSidebar } = useSidebar();
|
|
119
|
-
return (_jsx("button", { "data-sidebar": "rail", "data-slot": "sidebar-rail", "aria-label": "Toggle Sidebar", tabIndex: -1, onClick: toggleSidebar, title: "Toggle Sidebar", className: cn("absolute inset-y-0 z-20 hidden w-4 transition-all ease-linear group-data-[side=left]:-right-4 group-data-[side=right]:left-0 after:absolute after:inset-y-0 after:start-1/2 after:w-[2px] hover:after:bg-sidebar-border sm:flex ltr:-translate-x-1/2 rtl:-translate-x-1/2", "in-data-[side=left]:cursor-w-resize in-data-[side=right]:cursor-e-resize", "[[data-side=left][data-
|
|
109
|
+
return (_jsx("button", { "data-sidebar": "rail", "data-slot": "sidebar-rail", "aria-label": "Toggle Sidebar", tabIndex: -1, onClick: toggleSidebar, title: "Toggle Sidebar", className: cn("absolute inset-y-0 z-20 hidden w-4 transition-all ease-linear group-data-[side=left]:-right-4 group-data-[side=right]:left-0 after:absolute after:inset-y-0 after:start-1/2 after:w-[2px] hover:after:bg-sidebar-border sm:flex ltr:-translate-x-1/2 rtl:-translate-x-1/2", "in-data-[side=left]:cursor-w-resize in-data-[side=right]:cursor-e-resize", "[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize", "group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full hover:group-data-[collapsible=offcanvas]:bg-sidebar", "[[data-side=left][data-collapsible=offcanvas]_&]:-right-2", "[[data-side=right][data-collapsible=offcanvas]_&]:-left-2", className), ...props }));
|
|
120
110
|
}
|
|
121
111
|
function SidebarInset({ className, ...props }) {
|
|
122
|
-
return (_jsx("main", { "data-slot": "sidebar-inset", className: cn("relative flex w-full flex-1 flex-col bg-background md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm md:peer-data-[variant=inset]:peer-data-[
|
|
112
|
+
return (_jsx("main", { "data-slot": "sidebar-inset", className: cn("relative flex w-full flex-1 flex-col bg-background md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ml-2", className), ...props }));
|
|
123
113
|
}
|
|
124
114
|
function SidebarInput({ className, ...props }) {
|
|
125
115
|
return (_jsx(Input, { "data-slot": "sidebar-input", "data-sidebar": "input", className: cn("h-8 w-full bg-background shadow-none", className), ...props }));
|
|
@@ -134,7 +124,7 @@ function SidebarSeparator({ className, ...props }) {
|
|
|
134
124
|
return (_jsx(Separator, { "data-slot": "sidebar-separator", "data-sidebar": "separator", className: cn("mx-2 w-auto bg-sidebar-border", className), ...props }));
|
|
135
125
|
}
|
|
136
126
|
function SidebarContent({ className, ...props }) {
|
|
137
|
-
return (_jsx("div", { "data-slot": "sidebar-content", "data-sidebar": "content", className: cn("no-scrollbar flex min-h-0 flex-1 flex-col gap-
|
|
127
|
+
return (_jsx("div", { "data-slot": "sidebar-content", "data-sidebar": "content", className: cn("no-scrollbar flex min-h-0 flex-1 flex-col gap-0 overflow-auto group-data-[collapsible=icon]:overflow-hidden", className), ...props }));
|
|
138
128
|
}
|
|
139
129
|
function SidebarGroup({ className, ...props }) {
|
|
140
130
|
return (_jsx("div", { "data-slot": "sidebar-group", "data-sidebar": "group", className: cn("relative flex w-full min-w-0 flex-col p-2", className), ...props }));
|
|
@@ -169,7 +159,7 @@ function SidebarGroupContent({ className, ...props }) {
|
|
|
169
159
|
return (_jsx("div", { "data-slot": "sidebar-group-content", "data-sidebar": "group-content", className: cn("w-full text-sm", className), ...props }));
|
|
170
160
|
}
|
|
171
161
|
function SidebarMenu({ className, ...props }) {
|
|
172
|
-
return (_jsx("ul", { "data-slot": "sidebar-menu", "data-sidebar": "menu", className: cn("flex w-full min-w-0 flex-col gap-
|
|
162
|
+
return (_jsx("ul", { "data-slot": "sidebar-menu", "data-sidebar": "menu", className: cn("flex w-full min-w-0 flex-col gap-0", className), ...props }));
|
|
173
163
|
}
|
|
174
164
|
function SidebarMenuItem({ className, ...props }) {
|
|
175
165
|
return (_jsx("li", { "data-slot": "sidebar-menu-item", "data-sidebar": "menu-item", className: cn("group/menu-item relative", className), ...props }));
|
|
@@ -234,9 +224,10 @@ function SidebarMenuBadge({ className, ...props }) {
|
|
|
234
224
|
return (_jsx("div", { "data-slot": "sidebar-menu-badge", "data-sidebar": "menu-badge", className: cn("pointer-events-none absolute right-1 flex h-5 min-w-5 items-center justify-center rounded-md px-1 text-xs font-medium text-sidebar-foreground tabular-nums select-none group-data-[collapsible=icon]:hidden peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[size=default]/menu-button:top-1.5 peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=sm]/menu-button:top-1 peer-data-active/menu-button:text-sidebar-accent-foreground", className), ...props }));
|
|
235
225
|
}
|
|
236
226
|
function SidebarMenuSkeleton({ className, showIcon = false, ...props }) {
|
|
237
|
-
|
|
238
|
-
const
|
|
239
|
-
|
|
227
|
+
// Random width between 50 to 90%.
|
|
228
|
+
const [width] = React.useState(() => {
|
|
229
|
+
return `${Math.floor(Math.random() * 40) + 50}%`;
|
|
230
|
+
});
|
|
240
231
|
return (_jsxs("div", { "data-slot": "sidebar-menu-skeleton", "data-sidebar": "menu-skeleton", className: cn("flex h-8 items-center gap-2 rounded-md px-2", className), ...props, children: [showIcon && (_jsx(Skeleton, { className: "size-4 rounded-md", "data-sidebar": "menu-skeleton-icon" })), _jsx(Skeleton, { className: "h-4 max-w-(--skeleton-width) flex-1", "data-sidebar": "menu-skeleton-text", style: {
|
|
241
232
|
"--skeleton-width": width,
|
|
242
233
|
} })] }));
|
|
@@ -2,6 +2,6 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { Switch as SwitchPrimitive } from "@base-ui/react/switch";
|
|
3
3
|
import { cn } from "../../lib/utils";
|
|
4
4
|
function Switch({ className, size = "default", ...props }) {
|
|
5
|
-
return (_jsx(SwitchPrimitive.Root, { "data-slot": "switch", "data-size": size, className: cn("peer group/switch relative inline-flex shrink-0 items-center rounded-full border border-transparent
|
|
5
|
+
return (_jsx(SwitchPrimitive.Root, { "data-slot": "switch", "data-size": size, className: cn("peer group/switch relative inline-flex shrink-0 items-center rounded-full border border-transparent transition-all outline-none group-has-[:focus-visible]/field-label:border-transparent group-has-[:focus-visible]/field-label:ring-0 after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-[size=default]:h-[18.4px] data-[size=default]:w-[32px] data-[size=sm]:h-[14px] data-[size=sm]:w-[24px] dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:bg-primary data-unchecked:bg-input dark:data-unchecked:bg-input/80 data-disabled:cursor-not-allowed data-disabled:opacity-50", className), ...props, children: _jsx(SwitchPrimitive.Thumb, { "data-slot": "switch-thumb", className: "pointer-events-none block rounded-full bg-background ring-0 transition-transform group-data-[size=default]/switch:size-4 group-data-[size=sm]/switch:size-3 group-data-[size=default]/switch:data-checked:translate-x-[calc(100%-2px)] group-data-[size=sm]/switch:data-checked:translate-x-[calc(100%-2px)] dark:data-checked:bg-primary-foreground group-data-[size=default]/switch:data-unchecked:translate-x-0 group-data-[size=sm]/switch:data-unchecked:translate-x-0 dark:data-unchecked:bg-foreground" }) }));
|
|
6
6
|
}
|
|
7
7
|
export { Switch };
|
|
@@ -3,9 +3,9 @@ import { Tabs as TabsPrimitive } from "@base-ui/react/tabs";
|
|
|
3
3
|
import { cva } from "class-variance-authority";
|
|
4
4
|
import { cn } from "../../lib/utils";
|
|
5
5
|
function Tabs({ className, orientation = "horizontal", ...props }) {
|
|
6
|
-
return (_jsx(TabsPrimitive.Root, { "data-slot": "tabs", "data-orientation": orientation, className: cn("group/tabs flex gap-2 data-
|
|
6
|
+
return (_jsx(TabsPrimitive.Root, { "data-slot": "tabs", "data-orientation": orientation, className: cn("group/tabs flex gap-2 data-horizontal:flex-col", className), ...props }));
|
|
7
7
|
}
|
|
8
|
-
const tabsListVariants = cva("group/tabs-list inline-flex w-fit items-center justify-center rounded-lg p-[3px] text-muted-foreground h-
|
|
8
|
+
const tabsListVariants = cva("group/tabs-list inline-flex w-fit items-center justify-center rounded-lg p-[3px] text-muted-foreground group-data-horizontal/tabs:h-8 group-data-vertical/tabs:h-fit group-data-vertical/tabs:flex-col data-[variant=line]:rounded-none", {
|
|
9
9
|
variants: {
|
|
10
10
|
variant: {
|
|
11
11
|
default: "bg-muted",
|
|
@@ -20,7 +20,7 @@ function TabsList({ className, variant = "default", ...props }) {
|
|
|
20
20
|
return (_jsx(TabsPrimitive.List, { "data-slot": "tabs-list", "data-variant": variant, className: cn(tabsListVariants({ variant }), className), ...props }));
|
|
21
21
|
}
|
|
22
22
|
function TabsTrigger({ className, ...props }) {
|
|
23
|
-
return (_jsx(TabsPrimitive.Tab, { "data-slot": "tabs-trigger", className: cn("relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5
|
|
23
|
+
return (_jsx(TabsPrimitive.Tab, { "data-slot": "tabs-trigger", className: cn("relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-1.5 py-0.5 text-sm font-medium whitespace-nowrap text-foreground/60 transition-all group-data-vertical/tabs:w-full group-data-vertical/tabs:justify-start hover:text-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1 focus-visible:outline-ring disabled:pointer-events-none disabled:opacity-50 has-data-[icon=inline-end]:pr-1 has-data-[icon=inline-start]:pl-1 aria-disabled:pointer-events-none aria-disabled:opacity-50 dark:text-muted-foreground dark:hover:text-foreground group-data-[variant=default]/tabs-list:data-active:shadow-sm group-data-[variant=line]/tabs-list:data-active:shadow-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", "group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-active:bg-transparent dark:group-data-[variant=line]/tabs-list:data-active:border-transparent dark:group-data-[variant=line]/tabs-list:data-active:bg-transparent", "data-active:bg-background data-active:text-foreground dark:data-active:border-input dark:data-active:bg-input/30 dark:data-active:text-foreground", "after:absolute after:bg-foreground after:opacity-0 after:transition-opacity group-data-horizontal/tabs:after:inset-x-0 group-data-horizontal/tabs:after:bottom-[-5px] group-data-horizontal/tabs:after:h-0.5 group-data-vertical/tabs:after:inset-y-0 group-data-vertical/tabs:after:-right-1 group-data-vertical/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-active:after:opacity-100", className), ...props }));
|
|
24
24
|
}
|
|
25
25
|
function TabsContent({ className, ...props }) {
|
|
26
26
|
return (_jsx(TabsPrimitive.Panel, { "data-slot": "tabs-content", className: cn("flex-1 text-sm outline-none", className), ...props }));
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Textarea 多行文本域:与 Input 完全同族的 token 体系
|
|
4
|
+
* (border-input / bg-transparent / focus-visible ring / aria-invalid
|
|
5
|
+
* destructive / disabled / dark:bg-input/30),min-h 起步、支持
|
|
6
|
+
* ref 与 className 合并。
|
|
7
|
+
*/
|
|
8
|
+
declare function Textarea({ className, ...props }: React.ComponentProps<"textarea">): React.JSX.Element;
|
|
9
|
+
export { Textarea };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../../lib/utils";
|
|
3
|
+
/**
|
|
4
|
+
* Textarea 多行文本域:与 Input 完全同族的 token 体系
|
|
5
|
+
* (border-input / bg-transparent / focus-visible ring / aria-invalid
|
|
6
|
+
* destructive / disabled / dark:bg-input/30),min-h 起步、支持
|
|
7
|
+
* ref 与 className 合并。
|
|
8
|
+
*/
|
|
9
|
+
function Textarea({ className, ...props }) {
|
|
10
|
+
return (_jsx("textarea", { "data-slot": "textarea", className: cn("min-h-16 w-full rounded-lg border border-input bg-transparent px-2.5 py-1 text-base transition-colors outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40", className), ...props }));
|
|
11
|
+
}
|
|
12
|
+
export { Textarea };
|
|
@@ -11,6 +11,6 @@ function TooltipTrigger({ ...props }) {
|
|
|
11
11
|
return _jsx(TooltipPrimitive.Trigger, { "data-slot": "tooltip-trigger", ...props });
|
|
12
12
|
}
|
|
13
13
|
function TooltipContent({ className, side = "top", sideOffset = 4, align = "center", alignOffset = 0, children, ...props }) {
|
|
14
|
-
return (_jsx(TooltipPrimitive.Portal, { children: _jsx(TooltipPrimitive.Positioner, { align: align, alignOffset: alignOffset, side: side, sideOffset: sideOffset, className: "isolate z-50", children: _jsxs(TooltipPrimitive.Popup, { "data-slot": "tooltip-content", className: cn("z-50 inline-flex w-fit max-w-xs origin-(--transform-origin) items-center gap-1.5 rounded-md bg-foreground px-3 py-1.5 text-xs text-background has-data-[slot=kbd]:pr-1.5 data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 **:data-[slot=kbd]:relative **:data-[slot=kbd]:isolate **:data-[slot=kbd]:z-50 **:data-[slot=kbd]:rounded-sm data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", className), ...props, children: [children, _jsx(TooltipPrimitive.Arrow, { className: "z-50 size-2.5 translate-y-[calc(-50%-2px)] rotate-45 rounded-[2px] bg-foreground fill-foreground data-[side=bottom]:top-1 data-[side=inline-end]:top-1/2! data-[side=inline-end]:-left-1 data-[side=inline-end]:-translate-y-1/2 data-[side=inline-start]:top-1/2! data-[side=inline-start]:-right-1 data-[side=inline-start]:-translate-y-1/2 data-[side=left]:top-1/2! data-[side=left]:-right-1 data-[side=left]:-translate-y-1/2 data-[side=right]:top-1/2! data-[side=right]:-left-1 data-[side=right]:-translate-y-1/2 data-[side=top]:-bottom-2.5" })] }) }) }));
|
|
14
|
+
return (_jsx(TooltipPrimitive.Portal, { children: _jsx(TooltipPrimitive.Positioner, { align: align, alignOffset: alignOffset, side: side, sideOffset: sideOffset, className: "isolate z-50", children: _jsxs(TooltipPrimitive.Popup, { "data-slot": "tooltip-content", className: cn("z-50 inline-flex w-fit max-w-xs origin-(--transform-origin) items-center gap-1.5 rounded-md bg-foreground px-3 py-1.5 text-xs text-background has-data-[slot=kbd]:pr-1.5 data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 **:data-[slot=kbd]:relative **:data-[slot=kbd]:isolate **:data-[slot=kbd]:z-50 **:data-[slot=kbd]:rounded-sm data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", className), ...props, children: [children, _jsx(TooltipPrimitive.Arrow, { className: "z-50 size-2.5 translate-y-[calc(-50%-2px)] rotate-45 rounded-[2px] bg-foreground fill-foreground data-[side=bottom]:top-1 data-[side=inline-end]:top-1/2! data-[side=inline-end]:-left-1 data-[side=inline-end]:-translate-y-1/2 data-[side=inline-start]:top-1/2! data-[side=inline-start]:-right-1 data-[side=inline-start]:-translate-y-1/2 data-[side=left]:top-1/2! data-[side=left]:-right-1 data-[side=left]:-translate-y-1/2 data-[side=right]:top-1/2! data-[side=right]:-left-1 data-[side=right]:-translate-y-1/2 data-[side=top]:-bottom-2.5" })] }) }) }));
|
|
15
15
|
}
|
|
16
16
|
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
|