@flytedan/flytebot-design-system 0.1.0 → 0.1.2
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/README.md +87 -0
- package/dist/index.cjs +32 -31
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +32 -31
- package/dist/index.js.map +1 -1
- package/package.json +15 -2
- package/styles/components.css +42 -0
- package/styles/fonts/figtree-latin-ext.woff2 +0 -0
- package/styles/fonts/figtree-latin.woff2 +0 -0
- package/styles/foundations.css +44 -228
- package/styles/tokens.css +296 -264
package/README.md
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# @flytedan/flytebot-design-system
|
|
2
|
+
|
|
3
|
+
The flytedesk Design System's Media Planner UI kit, ported to a standalone,
|
|
4
|
+
framework-agnostic-consumer npm package: React 18 + TypeScript components,
|
|
5
|
+
tokens, and business-logic kits for flytedesk apps.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pnpm add @flytedan/flytebot-design-system
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
`react` and `react-dom` (^18.3.1) are peer dependencies.
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
Import the vendored CSS once, near your app's entry point, then use components
|
|
18
|
+
directly:
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
import "@flytedan/flytebot-design-system/styles/tokens.css";
|
|
22
|
+
import "@flytedan/flytebot-design-system/styles/foundations.css";
|
|
23
|
+
import "@flytedan/flytebot-design-system/styles/components.css";
|
|
24
|
+
|
|
25
|
+
import { Button, Card, DataTable } from "@flytedan/flytebot-design-system";
|
|
26
|
+
|
|
27
|
+
function Example() {
|
|
28
|
+
return (
|
|
29
|
+
<Card>
|
|
30
|
+
<Button variant="primary">Save</Button>
|
|
31
|
+
</Card>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## What's in the package
|
|
37
|
+
|
|
38
|
+
**32 core components** across seven groups — actions (Button, IconButton,
|
|
39
|
+
SegmentedControl, Popover, Menu, MenuButton), forms (Input, NumberInput,
|
|
40
|
+
Textarea, Select, DatePicker, TimePicker, Checkbox, Radio, Switch, Slider,
|
|
41
|
+
RangeSlider, FileGrid, Dropzone, MarkdownEditor), surfaces (Card, CardRow,
|
|
42
|
+
Collapsible, Modal, Drawer), data (DataTable, Pagination, SortMenu, StatTile,
|
|
43
|
+
Meter, CsiBadge, CsiMeter, CsiHero, Markdown, CodeBlock, DiffBlock, StepList,
|
|
44
|
+
SegmentedMeter, QuotaRow, Clamp, RelativeTime), feedback (Badge, Tag, Avatar,
|
|
45
|
+
AvatarStack, Flag, Toast, Tooltip, EmptyState, KeyHint), loading (Skeleton,
|
|
46
|
+
SkeletonText, LoadingRegion, Spinner, ProgressBar), and navigation (Tabs,
|
|
47
|
+
SidebarNav, Topbar).
|
|
48
|
+
|
|
49
|
+
**Platform components** for identity/session UI — AccountMenu,
|
|
50
|
+
ApiSpecBrowser, Gate/FeatureGate/PermissionDenied/PermissionHint,
|
|
51
|
+
ProfilePage, ComingSoon, RoadmapTimeline, ModeSwitch/TestModeBar.
|
|
52
|
+
|
|
53
|
+
**Planner components** for media-planning UIs — SaturationDistribution,
|
|
54
|
+
MixGap, ChannelContribution, SurroundSound, BudgetReallocator, ChannelMeta.
|
|
55
|
+
|
|
56
|
+
**Chat components** — AgentChatPanel, ChatComposer, ChatSessionBar,
|
|
57
|
+
ChatTranscript, ChatTurn, chatEngine.
|
|
58
|
+
|
|
59
|
+
**Business-logic kits** (framework-light, no UI) — SessionKit (roles,
|
|
60
|
+
permissions, feature flags), QueryKit (paged/sorted/filtered list state via
|
|
61
|
+
`useServerTable`), RuntimeKit (feature-completeness/live-vs-test derivation),
|
|
62
|
+
FileKit, MockJobKit (`{ jobId } → poll` async job simulation), VersionKit
|
|
63
|
+
(append-only version history stores).
|
|
64
|
+
|
|
65
|
+
Every export has its own documented page — props transcribed from the real
|
|
66
|
+
TypeScript interfaces, a live interactive example, and a usage snippet — in
|
|
67
|
+
the docs site included in this repo (not yet published as a hosted site):
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
git clone git@github.com:flytedan/flytebot-design-system.git
|
|
71
|
+
cd flytebot-design-system
|
|
72
|
+
pnpm install
|
|
73
|
+
pnpm run docs
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Development
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
pnpm run build # tsup — emits dist/{index.js,index.cjs,index.d.ts}
|
|
80
|
+
pnpm run typecheck # tsc --noEmit
|
|
81
|
+
pnpm run lint # eslint .
|
|
82
|
+
pnpm run test # vitest run
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## License
|
|
86
|
+
|
|
87
|
+
UNLICENSED — internal flytedesk use only.
|
package/dist/index.cjs
CHANGED
|
@@ -2195,7 +2195,8 @@ function SegmentedMeter({
|
|
|
2195
2195
|
const pct = safeTotal ? Math.min(100, Math.round(used / safeTotal * 100)) : 0;
|
|
2196
2196
|
const w = (v) => safeTotal ? Math.max(0, Math.min(100, Number(v) / safeTotal * 100)) : 0;
|
|
2197
2197
|
const fill = (s, i) => s.color || (s.variant ? VARIANT_FILL[s.variant] : void 0) || CHART[i % CHART.length];
|
|
2198
|
-
const
|
|
2198
|
+
const generatedId = React11.useId();
|
|
2199
|
+
const uid2 = id || generatedId;
|
|
2199
2200
|
return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: ["fd-segmeter", className].filter(Boolean).join(" "), onClick, children: [
|
|
2200
2201
|
label || showTotal ? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "fd-segmeter-head", children: [
|
|
2201
2202
|
label ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "fd-segmeter-label", id: uid2 + "-l", children: label }) : /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", {}),
|
|
@@ -3489,6 +3490,36 @@ function RangeSlider({
|
|
|
3489
3490
|
className = "",
|
|
3490
3491
|
...rest
|
|
3491
3492
|
}) {
|
|
3493
|
+
const fmt2 = format || ((v) => String(v));
|
|
3494
|
+
const [a, b] = value || [min, max];
|
|
3495
|
+
const [drag, setDrag] = React20.useState(null);
|
|
3496
|
+
const [focus, setFocus] = React20.useState(null);
|
|
3497
|
+
const railRef = React20.useRef(null);
|
|
3498
|
+
const pct = (v) => max === min ? 0 : (v - min) / (max - min) * 100;
|
|
3499
|
+
const clampPair = (i, v) => {
|
|
3500
|
+
v = Math.min(max, Math.max(min, Math.round(v / step) * step));
|
|
3501
|
+
if (snap && marks.length) {
|
|
3502
|
+
const near = marks.reduce((best, m) => Math.abs(m.value - v) < Math.abs(best - v) ? m.value : best, Infinity);
|
|
3503
|
+
if (Math.abs(near - v) <= (max - min) * 0.015) v = near;
|
|
3504
|
+
}
|
|
3505
|
+
const pair = i === 0 ? [Math.min(v, b - minGap), b] : [a, Math.max(v, a + minGap)];
|
|
3506
|
+
return pair;
|
|
3507
|
+
};
|
|
3508
|
+
const fromEvent = (e) => {
|
|
3509
|
+
const r = railRef.current.getBoundingClientRect();
|
|
3510
|
+
return min + Math.min(1, Math.max(0, (e.clientX - r.left) / r.width)) * (max - min);
|
|
3511
|
+
};
|
|
3512
|
+
React20.useEffect(() => {
|
|
3513
|
+
if (drag === null) return;
|
|
3514
|
+
const mv = (e) => onChange && onChange(clampPair(drag, fromEvent(e)));
|
|
3515
|
+
const upH = () => setDrag(null);
|
|
3516
|
+
window.addEventListener("pointermove", mv);
|
|
3517
|
+
window.addEventListener("pointerup", upH);
|
|
3518
|
+
return () => {
|
|
3519
|
+
window.removeEventListener("pointermove", mv);
|
|
3520
|
+
window.removeEventListener("pointerup", upH);
|
|
3521
|
+
};
|
|
3522
|
+
}, [drag, a, b]);
|
|
3492
3523
|
if (stops && stops.length > 1) {
|
|
3493
3524
|
const S = stops.map((s) => typeof s === "object" ? s : { value: s });
|
|
3494
3525
|
const num = (v) => v === Infinity || v == null ? Number.MAX_SAFE_INTEGER : v;
|
|
@@ -3517,25 +3548,6 @@ function RangeSlider({
|
|
|
3517
3548
|
}
|
|
3518
3549
|
);
|
|
3519
3550
|
}
|
|
3520
|
-
const fmt2 = format || ((v) => String(v));
|
|
3521
|
-
const [a, b] = value || [min, max];
|
|
3522
|
-
const [drag, setDrag] = React20.useState(null);
|
|
3523
|
-
const [focus, setFocus] = React20.useState(null);
|
|
3524
|
-
const railRef = React20.useRef(null);
|
|
3525
|
-
const pct = (v) => max === min ? 0 : (v - min) / (max - min) * 100;
|
|
3526
|
-
const clampPair = (i, v) => {
|
|
3527
|
-
v = Math.min(max, Math.max(min, Math.round(v / step) * step));
|
|
3528
|
-
if (snap && marks.length) {
|
|
3529
|
-
const near = marks.reduce((best, m) => Math.abs(m.value - v) < Math.abs(best - v) ? m.value : best, Infinity);
|
|
3530
|
-
if (Math.abs(near - v) <= (max - min) * 0.015) v = near;
|
|
3531
|
-
}
|
|
3532
|
-
const pair = i === 0 ? [Math.min(v, b - minGap), b] : [a, Math.max(v, a + minGap)];
|
|
3533
|
-
return pair;
|
|
3534
|
-
};
|
|
3535
|
-
const fromEvent = (e) => {
|
|
3536
|
-
const r = railRef.current.getBoundingClientRect();
|
|
3537
|
-
return min + Math.min(1, Math.max(0, (e.clientX - r.left) / r.width)) * (max - min);
|
|
3538
|
-
};
|
|
3539
3551
|
const startDrag = (i) => (e) => {
|
|
3540
3552
|
e.preventDefault();
|
|
3541
3553
|
e.target.setPointerCapture && e.target.setPointerCapture(e.pointerId);
|
|
@@ -3547,17 +3559,6 @@ function RangeSlider({
|
|
|
3547
3559
|
onChange && onChange(clampPair(i, v));
|
|
3548
3560
|
setDrag(i);
|
|
3549
3561
|
};
|
|
3550
|
-
React20.useEffect(() => {
|
|
3551
|
-
if (drag === null) return;
|
|
3552
|
-
const mv = (e) => onChange && onChange(clampPair(drag, fromEvent(e)));
|
|
3553
|
-
const upH = () => setDrag(null);
|
|
3554
|
-
window.addEventListener("pointermove", mv);
|
|
3555
|
-
window.addEventListener("pointerup", upH);
|
|
3556
|
-
return () => {
|
|
3557
|
-
window.removeEventListener("pointermove", mv);
|
|
3558
|
-
window.removeEventListener("pointerup", upH);
|
|
3559
|
-
};
|
|
3560
|
-
}, [drag, a, b]);
|
|
3561
3562
|
const key = (i) => (e) => {
|
|
3562
3563
|
const big = (max - min) / 10;
|
|
3563
3564
|
let d = 0;
|