@ctrl-ui/react 0.9.5 → 0.9.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/README.md +2 -2
  2. package/dist/action-bar.js +16 -8
  3. package/dist/activity.d.ts +1 -1
  4. package/dist/activity.js +3 -1
  5. package/dist/audio-visualizer.js +1 -1
  6. package/dist/blocks/agent-run-clock.d.ts +5 -0
  7. package/dist/blocks/agent-run-clock.js +52 -0
  8. package/dist/blocks/agent-run-sidebar.d.ts +13 -0
  9. package/dist/blocks/agent-run-sidebar.js +100 -0
  10. package/dist/blocks/agent-run-status.d.ts +32 -0
  11. package/dist/blocks/agent-run-status.js +27 -0
  12. package/dist/blocks/agent-run.d.ts +80 -0
  13. package/dist/blocks/agent-run.js +254 -0
  14. package/dist/blocks/coding-agent.d.ts +1 -1
  15. package/dist/blocks/design-canvas-data.d.ts +1 -1
  16. package/dist/blocks/design-canvas.d.ts +2 -1
  17. package/dist/blocks/design-canvas.js +15 -8
  18. package/dist/chat-message.js +33 -39
  19. package/dist/knob-contracts/infinite-canvas-knobs.d.ts +1 -1
  20. package/dist/knob-contracts/infinite-canvas-knobs.js +1 -7
  21. package/dist/knob-contracts/swap-knobs.d.ts +4 -0
  22. package/dist/knob-contracts/swap-knobs.js +9 -0
  23. package/dist/knob-contracts/timeline-knobs.d.ts +1 -1
  24. package/dist/knob-contracts/timeline-knobs.js +1 -0
  25. package/dist/knob-contracts/tool-approval-knobs.d.ts +4 -0
  26. package/dist/knob-contracts/tool-approval-knobs.js +32 -0
  27. package/dist/lib/infinite-canvas-camera-store.d.ts +65 -0
  28. package/dist/lib/infinite-canvas-camera-store.js +233 -0
  29. package/dist/lib/infinite-canvas-camera.d.ts +33 -0
  30. package/dist/lib/infinite-canvas-camera.js +98 -0
  31. package/dist/lib/infinite-canvas-navigation.d.ts +19 -0
  32. package/dist/lib/infinite-canvas-navigation.js +395 -0
  33. package/dist/markdown-editor/bubble-menu.d.ts +6 -0
  34. package/dist/markdown-editor/bubble-menu.js +45 -0
  35. package/dist/markdown-editor/toolbar.d.ts +17 -1
  36. package/dist/markdown-editor/toolbar.js +103 -81
  37. package/dist/styles/index.css +10 -8
  38. package/dist/styles/recipes/activity.css +8 -0
  39. package/dist/styles/recipes/button-group.css +12 -6
  40. package/dist/styles/recipes/button.css +12 -2
  41. package/dist/styles/recipes/chat-message-edit.css +6 -21
  42. package/dist/styles/recipes/infinite-canvas.css +17 -57
  43. package/dist/styles/recipes/markdown-editor.css +12 -0
  44. package/dist/styles/recipes/swap.css +143 -0
  45. package/dist/styles/recipes/timeline.css +11 -0
  46. package/dist/styles/recipes/tool-approval.css +267 -0
  47. package/dist/styles/recipes/track-highlight.css +19 -6
  48. package/dist/styles/theme.css +6 -5
  49. package/dist/styles/type-scale.css +1 -1
  50. package/dist/tool-approval.d.ts +49 -0
  51. package/dist/tool-approval.js +260 -0
  52. package/dist/ui/code.js +13 -3
  53. package/dist/ui/command.js +1 -0
  54. package/dist/ui/infinite-canvas.d.ts +19 -22
  55. package/dist/ui/infinite-canvas.js +264 -325
  56. package/dist/ui/rich-tooltip.d.ts +2 -1
  57. package/dist/ui/rich-tooltip.js +32 -29
  58. package/dist/ui/swap.d.ts +14 -0
  59. package/dist/ui/swap.js +69 -0
  60. package/dist/ui/timeline.d.ts +1 -1
  61. package/dist/ui/timeline.js +1 -1
  62. package/dist/user-ask.js +1 -1
  63. package/lint/no-raw-type-classes.grit +2 -2
  64. package/package.json +2 -2
@@ -146,7 +146,7 @@ function useAnchorScroll(anchor, open, enabled) {
146
146
  ]);
147
147
  }
148
148
  const richTooltipContentSelector = "[data-control-ui=\"rich-tooltip\"][data-slot=\"content\"]";
149
- function RichTooltipContent({ className, children, side = "bottom", align = "center", sideOffset = 10, anchor, collisionPadding = 12, arrow = true, scrollAnchorIntoView = true, ...props }) {
149
+ function RichTooltipContent({ className, children, side = "bottom", align = "center", sideOffset = 10, anchor, collisionPadding = 12, arrow = true, scrollAnchorIntoView = true, container, ...props }) {
150
150
  const skin = useSkin();
151
151
  const { tone, inTour, nextRef, descriptionId, progressId } = useRichTooltipContext();
152
152
  const isSurface = tone === "surface";
@@ -159,42 +159,45 @@ function RichTooltipContent({ className, children, side = "bottom", align = "cen
159
159
  if (openedWithoutInteraction && focusIsElsewhere) return false;
160
160
  return inTour && nextRef.current ? nextRef.current : true;
161
161
  };
162
- return /* @__PURE__ */ jsx(Popover.Portal, { children: /* @__PURE__ */ jsx(Popover.Positioner, {
163
- "data-control-ui": "rich-tooltip",
164
- "data-popup-kind": "rich-tooltip",
165
- "data-control-family": "popup",
166
- "data-slot": "positioner",
167
- "data-skin": skin.id,
168
- "data-effects": controlEffectsAttribute(skin.effects),
169
- side,
170
- align,
171
- sideOffset,
172
- anchor,
173
- collisionPadding,
174
- className: "z-(--z-popup)",
175
- children: /* @__PURE__ */ jsxs(Popover.Popup, {
162
+ return /* @__PURE__ */ jsx(Popover.Portal, {
163
+ container,
164
+ children: /* @__PURE__ */ jsx(Popover.Positioner, {
176
165
  "data-control-ui": "rich-tooltip",
177
166
  "data-popup-kind": "rich-tooltip",
178
167
  "data-control-family": "popup",
179
- "data-slot": "content",
180
- "data-tone": tone,
181
- "data-surface": isSurface ? "floating" : void 0,
182
- "data-popup-part": isSurface ? "surface" : void 0,
183
- className: cn("relative grid w-80 max-w-[calc(100vw-2rem)]", className),
184
- initialFocus,
185
- "aria-describedby": describedBy,
186
- ...props,
187
- children: [children, arrow ? /* @__PURE__ */ jsx(Popover.Arrow, {
168
+ "data-slot": "positioner",
169
+ "data-skin": skin.id,
170
+ "data-effects": controlEffectsAttribute(skin.effects),
171
+ side,
172
+ align,
173
+ sideOffset,
174
+ anchor,
175
+ collisionPadding,
176
+ className: "z-(--z-popup)",
177
+ children: /* @__PURE__ */ jsxs(Popover.Popup, {
188
178
  "data-control-ui": "rich-tooltip",
189
179
  "data-popup-kind": "rich-tooltip",
190
180
  "data-control-family": "popup",
191
- "data-slot": "arrow",
181
+ "data-slot": "content",
192
182
  "data-tone": tone,
193
- className: "flex",
194
- children: /* @__PURE__ */ jsx(PopupArrowShape, {})
195
- }) : null]
183
+ "data-surface": isSurface ? "floating" : void 0,
184
+ "data-popup-part": isSurface ? "surface" : void 0,
185
+ className: cn("relative grid w-80 max-w-[calc(100vw-2rem)]", className),
186
+ initialFocus,
187
+ "aria-describedby": describedBy,
188
+ ...props,
189
+ children: [children, arrow ? /* @__PURE__ */ jsx(Popover.Arrow, {
190
+ "data-control-ui": "rich-tooltip",
191
+ "data-popup-kind": "rich-tooltip",
192
+ "data-control-family": "popup",
193
+ "data-slot": "arrow",
194
+ "data-tone": tone,
195
+ className: "flex",
196
+ children: /* @__PURE__ */ jsx(PopupArrowShape, {})
197
+ }) : null]
198
+ })
196
199
  })
197
- }) });
200
+ });
198
201
  }
199
202
  function RichTooltipMedia({ className, ...props }) {
200
203
  return /* @__PURE__ */ jsx("div", {
@@ -0,0 +1,14 @@
1
+ import { SwapKnobStyle } from "../knob-contracts/swap-knobs.js";
2
+ import { CSSProperties, ComponentProps } from "react";
3
+ //#region src/ui/swap.d.ts
4
+ export type SwapItemState = "active" | "exiting" | "inactive";
5
+ export type SwapProps = Omit<ComponentProps<"span">, "style"> & {
6
+ value: string;
7
+ style?: CSSProperties & SwapKnobStyle;
8
+ };
9
+ export declare function Swap({ value, children, ...props }: SwapProps): import("react").JSX.Element;
10
+ export type SwapItemProps = Omit<ComponentProps<"span">, "ref"> & {
11
+ value: string;
12
+ };
13
+ export declare function SwapItem({ value, children, ...props }: SwapItemProps): import("react").JSX.Element;
14
+ //#endregion
@@ -0,0 +1,69 @@
1
+ "use client";
2
+ import { Children, createContext, useContext, useState } from "react";
3
+ import { jsx } from "react/jsx-runtime";
4
+ //#region src/ui/swap.tsx
5
+ const SwapContext = createContext(null);
6
+ function useSwap() {
7
+ const context = useContext(SwapContext);
8
+ if (!context) throw new Error("SwapItem must be rendered inside <Swap>.");
9
+ return context;
10
+ }
11
+ function fitRootToItem(item) {
12
+ const root = item.parentElement;
13
+ if (!root) return;
14
+ const observer = new ResizeObserver(([entry]) => {
15
+ const [borderBox] = entry.borderBoxSize;
16
+ root.style.setProperty("--_swap-inline-size", `${borderBox.inlineSize}px`);
17
+ });
18
+ observer.observe(item);
19
+ return () => observer.disconnect();
20
+ }
21
+ function Swap({ value, children, ...props }) {
22
+ const [transition, setTransition] = useState({
23
+ value,
24
+ previous: null
25
+ });
26
+ if (transition.value !== value) setTransition({
27
+ value,
28
+ previous: transition.value
29
+ });
30
+ return /* @__PURE__ */ jsx(SwapContext.Provider, {
31
+ value: transition,
32
+ children: /* @__PURE__ */ jsx("span", {
33
+ "data-control-ui": "swap",
34
+ "data-control-family": "swap",
35
+ "data-slot": "root",
36
+ "data-swapped": transition.previous === null ? void 0 : "",
37
+ ...props,
38
+ children
39
+ })
40
+ });
41
+ }
42
+ function itemState({ value, previous }, itemValue) {
43
+ if (itemValue === value) return "active";
44
+ if (itemValue === previous) return "exiting";
45
+ return "inactive";
46
+ }
47
+ function wrapLabelText(children) {
48
+ return Children.map(children, (child) => typeof child === "string" || typeof child === "number" ? /* @__PURE__ */ jsx("span", {
49
+ "data-control-ui": "swap",
50
+ "data-control-family": "swap",
51
+ "data-slot": "label",
52
+ children: child
53
+ }) : child);
54
+ }
55
+ function SwapItem({ value, children, ...props }) {
56
+ const state = itemState(useSwap(), value);
57
+ return /* @__PURE__ */ jsx("span", {
58
+ "data-control-ui": "swap",
59
+ "data-control-family": "swap",
60
+ "data-slot": "item",
61
+ "data-state": state,
62
+ "aria-hidden": state === "active" ? void 0 : true,
63
+ ...props,
64
+ ref: state === "active" ? fitRootToItem : void 0,
65
+ children: wrapLabelText(children)
66
+ });
67
+ }
68
+ //#endregion
69
+ export { Swap, SwapItem };
@@ -2,7 +2,7 @@ import { RenderProp } from "../control-props.js";
2
2
  import { TimelineKnobStyle } from "../knob-contracts/timeline-knobs.js";
3
3
  import { CSSProperties, ComponentProps } from "react";
4
4
  //#region src/ui/timeline.d.ts
5
- export type TimelineState = "neutral" | "pending" | "running" | "success" | "error";
5
+ export type TimelineState = "neutral" | "pending" | "running" | "waiting" | "success" | "error";
6
6
  export type TimelineProps = ComponentProps<"ol"> & {
7
7
  style?: CSSProperties & TimelineKnobStyle;
8
8
  };
@@ -18,7 +18,7 @@ function TimelineItem({ state = "neutral", className, ...props }) {
18
18
  "data-control-family": "timeline",
19
19
  "data-slot": "item",
20
20
  "data-state": state,
21
- "aria-current": state === "running" ? "step" : void 0,
21
+ "aria-current": state === "running" || state === "waiting" ? "step" : void 0,
22
22
  ...props,
23
23
  className: cn("group/timeline-item relative grid min-w-0 grid-cols-[1rem_minmax(0,1fr)]", className)
24
24
  });
package/dist/user-ask.js CHANGED
@@ -2,8 +2,8 @@
2
2
  import { cn } from "./lib/cn.js";
3
3
  import { Button } from "./ui/button.js";
4
4
  import { LiveStatus } from "./ui/live-status.js";
5
- import { useUserAsk } from "./hooks/use-user-ask.js";
6
5
  import { Kbd } from "./ui/kbd.js";
6
+ import { useUserAsk } from "./hooks/use-user-ask.js";
7
7
  import { createContext, useContext, useEffect, useId, useRef } from "react";
8
8
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
9
9
  import { Check, ChevronLeft, ChevronRight, PencilLine } from "lucide-react";
@@ -2,6 +2,6 @@ language js(typescript, jsx)
2
2
 
3
3
  JsxAttribute(name=$name, initializer=$value) as $attr where {
4
4
  $name <: `className`,
5
- $value <: contains r".*\btext-(?:micro|caption|label|body|body-lg|heading-[1-4]|display)\b.*",
6
- register_diagnostic(span=$attr, message="Type rung in className: render text through <Text>/<Heading>, or size the control with its size prop or --cui-*-font-size knob.", severity="warn")
5
+ $value <: contains r".*(?:^|[^\w-])text-(?:micro|caption|label|body|body-lg|heading-[1-4]|display|xs|sm|base|lg|xl|[2-9]xl)\b.*|.*(?:^|[^\w-])text-\[\d[^\]]*\].*",
6
+ register_diagnostic(span=$attr, message="Text size in className: render text through <Text>/<Heading> on the type scale, or size the control with its size prop or --cui-*-font-size knob.", severity="error")
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ctrl-ui/react",
3
- "version": "0.9.5",
3
+ "version": "0.9.6",
4
4
  "description": "100+ React components for Tailwind CSS and shadcn/ui: pickers, trees, editors, canvases, app templates, and AI chat surfaces, with neutral defaults and consumer-owned themes.",
5
5
  "keywords": [
6
6
  "react",
@@ -53,7 +53,7 @@
53
53
  "lint": "biome lint ."
54
54
  },
55
55
  "peerDependencies": {
56
- "@base-ui/react": "^1.8.0",
56
+ "@base-ui/react": "^1.9.0",
57
57
  "@tanstack/charts": "^1.1.0",
58
58
  "@tanstack/react-virtual": "^3.14.13",
59
59
  "@tiptap/core": "3.31.4",