@flytedan/flytebot-design-system 0.12.8 → 0.12.10
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.cjs +37 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +31 -11
- package/dist/index.d.ts +31 -11
- package/dist/index.js +37 -17
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/styles/components.css +165 -12
- package/styles/tokens.css +27 -0
package/dist/index.d.cts
CHANGED
|
@@ -31,12 +31,16 @@ interface IconButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>
|
|
|
31
31
|
size?: "sm" | "md" | "lg";
|
|
32
32
|
/** "ghost" and "outline" are quiet: no fill, the glyph carries the tone. "solid" is a
|
|
33
33
|
* filled button in the tone's colour — for the one action on a surface that has to be
|
|
34
|
-
* found at a glance, like the add/remove button on every row of a transfer list.
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
*
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
* found at a glance, like the add/remove button on every row of a transfer list. "soft"
|
|
35
|
+
* is the same idea with a lighter, less saturated fill and a visibly darker border
|
|
36
|
+
* drawn around it, for a caller that wants the button to read as a button without the
|
|
37
|
+
* full-saturation "solid" look — only "ok" and "danger" tones are defined for it. */
|
|
38
|
+
variant?: "ghost" | "outline" | "solid" | "soft";
|
|
39
|
+
/** What the action does. On "solid"/"soft" it picks the fill; on "ghost"/"outline" it
|
|
40
|
+
* tints the glyph. "neutral" is the default look of each variant, which for "solid" is
|
|
41
|
+
* the brand fill ("soft" has no neutral fill — pass "ok" or "danger"). Every tone has
|
|
42
|
+
* hover, pressed and focus states and is legible in both themes — the fills are the
|
|
43
|
+
* --btn-solid-* / --btn-soft-* tokens, measured against light and dark grounds. */
|
|
40
44
|
tone?: "neutral" | "ok" | "danger";
|
|
41
45
|
round?: boolean;
|
|
42
46
|
disabled?: boolean;
|
|
@@ -1346,10 +1350,11 @@ interface EntityRowAction {
|
|
|
1346
1350
|
label: string;
|
|
1347
1351
|
onClick: () => void;
|
|
1348
1352
|
/** Picks the fill — "add" is the constructive (ok) fill, "remove" the destructive
|
|
1349
|
-
* (danger) fill, and no tone the brand fill. The button is always a filled
|
|
1350
|
-
*
|
|
1351
|
-
* list, and has to be findable at a glance on a default
|
|
1352
|
-
* alike. No effect on layout, so a caller can still pass
|
|
1353
|
+
* (danger) fill, and no tone the brand fill. The button is always a filled IconButton
|
|
1354
|
+
* (variant "soft": a lighter fill with a darker border, MP-52): it is the one action on
|
|
1355
|
+
* the row, repeated down a long list, and has to be findable at a glance on a default
|
|
1356
|
+
* card and on a danger-toned one alike. No effect on layout, so a caller can still pass
|
|
1357
|
+
* any icon. */
|
|
1353
1358
|
tone?: "add" | "remove";
|
|
1354
1359
|
}
|
|
1355
1360
|
/** Width in px a metric cell takes when it doesn't ask for its own. Wide enough for a
|
|
@@ -1390,8 +1395,23 @@ interface EntityRowMetric {
|
|
|
1390
1395
|
* as the drag ghost) hands one of these around whole, so a prop added here can't be
|
|
1391
1396
|
* silently dropped by the second render site the way individually-spread props were.
|
|
1392
1397
|
*/
|
|
1398
|
+
/** An icon shown before the row's title, itself the Tooltip trigger together with the
|
|
1399
|
+
* title text (MP-52: "hovering EITHER the icon or the name" opens the same explanation —
|
|
1400
|
+
* one hoverable/focusable region rather than two separate targets that could disagree). */
|
|
1401
|
+
interface EntityRowTitleIcon {
|
|
1402
|
+
/** Phosphor icon name, e.g. "warning". */
|
|
1403
|
+
icon: string;
|
|
1404
|
+
tone?: "danger";
|
|
1405
|
+
/** The long-form explanation, shown in the kit's Tooltip on hover, keyboard focus and
|
|
1406
|
+
* tap — never a native `title`, so it is never truncated to a browser tooltip. */
|
|
1407
|
+
tooltip: React.ReactNode;
|
|
1408
|
+
}
|
|
1393
1409
|
interface EntityRowContent {
|
|
1394
1410
|
title: string;
|
|
1411
|
+
/** Renders before `title`, wrapped with it in the kit Tooltip. Drive this from the
|
|
1412
|
+
* row's own existing state (e.g. the same signal that sets `tone: "danger"`) — it is
|
|
1413
|
+
* not a second source of truth, just a second thing that one signal explains. */
|
|
1414
|
+
titleIcon?: EntityRowTitleIcon;
|
|
1395
1415
|
/** A secondary line — a count, a subtitle, whatever the caller's data has that a raw
|
|
1396
1416
|
* title doesn't. Optional because plenty of rows are fine with just a name. Sits
|
|
1397
1417
|
* inline after the title; for numbers that must line up row-to-row use `metrics`. */
|
|
@@ -1470,7 +1490,7 @@ declare function EntityRowMetrics({ metrics, className, style }: EntityRowMetric
|
|
|
1470
1490
|
* same move — pointer-only and keyboard users get an equally real affordance, not a
|
|
1471
1491
|
* degraded fallback.
|
|
1472
1492
|
*/
|
|
1473
|
-
declare function EntityRow({ title, meta, metrics, accessory, tone, action, draggable, onPointerDown, style, className, }: EntityRowProps): React.JSX.Element;
|
|
1493
|
+
declare function EntityRow({ title, titleIcon, meta, metrics, accessory, tone, action, draggable, onPointerDown, style, className, }: EntityRowProps): React.JSX.Element;
|
|
1474
1494
|
|
|
1475
1495
|
type TransferListSide = "left" | "right";
|
|
1476
1496
|
interface TransferListSideProps<T> {
|
package/dist/index.d.ts
CHANGED
|
@@ -31,12 +31,16 @@ interface IconButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>
|
|
|
31
31
|
size?: "sm" | "md" | "lg";
|
|
32
32
|
/** "ghost" and "outline" are quiet: no fill, the glyph carries the tone. "solid" is a
|
|
33
33
|
* filled button in the tone's colour — for the one action on a surface that has to be
|
|
34
|
-
* found at a glance, like the add/remove button on every row of a transfer list.
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
*
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
* found at a glance, like the add/remove button on every row of a transfer list. "soft"
|
|
35
|
+
* is the same idea with a lighter, less saturated fill and a visibly darker border
|
|
36
|
+
* drawn around it, for a caller that wants the button to read as a button without the
|
|
37
|
+
* full-saturation "solid" look — only "ok" and "danger" tones are defined for it. */
|
|
38
|
+
variant?: "ghost" | "outline" | "solid" | "soft";
|
|
39
|
+
/** What the action does. On "solid"/"soft" it picks the fill; on "ghost"/"outline" it
|
|
40
|
+
* tints the glyph. "neutral" is the default look of each variant, which for "solid" is
|
|
41
|
+
* the brand fill ("soft" has no neutral fill — pass "ok" or "danger"). Every tone has
|
|
42
|
+
* hover, pressed and focus states and is legible in both themes — the fills are the
|
|
43
|
+
* --btn-solid-* / --btn-soft-* tokens, measured against light and dark grounds. */
|
|
40
44
|
tone?: "neutral" | "ok" | "danger";
|
|
41
45
|
round?: boolean;
|
|
42
46
|
disabled?: boolean;
|
|
@@ -1346,10 +1350,11 @@ interface EntityRowAction {
|
|
|
1346
1350
|
label: string;
|
|
1347
1351
|
onClick: () => void;
|
|
1348
1352
|
/** Picks the fill — "add" is the constructive (ok) fill, "remove" the destructive
|
|
1349
|
-
* (danger) fill, and no tone the brand fill. The button is always a filled
|
|
1350
|
-
*
|
|
1351
|
-
* list, and has to be findable at a glance on a default
|
|
1352
|
-
* alike. No effect on layout, so a caller can still pass
|
|
1353
|
+
* (danger) fill, and no tone the brand fill. The button is always a filled IconButton
|
|
1354
|
+
* (variant "soft": a lighter fill with a darker border, MP-52): it is the one action on
|
|
1355
|
+
* the row, repeated down a long list, and has to be findable at a glance on a default
|
|
1356
|
+
* card and on a danger-toned one alike. No effect on layout, so a caller can still pass
|
|
1357
|
+
* any icon. */
|
|
1353
1358
|
tone?: "add" | "remove";
|
|
1354
1359
|
}
|
|
1355
1360
|
/** Width in px a metric cell takes when it doesn't ask for its own. Wide enough for a
|
|
@@ -1390,8 +1395,23 @@ interface EntityRowMetric {
|
|
|
1390
1395
|
* as the drag ghost) hands one of these around whole, so a prop added here can't be
|
|
1391
1396
|
* silently dropped by the second render site the way individually-spread props were.
|
|
1392
1397
|
*/
|
|
1398
|
+
/** An icon shown before the row's title, itself the Tooltip trigger together with the
|
|
1399
|
+
* title text (MP-52: "hovering EITHER the icon or the name" opens the same explanation —
|
|
1400
|
+
* one hoverable/focusable region rather than two separate targets that could disagree). */
|
|
1401
|
+
interface EntityRowTitleIcon {
|
|
1402
|
+
/** Phosphor icon name, e.g. "warning". */
|
|
1403
|
+
icon: string;
|
|
1404
|
+
tone?: "danger";
|
|
1405
|
+
/** The long-form explanation, shown in the kit's Tooltip on hover, keyboard focus and
|
|
1406
|
+
* tap — never a native `title`, so it is never truncated to a browser tooltip. */
|
|
1407
|
+
tooltip: React.ReactNode;
|
|
1408
|
+
}
|
|
1393
1409
|
interface EntityRowContent {
|
|
1394
1410
|
title: string;
|
|
1411
|
+
/** Renders before `title`, wrapped with it in the kit Tooltip. Drive this from the
|
|
1412
|
+
* row's own existing state (e.g. the same signal that sets `tone: "danger"`) — it is
|
|
1413
|
+
* not a second source of truth, just a second thing that one signal explains. */
|
|
1414
|
+
titleIcon?: EntityRowTitleIcon;
|
|
1395
1415
|
/** A secondary line — a count, a subtitle, whatever the caller's data has that a raw
|
|
1396
1416
|
* title doesn't. Optional because plenty of rows are fine with just a name. Sits
|
|
1397
1417
|
* inline after the title; for numbers that must line up row-to-row use `metrics`. */
|
|
@@ -1470,7 +1490,7 @@ declare function EntityRowMetrics({ metrics, className, style }: EntityRowMetric
|
|
|
1470
1490
|
* same move — pointer-only and keyboard users get an equally real affordance, not a
|
|
1471
1491
|
* degraded fallback.
|
|
1472
1492
|
*/
|
|
1473
|
-
declare function EntityRow({ title, meta, metrics, accessory, tone, action, draggable, onPointerDown, style, className, }: EntityRowProps): React.JSX.Element;
|
|
1493
|
+
declare function EntityRow({ title, titleIcon, meta, metrics, accessory, tone, action, draggable, onPointerDown, style, className, }: EntityRowProps): React.JSX.Element;
|
|
1474
1494
|
|
|
1475
1495
|
type TransferListSide = "left" | "right";
|
|
1476
1496
|
interface TransferListSideProps<T> {
|
package/dist/index.js
CHANGED
|
@@ -71,7 +71,7 @@ function IconButton({
|
|
|
71
71
|
const overflowRow = useOverflowRow();
|
|
72
72
|
const cls = [
|
|
73
73
|
"fd-btn-icon",
|
|
74
|
-
variant === "outline" ? "fd-btn-icon-outline" : variant === "solid" ? "fd-btn-icon-solid" : "",
|
|
74
|
+
variant === "outline" ? "fd-btn-icon-outline" : variant === "solid" ? "fd-btn-icon-solid" : variant === "soft" ? "fd-btn-icon-soft" : "",
|
|
75
75
|
tone !== "neutral" ? "is-" + tone : "",
|
|
76
76
|
size === "sm" ? "fd-btn-icon-sm" : size === "lg" ? "fd-btn-icon-lg" : "",
|
|
77
77
|
round ? "fd-btn-icon-round" : "",
|
|
@@ -2937,6 +2937,7 @@ function EntityRowMetrics({ metrics, className = "", style }) {
|
|
|
2937
2937
|
}
|
|
2938
2938
|
function EntityRow({
|
|
2939
2939
|
title,
|
|
2940
|
+
titleIcon,
|
|
2940
2941
|
meta,
|
|
2941
2942
|
metrics,
|
|
2942
2943
|
accessory,
|
|
@@ -2954,9 +2955,11 @@ function EntityRow({
|
|
|
2954
2955
|
onPointerDown,
|
|
2955
2956
|
className: ["fd-erow", tone === "danger" ? "fd-erow-danger" : "", className].filter(Boolean).join(" "),
|
|
2956
2957
|
style: {
|
|
2957
|
-
display
|
|
2958
|
-
|
|
2959
|
-
|
|
2958
|
+
// display/alignItems/gap moved to the .fd-erow stylesheet rule (MP-114
|
|
2959
|
+
// follow-up): an inline style always wins over a stylesheet rule regardless of
|
|
2960
|
+
// specificity or media/container query, which would have made it impossible
|
|
2961
|
+
// for the narrow-container rule below to ever switch this row from a flex row
|
|
2962
|
+
// to a grid (see that rule's own comment for why it needs to).
|
|
2960
2963
|
height: "100%",
|
|
2961
2964
|
padding: "0 12px",
|
|
2962
2965
|
cursor: draggable ? "grab" : void 0,
|
|
@@ -2966,10 +2969,20 @@ function EntityRow({
|
|
|
2966
2969
|
...style
|
|
2967
2970
|
},
|
|
2968
2971
|
children: [
|
|
2969
|
-
draggable ? /* @__PURE__ */ jsx39("i", { className: "ph ph-dots-six-vertical", "aria-hidden": "true", style: { fontSize: 14, flex: "none", color: "var(--text-muted)" } }) : null,
|
|
2972
|
+
draggable ? /* @__PURE__ */ jsx39("i", { className: "ph ph-dots-six-vertical fd-erow-grip", "aria-hidden": "true", style: { fontSize: 14, flex: "none", color: "var(--text-muted)" } }) : null,
|
|
2970
2973
|
/* @__PURE__ */ jsxs36("span", { className: "fd-erow-body", children: [
|
|
2971
2974
|
/* @__PURE__ */ jsxs36("span", { className: "fd-erow-titleline", children: [
|
|
2972
|
-
/* @__PURE__ */ jsx39(
|
|
2975
|
+
titleIcon ? /* @__PURE__ */ jsx39(Tooltip, { label: titleIcon.tooltip, children: /* @__PURE__ */ jsxs36(
|
|
2976
|
+
"button",
|
|
2977
|
+
{
|
|
2978
|
+
type: "button",
|
|
2979
|
+
className: ["fd-erow-title-icon", titleIcon.tone ? "is-" + titleIcon.tone : ""].filter(Boolean).join(" "),
|
|
2980
|
+
children: [
|
|
2981
|
+
/* @__PURE__ */ jsx39("i", { className: "ph ph-" + titleIcon.icon, "aria-hidden": "true" }),
|
|
2982
|
+
/* @__PURE__ */ jsx39("span", { className: "fd-erow-title fd-body-sm", children: title })
|
|
2983
|
+
]
|
|
2984
|
+
}
|
|
2985
|
+
) }) : /* @__PURE__ */ jsx39("span", { className: "fd-erow-title fd-body-sm", children: title }),
|
|
2973
2986
|
meta ? /* @__PURE__ */ jsx39("span", { className: "fd-erow-meta", children: meta }) : null
|
|
2974
2987
|
] }),
|
|
2975
2988
|
hasStrip ? /* @__PURE__ */ jsxs36("span", { className: "fd-erow-strip", children: [
|
|
@@ -2983,7 +2996,7 @@ function EntityRow({
|
|
|
2983
2996
|
icon: action.icon,
|
|
2984
2997
|
label: action.label,
|
|
2985
2998
|
size: "sm",
|
|
2986
|
-
variant: "solid",
|
|
2999
|
+
variant: action.tone ? "soft" : "solid",
|
|
2987
3000
|
tone: action.tone === "add" ? "ok" : action.tone === "remove" ? "danger" : "neutral",
|
|
2988
3001
|
className: "fd-erow-action",
|
|
2989
3002
|
onClick: action.onClick
|
|
@@ -8152,7 +8165,7 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
8152
8165
|
const tallest = Math.max(1, ...grouped.map((g) => g.items.length));
|
|
8153
8166
|
const floor = BANDS2.find((b) => b.key === floorBand) || BANDS2[0];
|
|
8154
8167
|
return /* @__PURE__ */ jsxs61("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
|
|
8155
|
-
/* @__PURE__ */ jsx65("div", { style: { display: "grid", gridTemplateColumns: "repeat(4,1fr)", gap: 12, alignItems: "end" }, children: grouped.map((g) => {
|
|
8168
|
+
/* @__PURE__ */ jsx65("div", { style: { display: "grid", gridTemplateColumns: "repeat(4,minmax(0,1fr))", gap: 12, alignItems: "end" }, children: grouped.map((g) => {
|
|
8156
8169
|
const mark = "var(--csi-" + g.n + "-mark)";
|
|
8157
8170
|
const active = selectedBand === g.key;
|
|
8158
8171
|
return /* @__PURE__ */ jsxs61(
|
|
@@ -8160,16 +8173,23 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
8160
8173
|
{
|
|
8161
8174
|
type: "button",
|
|
8162
8175
|
onClick: onSelectBand ? () => onSelectBand(active ? null : g.key) : void 0,
|
|
8163
|
-
style: { display: "flex", flexDirection: "column", justifyContent: "flex-end", gap: 10, padding: 12, border: "1px solid " + (active ? "var(--border-strong)" : "var(--border)"), borderRadius: "var(--r-lg)", background: active ? "var(--surface-2)" : "var(--surface)", cursor: onSelectBand ? "pointer" : "default", textAlign: "left", minHeight: 190, transition: "background var(--dur-fast) var(--ease),border-color var(--dur-fast) var(--ease)" },
|
|
8176
|
+
style: { display: "flex", flexDirection: "column", justifyContent: "flex-end", gap: 10, padding: 12, border: "1px solid " + (active ? "var(--border-strong)" : "var(--border)"), borderRadius: "var(--r-lg)", background: active ? "var(--surface-2)" : "var(--surface)", cursor: onSelectBand ? "pointer" : "default", textAlign: "left", minHeight: 190, minWidth: 0, transition: "background var(--dur-fast) var(--ease),border-color var(--dur-fast) var(--ease)" },
|
|
8164
8177
|
children: [
|
|
8165
|
-
/* @__PURE__ */ jsx65("span", { style: { display: "flex", flexDirection: "column-reverse", gap: 4, minHeight: tallest * 24 }, children: loading ? Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsx65("span", { className: "fd-skel", style: { height: 16, borderRadius: 4 } }, i)) : g.items.map((c) =>
|
|
8166
|
-
|
|
8167
|
-
|
|
8168
|
-
|
|
8169
|
-
|
|
8170
|
-
|
|
8171
|
-
|
|
8172
|
-
|
|
8178
|
+
/* @__PURE__ */ jsx65("span", { style: { display: "flex", flexDirection: "column-reverse", gap: 4, minHeight: tallest * 24, minWidth: 0 }, children: loading ? Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsx65("span", { className: "fd-skel", style: { height: 16, borderRadius: 4 } }, i)) : g.items.map((c) => (
|
|
8179
|
+
// `overflow: hidden` + `white-space: nowrap` only clips once the span
|
|
8180
|
+
// actually HAS a bounded width to clip against (see the grid/flex
|
|
8181
|
+
// `minWidth: 0` chain above) — `textOverflow: ellipsis` then makes
|
|
8182
|
+
// that clip readable instead of a hard cut mid-letter; the full name
|
|
8183
|
+
// is still one hover away via `title`.
|
|
8184
|
+
/* @__PURE__ */ jsx65(
|
|
8185
|
+
"span",
|
|
8186
|
+
{
|
|
8187
|
+
title: c.name + " \xB7 " + c.crp,
|
|
8188
|
+
style: { height: 18, borderRadius: 4, background: "var(--csi-" + g.n + "-fill)", border: "1px solid var(--csi-" + g.n + "-edge)", color: "var(--csi-" + g.n + "-text)", display: "flex", alignItems: "center", padding: "0 7px", fontSize: 10, fontWeight: 700, overflow: "hidden", whiteSpace: "nowrap", textOverflow: "ellipsis" },
|
|
8189
|
+
children: c.short || c.name
|
|
8190
|
+
},
|
|
8191
|
+
c.name
|
|
8192
|
+
)
|
|
8173
8193
|
)) }),
|
|
8174
8194
|
/* @__PURE__ */ jsxs61("span", { className: "fd-row", style: { gap: 8, alignItems: "baseline" }, children: [
|
|
8175
8195
|
/* @__PURE__ */ jsx65("span", { className: "fd-num-hero", style: { fontSize: 30, color: g.items.length ? "var(--text)" : "var(--text-disabled)" }, children: loading ? "\u2013" : g.items.length }),
|