@tangle-network/ui 11.35.0 → 11.37.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.
Files changed (93) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +1 -1
  3. package/dist/code-presentation.d.ts +2 -0
  4. package/dist/code-presentation.js +2 -0
  5. package/dist/index.d.ts +8 -5
  6. package/dist/index.js +6 -3
  7. package/dist/lib/code-presentation.d.ts +92 -0
  8. package/dist/lib/code-presentation.js +437 -0
  9. package/dist/lib/control-presentation.d.ts +34 -1
  10. package/dist/lib/control-presentation.js +1 -1
  11. package/dist/lib/focus.d.ts +2 -2
  12. package/dist/lib/focus.js +3 -2
  13. package/dist/lib/motion.d.ts +4 -0
  14. package/dist/lib/motion.js +7 -0
  15. package/dist/lib/surface-motion.js +105 -0
  16. package/dist/markdown/api-schema.d.ts +9 -0
  17. package/dist/markdown/api-schema.js +20 -0
  18. package/dist/markdown/code-block.d.ts +15 -7
  19. package/dist/markdown/code-block.js +120 -268
  20. package/dist/markdown.d.ts +4 -2
  21. package/dist/markdown.js +4 -2
  22. package/dist/presentation.d.ts +88 -0
  23. package/dist/presentation.js +183 -0
  24. package/dist/primitives/alert-dialog.js +1 -1
  25. package/dist/primitives/alert.d.ts +1 -2
  26. package/dist/primitives/button.d.ts +2 -5
  27. package/dist/primitives/button.js +5 -31
  28. package/dist/primitives/card.js +3 -7
  29. package/dist/primitives/code-block.d.ts +1 -1
  30. package/dist/primitives/date-picker.d.ts +1 -1
  31. package/dist/primitives/dialog.js +29 -16
  32. package/dist/primitives/empty-state.js +6 -5
  33. package/dist/primitives/heading.d.ts +1 -0
  34. package/dist/primitives/heading.js +3 -2
  35. package/dist/primitives/help-text.js +2 -1
  36. package/dist/primitives/input.d.ts +1 -4
  37. package/dist/primitives/input.js +3 -24
  38. package/dist/primitives/label.js +1 -2
  39. package/dist/primitives/metric-strip.js +7 -12
  40. package/dist/primitives/page-header.d.ts +1 -0
  41. package/dist/primitives/page-header.js +7 -6
  42. package/dist/primitives/page-shell.d.ts +8 -2
  43. package/dist/primitives/page-shell.js +21 -2
  44. package/dist/primitives/pagination.js +1 -1
  45. package/dist/primitives/popover.js +11 -3
  46. package/dist/primitives/sheet.js +29 -19
  47. package/dist/primitives/skeleton.js +1 -1
  48. package/dist/primitives/status-pill.d.ts +3 -1
  49. package/dist/primitives/status-pill.js +12 -3
  50. package/dist/primitives/table.js +10 -9
  51. package/dist/primitives/tabs.js +3 -12
  52. package/dist/primitives/tooltip.js +11 -3
  53. package/dist/primitives.d.ts +3 -2
  54. package/dist/primitives.js +2 -1
  55. package/dist/utils.d.ts +1 -1
  56. package/package.json +20 -5
  57. package/src/code-presentation.ts +2 -0
  58. package/src/lib/code-presentation.ts +257 -0
  59. package/src/lib/control-presentation.ts +2 -4
  60. package/src/lib/focus.ts +3 -2
  61. package/src/lib/motion.ts +7 -0
  62. package/src/lib/surface-motion.tsx +85 -0
  63. package/src/markdown/api-presentation.test.tsx +63 -0
  64. package/src/markdown/api-schema.tsx +9 -0
  65. package/src/markdown/code-block.tsx +54 -185
  66. package/src/markdown/index.ts +2 -1
  67. package/src/presentation.ts +205 -0
  68. package/src/primitives/alert.tsx +1 -2
  69. package/src/primitives/button.tsx +6 -41
  70. package/src/primitives/card.tsx +5 -10
  71. package/src/primitives/checkbox-separator-sheet-tooltip.test.tsx +2 -1
  72. package/src/primitives/code-block.tsx +1 -1
  73. package/src/primitives/control-presentation.test.tsx +2 -7
  74. package/src/primitives/dialog.tsx +19 -18
  75. package/src/primitives/empty-state.tsx +6 -5
  76. package/src/primitives/heading.tsx +4 -2
  77. package/src/primitives/help-text.tsx +3 -2
  78. package/src/primitives/input.tsx +3 -31
  79. package/src/primitives/label.tsx +2 -4
  80. package/src/primitives/metric-strip.tsx +8 -17
  81. package/src/primitives/page-header.tsx +8 -5
  82. package/src/primitives/page-shell.tsx +13 -2
  83. package/src/primitives/popover.tsx +6 -8
  84. package/src/primitives/sheet.tsx +16 -11
  85. package/src/primitives/skeleton.tsx +1 -1
  86. package/src/primitives/status-pill.test.tsx +1 -0
  87. package/src/primitives/status-pill.tsx +10 -4
  88. package/src/primitives/table.tsx +10 -9
  89. package/src/primitives/tabs.tsx +5 -17
  90. package/src/primitives/tooltip.tsx +6 -5
  91. package/src/styles/compat.css +12 -0
  92. package/src/styles/presentation.css +38 -0
  93. package/src/primitives/page-shell.test.tsx +0 -24
@@ -4,14 +4,14 @@ import * as React from "react";
4
4
  import { jsx, jsxs } from "react/jsx-runtime";
5
5
  //#region src/primitives/page-header.tsx
6
6
  const hasContent = (node) => Boolean(node) || node === 0;
7
- const PageHeader = React.forwardRef(({ className, title, description, actions, action, eyebrow, meta, titleId, titleAs, level = 1, ...props }, ref) => {
7
+ const PageHeader = React.forwardRef(({ className, presentation, title, description, actions, action, eyebrow, meta, titleId, titleAs, level = 1, ...props }, ref) => {
8
8
  const resolvedActions = actions === void 0 ? action : actions;
9
9
  return /* @__PURE__ */ jsxs("header", {
10
10
  ref,
11
- className: cn("mb-6 min-w-0", className),
11
+ className: cn(presentation === "expressive" ? "tangle-intro" : presentation === "operational" ? "tangle-page-header" : "mb-6 min-w-0", className),
12
12
  ...props,
13
13
  children: [/* @__PURE__ */ jsxs("div", {
14
- className: "flex min-w-0 flex-wrap items-start justify-between gap-x-6 gap-y-3",
14
+ className: presentation ? "tangle-page-header-main" : "flex min-w-0 flex-wrap items-start justify-between gap-x-6 gap-y-3",
15
15
  children: [/* @__PURE__ */ jsxs("div", {
16
16
  className: "min-w-0 flex-[1_1_16rem]",
17
17
  children: [
@@ -22,18 +22,19 @@ const PageHeader = React.forwardRef(({ className, title, description, actions, a
22
22
  }),
23
23
  /* @__PURE__ */ jsx(Heading, {
24
24
  id: titleId,
25
- variant: level === 1 ? "page" : "section",
25
+ variant: presentation === "expressive" ? "display" : level === 1 ? "page" : "section",
26
+ presentation,
26
27
  as: titleAs ?? (level === 1 ? "h1" : "h2"),
27
28
  className: "text-balance",
28
29
  children: title
29
30
  }),
30
31
  hasContent(description) && /* @__PURE__ */ jsx("p", {
31
- className: "mt-1 max-w-prose text-muted-foreground text-sm [overflow-wrap:anywhere]",
32
+ className: presentation === "expressive" ? "tangle-intro-description" : presentation ? "tangle-page-description" : "mt-1 max-w-prose text-muted-foreground text-sm [overflow-wrap:anywhere]",
32
33
  children: description
33
34
  })
34
35
  ]
35
36
  }), hasContent(resolvedActions) && /* @__PURE__ */ jsx("div", {
36
- className: "flex min-w-0 max-w-full flex-wrap items-center gap-2 [overflow-wrap:anywhere] [&>*]:min-w-0 [&>*]:max-w-full",
37
+ className: presentation === "expressive" ? "tangle-intro-actions" : "flex min-w-0 max-w-full flex-wrap items-center gap-2 [overflow-wrap:anywhere] [&>*]:min-w-0 [&>*]:max-w-full",
37
38
  children: resolvedActions
38
39
  })]
39
40
  }), hasContent(meta) && /* @__PURE__ */ jsx("div", {
@@ -1,7 +1,13 @@
1
1
  import { ReactNode } from "react";
2
2
  //#region src/primitives/page-shell.d.ts
3
3
  export interface PageShellProps {
4
- children: ReactNode;
4
+ children?: ReactNode;
5
+ /** Optional reading layout. Content, routing and navigation interaction stay caller-owned. */
6
+ navigation?: ReactNode;
7
+ article?: ReactNode;
8
+ outline?: ReactNode;
9
+ navigationLabel?: string;
10
+ outlineLabel?: string;
5
11
  className?: string;
6
12
  }
7
13
  /**
@@ -10,5 +16,5 @@ export interface PageShellProps {
10
16
  * The caller owns landmarks, routing, auth, navigation and data state. Use
11
17
  * className to override the bound/gutters, or omit it for a workbench layout.
12
18
  */
13
- export declare function PageShell({ children, className }: PageShellProps): import("react").JSX.Element;
19
+ export declare function PageShell({ children, className, navigation, article, outline, navigationLabel, outlineLabel }: PageShellProps): import("react").JSX.Element;
14
20
  //#endregion
@@ -1,5 +1,5 @@
1
1
  import { cn } from "../lib/utils.js";
2
- import { jsx } from "react/jsx-runtime";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
3
  //#region src/primitives/page-shell.tsx
4
4
  /**
5
5
  * Ported from sandbox-ui/src/primitives/page-shell.tsx. An optional bounded
@@ -7,7 +7,26 @@ import { jsx } from "react/jsx-runtime";
7
7
  * The caller owns landmarks, routing, auth, navigation and data state. Use
8
8
  * className to override the bound/gutters, or omit it for a workbench layout.
9
9
  */
10
- function PageShell({ children, className }) {
10
+ function PageShell({ children, className, navigation, article, outline, navigationLabel = "Sections", outlineLabel = "On this page" }) {
11
+ if (navigation || article || outline) return /* @__PURE__ */ jsxs("div", {
12
+ className: cn("tangle-reading-shell", className),
13
+ children: [
14
+ navigation && /* @__PURE__ */ jsx("nav", {
15
+ "aria-label": navigationLabel,
16
+ className: "tangle-reading-nav",
17
+ children: navigation
18
+ }),
19
+ /* @__PURE__ */ jsx("article", {
20
+ className: "tangle-reading-article",
21
+ children: article ?? children
22
+ }),
23
+ outline && /* @__PURE__ */ jsx("aside", {
24
+ "aria-label": outlineLabel,
25
+ className: "tangle-reading-outline",
26
+ children: outline
27
+ })
28
+ ]
29
+ });
11
30
  return /* @__PURE__ */ jsx("div", {
12
31
  className: cn("mx-auto min-w-0 w-full max-w-6xl space-y-8 px-6 py-8 lg:px-8", className),
13
32
  children
@@ -1,5 +1,5 @@
1
1
  import { cn } from "../lib/utils.js";
2
- import { buttonVariants } from "./button.js";
2
+ import { buttonVariants } from "../presentation.js";
3
3
  import "react";
4
4
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
5
5
  import { ChevronLeft, ChevronRight } from "lucide-react";
@@ -1,5 +1,7 @@
1
1
  "use client";
2
+ import { surfaceMotion } from "../lib/motion.js";
2
3
  import { cn } from "../lib/utils.js";
4
+ import { SurfaceMotion } from "../lib/surface-motion.js";
3
5
  import * as React from "react";
4
6
  import { jsx } from "react/jsx-runtime";
5
7
  import * as PopoverPrimitive from "@radix-ui/react-popover";
@@ -13,12 +15,18 @@ const PopoverClose = PopoverPrimitive.Close;
13
15
  * shadow as `DropdownMenuContent`. Width defaults to 18rem; pass a width class
14
16
  * for wider content and keep long text wrapping inside it.
15
17
  */
16
- const PopoverContent = React.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(PopoverPrimitive.Content, {
18
+ const PopoverContent = React.forwardRef(({ className, align = "center", sideOffset = 4, asChild, children, ...props }, ref) => /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(PopoverPrimitive.Content, {
17
19
  ref,
18
20
  align,
19
21
  sideOffset,
20
- className: cn("z-50 w-72 max-w-[calc(100vw-2rem)] origin-(--radix-popover-content-transform-origin) rounded-xl border border-border bg-card p-4 text-foreground shadow-[var(--shadow-card)] outline-hidden", "data-[state=closed]:animate-out data-[state=open]:animate-in", "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95", "data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2", "data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", "motion-reduce:animate-none", className),
21
- ...props
22
+ className: cn("z-50 w-72 max-w-[calc(100vw-2rem)] origin-(--radix-popover-content-transform-origin) rounded-xl border border-border bg-card p-4 text-foreground shadow-[var(--shadow-card)] outline-hidden", surfaceMotion, className),
23
+ ...props,
24
+ asChild: true,
25
+ children: /* @__PURE__ */ jsx(SurfaceMotion, {
26
+ kind: "popover",
27
+ asChild,
28
+ children
29
+ })
22
30
  }) }));
23
31
  PopoverContent.displayName = PopoverPrimitive.Content.displayName;
24
32
  //#endregion
@@ -1,6 +1,8 @@
1
1
  "use client";
2
+ import { surfaceMotion } from "../lib/motion.js";
2
3
  import { focusRing } from "../lib/focus.js";
3
4
  import { cn } from "../lib/utils.js";
5
+ import { SurfaceMotion } from "../lib/surface-motion.js";
4
6
  import { cva } from "class-variance-authority";
5
7
  import * as React from "react";
6
8
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -12,36 +14,44 @@ const Sheet = SheetPrimitive.Root;
12
14
  const SheetTrigger = SheetPrimitive.Trigger;
13
15
  const SheetClose = SheetPrimitive.Close;
14
16
  const SheetPortal = SheetPrimitive.Portal;
15
- const SheetOverlay = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(SheetPrimitive.Overlay, {
17
+ const SheetOverlay = React.forwardRef(({ className, asChild, children, ...props }, ref) => /* @__PURE__ */ jsx(SheetPrimitive.Overlay, {
16
18
  ref,
17
- className: cn("fixed inset-0 z-50 bg-black/40", "data-[state=closed]:animate-out data-[state=open]:animate-in", "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", className),
18
- ...props
19
+ className: cn("fixed inset-0 z-50 bg-black/40", surfaceMotion, className),
20
+ ...props,
21
+ asChild: true,
22
+ children: /* @__PURE__ */ jsx(SurfaceMotion, {
23
+ kind: "overlay",
24
+ asChild,
25
+ children
26
+ })
19
27
  }));
20
28
  SheetOverlay.displayName = SheetPrimitive.Overlay.displayName;
21
- const sheetVariants = cva([
22
- "fixed z-50 flex flex-col gap-4 border-border bg-card shadow-lg",
23
- "data-[state=closed]:animate-out data-[state=open]:animate-in",
24
- "data-[state=closed]:duration-200 data-[state=open]:duration-300 ease-out motion-reduce:animate-none"
25
- ], {
29
+ const sheetVariants = cva(["fixed z-50 flex flex-col gap-4 border-border bg-card shadow-lg", surfaceMotion], {
26
30
  variants: { side: {
27
- right: "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
28
- left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
29
- top: "inset-x-0 top-0 h-auto border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
30
- bottom: "inset-x-0 bottom-0 h-auto border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom"
31
+ right: "inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm",
32
+ left: "inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm",
33
+ top: "inset-x-0 top-0 h-auto border-b",
34
+ bottom: "inset-x-0 bottom-0 h-auto border-t"
31
35
  } },
32
36
  defaultVariants: { side: "right" }
33
37
  });
34
- const SheetContent = React.forwardRef(({ className, children, side = "right", hideCloseButton = false, ...props }, ref) => /* @__PURE__ */ jsxs(SheetPortal, { children: [/* @__PURE__ */ jsx(SheetOverlay, {}), /* @__PURE__ */ jsxs(SheetPrimitive.Content, {
38
+ const SheetContent = React.forwardRef(({ className, children, side = "right", hideCloseButton = false, asChild, ...props }, ref) => /* @__PURE__ */ jsxs(SheetPortal, { children: [/* @__PURE__ */ jsx(SheetOverlay, {}), /* @__PURE__ */ jsx(SheetPrimitive.Content, {
35
39
  ref,
36
40
  className: cn(sheetVariants({ side }), className),
37
41
  ...props,
38
- children: [children, !hideCloseButton && /* @__PURE__ */ jsxs(SheetPrimitive.Close, {
39
- className: cn("absolute top-4 right-4 rounded-sm text-muted-foreground opacity-70 transition-[opacity,box-shadow] hover:opacity-100 focus-visible:opacity-100 disabled:pointer-events-none", focusRing),
40
- children: [/* @__PURE__ */ jsx(X, { className: "size-4" }), /* @__PURE__ */ jsx("span", {
41
- className: "sr-only",
42
- children: "Close"
42
+ asChild: true,
43
+ children: /* @__PURE__ */ jsxs(SurfaceMotion, {
44
+ kind: "sheet",
45
+ side: side ?? "right",
46
+ asChild,
47
+ children: [children, !hideCloseButton && /* @__PURE__ */ jsxs(SheetPrimitive.Close, {
48
+ className: cn("absolute top-4 right-4 rounded-sm text-muted-foreground opacity-70 transition-[opacity,box-shadow] hover:opacity-100 focus-visible:opacity-100 disabled:pointer-events-none", "[transition:color_var(--motion-control),background-color_var(--motion-control),border-color_var(--motion-control),box-shadow_var(--motion-control),transform_var(--motion-control),scale_var(--motion-control),opacity_var(--motion-control)] motion-reduce:transition-none", focusRing),
49
+ children: [/* @__PURE__ */ jsx(X, { className: "size-4" }), /* @__PURE__ */ jsx("span", {
50
+ className: "sr-only",
51
+ children: "Close"
52
+ })]
43
53
  })]
44
- })]
54
+ })
45
55
  })] }));
46
56
  SheetContent.displayName = SheetPrimitive.Content.displayName;
47
57
  const SheetHeader = ({ className, ...props }) => /* @__PURE__ */ jsx("div", {
@@ -3,7 +3,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
3
3
  //#region src/primitives/skeleton.tsx
4
4
  function Skeleton({ className, ...props }) {
5
5
  return /* @__PURE__ */ jsx("div", {
6
- className: cn("animate-pulse rounded-lg bg-muted/50", className),
6
+ className: cn("animate-pulse motion-reduce:animate-none rounded-lg bg-muted/50", className),
7
7
  ...props
8
8
  });
9
9
  }
@@ -19,7 +19,7 @@ import * as React from "react";
19
19
  * that always brings its own background cannot be placed onto a plane that
20
20
  * breaks it.
21
21
  */
22
- export type StatusTone = "success" | "warning" | "danger" | "info" | "neutral" | "running";
22
+ export type StatusTone = "success" | "warning" | "danger" | "info" | "neutral" | "running" | "violet";
23
23
  export interface StatusPillProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, "children"> {
24
24
  tone: StatusTone;
25
25
  children: React.ReactNode;
@@ -37,6 +37,8 @@ export interface StatusPillProps extends Omit<React.HTMLAttributes<HTMLSpanEleme
37
37
  * For a control that supplies its own surface (a chip, a selected row).
38
38
  */
39
39
  bare?: boolean;
40
+ /** Decorative caller glyph; the visible text remains the accessible status. */
41
+ icon?: React.ReactNode;
40
42
  size?: "sm" | "md";
41
43
  }
42
44
  declare const StatusPill: React.ForwardRefExoticComponent<StatusPillProps & React.RefAttributes<HTMLSpanElement>>;
@@ -3,6 +3,7 @@ import * as React from "react";
3
3
  import { jsx, jsxs } from "react/jsx-runtime";
4
4
  //#region src/primitives/status-pill.tsx
5
5
  const TONE_SURFACE = {
6
+ violet: "bg-[var(--surface-violet-bg)] text-[var(--surface-violet-text)] border-[var(--surface-violet-border)]",
6
7
  success: "bg-[var(--surface-success-bg)] text-[var(--surface-success-text)] border-[var(--surface-success-border)]",
7
8
  warning: "bg-[var(--surface-warning-bg)] text-[var(--surface-warning-text)] border-[var(--surface-warning-border)]",
8
9
  danger: "bg-[var(--surface-danger-bg)] text-[var(--surface-danger-text)] border-[var(--surface-danger-border)]",
@@ -18,6 +19,7 @@ const TONE_SURFACE = {
18
19
  * has left — the glyph — with nothing to signal that it happened.
19
20
  */
20
21
  const TONE_TEXT = {
22
+ violet: "text-[var(--surface-violet-text)]",
21
23
  success: "text-[var(--surface-success-text)]",
22
24
  warning: "text-[var(--surface-warning-text)]",
23
25
  danger: "text-[var(--surface-danger-text)]",
@@ -35,6 +37,12 @@ function ToneGlyph({ tone }) {
35
37
  className: "size-2 shrink-0"
36
38
  };
37
39
  switch (tone) {
40
+ case "violet": return /* @__PURE__ */ jsx("svg", {
41
+ ...common,
42
+ "aria-hidden": "true",
43
+ fill: "currentColor",
44
+ children: /* @__PURE__ */ jsx("path", { d: "M4 .5 7.5 4 4 7.5 .5 4Z" })
45
+ });
38
46
  case "success": return /* @__PURE__ */ jsx("svg", {
39
47
  ...common,
40
48
  "aria-hidden": "true",
@@ -99,13 +107,14 @@ function ToneGlyph({ tone }) {
99
107
  });
100
108
  }
101
109
  }
102
- const StatusPill = React.forwardRef(({ className, tone, children, bare = false, size = "sm", ...props }, ref) => /* @__PURE__ */ jsxs("span", {
110
+ const StatusPill = React.forwardRef(({ className, tone, children, icon, bare = false, size = "sm", ...props }, ref) => /* @__PURE__ */ jsxs("span", {
103
111
  ref,
104
112
  className: cn("inline-flex items-center gap-1.5 whitespace-nowrap rounded-full font-medium", size === "sm" ? "px-2 py-0.5 text-xs" : "px-2.5 py-1 text-sm", bare ? "border border-transparent bg-transparent px-0" : cn("border", TONE_SURFACE[tone]), className),
105
113
  ...props,
106
114
  children: [/* @__PURE__ */ jsx("span", {
107
- className: cn("inline-flex", bare && TONE_TEXT[tone]),
108
- children: /* @__PURE__ */ jsx(ToneGlyph, { tone })
115
+ "aria-hidden": "true",
116
+ className: cn("inline-flex [&>svg]:size-3 [&>svg]:shrink-0", bare && TONE_TEXT[tone]),
117
+ children: icon ?? /* @__PURE__ */ jsx(ToneGlyph, { tone })
109
118
  }), children]
110
119
  }));
111
120
  StatusPill.displayName = "StatusPill";
@@ -1,61 +1,62 @@
1
1
  import { cn } from "../lib/utils.js";
2
+ import { tablePresentation } from "../presentation.js";
2
3
  import * as React from "react";
3
4
  import { jsx } from "react/jsx-runtime";
4
5
  //#region src/primitives/table.tsx
5
6
  const Table = React.forwardRef(({ className, wrapper = true, wrapperProps, ...props }, ref) => {
6
7
  const table = /* @__PURE__ */ jsx("table", {
7
8
  ref,
8
- className: cn("w-full caption-bottom text-sm", className),
9
+ className: cn(tablePresentation.root, className),
9
10
  ...props
10
11
  });
11
12
  if (!wrapper) return table;
12
13
  const { className: wrapperClassName, ...attributes } = wrapperProps ?? {};
13
14
  return /* @__PURE__ */ jsx("div", {
14
15
  ...attributes,
15
- className: cn("relative w-full overflow-auto", wrapperClassName),
16
+ className: cn(tablePresentation.wrapper, wrapperClassName),
16
17
  children: table
17
18
  });
18
19
  });
19
20
  Table.displayName = "Table";
20
21
  const TableHeader = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("thead", {
21
22
  ref,
22
- className: cn("[&_tr]:border-b", className),
23
+ className: cn(tablePresentation.head, className),
23
24
  ...props
24
25
  }));
25
26
  TableHeader.displayName = "TableHeader";
26
27
  const TableBody = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("tbody", {
27
28
  ref,
28
- className: cn("[&_tr:last-child]:border-0", className),
29
+ className: cn(tablePresentation.body, className),
29
30
  ...props
30
31
  }));
31
32
  TableBody.displayName = "TableBody";
32
33
  const TableFooter = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("tfoot", {
33
34
  ref,
34
- className: cn("border-t bg-card font-medium [&>tr]:last:border-b-0", className),
35
+ className: cn(tablePresentation.footer, className),
35
36
  ...props
36
37
  }));
37
38
  TableFooter.displayName = "TableFooter";
38
39
  const TableRow = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("tr", {
39
40
  ref,
40
- className: cn("border-border border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted/50", className),
41
+ className: cn(tablePresentation.row, className),
41
42
  ...props
42
43
  }));
43
44
  TableRow.displayName = "TableRow";
44
45
  const TableHead = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("th", {
45
46
  ref,
46
- className: cn("h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0", className),
47
+ className: cn(tablePresentation.columnHeader, className),
47
48
  ...props
48
49
  }));
49
50
  TableHead.displayName = "TableHead";
50
51
  const TableCell = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("td", {
51
52
  ref,
52
- className: cn("p-4 align-middle [&:has([role=checkbox])]:pr-0", className),
53
+ className: cn(tablePresentation.cell, className),
53
54
  ...props
54
55
  }));
55
56
  TableCell.displayName = "TableCell";
56
57
  const TableCaption = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("caption", {
57
58
  ref,
58
- className: cn("mt-4 text-muted-foreground text-sm", className),
59
+ className: cn(tablePresentation.caption, className),
59
60
  ...props
60
61
  }));
61
62
  TableCaption.displayName = "TableCaption";
@@ -1,6 +1,6 @@
1
- import { ixControlSoft, ixSelected, ixTabUnderline } from "../lib/interaction.js";
2
1
  import { focusRing } from "../lib/focus.js";
3
2
  import { cn } from "../lib/utils.js";
3
+ import { tabsPresentation } from "../presentation.js";
4
4
  import * as React from "react";
5
5
  import { jsx } from "react/jsx-runtime";
6
6
  import * as TabsPrimitive from "@radix-ui/react-tabs";
@@ -9,24 +9,15 @@ const Tabs = TabsPrimitive.Root;
9
9
  const TabsList = React.forwardRef(({ className, variant = "default", ...props }, ref) => {
10
10
  return /* @__PURE__ */ jsx(TabsPrimitive.List, {
11
11
  ref,
12
- className: cn({
13
- default: "inline-flex h-10 items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground",
14
- pills: "inline-flex items-center gap-2",
15
- underline: "inline-flex items-center gap-4 border-b border-border"
16
- }[variant], className),
12
+ className: cn(tabsPresentation.list[variant], className),
17
13
  ...props
18
14
  });
19
15
  });
20
16
  TabsList.displayName = TabsPrimitive.List.displayName;
21
17
  const TabsTrigger = React.forwardRef(({ className, variant = "default", ...props }, ref) => {
22
- const variants = {
23
- default: `inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1.5 text-sm font-medium transition-all ${focusRing} disabled:pointer-events-none disabled:opacity-50 ${ixControlSoft} ${ixSelected}`,
24
- pills: `inline-flex items-center justify-center whitespace-nowrap rounded-full px-4 py-2 text-sm font-medium transition-all ${focusRing} disabled:pointer-events-none disabled:opacity-50 data-[state=inactive]:text-muted-foreground ${ixControlSoft} ${ixSelected}`,
25
- underline: `inline-flex items-center justify-center whitespace-nowrap rounded-t-md pb-3 text-sm font-medium transition-all ${focusRing} disabled:pointer-events-none disabled:opacity-50 border-b-2 border-transparent data-[state=inactive]:text-muted-foreground ${ixTabUnderline}`
26
- };
27
18
  return /* @__PURE__ */ jsx(TabsPrimitive.Trigger, {
28
19
  ref,
29
- className: cn(variants[variant], className),
20
+ className: cn(tabsPresentation.trigger[variant], className),
30
21
  ...props
31
22
  });
32
23
  });
@@ -1,5 +1,7 @@
1
1
  "use client";
2
+ import { surfaceMotion } from "../lib/motion.js";
2
3
  import { cn } from "../lib/utils.js";
4
+ import { SurfaceMotion } from "../lib/surface-motion.js";
3
5
  import * as React from "react";
4
6
  import { jsx } from "react/jsx-runtime";
5
7
  import * as TooltipPrimitive from "@radix-ui/react-tooltip";
@@ -21,11 +23,17 @@ const TooltipTrigger = TooltipPrimitive.Trigger;
21
23
  * Inverse-surface label for a control whose name is otherwise only an icon.
22
24
  * It is supplementary: the trigger still needs its own accessible name.
23
25
  */
24
- const TooltipContent = React.forwardRef(({ className, sideOffset = 6, ...props }, ref) => /* @__PURE__ */ jsx(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsx(TooltipPrimitive.Content, {
26
+ const TooltipContent = React.forwardRef(({ className, sideOffset = 6, asChild, children, ...props }, ref) => /* @__PURE__ */ jsx(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsx(TooltipPrimitive.Content, {
25
27
  ref,
26
28
  sideOffset,
27
- className: cn("z-50 max-w-xs origin-(--radix-tooltip-content-transform-origin) rounded-md bg-foreground px-2.5 py-1.5 text-background text-xs leading-snug shadow-md", "data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95", "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95", "duration-150 ease-out motion-reduce:animate-none", className),
28
- ...props
29
+ className: cn("z-50 max-w-xs origin-(--radix-tooltip-content-transform-origin) rounded-md bg-foreground px-2.5 py-1.5 text-background text-xs leading-snug shadow-md", surfaceMotion, className),
30
+ ...props,
31
+ asChild: true,
32
+ children: /* @__PURE__ */ jsx(SurfaceMotion, {
33
+ kind: "tooltip",
34
+ asChild,
35
+ children
36
+ })
29
37
  }) }));
30
38
  TooltipContent.displayName = TooltipPrimitive.Content.displayName;
31
39
  //#endregion
@@ -1,4 +1,5 @@
1
- import { Button, ButtonProps, buttonVariants } from "./primitives/button.js";
1
+ import { buttonVariants } from "./presentation.js";
2
+ import { Button, ButtonProps } from "./primitives/button.js";
2
3
  import { ArtifactPane, ArtifactPaneProps } from "./primitives/artifact-pane.js";
3
4
  import { CATEGORY_TONES, CategoryTone, TONE_CLASSES, Tone, ToneClasses, toneFor } from "./primitives/tone.js";
4
5
  import { IconTile, IconTileProps, initialsOf } from "./primitives/icon-tile.js";
@@ -44,9 +45,9 @@ import { ThemeToggle, useTheme } from "./primitives/theme-toggle.js";
44
45
  import { Heading, HeadingProps, HeadingVariant } from "./primitives/heading.js";
45
46
  import { PageShell, PageShellProps } from "./primitives/page-shell.js";
46
47
  import { PageHeader, PageHeaderProps } from "./primitives/page-header.js";
47
- import { StatusPill, StatusPillProps, StatusTone } from "./primitives/status-pill.js";
48
48
  import { Alert, AlertDescription, AlertProps, AlertTitle, AlertTone } from "./primitives/alert.js";
49
49
  import { Pagination, PaginationProps } from "./primitives/pagination.js";
50
+ import { StatusPill, StatusPillProps, StatusTone } from "./primitives/status-pill.js";
50
51
  import { Tag, TagProps } from "./primitives/tag.js";
51
52
  import { Chip, ChipProps } from "./primitives/chip.js";
52
53
  import { Metric, MetricProps, MetricStrip, MetricStripProps } from "./primitives/metric-strip.js";
@@ -1,4 +1,5 @@
1
- import { Button, buttonVariants } from "./primitives/button.js";
1
+ import { buttonVariants } from "./presentation.js";
2
+ import { Button } from "./primitives/button.js";
2
3
  import { Heading } from "./primitives/heading.js";
3
4
  import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "./primitives/card.js";
4
5
  import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger } from "./primitives/dialog.js";
package/dist/utils.d.ts CHANGED
@@ -1,8 +1,8 @@
1
+ import { ixControl, ixControlAfter, ixControlSoft, ixField, ixRow, ixSelected, ixTabUnderline } from "./lib/interaction.js";
1
2
  import { copyText } from "./utils/copy-text.js";
2
3
  import { formatBytes, formatDuration, formatUptime, plainTextFromMarkdown, truncateText } from "./utils/format.js";
3
4
  import { timeAgo } from "./utils/time-ago.js";
4
5
  import { TOOL_CATEGORY_ICONS, getToolCategory, getToolDisplayMetadata, getToolErrorText } from "./utils/tool-display.js";
5
6
  import { cn } from "./lib/utils.js";
6
7
  import { focusField, focusFieldInvalid, focusFieldWithin, focusRing, focusRingInset } from "./lib/focus.js";
7
- import { ixControl, ixControlAfter, ixControlSoft, ixField, ixRow, ixSelected, ixTabUnderline } from "./lib/interaction.js";
8
8
  export { TOOL_CATEGORY_ICONS, cn, copyText, focusField, focusFieldInvalid, focusFieldWithin, focusRing, focusRingInset, formatBytes, formatDuration, formatUptime, getToolCategory, getToolDisplayMetadata, getToolErrorText, ixControl, ixControlAfter, ixControlSoft, ixField, ixRow, ixSelected, ixTabUnderline, plainTextFromMarkdown, timeAgo, truncateText };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/ui",
3
- "version": "11.35.0",
3
+ "version": "11.37.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",
@@ -13,7 +13,9 @@
13
13
  "url": "https://github.com/tangle-network/brand/issues"
14
14
  },
15
15
  "homepage": "https://github.com/tangle-network/brand",
16
- "sideEffects": false,
16
+ "sideEffects": [
17
+ "./src/styles/*.css"
18
+ ],
17
19
  "files": [
18
20
  "dist",
19
21
  "src",
@@ -111,7 +113,19 @@
111
113
  "types": "./dist/redaction.d.ts",
112
114
  "import": "./dist/redaction.js",
113
115
  "default": "./dist/redaction.js"
114
- }
116
+ },
117
+ "./presentation": {
118
+ "types": "./dist/presentation.d.ts",
119
+ "import": "./dist/presentation.js",
120
+ "default": "./dist/presentation.js"
121
+ },
122
+ "./styles/presentation.css": "./src/styles/presentation.css",
123
+ "./code-presentation": {
124
+ "types": "./dist/code-presentation.d.ts",
125
+ "import": "./dist/code-presentation.js",
126
+ "default": "./dist/code-presentation.js"
127
+ },
128
+ "./styles/compat.css": "./src/styles/compat.css"
115
129
  },
116
130
  "dependencies": {
117
131
  "@pierre/theme": "1.1.0",
@@ -139,6 +153,7 @@
139
153
  "github-slugger": "^2.0.0",
140
154
  "lucide-react": "^1.48.0",
141
155
  "marked": "^18.0.14",
156
+ "motion": "14.1.0",
142
157
  "react-markdown": "^10.1.0",
143
158
  "rehype-sanitize": "^6.0.0",
144
159
  "rehype-slug": "^6.0.0",
@@ -150,7 +165,7 @@
150
165
  "peerDependencies": {
151
166
  "@hocuspocus/provider": ">=2.15.0 <5.0.0",
152
167
  "@nanostores/react": ">=0.8.4 <3.0.0",
153
- "@tangle-network/brand": "^1.24.2",
168
+ "@tangle-network/brand": "^1.25.1",
154
169
  "@tiptap/core": ">=3.20.4 <4.0.0",
155
170
  "@tiptap/extension-collaboration": ">=3.20.4 <4.0.0",
156
171
  "@tiptap/extension-collaboration-caret": ">=3.7.0 <4.0.0",
@@ -228,7 +243,7 @@
228
243
  "design-system"
229
244
  ],
230
245
  "scripts": {
231
- "build": "node scripts/generate-openui-validators.mjs --check && tsdown && node ../../scripts/validate-dist.mjs && node scripts/probe-openui-worker.mjs",
246
+ "build": "node scripts/generate-openui-validators.mjs --check && tsdown && node scripts/generate-presentation-css.mjs --check && node ../../scripts/validate-dist.mjs && node scripts/probe-openui-worker.mjs",
232
247
  "gen:openui-schema": "node scripts/generate-openui-validators.mjs",
233
248
  "dev": "tsdown --watch"
234
249
  }
@@ -0,0 +1,2 @@
1
+ /** Framework-neutral highlighting, copy and tabs; no React runtime dependency. */
2
+ export { codeBlockGrammar, highlightCode, codePreStyle, codeTextStyle, codePresentation, bindCopyButton, bindCodeTabs, createCopyFeedback, interactionBudgets, writeClipboard, apiMetadataText, schemaRows, type CopyFeedback, type InteractionBudgets, type CodeExample, type ApiMetadata, type ApiField, type TokenStyle } from "./lib/code-presentation";