@lessly/ui 0.6.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +28 -6
- package/dist/index.js +112 -42
- package/dist/styles.css +17 -19
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -986,9 +986,19 @@ interface ConnectionCardProps extends React$1.HTMLAttributes<HTMLDivElement> {
|
|
|
986
986
|
glyph?: React$1.ReactNode;
|
|
987
987
|
/** Override the default status label (e.g. "Token expired" for `error`). */
|
|
988
988
|
statusLabel?: string;
|
|
989
|
-
/**
|
|
989
|
+
/**
|
|
990
|
+
* How many products hold a segment of this connection. `undefined` renders the
|
|
991
|
+
* "Not granted to any product yet" default — pass it ONLY on a surface where
|
|
992
|
+
* that claim is true and knowable (the org roster); on a product surface pass
|
|
993
|
+
* neither `grantedCount` nor a footer `action` to render no footer at all.
|
|
994
|
+
*/
|
|
990
995
|
grantedCount?: number;
|
|
991
|
-
/**
|
|
996
|
+
/**
|
|
997
|
+
* Footer action — typically a <Button> ("Manage", "Reconnect", "Connect").
|
|
998
|
+
* Flat mode: a disconnected card shows it in the header. Collapsible mode: the
|
|
999
|
+
* header is a disclosure trigger (nesting a button would be invalid), so the
|
|
1000
|
+
* action always renders in the expanded footer instead.
|
|
1001
|
+
*/
|
|
992
1002
|
action?: React$1.ReactNode;
|
|
993
1003
|
/**
|
|
994
1004
|
* Blast-radius disclosure. Some providers (GitHub, ClickUp) grant all-or-nothing
|
|
@@ -1000,12 +1010,24 @@ interface ConnectionCardProps extends React$1.HTMLAttributes<HTMLDivElement> {
|
|
|
1000
1010
|
*/
|
|
1001
1011
|
access?: React$1.ReactNode;
|
|
1002
1012
|
/**
|
|
1003
|
-
* Drawer content rendered below the card body — the
|
|
1004
|
-
*
|
|
1005
|
-
*
|
|
1006
|
-
* children
|
|
1013
|
+
* Drawer content rendered below the card body — the per-product grants roster,
|
|
1014
|
+
* inline requests, "+ Grant to a product". Flat mode: the caller owns visibility,
|
|
1015
|
+
* pass children only while open (unchanged behavior). Collapsible mode: pass
|
|
1016
|
+
* children unconditionally — the card shows them while expanded.
|
|
1007
1017
|
*/
|
|
1008
1018
|
children?: React$1.ReactNode;
|
|
1019
|
+
/**
|
|
1020
|
+
* Disclosure mode: the header row toggles the card open/closed; the footer and
|
|
1021
|
+
* drawer render only while open. The `access` blast-radius notice stays visible
|
|
1022
|
+
* even while collapsed — it is a safety disclosure, not a detail. Collapsed by
|
|
1023
|
+
* default.
|
|
1024
|
+
*/
|
|
1025
|
+
collapsible?: boolean;
|
|
1026
|
+
/** Uncontrolled initial state (collapsible mode). Default: false (collapsed). */
|
|
1027
|
+
defaultOpen?: boolean;
|
|
1028
|
+
/** Controlled open state (collapsible mode); pair with `onOpenChange`. */
|
|
1029
|
+
open?: boolean;
|
|
1030
|
+
onOpenChange?: (open: boolean) => void;
|
|
1009
1031
|
}
|
|
1010
1032
|
declare const ConnectionCard: React$1.ForwardRefExoticComponent<ConnectionCardProps & React$1.RefAttributes<HTMLDivElement>>;
|
|
1011
1033
|
|
package/dist/index.js
CHANGED
|
@@ -3366,7 +3366,7 @@ SegmentChip.displayName = "SegmentChip";
|
|
|
3366
3366
|
|
|
3367
3367
|
// src/components/connection-card.tsx
|
|
3368
3368
|
import * as React56 from "react";
|
|
3369
|
-
import { AlertTriangle } from "lucide-react";
|
|
3369
|
+
import { AlertTriangle, ChevronDown as ChevronDown4 } from "lucide-react";
|
|
3370
3370
|
import { Fragment as Fragment5, jsx as jsx66, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
3371
3371
|
var authLabels = { app: "App", oauth: "OAuth", token: "token" };
|
|
3372
3372
|
var statusMeta = {
|
|
@@ -3378,53 +3378,123 @@ function monogram(name) {
|
|
|
3378
3378
|
return name.replace(/[^a-zA-Z0-9 ]/g, " ").split(/\s+/).filter(Boolean).slice(0, 2).map((w) => w[0].toUpperCase()).join("");
|
|
3379
3379
|
}
|
|
3380
3380
|
var ConnectionCard = React56.forwardRef(
|
|
3381
|
-
({
|
|
3381
|
+
({
|
|
3382
|
+
name,
|
|
3383
|
+
scope,
|
|
3384
|
+
auth,
|
|
3385
|
+
status,
|
|
3386
|
+
glyph,
|
|
3387
|
+
statusLabel,
|
|
3388
|
+
grantedCount,
|
|
3389
|
+
action,
|
|
3390
|
+
access,
|
|
3391
|
+
children,
|
|
3392
|
+
collapsible = false,
|
|
3393
|
+
defaultOpen,
|
|
3394
|
+
open,
|
|
3395
|
+
onOpenChange,
|
|
3396
|
+
className,
|
|
3397
|
+
...props
|
|
3398
|
+
}, ref) => {
|
|
3382
3399
|
const meta = statusMeta[status];
|
|
3383
3400
|
const connected = status !== "disconnected";
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
"
|
|
3401
|
+
const glyphBox = /* @__PURE__ */ jsx66(
|
|
3402
|
+
"div",
|
|
3403
|
+
{
|
|
3404
|
+
"aria-hidden": "true",
|
|
3405
|
+
className: "flex size-8 shrink-0 items-center justify-center rounded-lg border border-border-subtle bg-bg-elevated text-sm font-bold text-text-secondary",
|
|
3406
|
+
children: glyph ?? monogram(name)
|
|
3407
|
+
}
|
|
3408
|
+
);
|
|
3409
|
+
const identity = /* @__PURE__ */ jsxs33("div", { className: "min-w-0", children: [
|
|
3410
|
+
/* @__PURE__ */ jsx66("p", { className: "truncate text-sm font-semibold text-text-primary", children: name }),
|
|
3411
|
+
/* @__PURE__ */ jsxs33("div", { className: "mt-0.5 flex flex-wrap gap-1", children: [
|
|
3412
|
+
/* @__PURE__ */ jsx66(Badge, { variant: "secondary", children: scope }),
|
|
3413
|
+
/* @__PURE__ */ jsx66(Badge, { variant: "secondary", children: authLabels[auth] })
|
|
3414
|
+
] })
|
|
3415
|
+
] });
|
|
3416
|
+
const statusBadge = /* @__PURE__ */ jsxs33(Badge, { variant: meta.badge, className: "gap-1.5", children: [
|
|
3417
|
+
/* @__PURE__ */ jsx66(StatusDot, { status: meta.dot, size: "sm" }),
|
|
3418
|
+
statusLabel ?? meta.label
|
|
3419
|
+
] });
|
|
3420
|
+
const accessNote = access ? /* @__PURE__ */ jsxs33(
|
|
3421
|
+
"div",
|
|
3422
|
+
{
|
|
3423
|
+
role: "note",
|
|
3424
|
+
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",
|
|
3425
|
+
children: [
|
|
3426
|
+
/* @__PURE__ */ jsx66(AlertTriangle, { className: "mt-0.5 size-3.5 shrink-0", "aria-hidden": "true" }),
|
|
3427
|
+
/* @__PURE__ */ jsx66("span", { children: access })
|
|
3428
|
+
]
|
|
3429
|
+
}
|
|
3430
|
+
) : null;
|
|
3431
|
+
const footerAction = collapsible ? action : connected && action;
|
|
3432
|
+
const footer = grantedCount !== void 0 || footerAction ? /* @__PURE__ */ jsxs33("div", { className: "flex items-center justify-between border-t border-border-subtle px-4 py-3", children: [
|
|
3433
|
+
/* @__PURE__ */ jsx66("span", { className: "text-sm text-text-secondary", children: grantedCount !== void 0 ? /* @__PURE__ */ jsxs33(Fragment5, { children: [
|
|
3434
|
+
"Granted to ",
|
|
3435
|
+
/* @__PURE__ */ jsx66("span", { className: "font-semibold text-text-primary", children: grantedCount }),
|
|
3436
|
+
" ",
|
|
3437
|
+
grantedCount === 1 ? "product" : "products"
|
|
3438
|
+
] }) : /* @__PURE__ */ jsx66("span", { className: "text-text-tertiary", children: "Not granted to any product yet" }) }),
|
|
3439
|
+
footerAction
|
|
3440
|
+
] }) : null;
|
|
3441
|
+
const drawer = children ? /* @__PURE__ */ jsx66("div", { "data-slot": "drawer", className: "border-t border-border-subtle", children }) : null;
|
|
3442
|
+
if (!collapsible) {
|
|
3443
|
+
return /* @__PURE__ */ jsxs33(
|
|
3444
|
+
Card,
|
|
3408
3445
|
{
|
|
3409
|
-
|
|
3410
|
-
className: "
|
|
3446
|
+
ref,
|
|
3447
|
+
className: cn(status === "disconnected" && "border-dashed border-border-default", className),
|
|
3448
|
+
...props,
|
|
3411
3449
|
children: [
|
|
3412
|
-
/* @__PURE__ */
|
|
3413
|
-
|
|
3450
|
+
/* @__PURE__ */ jsxs33("div", { className: "flex items-center gap-3 p-4", children: [
|
|
3451
|
+
glyphBox,
|
|
3452
|
+
identity,
|
|
3453
|
+
/* @__PURE__ */ jsx66("div", { className: "ml-auto shrink-0", children: connected ? statusBadge : action })
|
|
3454
|
+
] }),
|
|
3455
|
+
accessNote,
|
|
3456
|
+
footer,
|
|
3457
|
+
drawer
|
|
3414
3458
|
]
|
|
3415
3459
|
}
|
|
3416
|
-
)
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3460
|
+
);
|
|
3461
|
+
}
|
|
3462
|
+
return /* @__PURE__ */ jsx66(Collapsible, { defaultOpen, open, onOpenChange, children: /* @__PURE__ */ jsxs33(
|
|
3463
|
+
Card,
|
|
3464
|
+
{
|
|
3465
|
+
ref,
|
|
3466
|
+
className: cn(status === "disconnected" && "border-dashed border-border-default", className),
|
|
3467
|
+
...props,
|
|
3468
|
+
children: [
|
|
3469
|
+
/* @__PURE__ */ jsx66(CollapsibleTrigger2, { asChild: true, children: /* @__PURE__ */ jsxs33(
|
|
3470
|
+
"button",
|
|
3471
|
+
{
|
|
3472
|
+
type: "button",
|
|
3473
|
+
className: "group flex w-full cursor-pointer items-center gap-3 rounded-[inherit] p-4 text-left focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus",
|
|
3474
|
+
children: [
|
|
3475
|
+
glyphBox,
|
|
3476
|
+
identity,
|
|
3477
|
+
/* @__PURE__ */ jsxs33("div", { className: "ml-auto flex shrink-0 items-center gap-2", children: [
|
|
3478
|
+
statusBadge,
|
|
3479
|
+
/* @__PURE__ */ jsx66(
|
|
3480
|
+
ChevronDown4,
|
|
3481
|
+
{
|
|
3482
|
+
"aria-hidden": "true",
|
|
3483
|
+
className: "size-4 shrink-0 text-text-tertiary transition-transform group-data-[state=open]:rotate-180"
|
|
3484
|
+
}
|
|
3485
|
+
)
|
|
3486
|
+
] })
|
|
3487
|
+
]
|
|
3488
|
+
}
|
|
3489
|
+
) }),
|
|
3490
|
+
accessNote,
|
|
3491
|
+
/* @__PURE__ */ jsxs33(CollapsibleContent2, { children: [
|
|
3492
|
+
footer,
|
|
3493
|
+
drawer
|
|
3494
|
+
] })
|
|
3495
|
+
]
|
|
3496
|
+
}
|
|
3497
|
+
) });
|
|
3428
3498
|
}
|
|
3429
3499
|
);
|
|
3430
3500
|
ConnectionCard.displayName = "ConnectionCard";
|
package/dist/styles.css
CHANGED
|
@@ -11,13 +11,13 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
:root {
|
|
14
|
-
--bg-primary: #
|
|
14
|
+
--bg-primary: #191b24;
|
|
15
15
|
--bg-secondary: #12141b;
|
|
16
|
-
--bg-surface: #
|
|
17
|
-
--bg-elevated: #
|
|
18
|
-
--bg-sunken: #
|
|
16
|
+
--bg-surface: #1f222d;
|
|
17
|
+
--bg-elevated: #252936;
|
|
18
|
+
--bg-sunken: #0e1015;
|
|
19
19
|
--bg-brand: #06297d;
|
|
20
|
-
--bg-brand-subtle: #
|
|
20
|
+
--bg-brand-subtle: #1f2541;
|
|
21
21
|
--bg-brand-hover: #08349b;
|
|
22
22
|
--bg-brand-bright: #165ff2;
|
|
23
23
|
--bg-brand-bright-hover: #3d7af4;
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
--bg-rose-subtle: #1a090b;
|
|
34
34
|
--text-primary: #eeeff0;
|
|
35
35
|
--text-secondary: #a5a9b5;
|
|
36
|
-
--text-tertiary: #
|
|
36
|
+
--text-tertiary: #8a93a8;
|
|
37
37
|
--text-disabled: #60687f;
|
|
38
38
|
--text-inverse: #0e1015;
|
|
39
39
|
--text-on-brand: #f6f7f7;
|
|
@@ -57,9 +57,9 @@
|
|
|
57
57
|
--icon-success: #2eda76;
|
|
58
58
|
--icon-warning: #efb042;
|
|
59
59
|
--icon-danger: #f06a6a;
|
|
60
|
-
--border-subtle: #
|
|
61
|
-
--border-default: #
|
|
62
|
-
--border-strong: #
|
|
60
|
+
--border-subtle: #2a2e3b;
|
|
61
|
+
--border-default: #737c95;
|
|
62
|
+
--border-strong: #8a91a7;
|
|
63
63
|
--border-brand: #165ff2;
|
|
64
64
|
--border-focus: #165ff2;
|
|
65
65
|
--border-success: #1da456;
|
|
@@ -271,12 +271,12 @@
|
|
|
271
271
|
}
|
|
272
272
|
|
|
273
273
|
.light {
|
|
274
|
-
--bg-primary: #
|
|
275
|
-
--bg-secondary: #
|
|
276
|
-
--bg-surface: #
|
|
277
|
-
--bg-elevated: #
|
|
278
|
-
--bg-sunken: #
|
|
279
|
-
--bg-brand-subtle: #
|
|
274
|
+
--bg-primary: #f6f7f7;
|
|
275
|
+
--bg-secondary: #eeeff0;
|
|
276
|
+
--bg-surface: #f2f3f4;
|
|
277
|
+
--bg-elevated: #edeef0;
|
|
278
|
+
--bg-sunken: #e1e2e4;
|
|
279
|
+
--bg-brand-subtle: #e4ecfe;
|
|
280
280
|
--bg-brand-hover: #05226a;
|
|
281
281
|
--bg-brand-bright-hover: #0b4cd5;
|
|
282
282
|
--bg-success-subtle: #ebf3ef;
|
|
@@ -291,7 +291,7 @@
|
|
|
291
291
|
--text-tertiary: #535a6e;
|
|
292
292
|
--text-disabled: #737c95;
|
|
293
293
|
--text-inverse: #f6f7f7;
|
|
294
|
-
--text-brand: #
|
|
294
|
+
--text-brand: #0b4cd5;
|
|
295
295
|
--text-success: #13703c;
|
|
296
296
|
--text-warning: #7a5409;
|
|
297
297
|
--text-danger: #94120e;
|
|
@@ -303,12 +303,11 @@
|
|
|
303
303
|
--icon-primary: #252936;
|
|
304
304
|
--icon-secondary: #535a6e;
|
|
305
305
|
--icon-disabled: #8a91a7;
|
|
306
|
-
--icon-brand: #
|
|
306
|
+
--icon-brand: #165ff2;
|
|
307
307
|
--icon-success: #13703c;
|
|
308
308
|
--icon-warning: #7a5409;
|
|
309
309
|
--icon-danger: #94120e;
|
|
310
310
|
--border-subtle: #cfd1d7;
|
|
311
|
-
--border-default: #737c95;
|
|
312
311
|
--border-strong: #60687f;
|
|
313
312
|
--border-focus: #0940b8;
|
|
314
313
|
--border-success: #188a49;
|
|
@@ -668,7 +667,6 @@
|
|
|
668
667
|
--color-icon-warning: var(--icon-warning);
|
|
669
668
|
--color-icon-danger: var(--icon-danger);
|
|
670
669
|
--color-border-subtle: var(--border-subtle);
|
|
671
|
-
--color-border-default: var(--border-default);
|
|
672
670
|
--color-border-strong: var(--border-strong);
|
|
673
671
|
--color-border-focus: var(--border-focus);
|
|
674
672
|
--color-border-success: var(--border-success);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lessly/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"description": "Lessly design system — shared UI primitives, tokens, and theme",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"packageManager": "pnpm@10.30.3",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
}
|
|
58
58
|
},
|
|
59
59
|
"dependencies": {
|
|
60
|
-
"@lessly/tokens": "^0.1
|
|
60
|
+
"@lessly/tokens": "^0.3.1",
|
|
61
61
|
"@radix-ui/react-accordion": "^1.2.16",
|
|
62
62
|
"@radix-ui/react-alert-dialog": "^1.1.19",
|
|
63
63
|
"@radix-ui/react-aspect-ratio": "^1.1.11",
|