@flytedan/flytebot-design-system 0.56.0 → 0.58.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 CHANGED
@@ -49,6 +49,7 @@ __export(index_exports, {
49
49
  CHANNEL_WEIGHTS: () => CHANNEL_WEIGHTS,
50
50
  CHAT_UNAVAILABLE: () => CHAT_UNAVAILABLE,
51
51
  COPIED_FEEDBACK_MS: () => COPIED_FEEDBACK_MS,
52
+ CORNER_STACK_INSET_PROPERTY: () => CORNER_STACK_INSET_PROPERTY,
52
53
  Calendar: () => Calendar,
53
54
  Card: () => Card,
54
55
  CardGrid: () => CardGrid,
@@ -1386,9 +1387,11 @@ var React10 = __toESM(require("react"), 1);
1386
1387
  // src/kits/cornerStack.tsx
1387
1388
  var React9 = __toESM(require("react"), 1);
1388
1389
  var import_react_dom5 = require("react-dom");
1390
+ var CORNER_STACK_INSET_PROPERTY = "--fd-corner-stack-inset";
1389
1391
  var SLOTS = ["jobs", "toasts"];
1390
1392
  var references = /* @__PURE__ */ new Map();
1391
1393
  var host = null;
1394
+ var hostObserver = null;
1392
1395
  var slotElements = /* @__PURE__ */ new Map();
1393
1396
  function createHost() {
1394
1397
  const stack = document.createElement("div");
@@ -1402,8 +1405,18 @@ function createHost() {
1402
1405
  slotElements.set(slot, element);
1403
1406
  }
1404
1407
  document.body.appendChild(stack);
1408
+ publishInset(stack);
1409
+ if (typeof ResizeObserver === "function") {
1410
+ hostObserver = new ResizeObserver(() => publishInset(stack));
1411
+ hostObserver.observe(stack);
1412
+ }
1405
1413
  return stack;
1406
1414
  }
1415
+ function publishInset(stack) {
1416
+ const height = stack.offsetHeight;
1417
+ const inset = height > 0 ? height + parseFloat(getComputedStyle(stack).bottom) : 0;
1418
+ document.documentElement.style.setProperty(CORNER_STACK_INSET_PROPERTY, `${inset}px`);
1419
+ }
1407
1420
  function acquire(slot) {
1408
1421
  host ??= createHost();
1409
1422
  references.set(slot, (references.get(slot) ?? 0) + 1);
@@ -1414,6 +1427,9 @@ function release(slot) {
1414
1427
  if (remaining > 0) references.set(slot, remaining);
1415
1428
  else references.delete(slot);
1416
1429
  if (references.size === 0 && host) {
1430
+ hostObserver?.disconnect();
1431
+ hostObserver = null;
1432
+ document.documentElement.style.removeProperty(CORNER_STACK_INSET_PROPERTY);
1417
1433
  host.remove();
1418
1434
  host = null;
1419
1435
  slotElements.clear();
@@ -1852,7 +1868,7 @@ function AppShell({
1852
1868
  /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
1853
1869
  "div",
1854
1870
  {
1855
- className: contentClassName,
1871
+ className: ["fd-app-shell-content", contentClassName].filter(Boolean).join(" "),
1856
1872
  style: {
1857
1873
  flex: 1,
1858
1874
  minWidth: 0,
@@ -1860,7 +1876,6 @@ function AppShell({
1860
1876
  // table) is contained and clipped by this scroller, never stretching the document.
1861
1877
  position: "relative",
1862
1878
  overflowY: "auto",
1863
- padding: 24,
1864
1879
  maxWidth: contentMaxWidth,
1865
1880
  margin: "0 auto",
1866
1881
  width: "100%",
@@ -5686,52 +5701,155 @@ function InlinePanelSurface({ panel, align = "right", ...popover }) {
5686
5701
 
5687
5702
  // src/components/data/SortMenu.tsx
5688
5703
  var import_jsx_runtime58 = require("react/jsx-runtime");
5689
- function SortMenu({ fields = [], sort, onSort, align = "right", size = "md", className = "", ...rest }) {
5704
+ var directionWord = (field, dir) => dir === "asc" ? field.numeric ? "lowest first" : "A to Z" : field.numeric ? "highest first" : "Z to A";
5705
+ function moved(sort, from, to) {
5706
+ const next = [...sort];
5707
+ const [entry] = next.splice(from, 1);
5708
+ next.splice(to, 0, entry);
5709
+ return next;
5710
+ }
5711
+ function SortMenu({
5712
+ fields = [],
5713
+ sort = [],
5714
+ onSortChange,
5715
+ multiple = false,
5716
+ align = "right",
5717
+ size = "md",
5718
+ className = "",
5719
+ ...rest
5720
+ }) {
5690
5721
  const panel = useInlinePanel();
5691
5722
  const { open: open2, setOpen, ref } = panel;
5692
- const cur = fields.find((f) => f.key === (sort && sort.key));
5693
- const dir = sort && sort.dir;
5694
- const arrow = (f, d) => {
5695
- const on = cur && cur.key === f.key && dir === d;
5696
- const label = d === "asc" ? f.numeric ? "lowest first" : "A to Z" : f.numeric ? "highest first" : "Z to A";
5697
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
5698
- "button",
5723
+ const change = (next) => onSortChange && onSortChange(next);
5724
+ const fieldOf = (key) => fields.find((f) => f.key === key);
5725
+ const active = sort.filter((entry) => fieldOf(entry.key));
5726
+ const first = active[0];
5727
+ const firstField = first && fieldOf(first.key);
5728
+ const triggerLabel = firstField ? firstField.label + (active.length > 1 ? " +" + (active.length - 1) : "") : "Unsorted";
5729
+ const triggerTitle = active.map((entry) => {
5730
+ const field = fieldOf(entry.key);
5731
+ return field.label + " " + directionWord(field, entry.dir);
5732
+ }).join(", then ");
5733
+ const arrow = (field, dir, on, onClick) => /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
5734
+ "button",
5735
+ {
5736
+ type: "button",
5737
+ "aria-label": field.label + ", " + directionWord(field, dir),
5738
+ "aria-pressed": on,
5739
+ onClick,
5740
+ style: {
5741
+ display: "grid",
5742
+ placeItems: "center",
5743
+ width: 26,
5744
+ height: 26,
5745
+ borderRadius: 6,
5746
+ cursor: "pointer",
5747
+ flex: "none",
5748
+ border: "1px solid " + (on ? "var(--brand)" : "var(--border)"),
5749
+ background: on ? "var(--brand)" : "var(--surface)",
5750
+ color: on ? "#fff" : "var(--text-muted)"
5751
+ },
5752
+ children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("i", { className: "ph ph-arrow-" + (dir === "asc" ? "up" : "down"), style: { fontSize: 13 } })
5753
+ }
5754
+ );
5755
+ const rowStyle = (highlight) => ({
5756
+ gap: 8,
5757
+ padding: "4px 8px",
5758
+ borderRadius: 7,
5759
+ background: highlight ? "var(--surface-brand)" : "transparent"
5760
+ });
5761
+ const labelStyle = (highlight) => ({
5762
+ flex: 1,
5763
+ minWidth: 0,
5764
+ fontWeight: highlight ? 700 : 500,
5765
+ color: highlight ? "var(--text-on-surface-brand)" : "var(--text)"
5766
+ });
5767
+ const singleBody = fields.map((f) => {
5768
+ const on = !!first && first.key === f.key;
5769
+ return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-row", style: rowStyle(on), children: [
5770
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-body-sm", style: labelStyle(on), children: f.label }),
5771
+ arrow(f, "asc", on && first.dir === "asc", () => change([{ key: f.key, dir: "asc" }])),
5772
+ arrow(f, "desc", on && first.dir === "desc", () => change([{ key: f.key, dir: "desc" }]))
5773
+ ] }, f.key);
5774
+ });
5775
+ const unused = fields.filter((f) => !active.some((entry) => entry.key === f.key));
5776
+ const multipleBody = /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(import_jsx_runtime58.Fragment, { children: [
5777
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-overline fd-muted", style: { padding: "4px 8px 6px" }, children: "Sorted by" }),
5778
+ active.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-body-sm fd-muted", style: { padding: "4px 8px" }, children: "Unsorted" }) : /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("ol", { className: "fd-stack", style: { gap: 2, margin: 0, padding: 0, listStyle: "none" }, "aria-label": "Sort order", children: active.map((entry, index) => {
5779
+ const f = fieldOf(entry.key);
5780
+ const flipped = entry.dir === "asc" ? "desc" : "asc";
5781
+ return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("li", { className: "fd-row", style: rowStyle(false), children: [
5782
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-body-sm fd-muted", "aria-hidden": "true", style: { width: 14, flex: "none" }, children: index + 1 }),
5783
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-body-sm", style: labelStyle(false), children: f.label }),
5784
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
5785
+ IconButton,
5786
+ {
5787
+ size: "sm",
5788
+ variant: "outline",
5789
+ icon: entry.dir === "asc" ? "arrow-up" : "arrow-down",
5790
+ label: f.label + ", " + directionWord(f, entry.dir) + ". Switch to " + directionWord(f, flipped),
5791
+ onClick: () => change(active.map((e) => e.key === entry.key ? { key: e.key, dir: flipped } : e))
5792
+ }
5793
+ ),
5794
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
5795
+ IconButton,
5796
+ {
5797
+ size: "sm",
5798
+ icon: "caret-up",
5799
+ label: "Sort " + f.label + " earlier",
5800
+ disabled: index === 0,
5801
+ onClick: () => change(moved(active, index, index - 1))
5802
+ }
5803
+ ),
5804
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
5805
+ IconButton,
5806
+ {
5807
+ size: "sm",
5808
+ icon: "caret-down",
5809
+ label: "Sort " + f.label + " later",
5810
+ disabled: index === active.length - 1,
5811
+ onClick: () => change(moved(active, index, index + 1))
5812
+ }
5813
+ ),
5814
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
5815
+ IconButton,
5816
+ {
5817
+ size: "sm",
5818
+ icon: "x",
5819
+ label: "Remove " + f.label + " from the sort",
5820
+ onClick: () => change(active.filter((e) => e.key !== entry.key))
5821
+ }
5822
+ )
5823
+ ] }, entry.key);
5824
+ }) }),
5825
+ unused.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(import_jsx_runtime58.Fragment, { children: [
5826
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-overline fd-muted", style: { padding: "10px 8px 6px" }, children: "Add a sort" }),
5827
+ unused.map((f) => /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-row", style: rowStyle(false), children: [
5828
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-body-sm", style: labelStyle(false), children: f.label }),
5829
+ arrow(f, "asc", false, () => change([...active, { key: f.key, dir: "asc" }])),
5830
+ arrow(f, "desc", false, () => change([...active, { key: f.key, dir: "desc" }]))
5831
+ ] }, f.key))
5832
+ ] }) : null
5833
+ ] });
5834
+ return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className, style: { display: "inline-flex", minWidth: 0 }, ref, ...rest, children: [
5835
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
5836
+ Button,
5699
5837
  {
5700
- type: "button",
5701
- "aria-label": f.label + ", " + label,
5702
- "aria-pressed": on,
5703
- onClick: () => onSort && onSort(f.key, d),
5704
- style: {
5705
- display: "grid",
5706
- placeItems: "center",
5707
- width: 26,
5708
- height: 26,
5709
- borderRadius: 6,
5710
- cursor: "pointer",
5711
- border: "1px solid " + (on ? "var(--brand)" : "var(--border)"),
5712
- background: on ? "var(--brand)" : "var(--surface)",
5713
- color: on ? "#fff" : "var(--text-muted)"
5714
- },
5715
- children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("i", { className: "ph ph-arrow-" + (d === "asc" ? "up" : "down"), style: { fontSize: 13 } })
5838
+ size,
5839
+ variant: "secondary",
5840
+ icon: first && first.dir === "asc" ? "sort-ascending" : "sort-descending",
5841
+ title: triggerTitle || void 0,
5842
+ onClick: () => setOpen(!open2),
5843
+ children: [
5844
+ triggerLabel,
5845
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("i", { className: "ph ph-" + (first && first.dir === "asc" ? "arrow-up" : "arrow-down"), style: { fontSize: 12, marginLeft: 6, opacity: 0.75 } })
5846
+ ]
5716
5847
  }
5717
- );
5718
- };
5719
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className, style: { display: "inline-flex" }, ref, ...rest, children: [
5720
- /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(Button, { size, variant: "secondary", icon: dir === "asc" ? "sort-ascending" : "sort-descending", onClick: () => setOpen(!open2), children: [
5721
- cur ? cur.label : "Unsorted",
5722
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("i", { className: "ph ph-" + (dir === "asc" ? "arrow-up" : "arrow-down"), style: { fontSize: 12, marginLeft: 6, opacity: 0.75 } })
5723
- ] }),
5724
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(InlinePanelSurface, { panel, align, offset: 6, width: 280, label: "Sort by", children: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-stack", style: { gap: 2, padding: 8 }, children: [
5848
+ ),
5849
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(InlinePanelSurface, { panel, align, offset: 6, width: multiple ? 340 : 280, label: "Sort by", children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-stack", style: { gap: 2, padding: 8 }, children: multiple ? multipleBody : /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(import_jsx_runtime58.Fragment, { children: [
5725
5850
  /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-overline fd-muted", style: { padding: "4px 8px 6px" }, children: "Sort by" }),
5726
- fields.map((f) => {
5727
- const active = cur && cur.key === f.key;
5728
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-row", style: { gap: 8, padding: "4px 8px", borderRadius: 7, background: active ? "var(--surface-brand)" : "transparent" }, children: [
5729
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-body-sm", style: { flex: 1, fontWeight: active ? 700 : 500, color: active ? "var(--text-on-surface-brand)" : "var(--text)" }, children: f.label }),
5730
- arrow(f, "asc"),
5731
- arrow(f, "desc")
5732
- ] }, f.key);
5733
- })
5734
- ] }) })
5851
+ singleBody
5852
+ ] }) }) })
5735
5853
  ] });
5736
5854
  }
5737
5855
 
@@ -6269,7 +6387,7 @@ function TransferList({
6269
6387
  cfg.header ? /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("div", { className: "fd-tlist-header", children: cfg.header }) : null,
6270
6388
  /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
6271
6389
  /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(SearchField, { value: cfg.search, onChange: cfg.onSearchChange, placeholder: "Search", "aria-label": (cfg.label || side) + " search", style: { flex: 1 } }),
6272
- /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(SortMenu, { fields: cfg.sortFields, sort: cfg.sort, onSort: cfg.onSort, align: side === "left" ? "left" : "right" })
6390
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(SortMenu, { fields: cfg.sortFields, sort: cfg.sort ? [cfg.sort] : [], onSortChange: (next) => next[0] && cfg.onSort(next[0].key, next[0].dir), align: side === "left" ? "left" : "right" })
6273
6391
  ] }),
6274
6392
  /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
6275
6393
  VirtualList,
@@ -14610,6 +14728,7 @@ function useDocumentTitle(routeTitle, appName) {
14610
14728
  CHANNEL_WEIGHTS,
14611
14729
  CHAT_UNAVAILABLE,
14612
14730
  COPIED_FEEDBACK_MS,
14731
+ CORNER_STACK_INSET_PROPERTY,
14613
14732
  Calendar,
14614
14733
  Card,
14615
14734
  CardGrid,