@flytedan/flytebot-design-system 0.11.6 → 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 +56 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -1
- package/dist/index.d.ts +14 -1
- package/dist/index.js +74 -20
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/styles/components.css +18 -0
package/dist/index.d.cts
CHANGED
|
@@ -457,14 +457,27 @@ interface TopbarProps {
|
|
|
457
457
|
href?: string;
|
|
458
458
|
onClick?: () => void;
|
|
459
459
|
}>;
|
|
460
|
+
/** Rendered last, after any `overflowActions` — the one control every screen needs to
|
|
461
|
+
* keep directly reachable (typically the account menu). Never collapses, at any width. */
|
|
460
462
|
actions?: React.ReactNode;
|
|
463
|
+
/** Secondary controls (an assistant launcher, a version badge, appearance/dev-tools
|
|
464
|
+
* toggles, undo — whatever a screen needs beside `actions`). Rendered inline, in the
|
|
465
|
+
* same spot `actions` used to hold everything, on a viewport wider than
|
|
466
|
+
* `overflowBreakpoint`. At or under it, they collapse into a single "More actions"
|
|
467
|
+
* menu instead of pushing the rest of the bar past the screen edge. Decided once
|
|
468
|
+
* here, so every Topbar consumer gets it without re-solving it per screen. */
|
|
469
|
+
overflowActions?: React.ReactNode;
|
|
470
|
+
/** Viewport width (px) at or under which `overflowActions` collapses into the "More
|
|
471
|
+
* actions" menu. Default 640 — comfortably covers 320/375/430 phone widths without
|
|
472
|
+
* touching any tablet or desktop layout above it. */
|
|
473
|
+
overflowBreakpoint?: number;
|
|
461
474
|
/** Shows the indeterminate route loader on the top edge. */
|
|
462
475
|
loading?: boolean;
|
|
463
476
|
/** Mobile menu handler — renders the hamburger. */
|
|
464
477
|
onMenu?: () => void;
|
|
465
478
|
className?: string;
|
|
466
479
|
}
|
|
467
|
-
declare function Topbar({ crumbs, actions, loading, onMenu, className, ...rest }: TopbarProps): React.JSX.Element;
|
|
480
|
+
declare function Topbar({ crumbs, actions, overflowActions, overflowBreakpoint, loading, onMenu, className, ...rest }: TopbarProps): React.JSX.Element;
|
|
468
481
|
|
|
469
482
|
/** A person or organisation mark. Initials on a soft brand tint when no image exists. */
|
|
470
483
|
interface AvatarProps {
|
package/dist/index.d.ts
CHANGED
|
@@ -457,14 +457,27 @@ interface TopbarProps {
|
|
|
457
457
|
href?: string;
|
|
458
458
|
onClick?: () => void;
|
|
459
459
|
}>;
|
|
460
|
+
/** Rendered last, after any `overflowActions` — the one control every screen needs to
|
|
461
|
+
* keep directly reachable (typically the account menu). Never collapses, at any width. */
|
|
460
462
|
actions?: React.ReactNode;
|
|
463
|
+
/** Secondary controls (an assistant launcher, a version badge, appearance/dev-tools
|
|
464
|
+
* toggles, undo — whatever a screen needs beside `actions`). Rendered inline, in the
|
|
465
|
+
* same spot `actions` used to hold everything, on a viewport wider than
|
|
466
|
+
* `overflowBreakpoint`. At or under it, they collapse into a single "More actions"
|
|
467
|
+
* menu instead of pushing the rest of the bar past the screen edge. Decided once
|
|
468
|
+
* here, so every Topbar consumer gets it without re-solving it per screen. */
|
|
469
|
+
overflowActions?: React.ReactNode;
|
|
470
|
+
/** Viewport width (px) at or under which `overflowActions` collapses into the "More
|
|
471
|
+
* actions" menu. Default 640 — comfortably covers 320/375/430 phone widths without
|
|
472
|
+
* touching any tablet or desktop layout above it. */
|
|
473
|
+
overflowBreakpoint?: number;
|
|
461
474
|
/** Shows the indeterminate route loader on the top edge. */
|
|
462
475
|
loading?: boolean;
|
|
463
476
|
/** Mobile menu handler — renders the hamburger. */
|
|
464
477
|
onMenu?: () => void;
|
|
465
478
|
className?: string;
|
|
466
479
|
}
|
|
467
|
-
declare function Topbar({ crumbs, actions, loading, onMenu, className, ...rest }: TopbarProps): React.JSX.Element;
|
|
480
|
+
declare function Topbar({ crumbs, actions, overflowActions, overflowBreakpoint, loading, onMenu, className, ...rest }: TopbarProps): React.JSX.Element;
|
|
468
481
|
|
|
469
482
|
/** A person or organisation mark. Initials on a soft brand tint when no image exists. */
|
|
470
483
|
interface AvatarProps {
|
package/dist/index.js
CHANGED
|
@@ -888,9 +888,35 @@ function Tabs({ tabs = [], value, onChange, className = "", ...rest }) {
|
|
|
888
888
|
|
|
889
889
|
// src/components/navigation/Topbar.tsx
|
|
890
890
|
import * as React5 from "react";
|
|
891
|
-
import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
892
|
-
function
|
|
893
|
-
|
|
891
|
+
import { Fragment as Fragment4, jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
892
|
+
function useIsNarrow(breakpoint) {
|
|
893
|
+
const [narrow, setNarrow] = React5.useState(
|
|
894
|
+
() => typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia(`(max-width: ${breakpoint}px)`).matches
|
|
895
|
+
);
|
|
896
|
+
React5.useEffect(() => {
|
|
897
|
+
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
|
|
898
|
+
const mq = window.matchMedia(`(max-width: ${breakpoint}px)`);
|
|
899
|
+
const apply = () => setNarrow(mq.matches);
|
|
900
|
+
apply();
|
|
901
|
+
mq.addEventListener("change", apply);
|
|
902
|
+
return () => mq.removeEventListener("change", apply);
|
|
903
|
+
}, [breakpoint]);
|
|
904
|
+
return narrow;
|
|
905
|
+
}
|
|
906
|
+
function Topbar({
|
|
907
|
+
crumbs = [],
|
|
908
|
+
actions,
|
|
909
|
+
overflowActions,
|
|
910
|
+
overflowBreakpoint = 640,
|
|
911
|
+
loading = false,
|
|
912
|
+
onMenu,
|
|
913
|
+
className = "",
|
|
914
|
+
...rest
|
|
915
|
+
}) {
|
|
916
|
+
const narrow = useIsNarrow(overflowBreakpoint);
|
|
917
|
+
const [moreOpen, setMoreOpen] = React5.useState(false);
|
|
918
|
+
const moreRef = React5.useRef(null);
|
|
919
|
+
return /* @__PURE__ */ jsxs12("header", { className: ["fd-topbar", narrow ? "is-narrow" : "", className].filter(Boolean).join(" "), ...rest, children: [
|
|
894
920
|
onMenu ? /* @__PURE__ */ jsx16("button", { type: "button", className: "fd-btn-icon", "aria-label": "Menu", onClick: onMenu, children: /* @__PURE__ */ jsx16("i", { className: "ph ph-list" }) }) : null,
|
|
895
921
|
/* @__PURE__ */ jsx16("nav", { className: "fd-crumb", "aria-label": "Breadcrumb", children: crumbs.map((c, i) => /* @__PURE__ */ jsxs12(React5.Fragment, { children: [
|
|
896
922
|
i > 0 ? /* @__PURE__ */ jsx16("i", { className: "ph ph-caret-right", style: { fontSize: 11, opacity: 0.6 }, "aria-hidden": "true" }) : null,
|
|
@@ -907,6 +933,34 @@ function Topbar({ crumbs = [], actions, loading = false, onMenu, className = "",
|
|
|
907
933
|
)
|
|
908
934
|
] }, i)) }),
|
|
909
935
|
/* @__PURE__ */ jsx16("span", { style: { flex: 1 } }),
|
|
936
|
+
overflowActions != null ? narrow ? /* @__PURE__ */ jsxs12(Fragment4, { children: [
|
|
937
|
+
/* @__PURE__ */ jsx16(
|
|
938
|
+
"button",
|
|
939
|
+
{
|
|
940
|
+
type: "button",
|
|
941
|
+
ref: moreRef,
|
|
942
|
+
className: "fd-btn-icon",
|
|
943
|
+
"aria-label": "More actions",
|
|
944
|
+
"aria-haspopup": "dialog",
|
|
945
|
+
"aria-expanded": moreOpen,
|
|
946
|
+
onClick: () => setMoreOpen((v) => !v),
|
|
947
|
+
children: /* @__PURE__ */ jsx16("i", { className: "ph ph-dots-three-vertical", "aria-hidden": "true" })
|
|
948
|
+
}
|
|
949
|
+
),
|
|
950
|
+
/* @__PURE__ */ jsx16(
|
|
951
|
+
Popover,
|
|
952
|
+
{
|
|
953
|
+
open: moreOpen,
|
|
954
|
+
anchorRef: moreRef,
|
|
955
|
+
onClose: () => setMoreOpen(false),
|
|
956
|
+
placement: "bottom-end",
|
|
957
|
+
padded: true,
|
|
958
|
+
label: "More actions",
|
|
959
|
+
className: "fd-topbar-overflow",
|
|
960
|
+
children: /* @__PURE__ */ jsx16("div", { className: "fd-stack fd-topbar-overflow-list", children: overflowActions })
|
|
961
|
+
}
|
|
962
|
+
)
|
|
963
|
+
] }) : overflowActions : null,
|
|
910
964
|
actions,
|
|
911
965
|
loading ? /* @__PURE__ */ jsx16("span", { className: "fd-topload", "aria-hidden": "true" }) : null
|
|
912
966
|
] });
|
|
@@ -958,12 +1012,12 @@ function EmptyState({ icon = "tray", title, children, action, className = "", ..
|
|
|
958
1012
|
}
|
|
959
1013
|
|
|
960
1014
|
// src/components/feedback/Flag.tsx
|
|
961
|
-
import { Fragment as
|
|
1015
|
+
import { Fragment as Fragment5, jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
962
1016
|
function Flag({ statement, cost, actions, tone = "warning", className = "", ...rest }) {
|
|
963
1017
|
return /* @__PURE__ */ jsxs16("div", { className: ["fd-flag", "fd-flag-" + tone, className].filter(Boolean).join(" "), role: "status", ...rest, children: [
|
|
964
1018
|
/* @__PURE__ */ jsxs16("span", { className: "fd-flag-text", children: [
|
|
965
1019
|
statement,
|
|
966
|
-
cost ? /* @__PURE__ */ jsxs16(
|
|
1020
|
+
cost ? /* @__PURE__ */ jsxs16(Fragment5, { children: [
|
|
967
1021
|
" ",
|
|
968
1022
|
/* @__PURE__ */ jsx20("span", { className: "fd-flag-cost", children: cost })
|
|
969
1023
|
] }) : null
|
|
@@ -1546,7 +1600,7 @@ function StatTile({ label, value, sub, delta, loading = false, compact: compact3
|
|
|
1546
1600
|
|
|
1547
1601
|
// src/components/data/CodeBlock.tsx
|
|
1548
1602
|
import * as React9 from "react";
|
|
1549
|
-
import { Fragment as
|
|
1603
|
+
import { Fragment as Fragment6, jsx as jsx30, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
1550
1604
|
var JS_KW = /^(?:const|let|var|function|return|if|else|for|while|do|new|class|extends|import|from|export|default|await|async|try|catch|finally|throw|typeof|instanceof|of|in|switch|case|break|continue|delete|void|yield|static|get|set|this|super|interface|type|enum|implements|public|private|protected|readonly|abstract|as|satisfies|declare|namespace)$/;
|
|
1551
1605
|
var RULES = {
|
|
1552
1606
|
js: [
|
|
@@ -1702,7 +1756,7 @@ function tokenize(src, lang) {
|
|
|
1702
1756
|
}
|
|
1703
1757
|
function Highlighted({ code, lang }) {
|
|
1704
1758
|
const toks = React9.useMemo(() => tokenize(code, lang), [code, lang]);
|
|
1705
|
-
return /* @__PURE__ */ jsx30(
|
|
1759
|
+
return /* @__PURE__ */ jsx30(Fragment6, { children: toks.map((tk, i) => tk.c ? /* @__PURE__ */ jsx30("span", { className: "tok-" + tk.c, children: tk.t }, i) : tk.t) });
|
|
1706
1760
|
}
|
|
1707
1761
|
function useCopy() {
|
|
1708
1762
|
const [done, setDone] = React9.useState(false);
|
|
@@ -2066,7 +2120,7 @@ function Meter({ segments = [], unallocated = 0, height = 8, label, legend = fal
|
|
|
2066
2120
|
}
|
|
2067
2121
|
|
|
2068
2122
|
// src/components/data/Pagination.tsx
|
|
2069
|
-
import { Fragment as
|
|
2123
|
+
import { Fragment as Fragment8, jsx as jsx33, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
2070
2124
|
function Pagination({
|
|
2071
2125
|
page = 1,
|
|
2072
2126
|
pageSize = 25,
|
|
@@ -2092,10 +2146,10 @@ function Pagination({
|
|
|
2092
2146
|
else if (nums[nums.length - 1] !== "\u2026") nums.push("\u2026");
|
|
2093
2147
|
}
|
|
2094
2148
|
return /* @__PURE__ */ jsxs28("div", { className: ["fd-pag", className].filter(Boolean).join(" "), ...rest, children: [
|
|
2095
|
-
/* @__PURE__ */ jsx33("span", { className: "fd-pag-count", children: loading ? /* @__PURE__ */ jsx33("span", { className: "fd-skel fd-skel-text", style: { display: "inline-block", height: 12, width: 108 } }) : total === 0 ? /* @__PURE__ */ jsxs28(
|
|
2149
|
+
/* @__PURE__ */ jsx33("span", { className: "fd-pag-count", children: loading ? /* @__PURE__ */ jsx33("span", { className: "fd-skel fd-skel-text", style: { display: "inline-block", height: 12, width: 108 } }) : total === 0 ? /* @__PURE__ */ jsxs28(Fragment8, { children: [
|
|
2096
2150
|
"No ",
|
|
2097
2151
|
unit
|
|
2098
|
-
] }) : /* @__PURE__ */ jsxs28(
|
|
2152
|
+
] }) : /* @__PURE__ */ jsxs28(Fragment8, { children: [
|
|
2099
2153
|
/* @__PURE__ */ jsxs28("strong", { children: [
|
|
2100
2154
|
from.toLocaleString(),
|
|
2101
2155
|
"\u2013",
|
|
@@ -6579,7 +6633,7 @@ var SessionKit = {
|
|
|
6579
6633
|
};
|
|
6580
6634
|
|
|
6581
6635
|
// src/components/platform/AccountMenu.tsx
|
|
6582
|
-
import { Fragment as
|
|
6636
|
+
import { Fragment as Fragment15, jsx as jsx57, jsxs as jsxs52 } from "react/jsx-runtime";
|
|
6583
6637
|
var DEFAULT_LINKS = [
|
|
6584
6638
|
{ id: "profile", label: "Your profile", icon: "user-circle", href: "../admin/index.html#profile" },
|
|
6585
6639
|
{ id: "preferences", label: "Preferences", icon: "sliders-horizontal", href: "../admin/index.html#preferences" }
|
|
@@ -6632,7 +6686,7 @@ function AccountMenu({
|
|
|
6632
6686
|
if (onSignOut) return onSignOut();
|
|
6633
6687
|
window.alert("Signed out. (Simulated \u2014 no auth provider is wired up.)");
|
|
6634
6688
|
};
|
|
6635
|
-
return /* @__PURE__ */ jsxs52(
|
|
6689
|
+
return /* @__PURE__ */ jsxs52(Fragment15, { children: [
|
|
6636
6690
|
/* @__PURE__ */ jsxs52(
|
|
6637
6691
|
"button",
|
|
6638
6692
|
{
|
|
@@ -7469,7 +7523,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
7469
7523
|
// src/components/platform/ComingSoon.tsx
|
|
7470
7524
|
import * as React35 from "react";
|
|
7471
7525
|
import { createPortal as createPortal5 } from "react-dom";
|
|
7472
|
-
import { Fragment as
|
|
7526
|
+
import { Fragment as Fragment17, jsx as jsx61, jsxs as jsxs56 } from "react/jsx-runtime";
|
|
7473
7527
|
var BYPASS_STORE = "fd.soon.bypass.v1";
|
|
7474
7528
|
function readBypassed() {
|
|
7475
7529
|
try {
|
|
@@ -7499,7 +7553,7 @@ function useBypass(key) {
|
|
|
7499
7553
|
return [on, set];
|
|
7500
7554
|
}
|
|
7501
7555
|
function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass }) {
|
|
7502
|
-
return /* @__PURE__ */ jsxs56(
|
|
7556
|
+
return /* @__PURE__ */ jsxs56(Fragment17, { children: [
|
|
7503
7557
|
/* @__PURE__ */ jsxs56("span", { className: "fd-soon-badge", children: [
|
|
7504
7558
|
/* @__PURE__ */ jsx61("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
|
|
7505
7559
|
label
|
|
@@ -7850,7 +7904,7 @@ function PermissionHint({ perm, children }) {
|
|
|
7850
7904
|
|
|
7851
7905
|
// src/components/platform/ModeSwitch.tsx
|
|
7852
7906
|
import * as React36 from "react";
|
|
7853
|
-
import { Fragment as
|
|
7907
|
+
import { Fragment as Fragment18, jsx as jsx63, jsxs as jsxs58 } from "react/jsx-runtime";
|
|
7854
7908
|
function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
|
|
7855
7909
|
const mode2 = useRuntimeMode();
|
|
7856
7910
|
const [open, setOpen] = React36.useState(false);
|
|
@@ -7920,7 +7974,7 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
7920
7974
|
s.total,
|
|
7921
7975
|
" features complete"
|
|
7922
7976
|
] }),
|
|
7923
|
-
onOpenSpec ? /* @__PURE__ */ jsxs58(
|
|
7977
|
+
onOpenSpec ? /* @__PURE__ */ jsxs58(Fragment18, { children: [
|
|
7924
7978
|
/* @__PURE__ */ jsx63("span", { style: { flex: 1 } }),
|
|
7925
7979
|
/* @__PURE__ */ jsxs58("button", { type: "button", className: "fd-soon-link", onClick: () => {
|
|
7926
7980
|
setOpen(false);
|
|
@@ -8105,7 +8159,7 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
8105
8159
|
|
|
8106
8160
|
// src/components/planner/MixGap.tsx
|
|
8107
8161
|
import * as React37 from "react";
|
|
8108
|
-
import { Fragment as
|
|
8162
|
+
import { Fragment as Fragment19, jsx as jsx66, jsxs as jsxs61 } from "react/jsx-runtime";
|
|
8109
8163
|
var MIX_GAP_LAYOUT = {
|
|
8110
8164
|
trackHeight: 30,
|
|
8111
8165
|
barHeight: 20,
|
|
@@ -8149,7 +8203,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
8149
8203
|
onMouseLeave: () => setHover(null),
|
|
8150
8204
|
children: [
|
|
8151
8205
|
/* @__PURE__ */ jsx66("span", { style: { width: 128, flex: "none" }, children: /* @__PURE__ */ jsx66(ChannelTag, { channel: r.channel, size: "sm" }) }),
|
|
8152
|
-
/* @__PURE__ */ jsx66("span", { style: { position: "relative", flex: 1, height: trackHeight, minWidth: 120 }, children: loading ? /* @__PURE__ */ jsx66("span", { className: "fd-skel", style: { position: "absolute", left: 0, right: 0, top: barTop, height: barHeight, borderRadius: 3 } }) : /* @__PURE__ */ jsxs61(
|
|
8206
|
+
/* @__PURE__ */ jsx66("span", { style: { position: "relative", flex: 1, height: trackHeight, minWidth: 120 }, children: loading ? /* @__PURE__ */ jsx66("span", { className: "fd-skel", style: { position: "absolute", left: 0, right: 0, top: barTop, height: barHeight, borderRadius: 3 } }) : /* @__PURE__ */ jsxs61(Fragment19, { children: [
|
|
8153
8207
|
/* @__PURE__ */ jsx66("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)" } }),
|
|
8154
8208
|
/* @__PURE__ */ jsx66("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 } }),
|
|
8155
8209
|
/* @__PURE__ */ jsxs61("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: [
|
|
@@ -8263,7 +8317,7 @@ function ChannelContribution({
|
|
|
8263
8317
|
|
|
8264
8318
|
// src/components/planner/BudgetReallocator.tsx
|
|
8265
8319
|
import * as React38 from "react";
|
|
8266
|
-
import { Fragment as
|
|
8320
|
+
import { Fragment as Fragment20, jsx as jsx68, jsxs as jsxs63 } from "react/jsx-runtime";
|
|
8267
8321
|
var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
|
|
8268
8322
|
function BudgetReallocator({
|
|
8269
8323
|
campus,
|
|
@@ -8303,7 +8357,7 @@ function BudgetReallocator({
|
|
|
8303
8357
|
/* @__PURE__ */ jsxs63("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
8304
8358
|
/* @__PURE__ */ jsx68("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
|
|
8305
8359
|
/* @__PURE__ */ jsx68(CsiBadge, { band: nowBand, crp, size: "medium" }),
|
|
8306
|
-
dirty ? /* @__PURE__ */ jsxs63(
|
|
8360
|
+
dirty ? /* @__PURE__ */ jsxs63(Fragment20, { children: [
|
|
8307
8361
|
/* @__PURE__ */ jsx68("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
|
|
8308
8362
|
/* @__PURE__ */ jsx68(CsiBadge, { band: nextBand, crp: nextCrp, size: "medium", preview: true })
|
|
8309
8363
|
] }) : null
|