@lessly/ui 0.4.1 → 0.6.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 +29 -12
- package/dist/index.d.ts +119 -5
- package/dist/index.js +356 -93
- package/dist/styles.css +690 -106
- package/dist/tailwind-preset.d.ts +4 -394
- package/dist/tailwind-preset.js +4 -425
- package/package.json +9 -2
package/dist/index.js
CHANGED
|
@@ -11,7 +11,7 @@ import { Slot } from "@radix-ui/react-slot";
|
|
|
11
11
|
import { cva } from "class-variance-authority";
|
|
12
12
|
import { jsx } from "react/jsx-runtime";
|
|
13
13
|
var buttonVariants = cva(
|
|
14
|
-
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus disabled:pointer-events-none disabled:opacity-50",
|
|
14
|
+
"inline-flex cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus disabled:pointer-events-none disabled:opacity-50",
|
|
15
15
|
{
|
|
16
16
|
variants: {
|
|
17
17
|
variant: {
|
|
@@ -2618,8 +2618,9 @@ function initialsOf(name) {
|
|
|
2618
2618
|
if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase();
|
|
2619
2619
|
return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
|
|
2620
2620
|
}
|
|
2621
|
-
function UserMenu({ user, items, collapsed = false, align = "
|
|
2622
|
-
const
|
|
2621
|
+
function UserMenu({ user, items, collapsed = false, align = "start" }) {
|
|
2622
|
+
const secondLine = user.subtitle ?? user.email;
|
|
2623
|
+
const avatar = /* @__PURE__ */ jsxs25(Avatar, { className: collapsed ? "size-9" : "size-7", children: [
|
|
2623
2624
|
user.avatarUrl && /* @__PURE__ */ jsx52(AvatarImage, { src: user.avatarUrl, alt: user.name }),
|
|
2624
2625
|
/* @__PURE__ */ jsx52(AvatarFallback, { className: "text-xs", children: initialsOf(user.name) })
|
|
2625
2626
|
] });
|
|
@@ -2635,14 +2636,14 @@ function UserMenu({ user, items, collapsed = false, align = "end" }) {
|
|
|
2635
2636
|
"button",
|
|
2636
2637
|
{
|
|
2637
2638
|
type: "button",
|
|
2638
|
-
className: "flex w-full items-center gap-2.5 rounded-xl px-
|
|
2639
|
+
className: "flex w-full items-center gap-2.5 rounded-xl px-1.5 py-[5px] text-left transition-colors hover:bg-[var(--hov-bg)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus",
|
|
2639
2640
|
children: [
|
|
2640
2641
|
avatar,
|
|
2641
|
-
/* @__PURE__ */ jsxs25("span", { className: "min-w-0 flex-1", children: [
|
|
2642
|
-
/* @__PURE__ */ jsx52("span", { className: "
|
|
2643
|
-
|
|
2642
|
+
/* @__PURE__ */ jsxs25("span", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [
|
|
2643
|
+
/* @__PURE__ */ jsx52("span", { className: "truncate text-sm leading-[normal] font-medium text-text-primary", children: user.name }),
|
|
2644
|
+
secondLine && /* @__PURE__ */ jsx52("span", { className: "truncate text-xs leading-[normal] text-text-tertiary", children: secondLine })
|
|
2644
2645
|
] }),
|
|
2645
|
-
/* @__PURE__ */ jsx52(ChevronsUpDown, {
|
|
2646
|
+
/* @__PURE__ */ jsx52(ChevronsUpDown, { size: 14, "aria-hidden": "true", className: "shrink-0 text-text-tertiary" })
|
|
2646
2647
|
]
|
|
2647
2648
|
}
|
|
2648
2649
|
);
|
|
@@ -2661,7 +2662,7 @@ function UserMenu({ user, items, collapsed = false, align = "end" }) {
|
|
|
2661
2662
|
children: [
|
|
2662
2663
|
/* @__PURE__ */ jsxs25(DropdownMenuLabel, { className: "px-2 pt-1.5 pb-1 text-xs font-medium text-text-tertiary", children: [
|
|
2663
2664
|
/* @__PURE__ */ jsx52("span", { className: "block truncate text-sm font-medium text-text-primary", children: user.name }),
|
|
2664
|
-
|
|
2665
|
+
secondLine && /* @__PURE__ */ jsx52("span", { className: "block truncate text-xs font-normal text-text-tertiary", children: secondLine })
|
|
2665
2666
|
] }),
|
|
2666
2667
|
/* @__PURE__ */ jsx52(DropdownMenuSeparator, { className: "mx-0 shrink-0 bg-border-subtle" }),
|
|
2667
2668
|
items.map((item, i) => {
|
|
@@ -2938,8 +2939,8 @@ function SidebarNav({
|
|
|
2938
2939
|
"nav",
|
|
2939
2940
|
{
|
|
2940
2941
|
className: cn(
|
|
2941
|
-
"flex flex-col gap-
|
|
2942
|
-
collapsed
|
|
2942
|
+
"flex flex-col gap-2",
|
|
2943
|
+
collapsed && "items-center",
|
|
2943
2944
|
className
|
|
2944
2945
|
),
|
|
2945
2946
|
children: items.map((item) => {
|
|
@@ -2964,13 +2965,27 @@ function SidebarNav({
|
|
|
2964
2965
|
|
|
2965
2966
|
// src/components/app-sidebar.tsx
|
|
2966
2967
|
import { PanelLeft } from "lucide-react";
|
|
2967
|
-
import { jsx as jsx59, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
2968
|
+
import { Fragment as Fragment3, jsx as jsx59, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
2969
|
+
function Divider({ collapsed, testId, className }) {
|
|
2970
|
+
return /* @__PURE__ */ jsx59(
|
|
2971
|
+
"div",
|
|
2972
|
+
{
|
|
2973
|
+
"data-testid": testId,
|
|
2974
|
+
className: cn(
|
|
2975
|
+
"h-px shrink-0 bg-border-subtle",
|
|
2976
|
+
collapsed ? "ml-[6px] w-[40px]" : "ml-[14px] w-[220px]",
|
|
2977
|
+
className
|
|
2978
|
+
)
|
|
2979
|
+
}
|
|
2980
|
+
);
|
|
2981
|
+
}
|
|
2968
2982
|
function AppSidebar({
|
|
2969
2983
|
items,
|
|
2970
2984
|
logo,
|
|
2971
2985
|
logoCollapsed,
|
|
2972
2986
|
header,
|
|
2973
2987
|
footer,
|
|
2988
|
+
collapsible = false,
|
|
2974
2989
|
collapsed: controlled,
|
|
2975
2990
|
defaultCollapsed,
|
|
2976
2991
|
onCollapsedChange,
|
|
@@ -2984,18 +2999,49 @@ function AppSidebar({
|
|
|
2984
2999
|
defaultCollapsed,
|
|
2985
3000
|
onCollapsedChange
|
|
2986
3001
|
});
|
|
3002
|
+
const pin = collapsible ? /* @__PURE__ */ jsx59(
|
|
3003
|
+
"button",
|
|
3004
|
+
{
|
|
3005
|
+
type: "button",
|
|
3006
|
+
onClick: toggle,
|
|
3007
|
+
"aria-label": collapsed ? "Expand sidebar" : "Collapse sidebar",
|
|
3008
|
+
"aria-expanded": !collapsed,
|
|
3009
|
+
className: "flex size-6 shrink-0 items-center justify-center rounded-md text-text-secondary transition-colors hover:bg-[var(--hov-bg)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus",
|
|
3010
|
+
children: /* @__PURE__ */ jsx59(PanelLeft, { className: "size-4", "aria-hidden": "true" })
|
|
3011
|
+
}
|
|
3012
|
+
) : null;
|
|
2987
3013
|
return /* @__PURE__ */ jsxs29(
|
|
2988
3014
|
"aside",
|
|
2989
3015
|
{
|
|
2990
3016
|
"data-collapsed": collapsed,
|
|
2991
3017
|
className: cn(
|
|
2992
|
-
"flex h-full flex-col overflow-hidden
|
|
2993
|
-
collapsed ? "w-[52px]" : "w-[
|
|
3018
|
+
"flex h-full shrink-0 flex-col overflow-hidden transition-[width] duration-200 ease-in-out",
|
|
3019
|
+
collapsed ? "w-[52px]" : "w-[248px]",
|
|
2994
3020
|
className
|
|
2995
3021
|
),
|
|
2996
3022
|
children: [
|
|
2997
|
-
|
|
2998
|
-
/*
|
|
3023
|
+
/* @__PURE__ */ jsx59("div", { className: cn("flex items-center gap-2", collapsed ? "justify-center px-1 pt-2" : "px-3 pt-[13px]"), children: collapsed ? collapsible ? logoCollapsed ?? logo ? (
|
|
3024
|
+
/* The collapsed rail (52px) can't fit the logo mark beside the pin side by side —
|
|
3025
|
+
so the pin overlays the mark instead, revealed on hover/focus, same as pre-flat-rail. */
|
|
3026
|
+
/* @__PURE__ */ jsxs29("div", { className: "group relative flex size-8 items-center justify-center", children: [
|
|
3027
|
+
/* @__PURE__ */ jsx59("span", { className: "pointer-events-none transition-opacity group-hover:opacity-0 group-focus-within:opacity-0", children: logoCollapsed ?? logo }),
|
|
3028
|
+
/* @__PURE__ */ jsx59(
|
|
3029
|
+
"button",
|
|
3030
|
+
{
|
|
3031
|
+
type: "button",
|
|
3032
|
+
onClick: toggle,
|
|
3033
|
+
"aria-label": "Expand sidebar",
|
|
3034
|
+
"aria-expanded": false,
|
|
3035
|
+
className: "absolute inset-0 flex items-center justify-center rounded-md text-text-secondary opacity-0 transition-opacity hover:bg-[var(--hov-bg)] focus-visible:outline-none focus-visible:opacity-100 focus-visible:ring-2 focus-visible:ring-border-focus group-hover:opacity-100 group-focus-within:opacity-100",
|
|
3036
|
+
children: /* @__PURE__ */ jsx59(PanelLeft, { className: "size-4", "aria-hidden": "true" })
|
|
3037
|
+
}
|
|
3038
|
+
)
|
|
3039
|
+
] })
|
|
3040
|
+
) : (
|
|
3041
|
+
/* No mark to hide behind (no `logoCollapsed`/`logo` given — `header` doesn't
|
|
3042
|
+
count, it's expanded-only). Hover-revealing the pin over nothing would leave
|
|
3043
|
+
an invisible 32px box as the only way back to expanded, so render it plain
|
|
3044
|
+
and fully visible instead. */
|
|
2999
3045
|
/* @__PURE__ */ jsx59(
|
|
3000
3046
|
"button",
|
|
3001
3047
|
{
|
|
@@ -3003,77 +3049,290 @@ function AppSidebar({
|
|
|
3003
3049
|
onClick: toggle,
|
|
3004
3050
|
"aria-label": "Expand sidebar",
|
|
3005
3051
|
"aria-expanded": false,
|
|
3006
|
-
className: "
|
|
3052
|
+
className: "flex size-8 shrink-0 items-center justify-center rounded-md text-text-secondary transition-colors hover:bg-[var(--hov-bg)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus",
|
|
3007
3053
|
children: /* @__PURE__ */ jsx59(PanelLeft, { className: "size-4", "aria-hidden": "true" })
|
|
3008
3054
|
}
|
|
3009
3055
|
)
|
|
3010
|
-
|
|
3056
|
+
) : logoCollapsed ?? logo : /* @__PURE__ */ jsxs29(Fragment3, { children: [
|
|
3011
3057
|
header ?? logo,
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3058
|
+
pin
|
|
3059
|
+
] }) }),
|
|
3060
|
+
/* @__PURE__ */ jsx59(Divider, { collapsed, testId: "sidebar-divider-header", className: "mt-3" }),
|
|
3061
|
+
/* @__PURE__ */ jsx59(
|
|
3062
|
+
"div",
|
|
3063
|
+
{
|
|
3064
|
+
"data-testid": "sidebar-scroll",
|
|
3065
|
+
className: cn(
|
|
3066
|
+
"min-h-0 flex-1 overflow-y-auto overflow-x-hidden pt-3 pb-2",
|
|
3067
|
+
collapsed ? "px-1" : "px-3"
|
|
3068
|
+
),
|
|
3069
|
+
children: /* @__PURE__ */ jsx59(SidebarNav, { items, collapsed, basePath, LinkComponent, isItemActive })
|
|
3070
|
+
}
|
|
3071
|
+
),
|
|
3072
|
+
footer && /* @__PURE__ */ jsxs29(Fragment3, { children: [
|
|
3073
|
+
/* @__PURE__ */ jsx59(Divider, { collapsed, testId: "sidebar-divider-account" }),
|
|
3074
|
+
/* @__PURE__ */ jsx59("div", { className: cn("py-2", collapsed ? "px-1" : "px-3"), children: footer })
|
|
3075
|
+
] })
|
|
3026
3076
|
]
|
|
3027
3077
|
}
|
|
3028
3078
|
);
|
|
3029
3079
|
}
|
|
3030
3080
|
|
|
3031
|
-
// src/components/
|
|
3081
|
+
// src/components/sidebar-product-header.tsx
|
|
3032
3082
|
import * as React50 from "react";
|
|
3083
|
+
import { Slot as Slot5 } from "@radix-ui/react-slot";
|
|
3084
|
+
import { ChevronsUpDown as ChevronsUpDown2 } from "lucide-react";
|
|
3085
|
+
import { Fragment as Fragment4, jsx as jsx60, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
3086
|
+
var SidebarProductHeader = React50.forwardRef(
|
|
3087
|
+
function SidebarProductHeader2({ name, icon, trailing, asChild = false, className, children, ...props }, ref) {
|
|
3088
|
+
const adornment = trailing === void 0 ? /* @__PURE__ */ jsx60(ChevronsUpDown2, { size: 14, "aria-hidden": "true", className: "shrink-0 text-text-tertiary" }) : trailing;
|
|
3089
|
+
const content = /* @__PURE__ */ jsxs30(Fragment4, { children: [
|
|
3090
|
+
icon && /* @__PURE__ */ jsx60("span", { className: "flex size-7 shrink-0 items-center justify-center overflow-hidden rounded-md", "aria-hidden": "true", children: icon }),
|
|
3091
|
+
/* @__PURE__ */ jsx60("span", { className: "min-w-0 flex-1 truncate text-sm font-semibold text-text-primary", children: name }),
|
|
3092
|
+
adornment && /* @__PURE__ */ jsx60("span", { className: "flex shrink-0 items-center", children: adornment })
|
|
3093
|
+
] });
|
|
3094
|
+
const classes = cn("flex w-full items-center gap-2.5 rounded-xl px-1.5 py-0 text-left", className);
|
|
3095
|
+
if (asChild) {
|
|
3096
|
+
const child = React50.Children.only(children);
|
|
3097
|
+
return /* @__PURE__ */ jsx60(Slot5, { ref, className: classes, ...props, children: React50.cloneElement(child, void 0, content) });
|
|
3098
|
+
}
|
|
3099
|
+
return /* @__PURE__ */ jsx60("button", { ref, type: "button", className: classes, ...props, children: content });
|
|
3100
|
+
}
|
|
3101
|
+
);
|
|
3102
|
+
SidebarProductHeader.displayName = "SidebarProductHeader";
|
|
3103
|
+
|
|
3104
|
+
// src/components/app-shell.tsx
|
|
3105
|
+
import * as React51 from "react";
|
|
3033
3106
|
import { Menu as Menu2 } from "lucide-react";
|
|
3034
3107
|
import { useLocation as useLocation2 } from "react-router";
|
|
3035
|
-
import { jsx as
|
|
3108
|
+
import { jsx as jsx61, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
3036
3109
|
function expandedSidebar(sidebar) {
|
|
3037
|
-
return
|
|
3110
|
+
return React51.isValidElement(sidebar) ? React51.cloneElement(sidebar, { collapsed: false }) : sidebar;
|
|
3038
3111
|
}
|
|
3039
3112
|
function AppShell({ sidebar, topBar, children, className }) {
|
|
3040
3113
|
const { pathname } = useLocation2();
|
|
3041
|
-
const [mobileOpen, setMobileOpen] =
|
|
3042
|
-
|
|
3114
|
+
const [mobileOpen, setMobileOpen] = React51.useState(false);
|
|
3115
|
+
React51.useEffect(() => {
|
|
3043
3116
|
setMobileOpen(false);
|
|
3044
3117
|
}, [pathname]);
|
|
3045
3118
|
const isMobile = useIsMobile();
|
|
3046
3119
|
if (isMobile) {
|
|
3047
|
-
return /* @__PURE__ */
|
|
3048
|
-
/* @__PURE__ */
|
|
3049
|
-
/* @__PURE__ */
|
|
3050
|
-
/* @__PURE__ */
|
|
3051
|
-
/* @__PURE__ */
|
|
3052
|
-
/* @__PURE__ */
|
|
3053
|
-
/* @__PURE__ */
|
|
3120
|
+
return /* @__PURE__ */ jsx61(TooltipProvider, { children: /* @__PURE__ */ jsxs31("div", { className: cn("flex min-h-screen flex-col bg-bg-surface", className), children: [
|
|
3121
|
+
/* @__PURE__ */ jsxs31("header", { className: "flex shrink-0 items-center justify-between border-b border-border-subtle bg-bg-surface px-4 py-3", children: [
|
|
3122
|
+
/* @__PURE__ */ jsxs31(Sheet, { open: mobileOpen, onOpenChange: setMobileOpen, children: [
|
|
3123
|
+
/* @__PURE__ */ jsx61(SheetTrigger, { asChild: true, children: /* @__PURE__ */ jsx61(Button, { variant: "ghost", size: "icon", className: "size-8 text-text-secondary", "aria-label": "Open navigation", children: /* @__PURE__ */ jsx61(Menu2, { className: "size-5" }) }) }),
|
|
3124
|
+
/* @__PURE__ */ jsxs31(SheetContent, { side: "left", className: "w-[248px] bg-bg-surface p-0", children: [
|
|
3125
|
+
/* @__PURE__ */ jsx61(SheetTitle, { className: "sr-only", children: "Navigation" }),
|
|
3126
|
+
/* @__PURE__ */ jsx61(SheetDescription, { className: "sr-only", children: "Application navigation menu" }),
|
|
3054
3127
|
expandedSidebar(sidebar)
|
|
3055
3128
|
] })
|
|
3056
3129
|
] }),
|
|
3057
|
-
/* @__PURE__ */
|
|
3130
|
+
/* @__PURE__ */ jsx61("div", { className: "flex items-center gap-2", children: topBar })
|
|
3058
3131
|
] }),
|
|
3059
|
-
/* @__PURE__ */
|
|
3132
|
+
/* @__PURE__ */ jsx61("main", { className: "flex-1 overflow-auto", children })
|
|
3060
3133
|
] }) });
|
|
3061
3134
|
}
|
|
3062
|
-
return /* @__PURE__ */
|
|
3063
|
-
/* @__PURE__ */
|
|
3064
|
-
/* @__PURE__ */
|
|
3065
|
-
/* @__PURE__ */
|
|
3066
|
-
/* @__PURE__ */
|
|
3135
|
+
return /* @__PURE__ */ jsx61(TooltipProvider, { children: /* @__PURE__ */ jsxs31("div", { className: cn("flex min-h-screen gap-3 bg-bg-surface p-4", className), children: [
|
|
3136
|
+
/* @__PURE__ */ jsx61("div", { className: "sticky top-4 h-[calc(100vh-32px)] shrink-0", children: sidebar }),
|
|
3137
|
+
/* @__PURE__ */ jsxs31("div", { className: "flex min-w-0 flex-1 flex-col overflow-hidden", children: [
|
|
3138
|
+
topBar && /* @__PURE__ */ jsx61("div", { className: "flex shrink-0 items-center justify-end gap-2", children: topBar }),
|
|
3139
|
+
/* @__PURE__ */ jsx61("main", { className: "flex-1 overflow-y-auto", children })
|
|
3067
3140
|
] })
|
|
3068
3141
|
] }) });
|
|
3069
3142
|
}
|
|
3070
3143
|
var AuthenticatedLayout = AppShell;
|
|
3071
3144
|
|
|
3145
|
+
// src/components/grid.tsx
|
|
3146
|
+
import * as React52 from "react";
|
|
3147
|
+
import { Slot as Slot6 } from "@radix-ui/react-slot";
|
|
3148
|
+
import { jsx as jsx62 } from "react/jsx-runtime";
|
|
3149
|
+
var Grid = React52.forwardRef(
|
|
3150
|
+
({ fluid = false, asChild = false, className, ...props }, ref) => {
|
|
3151
|
+
const Comp = asChild ? Slot6 : "div";
|
|
3152
|
+
return /* @__PURE__ */ jsx62(
|
|
3153
|
+
Comp,
|
|
3154
|
+
{
|
|
3155
|
+
ref,
|
|
3156
|
+
className: cn(
|
|
3157
|
+
"grid grid-cols-4 md:grid-cols-8 xl:grid-cols-12",
|
|
3158
|
+
"gap-gutter px-grid-sm md:px-grid-md xl:px-grid-xl",
|
|
3159
|
+
!fluid && "mx-auto max-w-container",
|
|
3160
|
+
className
|
|
3161
|
+
),
|
|
3162
|
+
...props
|
|
3163
|
+
}
|
|
3164
|
+
);
|
|
3165
|
+
}
|
|
3166
|
+
);
|
|
3167
|
+
Grid.displayName = "Grid";
|
|
3168
|
+
|
|
3169
|
+
// src/components/col.tsx
|
|
3170
|
+
import * as React53 from "react";
|
|
3171
|
+
import { Slot as Slot7 } from "@radix-ui/react-slot";
|
|
3172
|
+
import { jsx as jsx63 } from "react/jsx-runtime";
|
|
3173
|
+
var TIER_MAX = { base: 4, md: 8, xl: 12 };
|
|
3174
|
+
var SPAN = {
|
|
3175
|
+
base: { 1: "col-span-1", 2: "col-span-2", 3: "col-span-3", 4: "col-span-4" },
|
|
3176
|
+
md: {
|
|
3177
|
+
1: "md:col-span-1",
|
|
3178
|
+
2: "md:col-span-2",
|
|
3179
|
+
3: "md:col-span-3",
|
|
3180
|
+
4: "md:col-span-4",
|
|
3181
|
+
5: "md:col-span-5",
|
|
3182
|
+
6: "md:col-span-6",
|
|
3183
|
+
7: "md:col-span-7",
|
|
3184
|
+
8: "md:col-span-8"
|
|
3185
|
+
},
|
|
3186
|
+
xl: {
|
|
3187
|
+
1: "xl:col-span-1",
|
|
3188
|
+
2: "xl:col-span-2",
|
|
3189
|
+
3: "xl:col-span-3",
|
|
3190
|
+
4: "xl:col-span-4",
|
|
3191
|
+
5: "xl:col-span-5",
|
|
3192
|
+
6: "xl:col-span-6",
|
|
3193
|
+
7: "xl:col-span-7",
|
|
3194
|
+
8: "xl:col-span-8",
|
|
3195
|
+
9: "xl:col-span-9",
|
|
3196
|
+
10: "xl:col-span-10",
|
|
3197
|
+
11: "xl:col-span-11",
|
|
3198
|
+
12: "xl:col-span-12"
|
|
3199
|
+
}
|
|
3200
|
+
};
|
|
3201
|
+
var START = {
|
|
3202
|
+
base: { 1: "col-start-1", 2: "col-start-2", 3: "col-start-3", 4: "col-start-4" },
|
|
3203
|
+
md: {
|
|
3204
|
+
1: "md:col-start-1",
|
|
3205
|
+
2: "md:col-start-2",
|
|
3206
|
+
3: "md:col-start-3",
|
|
3207
|
+
4: "md:col-start-4",
|
|
3208
|
+
5: "md:col-start-5",
|
|
3209
|
+
6: "md:col-start-6",
|
|
3210
|
+
7: "md:col-start-7",
|
|
3211
|
+
8: "md:col-start-8"
|
|
3212
|
+
},
|
|
3213
|
+
xl: {
|
|
3214
|
+
1: "xl:col-start-1",
|
|
3215
|
+
2: "xl:col-start-2",
|
|
3216
|
+
3: "xl:col-start-3",
|
|
3217
|
+
4: "xl:col-start-4",
|
|
3218
|
+
5: "xl:col-start-5",
|
|
3219
|
+
6: "xl:col-start-6",
|
|
3220
|
+
7: "xl:col-start-7",
|
|
3221
|
+
8: "xl:col-start-8",
|
|
3222
|
+
9: "xl:col-start-9",
|
|
3223
|
+
10: "xl:col-start-10",
|
|
3224
|
+
11: "xl:col-start-11",
|
|
3225
|
+
12: "xl:col-start-12"
|
|
3226
|
+
}
|
|
3227
|
+
};
|
|
3228
|
+
var TIERS = ["base", "md", "xl"];
|
|
3229
|
+
function tiersOf(value) {
|
|
3230
|
+
return typeof value === "number" ? TIERS : Object.keys(value);
|
|
3231
|
+
}
|
|
3232
|
+
function resolveTiers(value, kind) {
|
|
3233
|
+
const out = {};
|
|
3234
|
+
if (value == null) return out;
|
|
3235
|
+
for (const tier of tiersOf(value)) {
|
|
3236
|
+
if (!(tier in TIER_MAX)) {
|
|
3237
|
+
if (process.env.NODE_ENV !== "production") {
|
|
3238
|
+
console.warn(`[Col] unknown breakpoint "${tier}" (grid tiers are base/md/xl); skipped.`);
|
|
3239
|
+
}
|
|
3240
|
+
continue;
|
|
3241
|
+
}
|
|
3242
|
+
const requested = typeof value === "number" ? value : value[tier];
|
|
3243
|
+
if (requested == null) continue;
|
|
3244
|
+
const index = kind === "offset" ? requested + 1 : requested;
|
|
3245
|
+
if (!Number.isFinite(index)) {
|
|
3246
|
+
if (process.env.NODE_ENV !== "production") {
|
|
3247
|
+
console.warn(`[Col] ${kind} ${requested} is not a finite number at the "${tier}" tier; skipped.`);
|
|
3248
|
+
}
|
|
3249
|
+
continue;
|
|
3250
|
+
}
|
|
3251
|
+
const rounded = Math.round(index);
|
|
3252
|
+
const clamped = Math.min(Math.max(1, rounded), TIER_MAX[tier]);
|
|
3253
|
+
if (process.env.NODE_ENV !== "production" && (rounded < 1 || rounded > TIER_MAX[tier])) {
|
|
3254
|
+
console.warn(
|
|
3255
|
+
`[Col] ${kind} ${requested} is out of range at the "${tier}" tier (${TIER_MAX[tier]} columns); clamped.`
|
|
3256
|
+
);
|
|
3257
|
+
}
|
|
3258
|
+
out[tier] = clamped;
|
|
3259
|
+
}
|
|
3260
|
+
return out;
|
|
3261
|
+
}
|
|
3262
|
+
function responsiveClasses(span, offset) {
|
|
3263
|
+
const spans = resolveTiers(span, "span");
|
|
3264
|
+
const starts = resolveTiers(offset, "offset");
|
|
3265
|
+
const spanClasses = [];
|
|
3266
|
+
const startClasses = [];
|
|
3267
|
+
let effectiveSpan = 1;
|
|
3268
|
+
let requestedStart;
|
|
3269
|
+
let emittedStart;
|
|
3270
|
+
for (const tier of TIERS) {
|
|
3271
|
+
const tierSpan = spans[tier];
|
|
3272
|
+
if (tierSpan != null) {
|
|
3273
|
+
effectiveSpan = tierSpan;
|
|
3274
|
+
spanClasses.push(SPAN[tier][tierSpan]);
|
|
3275
|
+
}
|
|
3276
|
+
if (starts[tier] != null) requestedStart = starts[tier];
|
|
3277
|
+
if (requestedStart == null) continue;
|
|
3278
|
+
const lastFittingStart = TIER_MAX[tier] - effectiveSpan + 1;
|
|
3279
|
+
const tierStart = Math.min(requestedStart, lastFittingStart);
|
|
3280
|
+
if (tierStart < requestedStart && process.env.NODE_ENV !== "production") {
|
|
3281
|
+
console.warn(
|
|
3282
|
+
`[Col] span ${effectiveSpan} + offset ${requestedStart - 1} spill past the "${tier}" tier (${TIER_MAX[tier]} columns); offset clamped to ${tierStart - 1}.`
|
|
3283
|
+
);
|
|
3284
|
+
}
|
|
3285
|
+
if (starts[tier] != null || tierStart !== emittedStart) {
|
|
3286
|
+
emittedStart = tierStart;
|
|
3287
|
+
startClasses.push(START[tier][tierStart]);
|
|
3288
|
+
}
|
|
3289
|
+
}
|
|
3290
|
+
return cn(...spanClasses, ...startClasses);
|
|
3291
|
+
}
|
|
3292
|
+
var Col = React53.forwardRef(
|
|
3293
|
+
({ span, offset, asChild = false, className, ...props }, ref) => {
|
|
3294
|
+
const Comp = asChild ? Slot7 : "div";
|
|
3295
|
+
return /* @__PURE__ */ jsx63(Comp, { ref, className: cn(responsiveClasses(span, offset), className), ...props });
|
|
3296
|
+
}
|
|
3297
|
+
);
|
|
3298
|
+
Col.displayName = "Col";
|
|
3299
|
+
|
|
3300
|
+
// src/components/grid-overlay.tsx
|
|
3301
|
+
import * as React54 from "react";
|
|
3302
|
+
import { jsx as jsx64 } from "react/jsx-runtime";
|
|
3303
|
+
var BASELINE = "var(--grid-gutter) / 2";
|
|
3304
|
+
var GridOverlay = React54.forwardRef(
|
|
3305
|
+
({ columns, baseline = false, className, style, ...props }, ref) => {
|
|
3306
|
+
const count = Number.isFinite(columns) ? Math.max(1, Math.floor(columns)) : 1;
|
|
3307
|
+
return /* @__PURE__ */ jsx64(
|
|
3308
|
+
"div",
|
|
3309
|
+
{
|
|
3310
|
+
ref,
|
|
3311
|
+
"aria-hidden": true,
|
|
3312
|
+
className: cn("pointer-events-none absolute inset-0", className),
|
|
3313
|
+
style: {
|
|
3314
|
+
display: "grid",
|
|
3315
|
+
gridTemplateColumns: `repeat(${count}, minmax(0, 1fr))`,
|
|
3316
|
+
gridTemplateRows: "1fr",
|
|
3317
|
+
gap: "var(--grid-gutter)",
|
|
3318
|
+
...baseline && {
|
|
3319
|
+
backgroundImage: `repeating-linear-gradient(to bottom, transparent 0, transparent calc(${BASELINE} - 1px), var(--border-subtle) calc(${BASELINE} - 1px), var(--border-subtle) calc(${BASELINE}))`
|
|
3320
|
+
},
|
|
3321
|
+
...style
|
|
3322
|
+
},
|
|
3323
|
+
...props,
|
|
3324
|
+
children: Array.from({ length: count }).map((_, i) => /* @__PURE__ */ jsx64("span", { style: { backgroundColor: "var(--bg-brand)", opacity: 0.1 } }, i))
|
|
3325
|
+
}
|
|
3326
|
+
);
|
|
3327
|
+
}
|
|
3328
|
+
);
|
|
3329
|
+
GridOverlay.displayName = "GridOverlay";
|
|
3330
|
+
|
|
3072
3331
|
// src/components/segment-chip.tsx
|
|
3073
|
-
import * as
|
|
3332
|
+
import * as React55 from "react";
|
|
3074
3333
|
import { cva as cva9 } from "class-variance-authority";
|
|
3075
3334
|
import { Link2 as Link22, KeyRound, Clock, Plus } from "lucide-react";
|
|
3076
|
-
import { jsx as
|
|
3335
|
+
import { jsx as jsx65, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
3077
3336
|
var segmentChipVariants = cva9(
|
|
3078
3337
|
"inline-flex items-center gap-1.5 rounded-lg border px-2.5 py-1 text-sm font-medium leading-tight",
|
|
3079
3338
|
{
|
|
@@ -3094,11 +3353,11 @@ var kindIcons = {
|
|
|
3094
3353
|
pending: Clock,
|
|
3095
3354
|
available: Plus
|
|
3096
3355
|
};
|
|
3097
|
-
var SegmentChip =
|
|
3356
|
+
var SegmentChip = React55.forwardRef(
|
|
3098
3357
|
({ kind, resource, icon, hideIcon = false, className, ...props }, ref) => {
|
|
3099
3358
|
const Icon = icon ?? kindIcons[kind ?? "granted"];
|
|
3100
|
-
return /* @__PURE__ */
|
|
3101
|
-
!hideIcon && /* @__PURE__ */
|
|
3359
|
+
return /* @__PURE__ */ jsxs32("span", { ref, className: cn(segmentChipVariants({ kind }), className), ...props, children: [
|
|
3360
|
+
!hideIcon && /* @__PURE__ */ jsx65(Icon, { className: "size-3.5 shrink-0 opacity-90", "aria-hidden": "true" }),
|
|
3102
3361
|
resource
|
|
3103
3362
|
] });
|
|
3104
3363
|
}
|
|
@@ -3106,9 +3365,9 @@ var SegmentChip = React51.forwardRef(
|
|
|
3106
3365
|
SegmentChip.displayName = "SegmentChip";
|
|
3107
3366
|
|
|
3108
3367
|
// src/components/connection-card.tsx
|
|
3109
|
-
import * as
|
|
3368
|
+
import * as React56 from "react";
|
|
3110
3369
|
import { AlertTriangle } from "lucide-react";
|
|
3111
|
-
import { Fragment as
|
|
3370
|
+
import { Fragment as Fragment5, jsx as jsx66, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
3112
3371
|
var authLabels = { app: "App", oauth: "OAuth", token: "token" };
|
|
3113
3372
|
var statusMeta = {
|
|
3114
3373
|
connected: { label: "Connected", badge: "success", dot: "success" },
|
|
@@ -3118,13 +3377,13 @@ var statusMeta = {
|
|
|
3118
3377
|
function monogram(name) {
|
|
3119
3378
|
return name.replace(/[^a-zA-Z0-9 ]/g, " ").split(/\s+/).filter(Boolean).slice(0, 2).map((w) => w[0].toUpperCase()).join("");
|
|
3120
3379
|
}
|
|
3121
|
-
var ConnectionCard =
|
|
3380
|
+
var ConnectionCard = React56.forwardRef(
|
|
3122
3381
|
({ name, scope, auth, status, glyph, statusLabel, grantedCount, action, access, children, className, ...props }, ref) => {
|
|
3123
3382
|
const meta = statusMeta[status];
|
|
3124
3383
|
const connected = status !== "disconnected";
|
|
3125
|
-
return /* @__PURE__ */
|
|
3126
|
-
/* @__PURE__ */
|
|
3127
|
-
/* @__PURE__ */
|
|
3384
|
+
return /* @__PURE__ */ jsxs33(Card, { ref, className: cn(status === "disconnected" && "border-dashed border-border-default", className), ...props, children: [
|
|
3385
|
+
/* @__PURE__ */ jsxs33("div", { className: "flex items-center gap-3 p-4", children: [
|
|
3386
|
+
/* @__PURE__ */ jsx66(
|
|
3128
3387
|
"div",
|
|
3129
3388
|
{
|
|
3130
3389
|
"aria-hidden": "true",
|
|
@@ -3132,71 +3391,71 @@ var ConnectionCard = React52.forwardRef(
|
|
|
3132
3391
|
children: glyph ?? monogram(name)
|
|
3133
3392
|
}
|
|
3134
3393
|
),
|
|
3135
|
-
/* @__PURE__ */
|
|
3136
|
-
/* @__PURE__ */
|
|
3137
|
-
/* @__PURE__ */
|
|
3138
|
-
/* @__PURE__ */
|
|
3139
|
-
/* @__PURE__ */
|
|
3394
|
+
/* @__PURE__ */ jsxs33("div", { className: "min-w-0", children: [
|
|
3395
|
+
/* @__PURE__ */ jsx66("p", { className: "truncate text-sm font-semibold text-text-primary", children: name }),
|
|
3396
|
+
/* @__PURE__ */ jsxs33("div", { className: "mt-0.5 flex flex-wrap gap-1", children: [
|
|
3397
|
+
/* @__PURE__ */ jsx66(Badge, { variant: "secondary", children: scope }),
|
|
3398
|
+
/* @__PURE__ */ jsx66(Badge, { variant: "secondary", children: authLabels[auth] })
|
|
3140
3399
|
] })
|
|
3141
3400
|
] }),
|
|
3142
|
-
/* @__PURE__ */
|
|
3143
|
-
/* @__PURE__ */
|
|
3401
|
+
/* @__PURE__ */ jsx66("div", { className: "ml-auto shrink-0", children: connected ? /* @__PURE__ */ jsxs33(Badge, { variant: meta.badge, className: "gap-1.5", children: [
|
|
3402
|
+
/* @__PURE__ */ jsx66(StatusDot, { status: meta.dot, size: "sm" }),
|
|
3144
3403
|
statusLabel ?? meta.label
|
|
3145
3404
|
] }) : action })
|
|
3146
3405
|
] }),
|
|
3147
|
-
access && /* @__PURE__ */
|
|
3406
|
+
access && /* @__PURE__ */ jsxs33(
|
|
3148
3407
|
"div",
|
|
3149
3408
|
{
|
|
3150
3409
|
role: "note",
|
|
3151
3410
|
className: "flex items-start gap-2 border-t border-border-subtle bg-bg-warning-subtle px-4 py-2.5 text-xs font-medium text-text-warning",
|
|
3152
3411
|
children: [
|
|
3153
|
-
/* @__PURE__ */
|
|
3154
|
-
/* @__PURE__ */
|
|
3412
|
+
/* @__PURE__ */ jsx66(AlertTriangle, { className: "mt-0.5 size-3.5 shrink-0", "aria-hidden": "true" }),
|
|
3413
|
+
/* @__PURE__ */ jsx66("span", { children: access })
|
|
3155
3414
|
]
|
|
3156
3415
|
}
|
|
3157
3416
|
),
|
|
3158
|
-
(grantedCount !== void 0 || connected && action) && /* @__PURE__ */
|
|
3159
|
-
/* @__PURE__ */
|
|
3417
|
+
(grantedCount !== void 0 || connected && action) && /* @__PURE__ */ jsxs33("div", { className: "flex items-center justify-between border-t border-border-subtle px-4 py-3", children: [
|
|
3418
|
+
/* @__PURE__ */ jsx66("span", { className: "text-sm text-text-secondary", children: grantedCount !== void 0 ? /* @__PURE__ */ jsxs33(Fragment5, { children: [
|
|
3160
3419
|
"Granted to ",
|
|
3161
|
-
/* @__PURE__ */
|
|
3420
|
+
/* @__PURE__ */ jsx66("span", { className: "font-semibold text-text-primary", children: grantedCount }),
|
|
3162
3421
|
" ",
|
|
3163
3422
|
grantedCount === 1 ? "product" : "products"
|
|
3164
|
-
] }) : /* @__PURE__ */
|
|
3423
|
+
] }) : /* @__PURE__ */ jsx66("span", { className: "text-text-tertiary", children: "Not granted to any product yet" }) }),
|
|
3165
3424
|
connected && action
|
|
3166
3425
|
] }),
|
|
3167
|
-
children && /* @__PURE__ */
|
|
3426
|
+
children && /* @__PURE__ */ jsx66("div", { "data-slot": "drawer", className: "border-t border-border-subtle", children })
|
|
3168
3427
|
] });
|
|
3169
3428
|
}
|
|
3170
3429
|
);
|
|
3171
3430
|
ConnectionCard.displayName = "ConnectionCard";
|
|
3172
3431
|
|
|
3173
3432
|
// src/components/request-row.tsx
|
|
3174
|
-
import * as
|
|
3175
|
-
import { Fragment as
|
|
3433
|
+
import * as React57 from "react";
|
|
3434
|
+
import { Fragment as Fragment6, jsx as jsx67, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
3176
3435
|
function monogram2(name) {
|
|
3177
3436
|
return name.replace(/[^a-zA-Z0-9 ]/g, " ").split(/\s+/).filter(Boolean).slice(0, 2).map((w) => w[0].toUpperCase()).join("");
|
|
3178
3437
|
}
|
|
3179
|
-
var RequestRow =
|
|
3438
|
+
var RequestRow = React57.forwardRef(
|
|
3180
3439
|
({ surface, name, state: state2, glyph, subtitle, grantedResource, onApprove, onDeny, onRequest, action, className, ...props }, ref) => {
|
|
3181
3440
|
let controls = action;
|
|
3182
3441
|
if (controls === void 0) {
|
|
3183
3442
|
if (surface === "org" && state2 === "pending") {
|
|
3184
|
-
controls = /* @__PURE__ */
|
|
3185
|
-
/* @__PURE__ */
|
|
3186
|
-
/* @__PURE__ */
|
|
3443
|
+
controls = /* @__PURE__ */ jsxs34(Fragment6, { children: [
|
|
3444
|
+
/* @__PURE__ */ jsx67(Button, { variant: "outline", size: "sm", onClick: onDeny, children: "Deny" }),
|
|
3445
|
+
/* @__PURE__ */ jsx67(Button, { size: "sm", onClick: onApprove, children: "Approve" })
|
|
3187
3446
|
] });
|
|
3188
3447
|
} else if (state2 === "available") {
|
|
3189
|
-
controls = /* @__PURE__ */
|
|
3448
|
+
controls = /* @__PURE__ */ jsx67(Button, { size: "sm", onClick: onRequest, children: "Request" });
|
|
3190
3449
|
} else if (state2 === "pending") {
|
|
3191
|
-
controls = /* @__PURE__ */
|
|
3192
|
-
/* @__PURE__ */
|
|
3450
|
+
controls = /* @__PURE__ */ jsxs34(Badge, { variant: "secondary", className: "gap-1.5", children: [
|
|
3451
|
+
/* @__PURE__ */ jsx67(StatusDot, { status: "neutral", size: "sm" }),
|
|
3193
3452
|
"Pending"
|
|
3194
3453
|
] });
|
|
3195
3454
|
} else if (state2 === "granted") {
|
|
3196
|
-
controls = /* @__PURE__ */
|
|
3455
|
+
controls = /* @__PURE__ */ jsx67(SegmentChip, { kind: "granted", resource: grantedResource ?? "a segment" });
|
|
3197
3456
|
}
|
|
3198
3457
|
}
|
|
3199
|
-
return /* @__PURE__ */
|
|
3458
|
+
return /* @__PURE__ */ jsxs34(
|
|
3200
3459
|
"div",
|
|
3201
3460
|
{
|
|
3202
3461
|
ref,
|
|
@@ -3206,7 +3465,7 @@ var RequestRow = React53.forwardRef(
|
|
|
3206
3465
|
),
|
|
3207
3466
|
...props,
|
|
3208
3467
|
children: [
|
|
3209
|
-
/* @__PURE__ */
|
|
3468
|
+
/* @__PURE__ */ jsx67(
|
|
3210
3469
|
"div",
|
|
3211
3470
|
{
|
|
3212
3471
|
"aria-hidden": "true",
|
|
@@ -3214,11 +3473,11 @@ var RequestRow = React53.forwardRef(
|
|
|
3214
3473
|
children: glyph ?? monogram2(name)
|
|
3215
3474
|
}
|
|
3216
3475
|
),
|
|
3217
|
-
/* @__PURE__ */
|
|
3218
|
-
/* @__PURE__ */
|
|
3219
|
-
subtitle && /* @__PURE__ */
|
|
3476
|
+
/* @__PURE__ */ jsxs34("div", { className: "min-w-0", children: [
|
|
3477
|
+
/* @__PURE__ */ jsx67("p", { className: "truncate text-sm font-semibold text-text-primary", children: name }),
|
|
3478
|
+
subtitle && /* @__PURE__ */ jsx67("p", { className: "truncate text-xs text-text-tertiary", children: subtitle })
|
|
3220
3479
|
] }),
|
|
3221
|
-
/* @__PURE__ */
|
|
3480
|
+
/* @__PURE__ */ jsx67("div", { className: "ml-auto flex shrink-0 items-center gap-2", children: controls })
|
|
3222
3481
|
]
|
|
3223
3482
|
}
|
|
3224
3483
|
);
|
|
@@ -3273,6 +3532,7 @@ export {
|
|
|
3273
3532
|
CarouselNext,
|
|
3274
3533
|
CarouselPrevious,
|
|
3275
3534
|
Checkbox,
|
|
3535
|
+
Col,
|
|
3276
3536
|
Collapsible,
|
|
3277
3537
|
CollapsibleContent2 as CollapsibleContent,
|
|
3278
3538
|
CollapsibleTrigger2 as CollapsibleTrigger,
|
|
@@ -3350,6 +3610,8 @@ export {
|
|
|
3350
3610
|
FormItem,
|
|
3351
3611
|
FormLabel,
|
|
3352
3612
|
FormMessage,
|
|
3613
|
+
Grid,
|
|
3614
|
+
GridOverlay,
|
|
3353
3615
|
HoverCard,
|
|
3354
3616
|
HoverCardContent,
|
|
3355
3617
|
HoverCardTrigger,
|
|
@@ -3421,6 +3683,7 @@ export {
|
|
|
3421
3683
|
SheetTrigger,
|
|
3422
3684
|
SidebarNav,
|
|
3423
3685
|
SidebarNavLink,
|
|
3686
|
+
SidebarProductHeader,
|
|
3424
3687
|
Skeleton,
|
|
3425
3688
|
Slider,
|
|
3426
3689
|
StatCard,
|