@tangle-network/ui 11.2.4 → 11.3.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/CHANGELOG.md +14 -0
- package/dist/{chunk-HSMVDKL3.js → chunk-EJ5NBW7V.js} +275 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +13 -1
- package/dist/primitives.d.ts +171 -1
- package/dist/primitives.js +13 -1
- package/package.json +2 -2
- package/src/primitives/index.ts +12 -0
- package/src/primitives/metric-strip.test.tsx +181 -0
- package/src/primitives/metric-strip.tsx +122 -0
- package/src/primitives/page-header.test.tsx +57 -0
- package/src/primitives/page-header.tsx +86 -0
- package/src/primitives/status-pill.test.tsx +104 -0
- package/src/primitives/status-pill.tsx +193 -0
- package/src/primitives/toolbar.test.tsx +89 -0
- package/src/primitives/toolbar.tsx +105 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @tangle-network/ui
|
|
2
2
|
|
|
3
|
+
## 11.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- e67a809: Raise the dark surface ladder to AA and add the page-level primitives.
|
|
8
|
+
|
|
9
|
+
In the dark spine, `--md3-surface-container-high` and `--md3-surface-container-highest` sat close enough to the ink ramp that `--text-dim` fell under 4.5:1 on them. The ladder is re-spaced and the ink ramp moves with it, so every ink tier clears AA on all five planes.
|
|
10
|
+
|
|
11
|
+
Dark status chips keep their hue, drop 14% chroma, and lift the fill to 1.50:1 from the card. A new `--run-mix-*` ramp carries proportional bars, spaced in relative luminance so adjacent segments clear the 3:1 floor for non-text contrast.
|
|
12
|
+
|
|
13
|
+
One light token moves: `--surface-warning-text` goes `#b45309` to `#ab4f09`. It is a contrast fix, not a hue change. The old value measured 4.16:1 on the light page canvas, under the 4.5:1 body floor, whenever the colour was used as text away from its own pill background; the new value measures 4.51:1 there and 5.25:1 on the pill. Every other light value is unchanged.
|
|
14
|
+
|
|
15
|
+
`@tangle-network/ui` gains four primitives: `PageHeader`, `StatusPill`, `MetricStrip`, and `Toolbar`/`FilterField`. All additive; no existing export changes.
|
|
16
|
+
|
|
3
17
|
## 11.2.4
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
|
@@ -1261,6 +1261,275 @@ function ThemeToggle() {
|
|
|
1261
1261
|
);
|
|
1262
1262
|
}
|
|
1263
1263
|
|
|
1264
|
+
// src/primitives/page-header.tsx
|
|
1265
|
+
import * as React12 from "react";
|
|
1266
|
+
import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1267
|
+
var PageHeader = React12.forwardRef(
|
|
1268
|
+
({
|
|
1269
|
+
className,
|
|
1270
|
+
title,
|
|
1271
|
+
description,
|
|
1272
|
+
actions,
|
|
1273
|
+
meta,
|
|
1274
|
+
titleId,
|
|
1275
|
+
level = 1,
|
|
1276
|
+
...props
|
|
1277
|
+
}, ref) => {
|
|
1278
|
+
const Heading = level === 1 ? "h1" : "h2";
|
|
1279
|
+
return /* @__PURE__ */ jsxs15("header", { ref, className: cn("mb-6", className), ...props, children: [
|
|
1280
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex flex-wrap items-start justify-between gap-x-6 gap-y-3", children: [
|
|
1281
|
+
/* @__PURE__ */ jsxs15("div", { className: "min-w-0", children: [
|
|
1282
|
+
/* @__PURE__ */ jsx17(
|
|
1283
|
+
Heading,
|
|
1284
|
+
{
|
|
1285
|
+
id: titleId,
|
|
1286
|
+
className: cn(
|
|
1287
|
+
"text-balance font-semibold tracking-tight",
|
|
1288
|
+
level === 1 ? "text-2xl" : "text-lg"
|
|
1289
|
+
),
|
|
1290
|
+
children: title
|
|
1291
|
+
}
|
|
1292
|
+
),
|
|
1293
|
+
description && /* @__PURE__ */ jsx17("p", { className: "mt-1 max-w-prose text-muted-foreground text-sm", children: description })
|
|
1294
|
+
] }),
|
|
1295
|
+
actions && /* @__PURE__ */ jsx17("div", { className: "flex flex-wrap items-center gap-2", children: actions })
|
|
1296
|
+
] }),
|
|
1297
|
+
meta && /* @__PURE__ */ jsx17("div", { className: "mt-3 flex flex-wrap items-center gap-x-4 gap-y-2 text-[var(--text-dim)] text-xs", children: meta })
|
|
1298
|
+
] });
|
|
1299
|
+
}
|
|
1300
|
+
);
|
|
1301
|
+
PageHeader.displayName = "PageHeader";
|
|
1302
|
+
|
|
1303
|
+
// src/primitives/status-pill.tsx
|
|
1304
|
+
import * as React13 from "react";
|
|
1305
|
+
import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1306
|
+
var TONE_SURFACE = {
|
|
1307
|
+
success: "bg-[var(--surface-success-bg)] text-[var(--surface-success-text)] border-[var(--surface-success-border)]",
|
|
1308
|
+
warning: "bg-[var(--surface-warning-bg)] text-[var(--surface-warning-text)] border-[var(--surface-warning-border)]",
|
|
1309
|
+
danger: "bg-[var(--surface-danger-bg)] text-[var(--surface-danger-text)] border-[var(--surface-danger-border)]",
|
|
1310
|
+
info: "bg-[var(--surface-info-bg)] text-[var(--surface-info-text)] border-[var(--surface-info-border)]",
|
|
1311
|
+
// `running` shares the info triple on purpose. `--status-running` exists but
|
|
1312
|
+
// is the green dot on a sandbox — a machine's power state, not a run's
|
|
1313
|
+
// outcome — and it ships as one colour with no paired background or text
|
|
1314
|
+
// tier, which is the pairing this component is built to guarantee. Green also
|
|
1315
|
+
// already means SUCCEEDED here, so a green "running" pill would say a run had
|
|
1316
|
+
// finished well while it was still going.
|
|
1317
|
+
running: "bg-[var(--surface-info-bg)] text-[var(--surface-info-text)] border-[var(--surface-info-border)]",
|
|
1318
|
+
neutral: "bg-[var(--surface-neutral-bg)] text-[var(--surface-neutral-text)] border-[var(--surface-neutral-border)]"
|
|
1319
|
+
};
|
|
1320
|
+
var TONE_TEXT = {
|
|
1321
|
+
success: "text-[var(--surface-success-text)]",
|
|
1322
|
+
warning: "text-[var(--surface-warning-text)]",
|
|
1323
|
+
danger: "text-[var(--surface-danger-text)]",
|
|
1324
|
+
info: "text-[var(--surface-info-text)]",
|
|
1325
|
+
running: "text-[var(--surface-info-text)]",
|
|
1326
|
+
neutral: "text-[var(--surface-neutral-text)]"
|
|
1327
|
+
};
|
|
1328
|
+
function ToneGlyph({ tone }) {
|
|
1329
|
+
const common = {
|
|
1330
|
+
viewBox: "0 0 8 8",
|
|
1331
|
+
className: "size-2 shrink-0"
|
|
1332
|
+
};
|
|
1333
|
+
switch (tone) {
|
|
1334
|
+
// Settled and good: a solid disc.
|
|
1335
|
+
case "success":
|
|
1336
|
+
return /* @__PURE__ */ jsx18("svg", { ...common, "aria-hidden": "true", fill: "currentColor", children: /* @__PURE__ */ jsx18("circle", { cx: "4", cy: "4", r: "3.25" }) });
|
|
1337
|
+
// Settled and bad: a disc with a bar through it, so it differs from
|
|
1338
|
+
// success in OUTLINE and not only in hue.
|
|
1339
|
+
case "danger":
|
|
1340
|
+
return /* @__PURE__ */ jsxs16(
|
|
1341
|
+
"svg",
|
|
1342
|
+
{
|
|
1343
|
+
...common,
|
|
1344
|
+
"aria-hidden": "true",
|
|
1345
|
+
fill: "none",
|
|
1346
|
+
stroke: "currentColor",
|
|
1347
|
+
strokeWidth: "1.5",
|
|
1348
|
+
children: [
|
|
1349
|
+
/* @__PURE__ */ jsx18("circle", { cx: "4", cy: "4", r: "3.1", fill: "currentColor", opacity: "0.35" }),
|
|
1350
|
+
/* @__PURE__ */ jsx18("path", { d: "M1.9 6.1 6.1 1.9", strokeLinecap: "round" })
|
|
1351
|
+
]
|
|
1352
|
+
}
|
|
1353
|
+
);
|
|
1354
|
+
// Needs a person: a triangle.
|
|
1355
|
+
case "warning":
|
|
1356
|
+
return /* @__PURE__ */ jsx18("svg", { ...common, "aria-hidden": "true", fill: "currentColor", children: /* @__PURE__ */ jsx18("path", { d: "M4 0.6 7.7 7.1H0.3z" }) });
|
|
1357
|
+
// Still moving: an open ring, visibly hollow at 8px.
|
|
1358
|
+
case "running":
|
|
1359
|
+
return /* @__PURE__ */ jsx18(
|
|
1360
|
+
"svg",
|
|
1361
|
+
{
|
|
1362
|
+
...common,
|
|
1363
|
+
"aria-hidden": "true",
|
|
1364
|
+
fill: "none",
|
|
1365
|
+
stroke: "currentColor",
|
|
1366
|
+
strokeWidth: "1.75",
|
|
1367
|
+
children: /* @__PURE__ */ jsx18("circle", { cx: "4", cy: "4", r: "2.9" })
|
|
1368
|
+
}
|
|
1369
|
+
);
|
|
1370
|
+
// Informational: a square, the only right-angled mark in the set.
|
|
1371
|
+
case "info":
|
|
1372
|
+
return /* @__PURE__ */ jsx18("svg", { ...common, "aria-hidden": "true", fill: "currentColor", children: /* @__PURE__ */ jsx18("rect", { x: "0.9", y: "0.9", width: "6.2", height: "6.2", rx: "1.2" }) });
|
|
1373
|
+
// Nothing has happened: a dash. No enclosed area at all.
|
|
1374
|
+
default:
|
|
1375
|
+
return /* @__PURE__ */ jsx18(
|
|
1376
|
+
"svg",
|
|
1377
|
+
{
|
|
1378
|
+
...common,
|
|
1379
|
+
"aria-hidden": "true",
|
|
1380
|
+
fill: "none",
|
|
1381
|
+
stroke: "currentColor",
|
|
1382
|
+
strokeWidth: "1.75",
|
|
1383
|
+
children: /* @__PURE__ */ jsx18("path", { d: "M1 4h6", strokeLinecap: "round" })
|
|
1384
|
+
}
|
|
1385
|
+
);
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
var StatusPill = React13.forwardRef(
|
|
1389
|
+
({ className, tone, children, bare = false, size = "sm", ...props }, ref) => /* @__PURE__ */ jsxs16(
|
|
1390
|
+
"span",
|
|
1391
|
+
{
|
|
1392
|
+
ref,
|
|
1393
|
+
className: cn(
|
|
1394
|
+
"inline-flex items-center gap-1.5 whitespace-nowrap rounded-full font-medium",
|
|
1395
|
+
size === "sm" ? "px-2 py-0.5 text-xs" : "px-2.5 py-1 text-sm",
|
|
1396
|
+
bare ? "border border-transparent bg-transparent px-0" : cn("border", TONE_SURFACE[tone]),
|
|
1397
|
+
className
|
|
1398
|
+
),
|
|
1399
|
+
...props,
|
|
1400
|
+
children: [
|
|
1401
|
+
/* @__PURE__ */ jsx18("span", { className: cn("inline-flex", bare && TONE_TEXT[tone]), children: /* @__PURE__ */ jsx18(ToneGlyph, { tone }) }),
|
|
1402
|
+
children
|
|
1403
|
+
]
|
|
1404
|
+
}
|
|
1405
|
+
)
|
|
1406
|
+
);
|
|
1407
|
+
StatusPill.displayName = "StatusPill";
|
|
1408
|
+
|
|
1409
|
+
// src/primitives/metric-strip.tsx
|
|
1410
|
+
import * as React14 from "react";
|
|
1411
|
+
import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1412
|
+
var MetricStrip = React14.forwardRef(
|
|
1413
|
+
({ className, children, ...props }, ref) => /* @__PURE__ */ jsx19(
|
|
1414
|
+
"dl",
|
|
1415
|
+
{
|
|
1416
|
+
ref,
|
|
1417
|
+
className: cn(
|
|
1418
|
+
"grid grid-cols-2 rounded-[var(--radius-lg)] border border-border bg-card shadow-[var(--shadow-card)] sm:grid-cols-4",
|
|
1419
|
+
className
|
|
1420
|
+
),
|
|
1421
|
+
...props,
|
|
1422
|
+
children
|
|
1423
|
+
}
|
|
1424
|
+
)
|
|
1425
|
+
);
|
|
1426
|
+
MetricStrip.displayName = "MetricStrip";
|
|
1427
|
+
var Metric = React14.forwardRef(
|
|
1428
|
+
({ className, label, value, hint, attention, ...props }, ref) => /* @__PURE__ */ jsxs17(
|
|
1429
|
+
"div",
|
|
1430
|
+
{
|
|
1431
|
+
ref,
|
|
1432
|
+
className: cn(
|
|
1433
|
+
// Leading hairline, DRAWN only where a divider belongs — never drawn
|
|
1434
|
+
// and then suppressed. Stating it as `border-l` plus `border-l-0`
|
|
1435
|
+
// variants puts both in one conflict group, where the winner is decided
|
|
1436
|
+
// by emitted-rule order rather than by intent; that resolved the wrong
|
|
1437
|
+
// way at every breakpoint and left a rule down the start of each row.
|
|
1438
|
+
// `:not(:nth-child(Nn+1))` is the row-start test for the column count
|
|
1439
|
+
// at that breakpoint, so no rule ever contradicts another.
|
|
1440
|
+
//
|
|
1441
|
+
// N is COUPLED to the grid template on `MetricStrip`: 2 columns below
|
|
1442
|
+
// `sm`, 4 from `sm`. A new breakpoint there — `md:grid-cols-3`, say —
|
|
1443
|
+
// needs its `md:[&:not(:nth-child(3n+1))]:border-l` here in the same
|
|
1444
|
+
// change, or the dividers land mid-row at that width.
|
|
1445
|
+
"border-border p-4 sm:p-5",
|
|
1446
|
+
"max-sm:[&:not(:nth-child(2n+1))]:border-l",
|
|
1447
|
+
"sm:[&:not(:nth-child(4n+1))]:border-l",
|
|
1448
|
+
className
|
|
1449
|
+
),
|
|
1450
|
+
...props,
|
|
1451
|
+
children: [
|
|
1452
|
+
/* @__PURE__ */ jsxs17("dt", { className: "flex items-center gap-2 text-muted-foreground text-sm", children: [
|
|
1453
|
+
/* @__PURE__ */ jsx19("span", { className: "truncate", children: label }),
|
|
1454
|
+
attention && /* @__PURE__ */ jsx19(StatusPill, { tone: attention.tone, children: attention.label })
|
|
1455
|
+
] }),
|
|
1456
|
+
/* @__PURE__ */ jsx19(
|
|
1457
|
+
"dd",
|
|
1458
|
+
{
|
|
1459
|
+
className: cn(
|
|
1460
|
+
"mt-1 truncate font-semibold text-xl tabular-nums tracking-tight lg:text-2xl",
|
|
1461
|
+
attention?.tone === "danger" && "text-[var(--surface-danger-text)]"
|
|
1462
|
+
),
|
|
1463
|
+
title: typeof value === "string" ? value : void 0,
|
|
1464
|
+
children: value
|
|
1465
|
+
}
|
|
1466
|
+
),
|
|
1467
|
+
hint && // Titled for the same reason the value is: the line truncates, and a
|
|
1468
|
+
// hint is where the qualifying detail lives — which wallet, which
|
|
1469
|
+
// window — so a clipped one is the case most worth recovering.
|
|
1470
|
+
/* @__PURE__ */ jsx19(
|
|
1471
|
+
"dd",
|
|
1472
|
+
{
|
|
1473
|
+
className: "mt-0.5 truncate text-[var(--text-dim)] text-xs",
|
|
1474
|
+
title: typeof hint === "string" ? hint : void 0,
|
|
1475
|
+
children: hint
|
|
1476
|
+
}
|
|
1477
|
+
)
|
|
1478
|
+
]
|
|
1479
|
+
}
|
|
1480
|
+
)
|
|
1481
|
+
);
|
|
1482
|
+
Metric.displayName = "Metric";
|
|
1483
|
+
|
|
1484
|
+
// src/primitives/toolbar.tsx
|
|
1485
|
+
import * as React15 from "react";
|
|
1486
|
+
import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1487
|
+
var Toolbar = React15.forwardRef(
|
|
1488
|
+
({ className, search, filters, actions, ...props }, ref) => /* @__PURE__ */ jsxs18(
|
|
1489
|
+
"div",
|
|
1490
|
+
{
|
|
1491
|
+
ref,
|
|
1492
|
+
className: cn(
|
|
1493
|
+
"mb-4 flex flex-col gap-3 lg:flex-row lg:items-center",
|
|
1494
|
+
className
|
|
1495
|
+
),
|
|
1496
|
+
...props,
|
|
1497
|
+
children: [
|
|
1498
|
+
search && /* @__PURE__ */ jsx20("div", { className: "min-w-0 lg:max-w-sm lg:flex-1", children: search }),
|
|
1499
|
+
filters && // `py-1` leaves room for a focus ring above and below; horizontally the
|
|
1500
|
+
// scroll container clips it, which is the trade a single-line filter row
|
|
1501
|
+
// makes. No negative margin — pulling the row wider than its parent is
|
|
1502
|
+
// what made every page report 4px of horizontal overflow.
|
|
1503
|
+
/* @__PURE__ */ jsx20("div", { className: "flex min-w-0 items-center gap-2 overflow-x-auto py-1 lg:flex-1", children: filters }),
|
|
1504
|
+
actions && /* @__PURE__ */ jsx20("div", { className: "flex shrink-0 items-center gap-2 lg:ml-auto", children: actions })
|
|
1505
|
+
]
|
|
1506
|
+
}
|
|
1507
|
+
)
|
|
1508
|
+
);
|
|
1509
|
+
Toolbar.displayName = "Toolbar";
|
|
1510
|
+
var FilterField = React15.forwardRef(
|
|
1511
|
+
({ className, label, htmlFor, children, ...props }, ref) => /* @__PURE__ */ jsxs18(
|
|
1512
|
+
"div",
|
|
1513
|
+
{
|
|
1514
|
+
ref,
|
|
1515
|
+
className: cn("flex shrink-0 items-center gap-2", className),
|
|
1516
|
+
...props,
|
|
1517
|
+
children: [
|
|
1518
|
+
/* @__PURE__ */ jsx20(
|
|
1519
|
+
"label",
|
|
1520
|
+
{
|
|
1521
|
+
htmlFor,
|
|
1522
|
+
className: "whitespace-nowrap text-muted-foreground text-xs",
|
|
1523
|
+
children: label
|
|
1524
|
+
}
|
|
1525
|
+
),
|
|
1526
|
+
children
|
|
1527
|
+
]
|
|
1528
|
+
}
|
|
1529
|
+
)
|
|
1530
|
+
);
|
|
1531
|
+
FilterField.displayName = "FilterField";
|
|
1532
|
+
|
|
1264
1533
|
export {
|
|
1265
1534
|
Dialog,
|
|
1266
1535
|
DialogTrigger,
|
|
@@ -1305,6 +1574,12 @@ export {
|
|
|
1305
1574
|
SidebarDropZone,
|
|
1306
1575
|
useTheme,
|
|
1307
1576
|
ThemeToggle,
|
|
1577
|
+
PageHeader,
|
|
1578
|
+
StatusPill,
|
|
1579
|
+
MetricStrip,
|
|
1580
|
+
Metric,
|
|
1581
|
+
Toolbar,
|
|
1582
|
+
FilterField,
|
|
1308
1583
|
Logo,
|
|
1309
1584
|
TangleKnot
|
|
1310
1585
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { B as Button, a as ButtonProps, b as buttonVariants } from './button-CMQuQEW_.js';
|
|
2
|
-
export { Avatar, AvatarFallback, AvatarImage, Badge, BadgeProps, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropZone, DropZoneProps, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, EmptyStateProps, InlineCode, InlineCodeProps, Input, InputProps, Label, Progress, SegmentedControl, SegmentedControlOption, SegmentedControlProps, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, SidebarDropZone, SidebarDropZoneProps, Skeleton, SkeletonCard, SkeletonTable, StatCard, StatCardProps, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, TerminalCursor, TerminalDisplay, TerminalInput, TerminalLine, Textarea, TextareaProps, ThemeToggle, Toast, ToastContainer, ToastProvider, UploadFile, UploadProgress, UploadProgressProps, badgeVariants, useTheme, useToast } from './primitives.js';
|
|
2
|
+
export { Avatar, AvatarFallback, AvatarImage, Badge, BadgeProps, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropZone, DropZoneProps, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, EmptyStateProps, FilterField, FilterFieldProps, InlineCode, InlineCodeProps, Input, InputProps, Label, Metric, MetricProps, MetricStrip, MetricStripProps, PageHeader, PageHeaderProps, Progress, SegmentedControl, SegmentedControlOption, SegmentedControlProps, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, SidebarDropZone, SidebarDropZoneProps, Skeleton, SkeletonCard, SkeletonTable, StatCard, StatCardProps, StatusPill, StatusPillProps, StatusTone, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, TerminalCursor, TerminalDisplay, TerminalInput, TerminalLine, Textarea, TextareaProps, ThemeToggle, Toast, ToastContainer, ToastProvider, Toolbar, ToolbarProps, UploadFile, UploadProgress, UploadProgressProps, badgeVariants, useTheme, useToast } from './primitives.js';
|
|
3
3
|
export { Logo, LogoProps, TangleKnot } from '@tangle-network/brand';
|
|
4
4
|
export { A as ArtifactPane, a as ArtifactPaneProps } from './artifact-pane-DpuWcAiF.js';
|
|
5
5
|
export { AgentTimeline, AgentTimelineArtifactItem, AgentTimelineCustomItem, AgentTimelineItem, AgentTimelineMessageItem, AgentTimelineProps, AgentTimelineStatusItem, AgentTimelineTone, AgentTimelineToolGroupItem, AgentTimelineToolItem, ChatContainer, ChatContainerProps, ChatMessage, ChatMessageProps, MessageList, MessageListProps, MessageRole, ThinkingIndicator, ThinkingIndicatorProps, UserMessage, UserMessageProps } from './chat.js';
|
package/dist/index.js
CHANGED
|
@@ -76,9 +76,13 @@ import {
|
|
|
76
76
|
DialogTrigger,
|
|
77
77
|
DropZone,
|
|
78
78
|
EmptyState,
|
|
79
|
+
FilterField,
|
|
79
80
|
Input,
|
|
80
81
|
Label,
|
|
81
82
|
Logo,
|
|
83
|
+
Metric,
|
|
84
|
+
MetricStrip,
|
|
85
|
+
PageHeader,
|
|
82
86
|
Progress,
|
|
83
87
|
SegmentedControl,
|
|
84
88
|
Select,
|
|
@@ -96,6 +100,7 @@ import {
|
|
|
96
100
|
SkeletonCard,
|
|
97
101
|
SkeletonTable,
|
|
98
102
|
StatCard,
|
|
103
|
+
StatusPill,
|
|
99
104
|
Switch,
|
|
100
105
|
TangleKnot,
|
|
101
106
|
TerminalCursor,
|
|
@@ -106,10 +111,11 @@ import {
|
|
|
106
111
|
ThemeToggle,
|
|
107
112
|
ToastContainer,
|
|
108
113
|
ToastProvider,
|
|
114
|
+
Toolbar,
|
|
109
115
|
UploadProgress,
|
|
110
116
|
useTheme,
|
|
111
117
|
useToast
|
|
112
|
-
} from "./chunk-
|
|
118
|
+
} from "./chunk-EJ5NBW7V.js";
|
|
113
119
|
import {
|
|
114
120
|
Avatar,
|
|
115
121
|
AvatarFallback,
|
|
@@ -388,6 +394,7 @@ export {
|
|
|
388
394
|
FilePreview,
|
|
389
395
|
FileTabs,
|
|
390
396
|
FileTree,
|
|
397
|
+
FilterField,
|
|
391
398
|
GitHubLoginButton,
|
|
392
399
|
GlobResultsPreview,
|
|
393
400
|
GrepResultsPreview,
|
|
@@ -401,7 +408,10 @@ export {
|
|
|
401
408
|
Logo,
|
|
402
409
|
Markdown,
|
|
403
410
|
MessageList,
|
|
411
|
+
Metric,
|
|
412
|
+
MetricStrip,
|
|
404
413
|
OpenUIArtifactRenderer,
|
|
414
|
+
PageHeader,
|
|
405
415
|
Progress,
|
|
406
416
|
QuestionPreview,
|
|
407
417
|
RealtimeSessionRegistry,
|
|
@@ -424,6 +434,7 @@ export {
|
|
|
424
434
|
SkeletonCard,
|
|
425
435
|
SkeletonTable,
|
|
426
436
|
StatCard,
|
|
437
|
+
StatusPill,
|
|
427
438
|
Switch,
|
|
428
439
|
TOOL_CATEGORY_ICONS,
|
|
429
440
|
Table,
|
|
@@ -449,6 +460,7 @@ export {
|
|
|
449
460
|
ToastContainer,
|
|
450
461
|
ToastProvider,
|
|
451
462
|
ToolCallFeed,
|
|
463
|
+
Toolbar,
|
|
452
464
|
UploadProgress,
|
|
453
465
|
UserMenu,
|
|
454
466
|
UserMessage,
|
package/dist/primitives.d.ts
CHANGED
|
@@ -336,4 +336,174 @@ declare function useTheme(): {
|
|
|
336
336
|
};
|
|
337
337
|
declare function ThemeToggle(): react_jsx_runtime.JSX.Element;
|
|
338
338
|
|
|
339
|
-
|
|
339
|
+
/**
|
|
340
|
+
* The one masthead every console page opens with.
|
|
341
|
+
*
|
|
342
|
+
* A page identifies itself in three separate registers, and each gets its own
|
|
343
|
+
* slot here so they cannot compete for the same one:
|
|
344
|
+
*
|
|
345
|
+
* - `title` — what the page IS. The `<h1>`, and the only `<h1>`.
|
|
346
|
+
* - `description` — one line on what it is for. Prose belongs here, never in
|
|
347
|
+
* the title slot: a paragraph rendered where a heading goes reads as body
|
|
348
|
+
* copy to a sighted reader and as nothing at all to a screen reader, which
|
|
349
|
+
* is how a page ends up with no accessible name.
|
|
350
|
+
* - `actions` — what the reader can DO from here, right-aligned and wrapping
|
|
351
|
+
* under the title on a narrow viewport rather than squeezing it.
|
|
352
|
+
*
|
|
353
|
+
* `meta` is the fourth register and the one most often missing: the small facts
|
|
354
|
+
* that qualify everything below (a count, a scope, a window). They sit on their
|
|
355
|
+
* own line under the title so a reader can tell the difference between "this
|
|
356
|
+
* page has nothing in it" and "this filter matches nothing".
|
|
357
|
+
*
|
|
358
|
+
* `titleId` is exposed so a page can point `aria-labelledby` at the heading
|
|
359
|
+
* from a region further down without minting a second copy of the string.
|
|
360
|
+
*/
|
|
361
|
+
interface PageHeaderProps extends Omit<React$1.HTMLAttributes<HTMLElement>, "title"> {
|
|
362
|
+
title: React$1.ReactNode;
|
|
363
|
+
description?: React$1.ReactNode;
|
|
364
|
+
actions?: React$1.ReactNode;
|
|
365
|
+
meta?: React$1.ReactNode;
|
|
366
|
+
titleId?: string;
|
|
367
|
+
/** Renders the title one step down for a nested/tab surface. */
|
|
368
|
+
level?: 1 | 2;
|
|
369
|
+
}
|
|
370
|
+
declare const PageHeader: React$1.ForwardRefExoticComponent<PageHeaderProps & React$1.RefAttributes<HTMLElement>>;
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* A run/resource state, told three ways at once.
|
|
374
|
+
*
|
|
375
|
+
* Status is the one place a console cannot afford to speak in colour alone: a
|
|
376
|
+
* red dot and a green dot are the same dot to roughly one man in twelve, and
|
|
377
|
+
* identical in a greyscale print or a screenshot pasted into a ticket. So every
|
|
378
|
+
* pill carries all three channels — a GLYPH whose silhouette differs per tone,
|
|
379
|
+
* the tone's COLOUR, and the state's own LABEL as text.
|
|
380
|
+
*
|
|
381
|
+
* The glyphs are chosen to survive at 8px and to differ in outline rather than
|
|
382
|
+
* in fill: a ring reads as "still open", a solid disc as "settled", a slashed
|
|
383
|
+
* disc as "stopped". Two states never share one silhouette.
|
|
384
|
+
*
|
|
385
|
+
* Each tone draws its fill, border and text from ONE matched token triple.
|
|
386
|
+
* That pairing is the whole point: a status colour is solved against its own
|
|
387
|
+
* background, and nothing guarantees it against an arbitrary one. A component
|
|
388
|
+
* that always brings its own background cannot be placed onto a plane that
|
|
389
|
+
* breaks it.
|
|
390
|
+
*/
|
|
391
|
+
type StatusTone = "success" | "warning" | "danger" | "info" | "neutral" | "running";
|
|
392
|
+
interface StatusPillProps extends Omit<React$1.HTMLAttributes<HTMLSpanElement>, "children"> {
|
|
393
|
+
tone: StatusTone;
|
|
394
|
+
children: React$1.ReactNode;
|
|
395
|
+
/**
|
|
396
|
+
* Drops the fill and border, leaving a toned GLYPH beside a label in the
|
|
397
|
+
* inherited body colour.
|
|
398
|
+
*
|
|
399
|
+
* The label deliberately does not keep the tone. Every status text token
|
|
400
|
+
* clears the 4.5:1 body floor on the page canvas — a gate holds them there —
|
|
401
|
+
* but in light the margin is thin (4.51:1 for warning, 4.54:1 for success),
|
|
402
|
+
* and the canvas is only one of the planes a caller can put a pill on. The
|
|
403
|
+
* glyph keeps the tone instead because a glyph is non-text content against a
|
|
404
|
+
* 3:1 floor, so the tone still reads with room to spare on any plane.
|
|
405
|
+
*
|
|
406
|
+
* For a control that supplies its own surface (a chip, a selected row).
|
|
407
|
+
*/
|
|
408
|
+
bare?: boolean;
|
|
409
|
+
size?: "sm" | "md";
|
|
410
|
+
}
|
|
411
|
+
declare const StatusPill: React$1.ForwardRefExoticComponent<StatusPillProps & React$1.RefAttributes<HTMLSpanElement>>;
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* The headline figures for a console page, as ONE statement rather than four.
|
|
415
|
+
*
|
|
416
|
+
* A row of separate stat cards is the default and it is usually wrong here.
|
|
417
|
+
* Each card is a box that must be tall enough for its longest member, so a row
|
|
418
|
+
* mixing "$248.55 / Personal wallet" against a bare "0" leaves the short ones
|
|
419
|
+
* mostly empty; and four bordered boxes read as four unrelated facts when they
|
|
420
|
+
* are four readings of one account. `MetricStrip` puts them on one plane
|
|
421
|
+
* divided by hairlines: same information, one object, no holes.
|
|
422
|
+
*
|
|
423
|
+
* The divider is a border on the item rather than a `divide-*` utility on the
|
|
424
|
+
* parent, because these wrap. `divide-x` draws from DOM order and leaves a
|
|
425
|
+
* stray rule at the start of every wrapped line; a per-item leading border
|
|
426
|
+
* suppressed at each row start does not.
|
|
427
|
+
*/
|
|
428
|
+
interface MetricStripProps extends React$1.HTMLAttributes<HTMLDListElement> {
|
|
429
|
+
children: React$1.ReactNode;
|
|
430
|
+
}
|
|
431
|
+
declare const MetricStrip: React$1.ForwardRefExoticComponent<MetricStripProps & React$1.RefAttributes<HTMLDListElement>>;
|
|
432
|
+
interface MetricProps extends React$1.HTMLAttributes<HTMLDivElement> {
|
|
433
|
+
label: React$1.ReactNode;
|
|
434
|
+
value: React$1.ReactNode;
|
|
435
|
+
/** The qualifying line: which wallet, which window, what the limit is. */
|
|
436
|
+
hint?: React$1.ReactNode;
|
|
437
|
+
/** Raises the value's tone and shows a pill beside the label. A metric is
|
|
438
|
+
* `attention` only when a person has to DO something — not merely when a
|
|
439
|
+
* number is zero. */
|
|
440
|
+
attention?: {
|
|
441
|
+
tone: StatusTone;
|
|
442
|
+
label: string;
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
446
|
+
* One reading inside a `MetricStrip`.
|
|
447
|
+
*
|
|
448
|
+
* `<dt>` carries the label and `<dd>` the value, so the pair is announced as a
|
|
449
|
+
* described term rather than as two loose strings — the semantic that makes a
|
|
450
|
+
* figure legible without the visual grouping.
|
|
451
|
+
*
|
|
452
|
+
* The value is `tabular-nums`: these sit in a row and change on a timer, and
|
|
453
|
+
* proportional digits make the column jitter every time a 1 becomes an 8.
|
|
454
|
+
*/
|
|
455
|
+
declare const Metric: React$1.ForwardRefExoticComponent<MetricProps & React$1.RefAttributes<HTMLDivElement>>;
|
|
456
|
+
|
|
457
|
+
/**
|
|
458
|
+
* The control row above a table or list: search, filters, then the view switch.
|
|
459
|
+
*
|
|
460
|
+
* It exists because the alternative keeps producing the same two failures. A
|
|
461
|
+
* bare flex row gives every control its natural width, so a search field sits
|
|
462
|
+
* at 1120px on one line and three selects stack full-width beneath it — three
|
|
463
|
+
* enormous empty bars where a compact bar belongs. And each control brought its
|
|
464
|
+
* own visual language, so one row carried a native `<select>`, a custom input
|
|
465
|
+
* and a segmented control side by side.
|
|
466
|
+
*
|
|
467
|
+
* So search and filters SHARE the free space and `actions` stays at its content
|
|
468
|
+
* width, and the row is the one place those controls are composed, which is what
|
|
469
|
+
* keeps them looking like one set.
|
|
470
|
+
*
|
|
471
|
+
* Sharing is deliberate, and the alternative is worse. Giving the filter row its
|
|
472
|
+
* content width starves search: measured with a 537px filter row in an 832px
|
|
473
|
+
* toolbar, the search field collapses to 89px. Letting both flex bounds the
|
|
474
|
+
* filter row instead, so it scrolls within its half — 313px each in that same
|
|
475
|
+
* case — and search stays usable however many filters a page adds. `max-w-sm`
|
|
476
|
+
* then stops search claiming more than it can use when there are few filters.
|
|
477
|
+
*
|
|
478
|
+
* On a narrow viewport the row becomes a column and the filters scroll
|
|
479
|
+
* horizontally as a group rather than wrapping into a tall stack that pushes
|
|
480
|
+
* the table itself below the fold.
|
|
481
|
+
*/
|
|
482
|
+
/**
|
|
483
|
+
* Slots only — `children` is omitted deliberately. A free child would render as
|
|
484
|
+
* a bare flex item with none of the `min-w-0` / `shrink-0` guards the named
|
|
485
|
+
* slots carry, so it would size itself off its content and push the row into
|
|
486
|
+
* the overflow this layout exists to prevent.
|
|
487
|
+
*/
|
|
488
|
+
interface ToolbarProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, "children"> {
|
|
489
|
+
/** The one control that expands to fill the row. */
|
|
490
|
+
search?: React$1.ReactNode;
|
|
491
|
+
/** Filters, in reading order. Kept on one scrollable line when space runs out. */
|
|
492
|
+
filters?: React$1.ReactNode;
|
|
493
|
+
/** View switches and exports, pinned to the end. */
|
|
494
|
+
actions?: React$1.ReactNode;
|
|
495
|
+
}
|
|
496
|
+
declare const Toolbar: React$1.ForwardRefExoticComponent<ToolbarProps & React$1.RefAttributes<HTMLDivElement>>;
|
|
497
|
+
/**
|
|
498
|
+
* A labelled filter control. The label is visible, not a placeholder: a select
|
|
499
|
+
* whose current value IS its label ("All products") tells the reader what is
|
|
500
|
+
* selected but never what the control governs, so a row of three reads as three
|
|
501
|
+
* unrelated words.
|
|
502
|
+
*/
|
|
503
|
+
interface FilterFieldProps extends React$1.HTMLAttributes<HTMLDivElement> {
|
|
504
|
+
label: string;
|
|
505
|
+
htmlFor?: string;
|
|
506
|
+
}
|
|
507
|
+
declare const FilterField: React$1.ForwardRefExoticComponent<FilterFieldProps & React$1.RefAttributes<HTMLDivElement>>;
|
|
508
|
+
|
|
509
|
+
export { Avatar, AvatarFallback, AvatarImage, Badge, type BadgeProps, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropZone, type DropZoneProps, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, type EmptyStateProps, FilterField, type FilterFieldProps, InlineCode, type InlineCodeProps, Input, type InputProps, Label, Metric, type MetricProps, MetricStrip, type MetricStripProps, PageHeader, type PageHeaderProps, Progress, SegmentedControl, type SegmentedControlOption, type SegmentedControlProps, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, SidebarDropZone, type SidebarDropZoneProps, Skeleton, SkeletonCard, SkeletonTable, StatCard, type StatCardProps, StatusPill, type StatusPillProps, type StatusTone, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, TerminalCursor, TerminalDisplay, TerminalInput, TerminalLine, Textarea, type TextareaProps, ThemeToggle, type Toast, ToastContainer, ToastProvider, Toolbar, type ToolbarProps, type UploadFile, UploadProgress, type UploadProgressProps, badgeVariants, useTheme, useToast };
|
package/dist/primitives.js
CHANGED
|
@@ -11,9 +11,13 @@ import {
|
|
|
11
11
|
DialogTrigger,
|
|
12
12
|
DropZone,
|
|
13
13
|
EmptyState,
|
|
14
|
+
FilterField,
|
|
14
15
|
Input,
|
|
15
16
|
Label,
|
|
16
17
|
Logo,
|
|
18
|
+
Metric,
|
|
19
|
+
MetricStrip,
|
|
20
|
+
PageHeader,
|
|
17
21
|
Progress,
|
|
18
22
|
SegmentedControl,
|
|
19
23
|
Select,
|
|
@@ -31,6 +35,7 @@ import {
|
|
|
31
35
|
SkeletonCard,
|
|
32
36
|
SkeletonTable,
|
|
33
37
|
StatCard,
|
|
38
|
+
StatusPill,
|
|
34
39
|
Switch,
|
|
35
40
|
TangleKnot,
|
|
36
41
|
TerminalCursor,
|
|
@@ -41,10 +46,11 @@ import {
|
|
|
41
46
|
ThemeToggle,
|
|
42
47
|
ToastContainer,
|
|
43
48
|
ToastProvider,
|
|
49
|
+
Toolbar,
|
|
44
50
|
UploadProgress,
|
|
45
51
|
useTheme,
|
|
46
52
|
useToast
|
|
47
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-EJ5NBW7V.js";
|
|
48
54
|
import {
|
|
49
55
|
Avatar,
|
|
50
56
|
AvatarFallback,
|
|
@@ -144,10 +150,14 @@ export {
|
|
|
144
150
|
DropdownMenuSubTrigger,
|
|
145
151
|
DropdownMenuTrigger,
|
|
146
152
|
EmptyState,
|
|
153
|
+
FilterField,
|
|
147
154
|
InlineCode,
|
|
148
155
|
Input,
|
|
149
156
|
Label,
|
|
150
157
|
Logo,
|
|
158
|
+
Metric,
|
|
159
|
+
MetricStrip,
|
|
160
|
+
PageHeader,
|
|
151
161
|
Progress,
|
|
152
162
|
SegmentedControl,
|
|
153
163
|
Select,
|
|
@@ -165,6 +175,7 @@ export {
|
|
|
165
175
|
SkeletonCard,
|
|
166
176
|
SkeletonTable,
|
|
167
177
|
StatCard,
|
|
178
|
+
StatusPill,
|
|
168
179
|
Switch,
|
|
169
180
|
Table,
|
|
170
181
|
TableBody,
|
|
@@ -187,6 +198,7 @@ export {
|
|
|
187
198
|
ThemeToggle,
|
|
188
199
|
ToastContainer,
|
|
189
200
|
ToastProvider,
|
|
201
|
+
Toolbar,
|
|
190
202
|
UploadProgress,
|
|
191
203
|
badgeVariants,
|
|
192
204
|
buttonVariants,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tangle-network/ui",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.3.0",
|
|
4
4
|
"description": "Generic React UI components for Tangle products — primitives, chat, run, files, editor, markdown.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -141,7 +141,7 @@
|
|
|
141
141
|
"react-dom": "^18 || ^19",
|
|
142
142
|
"react-router": "^7 || ^8",
|
|
143
143
|
"yjs": "^13.6.0",
|
|
144
|
-
"@tangle-network/brand": "^1.
|
|
144
|
+
"@tangle-network/brand": "^1.4.0"
|
|
145
145
|
},
|
|
146
146
|
"peerDependenciesMeta": {
|
|
147
147
|
"@nanostores/react": {
|
package/src/primitives/index.ts
CHANGED
|
@@ -118,3 +118,15 @@ export { CodeBlock, CopyButton, InlineCode } from "./code-block";
|
|
|
118
118
|
export type { CodeBlockProps, InlineCodeProps } from "./code-block";
|
|
119
119
|
|
|
120
120
|
export { ThemeToggle, useTheme } from "./theme-toggle";
|
|
121
|
+
|
|
122
|
+
export { PageHeader } from "./page-header";
|
|
123
|
+
export type { PageHeaderProps } from "./page-header";
|
|
124
|
+
|
|
125
|
+
export { StatusPill } from "./status-pill";
|
|
126
|
+
export type { StatusPillProps, StatusTone } from "./status-pill";
|
|
127
|
+
|
|
128
|
+
export { MetricStrip, Metric } from "./metric-strip";
|
|
129
|
+
export type { MetricStripProps, MetricProps } from "./metric-strip";
|
|
130
|
+
|
|
131
|
+
export { Toolbar, FilterField } from "./toolbar";
|
|
132
|
+
export type { ToolbarProps, FilterFieldProps } from "./toolbar";
|