@flytedan/flytebot-design-system 0.11.5 → 0.12.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/dist/index.cjs +76 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +17 -4
- package/dist/index.d.ts +17 -4
- package/dist/index.js +93 -25
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/styles/components.css +18 -0
package/dist/index.cjs
CHANGED
|
@@ -1092,8 +1092,34 @@ function Tabs({ tabs = [], value, onChange, className = "", ...rest }) {
|
|
|
1092
1092
|
// src/components/navigation/Topbar.tsx
|
|
1093
1093
|
var React5 = __toESM(require("react"), 1);
|
|
1094
1094
|
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
1095
|
-
function
|
|
1096
|
-
|
|
1095
|
+
function useIsNarrow(breakpoint) {
|
|
1096
|
+
const [narrow, setNarrow] = React5.useState(
|
|
1097
|
+
() => typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia(`(max-width: ${breakpoint}px)`).matches
|
|
1098
|
+
);
|
|
1099
|
+
React5.useEffect(() => {
|
|
1100
|
+
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
|
|
1101
|
+
const mq = window.matchMedia(`(max-width: ${breakpoint}px)`);
|
|
1102
|
+
const apply = () => setNarrow(mq.matches);
|
|
1103
|
+
apply();
|
|
1104
|
+
mq.addEventListener("change", apply);
|
|
1105
|
+
return () => mq.removeEventListener("change", apply);
|
|
1106
|
+
}, [breakpoint]);
|
|
1107
|
+
return narrow;
|
|
1108
|
+
}
|
|
1109
|
+
function Topbar({
|
|
1110
|
+
crumbs = [],
|
|
1111
|
+
actions,
|
|
1112
|
+
overflowActions,
|
|
1113
|
+
overflowBreakpoint = 640,
|
|
1114
|
+
loading = false,
|
|
1115
|
+
onMenu,
|
|
1116
|
+
className = "",
|
|
1117
|
+
...rest
|
|
1118
|
+
}) {
|
|
1119
|
+
const narrow = useIsNarrow(overflowBreakpoint);
|
|
1120
|
+
const [moreOpen, setMoreOpen] = React5.useState(false);
|
|
1121
|
+
const moreRef = React5.useRef(null);
|
|
1122
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("header", { className: ["fd-topbar", narrow ? "is-narrow" : "", className].filter(Boolean).join(" "), ...rest, children: [
|
|
1097
1123
|
onMenu ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("button", { type: "button", className: "fd-btn-icon", "aria-label": "Menu", onClick: onMenu, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("i", { className: "ph ph-list" }) }) : null,
|
|
1098
1124
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("nav", { className: "fd-crumb", "aria-label": "Breadcrumb", children: crumbs.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(React5.Fragment, { children: [
|
|
1099
1125
|
i > 0 ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("i", { className: "ph ph-caret-right", style: { fontSize: 11, opacity: 0.6 }, "aria-hidden": "true" }) : null,
|
|
@@ -1110,6 +1136,34 @@ function Topbar({ crumbs = [], actions, loading = false, onMenu, className = "",
|
|
|
1110
1136
|
)
|
|
1111
1137
|
] }, i)) }),
|
|
1112
1138
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { style: { flex: 1 } }),
|
|
1139
|
+
overflowActions != null ? narrow ? /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
|
|
1140
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
1141
|
+
"button",
|
|
1142
|
+
{
|
|
1143
|
+
type: "button",
|
|
1144
|
+
ref: moreRef,
|
|
1145
|
+
className: "fd-btn-icon",
|
|
1146
|
+
"aria-label": "More actions",
|
|
1147
|
+
"aria-haspopup": "dialog",
|
|
1148
|
+
"aria-expanded": moreOpen,
|
|
1149
|
+
onClick: () => setMoreOpen((v) => !v),
|
|
1150
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("i", { className: "ph ph-dots-three-vertical", "aria-hidden": "true" })
|
|
1151
|
+
}
|
|
1152
|
+
),
|
|
1153
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
1154
|
+
Popover,
|
|
1155
|
+
{
|
|
1156
|
+
open: moreOpen,
|
|
1157
|
+
anchorRef: moreRef,
|
|
1158
|
+
onClose: () => setMoreOpen(false),
|
|
1159
|
+
placement: "bottom-end",
|
|
1160
|
+
padded: true,
|
|
1161
|
+
label: "More actions",
|
|
1162
|
+
className: "fd-topbar-overflow",
|
|
1163
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "fd-stack fd-topbar-overflow-list", children: overflowActions })
|
|
1164
|
+
}
|
|
1165
|
+
)
|
|
1166
|
+
] }) : overflowActions : null,
|
|
1113
1167
|
actions,
|
|
1114
1168
|
loading ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "fd-topload", "aria-hidden": "true" }) : null
|
|
1115
1169
|
] });
|
|
@@ -8309,11 +8363,24 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
8309
8363
|
// src/components/planner/MixGap.tsx
|
|
8310
8364
|
var React37 = __toESM(require("react"), 1);
|
|
8311
8365
|
var import_jsx_runtime67 = require("react/jsx-runtime");
|
|
8366
|
+
var MIX_GAP_LAYOUT = {
|
|
8367
|
+
trackHeight: 30,
|
|
8368
|
+
barHeight: 20,
|
|
8369
|
+
targetWidth: 6,
|
|
8370
|
+
labelGap: 6,
|
|
8371
|
+
labelGutter: 50
|
|
8372
|
+
};
|
|
8373
|
+
var MIX_GAP_TARGET_STRIPE = "repeating-linear-gradient(135deg, var(--n-600) 0 2px, var(--n-300) 2px 4px)";
|
|
8374
|
+
function mixGapOffset(value, max) {
|
|
8375
|
+
return `calc((100% - ${MIX_GAP_LAYOUT.labelGutter}px) * ${value / max})`;
|
|
8376
|
+
}
|
|
8312
8377
|
function MixGap({ rows = [], loading = false, className = "" }) {
|
|
8313
8378
|
const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
|
|
8314
8379
|
const [hover, setHover] = React37.useState(null);
|
|
8315
8380
|
const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
|
|
8316
8381
|
const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
|
|
8382
|
+
const { trackHeight, barHeight, targetWidth, labelGap } = MIX_GAP_LAYOUT;
|
|
8383
|
+
const barTop = (trackHeight - barHeight) / 2;
|
|
8317
8384
|
return /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
|
|
8318
8385
|
/* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
|
|
8319
8386
|
[["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
|
|
@@ -8321,7 +8388,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
8321
8388
|
l
|
|
8322
8389
|
] }, l)),
|
|
8323
8390
|
/* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
|
|
8324
|
-
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { style: { width:
|
|
8391
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { "data-mixgap-legend-target": "", style: { width: targetWidth, height: 16, borderRadius: 1, background: MIX_GAP_TARGET_STRIPE } }),
|
|
8325
8392
|
"Target"
|
|
8326
8393
|
] })
|
|
8327
8394
|
] }),
|
|
@@ -8329,6 +8396,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
8329
8396
|
const gap = r.realized - r.target;
|
|
8330
8397
|
const tone = toneOf(gap);
|
|
8331
8398
|
const tip = "Realized " + r.realized + "% vs " + r.target + "% target" + (gap < -1 ? " \xB7 " + Math.abs(gap).toFixed(0) + " pts short" : gap > 1 ? " \xB7 " + gap.toFixed(0) + " pts over" : " \xB7 on target") + (r.note ? " \u2014 " + r.note : "");
|
|
8399
|
+
const labelLeft = r.realized > r.target ? `calc(${mixGapOffset(r.realized, max)} + ${labelGap}px)` : `calc(${mixGapOffset(r.target, max)} + ${targetWidth / 2 + labelGap}px)`;
|
|
8332
8400
|
return /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(
|
|
8333
8401
|
"div",
|
|
8334
8402
|
{
|
|
@@ -8338,14 +8406,14 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
8338
8406
|
onMouseLeave: () => setHover(null),
|
|
8339
8407
|
children: [
|
|
8340
8408
|
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { style: { width: 128, flex: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(ChannelTag, { channel: r.channel, size: "sm" }) }),
|
|
8341
|
-
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { style: { position: "relative", flex: 1, height:
|
|
8342
|
-
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { style: { position: "absolute", left: 0, top:
|
|
8343
|
-
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { style: { position: "absolute", left: r.target
|
|
8344
|
-
/* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("span", { className: "fd-num", style: { position: "absolute",
|
|
8409
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { style: { position: "relative", flex: 1, height: trackHeight, minWidth: 120 }, children: loading ? /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { className: "fd-skel", style: { position: "absolute", left: 0, right: 0, top: barTop, height: barHeight, borderRadius: 3 } }) : /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(import_jsx_runtime67.Fragment, { children: [
|
|
8410
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { "data-mixgap-bar": "", style: { position: "absolute", left: 0, top: barTop, height: barHeight, width: mixGapOffset(r.realized, max), background: TONE[tone], borderRadius: "2px 3px 3px 2px", transition: "width var(--dur-slow) var(--ease), background var(--dur-base) var(--ease)" } }),
|
|
8411
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { "data-mixgap-target": "", style: { position: "absolute", left: `calc(${mixGapOffset(r.target, max)} - ${targetWidth / 2}px)`, top: 0, width: targetWidth, height: trackHeight, background: MIX_GAP_TARGET_STRIPE, borderRadius: 1 } }),
|
|
8412
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("span", { "data-mixgap-label": "", className: "fd-num", style: { position: "absolute", left: labelLeft, top: "50%", transform: "translateY(-50%)", fontSize: 12, color: "var(--text-muted)", whiteSpace: "nowrap" }, children: [
|
|
8345
8413
|
r.realized,
|
|
8346
8414
|
"%"
|
|
8347
8415
|
] }),
|
|
8348
|
-
hover === r.channel ? /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { className: "fd-tooltip", role: "tooltip", style: { position: "absolute", left: 0, right: "auto", bottom:
|
|
8416
|
+
hover === r.channel ? /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { className: "fd-tooltip", role: "tooltip", style: { position: "absolute", left: 0, right: "auto", bottom: trackHeight + 4, maxWidth: "min(340px, 100%)", whiteSpace: "normal", textAlign: "left", width: "max-content" }, children: tip }) : null
|
|
8349
8417
|
] }) })
|
|
8350
8418
|
]
|
|
8351
8419
|
},
|