@flytedan/flytebot-design-system 0.11.4 → 0.11.6
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 +26 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -5
- package/dist/index.d.ts +6 -5
- package/dist/index.js +26 -13
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/styles/components.css +37 -32
package/dist/index.d.cts
CHANGED
|
@@ -1354,8 +1354,9 @@ interface EntityRowMetric {
|
|
|
1354
1354
|
icon?: string;
|
|
1355
1355
|
/** Fixed cell width in px. Same value on the same column of every row is what makes
|
|
1356
1356
|
* the strip a real aligned column rather than text that happens to sit near text.
|
|
1357
|
-
*
|
|
1358
|
-
*
|
|
1357
|
+
* It is the width a cell takes when the strip has room for every column at its width;
|
|
1358
|
+
* in a strip too narrow for that, cells shrink toward their own figure first, so a
|
|
1359
|
+
* narrow row loses alignment before it loses a figure. */
|
|
1359
1360
|
width?: number;
|
|
1360
1361
|
tone?: "default" | "muted" | "danger";
|
|
1361
1362
|
}
|
|
@@ -2558,9 +2559,9 @@ declare function SaturationDistribution({ campuses, floorBand, floorScore, onSel
|
|
|
2558
2559
|
|
|
2559
2560
|
/**
|
|
2560
2561
|
* Realized media mix against the strategic target, one row per channel.
|
|
2561
|
-
* Realized is a solid
|
|
2562
|
-
*
|
|
2563
|
-
* in a legend.
|
|
2562
|
+
* Realized is a solid tone bar, target a striped marker on the same row, and the
|
|
2563
|
+
* realized share is labelled directly beside them — the gap is the story, so it
|
|
2564
|
+
* never hides in a legend.
|
|
2564
2565
|
*/
|
|
2565
2566
|
interface MixGapRow {
|
|
2566
2567
|
channel: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -1354,8 +1354,9 @@ interface EntityRowMetric {
|
|
|
1354
1354
|
icon?: string;
|
|
1355
1355
|
/** Fixed cell width in px. Same value on the same column of every row is what makes
|
|
1356
1356
|
* the strip a real aligned column rather than text that happens to sit near text.
|
|
1357
|
-
*
|
|
1358
|
-
*
|
|
1357
|
+
* It is the width a cell takes when the strip has room for every column at its width;
|
|
1358
|
+
* in a strip too narrow for that, cells shrink toward their own figure first, so a
|
|
1359
|
+
* narrow row loses alignment before it loses a figure. */
|
|
1359
1360
|
width?: number;
|
|
1360
1361
|
tone?: "default" | "muted" | "danger";
|
|
1361
1362
|
}
|
|
@@ -2558,9 +2559,9 @@ declare function SaturationDistribution({ campuses, floorBand, floorScore, onSel
|
|
|
2558
2559
|
|
|
2559
2560
|
/**
|
|
2560
2561
|
* Realized media mix against the strategic target, one row per channel.
|
|
2561
|
-
* Realized is a solid
|
|
2562
|
-
*
|
|
2563
|
-
* in a legend.
|
|
2562
|
+
* Realized is a solid tone bar, target a striped marker on the same row, and the
|
|
2563
|
+
* realized share is labelled directly beside them — the gap is the story, so it
|
|
2564
|
+
* never hides in a legend.
|
|
2564
2565
|
*/
|
|
2565
2566
|
interface MixGapRow {
|
|
2566
2567
|
channel: string;
|
package/dist/index.js
CHANGED
|
@@ -2833,16 +2833,13 @@ function EntityRowMetrics({ metrics, className = "", style }) {
|
|
|
2833
2833
|
return /* @__PURE__ */ jsx39("span", { className: ["fd-erow-metrics", className].filter(Boolean).join(" "), style, children: metrics.map((m, i) => {
|
|
2834
2834
|
const key = m.id || m.label || i;
|
|
2835
2835
|
const className2 = ["fd-erow-metric", m.tone && m.tone !== "default" ? "is-" + m.tone : "", m.tooltip != null ? "is-described" : ""].filter(Boolean).join(" ");
|
|
2836
|
-
const
|
|
2836
|
+
const tone = { color: METRIC_TONE_COLOR[m.tone || "default"] };
|
|
2837
2837
|
const content = /* @__PURE__ */ jsxs35(React17.Fragment, { children: [
|
|
2838
2838
|
m.icon ? /* @__PURE__ */ jsx39("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }) : null,
|
|
2839
2839
|
/* @__PURE__ */ jsx39("span", { className: "fd-erow-metric-value fd-tabular", children: m.value }),
|
|
2840
2840
|
/* @__PURE__ */ jsx39("span", { className: "fd-sr", children: " " + m.label })
|
|
2841
2841
|
] });
|
|
2842
|
-
|
|
2843
|
-
return /* @__PURE__ */ jsx39("span", { className: className2, style: cellStyle, title: m.label, children: content }, key);
|
|
2844
|
-
}
|
|
2845
|
-
return /* @__PURE__ */ jsx39(Tooltip, { label: m.tooltip, children: /* @__PURE__ */ jsx39("button", { type: "button", className: className2, style: cellStyle, children: content }) }, key);
|
|
2842
|
+
return /* @__PURE__ */ jsx39("span", { className: "fd-erow-cell", style: { "--erow-metric-w": (m.width || ENTITY_ROW_METRIC_WIDTH) + "px" }, children: m.tooltip == null ? /* @__PURE__ */ jsx39("span", { className: className2, style: tone, title: m.label, children: content }) : /* @__PURE__ */ jsx39(Tooltip, { label: m.tooltip, children: /* @__PURE__ */ jsx39("button", { type: "button", className: className2, style: tone, children: content }) }) }, key);
|
|
2846
2843
|
}) });
|
|
2847
2844
|
}
|
|
2848
2845
|
function EntityRow({
|
|
@@ -3198,8 +3195,10 @@ function TransferList({
|
|
|
3198
3195
|
);
|
|
3199
3196
|
};
|
|
3200
3197
|
return /* @__PURE__ */ jsxs38("div", { className: ["fd-tlist", className].filter(Boolean).join(" "), children: [
|
|
3201
|
-
|
|
3202
|
-
|
|
3198
|
+
/* @__PURE__ */ jsxs38("div", { className: "fd-tlist-panes", children: [
|
|
3199
|
+
renderSide("left", left, "right"),
|
|
3200
|
+
renderSide("right", right, "left")
|
|
3201
|
+
] }),
|
|
3203
3202
|
drag ? createPortal4(
|
|
3204
3203
|
/* @__PURE__ */ jsx43(
|
|
3205
3204
|
"div",
|
|
@@ -8107,11 +8106,24 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
8107
8106
|
// src/components/planner/MixGap.tsx
|
|
8108
8107
|
import * as React37 from "react";
|
|
8109
8108
|
import { Fragment as Fragment18, jsx as jsx66, jsxs as jsxs61 } from "react/jsx-runtime";
|
|
8109
|
+
var MIX_GAP_LAYOUT = {
|
|
8110
|
+
trackHeight: 30,
|
|
8111
|
+
barHeight: 20,
|
|
8112
|
+
targetWidth: 6,
|
|
8113
|
+
labelGap: 6,
|
|
8114
|
+
labelGutter: 50
|
|
8115
|
+
};
|
|
8116
|
+
var MIX_GAP_TARGET_STRIPE = "repeating-linear-gradient(135deg, var(--n-600) 0 2px, var(--n-300) 2px 4px)";
|
|
8117
|
+
function mixGapOffset(value, max) {
|
|
8118
|
+
return `calc((100% - ${MIX_GAP_LAYOUT.labelGutter}px) * ${value / max})`;
|
|
8119
|
+
}
|
|
8110
8120
|
function MixGap({ rows = [], loading = false, className = "" }) {
|
|
8111
8121
|
const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
|
|
8112
8122
|
const [hover, setHover] = React37.useState(null);
|
|
8113
8123
|
const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
|
|
8114
8124
|
const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
|
|
8125
|
+
const { trackHeight, barHeight, targetWidth, labelGap } = MIX_GAP_LAYOUT;
|
|
8126
|
+
const barTop = (trackHeight - barHeight) / 2;
|
|
8115
8127
|
return /* @__PURE__ */ jsxs61("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
|
|
8116
8128
|
/* @__PURE__ */ jsxs61("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
|
|
8117
8129
|
[["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ jsxs61("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
|
|
@@ -8119,7 +8131,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
8119
8131
|
l
|
|
8120
8132
|
] }, l)),
|
|
8121
8133
|
/* @__PURE__ */ jsxs61("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
|
|
8122
|
-
/* @__PURE__ */ jsx66("span", { style: { width:
|
|
8134
|
+
/* @__PURE__ */ jsx66("span", { "data-mixgap-legend-target": "", style: { width: targetWidth, height: 16, borderRadius: 1, background: MIX_GAP_TARGET_STRIPE } }),
|
|
8123
8135
|
"Target"
|
|
8124
8136
|
] })
|
|
8125
8137
|
] }),
|
|
@@ -8127,6 +8139,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
8127
8139
|
const gap = r.realized - r.target;
|
|
8128
8140
|
const tone = toneOf(gap);
|
|
8129
8141
|
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 : "");
|
|
8142
|
+
const labelLeft = r.realized > r.target ? `calc(${mixGapOffset(r.realized, max)} + ${labelGap}px)` : `calc(${mixGapOffset(r.target, max)} + ${targetWidth / 2 + labelGap}px)`;
|
|
8130
8143
|
return /* @__PURE__ */ jsxs61(
|
|
8131
8144
|
"div",
|
|
8132
8145
|
{
|
|
@@ -8136,14 +8149,14 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
8136
8149
|
onMouseLeave: () => setHover(null),
|
|
8137
8150
|
children: [
|
|
8138
8151
|
/* @__PURE__ */ jsx66("span", { style: { width: 128, flex: "none" }, children: /* @__PURE__ */ jsx66(ChannelTag, { channel: r.channel, size: "sm" }) }),
|
|
8139
|
-
/* @__PURE__ */ jsx66("span", { style: { position: "relative", flex: 1, height:
|
|
8140
|
-
/* @__PURE__ */ jsx66("span", { style: { position: "absolute", left: 0, top:
|
|
8141
|
-
/* @__PURE__ */ jsx66("span", { style: { position: "absolute", left: r.target
|
|
8142
|
-
/* @__PURE__ */ jsxs61("span", { className: "fd-num", style: { position: "absolute",
|
|
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(Fragment18, { children: [
|
|
8153
|
+
/* @__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
|
+
/* @__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
|
+
/* @__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: [
|
|
8143
8156
|
r.realized,
|
|
8144
8157
|
"%"
|
|
8145
8158
|
] }),
|
|
8146
|
-
hover === r.channel ? /* @__PURE__ */ jsx66("span", { className: "fd-tooltip", role: "tooltip", style: { position: "absolute", left: 0, right: "auto", bottom:
|
|
8159
|
+
hover === r.channel ? /* @__PURE__ */ jsx66("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
|
|
8147
8160
|
] }) })
|
|
8148
8161
|
]
|
|
8149
8162
|
},
|