@ctrl-ui/react 0.9.5 → 0.9.8

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 (165) hide show
  1. package/README.md +38 -2
  2. package/dist/action-bar.js +16 -8
  3. package/dist/activity.d.ts +4 -2
  4. package/dist/activity.js +5 -2
  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 +101 -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 +82 -0
  13. package/dist/blocks/agent-run.js +262 -0
  14. package/dist/blocks/coding-agent.d.ts +1 -1
  15. package/dist/blocks/coding-agent.js +50 -69
  16. package/dist/blocks/design-canvas-data.d.ts +1 -1
  17. package/dist/blocks/design-canvas-inspector.js +1 -1
  18. package/dist/blocks/design-canvas.d.ts +2 -1
  19. package/dist/blocks/design-canvas.js +56 -42
  20. package/dist/blocks/discussion.js +1 -1
  21. package/dist/blocks/file-explorer.js +66 -47
  22. package/dist/blocks/settings.js +37 -41
  23. package/dist/blocks/team-chat.js +2 -1
  24. package/dist/blocks/theme-toggle.d.ts +2 -1
  25. package/dist/blocks/theme-toggle.js +13 -4
  26. package/dist/chat-message.js +33 -39
  27. package/dist/hooks/use-mobile.d.ts +1 -1
  28. package/dist/hooks/use-mobile.js +1 -1
  29. package/dist/knob-contracts/badge-knobs.d.ts +1 -1
  30. package/dist/knob-contracts/badge-knobs.js +3 -1
  31. package/dist/knob-contracts/button-knobs.d.ts +1 -1
  32. package/dist/knob-contracts/button-knobs.js +1 -0
  33. package/dist/knob-contracts/calendar-knobs.d.ts +1 -1
  34. package/dist/knob-contracts/calendar-knobs.js +9 -1
  35. package/dist/knob-contracts/card-knobs.d.ts +1 -1
  36. package/dist/knob-contracts/card-knobs.js +5 -1
  37. package/dist/knob-contracts/choice-knobs.d.ts +1 -1
  38. package/dist/knob-contracts/choice-knobs.js +1 -0
  39. package/dist/knob-contracts/collapsible-knobs.d.ts +1 -1
  40. package/dist/knob-contracts/collapsible-knobs.js +5 -1
  41. package/dist/knob-contracts/emoji-picker-knobs.d.ts +1 -1
  42. package/dist/knob-contracts/emoji-picker-knobs.js +3 -1
  43. package/dist/knob-contracts/field-knobs.d.ts +1 -1
  44. package/dist/knob-contracts/field-knobs.js +17 -1
  45. package/dist/knob-contracts/infinite-canvas-knobs.d.ts +1 -1
  46. package/dist/knob-contracts/infinite-canvas-knobs.js +1 -7
  47. package/dist/knob-contracts/item-knobs.d.ts +1 -1
  48. package/dist/knob-contracts/item-knobs.js +5 -1
  49. package/dist/knob-contracts/kbd-knobs.d.ts +1 -1
  50. package/dist/knob-contracts/kbd-knobs.js +4 -1
  51. package/dist/knob-contracts/page-layout-knobs.d.ts +1 -1
  52. package/dist/knob-contracts/page-layout-knobs.js +1 -0
  53. package/dist/knob-contracts/pagination-knobs.d.ts +1 -1
  54. package/dist/knob-contracts/pagination-knobs.js +2 -1
  55. package/dist/knob-contracts/popup-knobs.d.ts +1 -1
  56. package/dist/knob-contracts/popup-knobs.js +9 -0
  57. package/dist/knob-contracts/range-knobs.d.ts +1 -1
  58. package/dist/knob-contracts/range-knobs.js +2 -0
  59. package/dist/knob-contracts/sidebar-knobs.d.ts +1 -1
  60. package/dist/knob-contracts/sidebar-knobs.js +2 -0
  61. package/dist/knob-contracts/swap-knobs.d.ts +4 -0
  62. package/dist/knob-contracts/swap-knobs.js +9 -0
  63. package/dist/knob-contracts/tabs-knobs.d.ts +1 -1
  64. package/dist/knob-contracts/tabs-knobs.js +3 -0
  65. package/dist/knob-contracts/timeline-knobs.d.ts +1 -1
  66. package/dist/knob-contracts/timeline-knobs.js +5 -1
  67. package/dist/knob-contracts/tool-approval-knobs.d.ts +4 -0
  68. package/dist/knob-contracts/tool-approval-knobs.js +32 -0
  69. package/dist/knob-contracts/tree-knobs.d.ts +1 -1
  70. package/dist/knob-contracts/tree-knobs.js +3 -1
  71. package/dist/lib/infinite-canvas-camera-store.d.ts +65 -0
  72. package/dist/lib/infinite-canvas-camera-store.js +233 -0
  73. package/dist/lib/infinite-canvas-camera.d.ts +33 -0
  74. package/dist/lib/infinite-canvas-camera.js +98 -0
  75. package/dist/lib/infinite-canvas-navigation.d.ts +19 -0
  76. package/dist/lib/infinite-canvas-navigation.js +395 -0
  77. package/dist/markdown-editor/bubble-menu.d.ts +6 -0
  78. package/dist/markdown-editor/bubble-menu.js +45 -0
  79. package/dist/markdown-editor/toolbar.d.ts +17 -1
  80. package/dist/markdown-editor/toolbar.js +103 -81
  81. package/dist/skin.d.ts +2 -0
  82. package/dist/styles/index.css +11 -10
  83. package/dist/styles/recipes/activity.css +12 -0
  84. package/dist/styles/recipes/avatar.css +1 -1
  85. package/dist/styles/recipes/badge.css +17 -0
  86. package/dist/styles/recipes/button-group.css +12 -6
  87. package/dist/styles/recipes/button.css +20 -3
  88. package/dist/styles/recipes/calendar.css +82 -6
  89. package/dist/styles/recipes/card.css +40 -5
  90. package/dist/styles/recipes/chat-message-edit.css +6 -21
  91. package/dist/styles/recipes/choice.css +9 -2
  92. package/dist/styles/recipes/collapsible.css +8 -1
  93. package/dist/styles/recipes/color-picker-values.css +4 -0
  94. package/dist/styles/recipes/emoji-picker.css +29 -8
  95. package/dist/styles/recipes/field-parts.css +80 -5
  96. package/dist/styles/recipes/field.css +113 -40
  97. package/dist/styles/recipes/infinite-canvas.css +17 -57
  98. package/dist/styles/recipes/item.css +33 -5
  99. package/dist/styles/recipes/kbd.css +26 -6
  100. package/dist/styles/recipes/markdown-editor.css +12 -0
  101. package/dist/styles/recipes/morphing-panel.css +1 -1
  102. package/dist/styles/recipes/page-layout.css +18 -2
  103. package/dist/styles/recipes/pagination.css +8 -0
  104. package/dist/styles/recipes/popup-controls.css +9 -0
  105. package/dist/styles/recipes/popup-drawer.css +1 -0
  106. package/dist/styles/recipes/popup-lists.css +55 -6
  107. package/dist/styles/recipes/popup-motion.css +7 -1
  108. package/dist/styles/recipes/popup.css +10 -0
  109. package/dist/styles/recipes/range.css +16 -2
  110. package/dist/styles/recipes/sidebar-mobile.css +1 -1
  111. package/dist/styles/recipes/sidebar-parts.css +17 -1
  112. package/dist/styles/recipes/sidebar.css +11 -0
  113. package/dist/styles/recipes/swap.css +143 -0
  114. package/dist/styles/recipes/tabs.css +41 -8
  115. package/dist/styles/recipes/timeline.css +36 -2
  116. package/dist/styles/recipes/tool-approval.css +267 -0
  117. package/dist/styles/recipes/track-highlight.css +19 -6
  118. package/dist/styles/recipes/tree.css +33 -0
  119. package/dist/styles/theme.css +17 -6
  120. package/dist/tool-approval.d.ts +49 -0
  121. package/dist/tool-approval.js +260 -0
  122. package/dist/ui/alert-dialog.js +1 -1
  123. package/dist/ui/badge.js +1 -1
  124. package/dist/ui/calendar.js +9 -4
  125. package/dist/ui/card.d.ts +3 -1
  126. package/dist/ui/card.js +2 -1
  127. package/dist/ui/code.js +13 -3
  128. package/dist/ui/command.js +1 -0
  129. package/dist/ui/dialog.js +1 -1
  130. package/dist/ui/dropdown-menu.d.ts +1 -1
  131. package/dist/ui/dropdown-menu.js +23 -6
  132. package/dist/ui/dropzone.js +10 -11
  133. package/dist/ui/field.d.ts +6 -2
  134. package/dist/ui/field.js +4 -2
  135. package/dist/ui/infinite-canvas.d.ts +19 -22
  136. package/dist/ui/infinite-canvas.js +264 -325
  137. package/dist/ui/morphing-panel.d.ts +5 -1
  138. package/dist/ui/morphing-panel.js +4 -2
  139. package/dist/ui/rich-tooltip.d.ts +2 -1
  140. package/dist/ui/rich-tooltip.js +32 -29
  141. package/dist/ui/select.js +2 -2
  142. package/dist/ui/sidebar-mobile.js +1 -1
  143. package/dist/ui/sidebar-provider.d.ts +3 -1
  144. package/dist/ui/sidebar-provider.js +3 -2
  145. package/dist/ui/sidebar-resize-rail.js +1 -1
  146. package/dist/ui/sidebar.d.ts +6 -5
  147. package/dist/ui/sidebar.js +10 -9
  148. package/dist/ui/swap.d.ts +14 -0
  149. package/dist/ui/swap.js +69 -0
  150. package/dist/ui/tabs.d.ts +1 -1
  151. package/dist/ui/tabs.js +2 -13
  152. package/dist/ui/timeline.d.ts +1 -1
  153. package/dist/ui/timeline.js +2 -2
  154. package/dist/ui/typography.d.ts +11 -5
  155. package/dist/ui/typography.js +18 -6
  156. package/dist/user-ask.js +1 -1
  157. package/lint/biome-preset.json +3 -0
  158. package/lint/class-policy.mjs +17 -0
  159. package/lint/eslint-plugin.mjs +87 -0
  160. package/lint/grit-rules.mjs +40 -0
  161. package/lint/no-component-style-classes.grit +16 -0
  162. package/lint/no-raw-type-classes.grit +3 -4
  163. package/lint/write-grit-rules.mjs +19 -0
  164. package/package.json +12 -3
  165. package/dist/styles/type-scale.css +0 -72
@@ -0,0 +1,260 @@
1
+ "use client";
2
+ import { cn } from "./lib/cn.js";
3
+ import { Button } from "./ui/button.js";
4
+ import { LiveStatus } from "./ui/live-status.js";
5
+ import { Badge } from "./ui/badge.js";
6
+ import { Kbd } from "./ui/kbd.js";
7
+ import { createContext, useContext, useEffect, useId, useRef } from "react";
8
+ import { useRender } from "@base-ui/react/use-render";
9
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
10
+ import { Check, ShieldAlert, X } from "lucide-react";
11
+ //#region src/tool-approval.tsx
12
+ const ToolApprovalContext = createContext(null);
13
+ function useToolApprovalContext() {
14
+ const context = useContext(ToolApprovalContext);
15
+ if (!context) throw new Error("ToolApproval compound components must be rendered inside <ToolApproval>.");
16
+ return context;
17
+ }
18
+ const decisionAnnouncements = {
19
+ pending: "",
20
+ approved: "Action approved",
21
+ denied: "Action denied"
22
+ };
23
+ function ToolApproval({ state = "pending", risk = "medium", onApprove, onDeny, autoFocus = false, className, children, onKeyDown, ...props }) {
24
+ const titleId = useId();
25
+ const rootRef = useRef(null);
26
+ const isPending = state === "pending";
27
+ const approve = () => {
28
+ if (isPending) onApprove?.();
29
+ };
30
+ const deny = () => {
31
+ if (isPending) onDeny?.();
32
+ };
33
+ useEffect(() => {
34
+ if (autoFocus) rootRef.current?.focus();
35
+ }, [autoFocus]);
36
+ function handleKeyDown(event) {
37
+ onKeyDown?.(event);
38
+ if (event.defaultPrevented || !isPending || event.nativeEvent.isComposing) return;
39
+ if (event.key === "Escape") {
40
+ event.preventDefault();
41
+ deny();
42
+ return;
43
+ }
44
+ if (event.key === "Enter" && (event.metaKey || event.ctrlKey)) {
45
+ event.preventDefault();
46
+ approve();
47
+ }
48
+ }
49
+ return /* @__PURE__ */ jsx(ToolApprovalContext.Provider, {
50
+ value: {
51
+ state,
52
+ risk,
53
+ titleId,
54
+ approve,
55
+ deny
56
+ },
57
+ children: /* @__PURE__ */ jsxs("section", {
58
+ ref: rootRef,
59
+ "data-control-ui": "tool-approval",
60
+ "data-control-family": "tool-approval",
61
+ "data-slot": "root",
62
+ "data-state": state,
63
+ "data-risk": risk,
64
+ "aria-labelledby": titleId,
65
+ tabIndex: -1,
66
+ onKeyDown: handleKeyDown,
67
+ className: cn("relative w-full min-w-0", className),
68
+ ...props,
69
+ children: [children, /* @__PURE__ */ jsx(LiveStatus, { message: decisionAnnouncements[state] })]
70
+ })
71
+ });
72
+ }
73
+ function ToolApprovalBody({ className, ...props }) {
74
+ return /* @__PURE__ */ jsx("div", {
75
+ "data-control-ui": "tool-approval",
76
+ "data-control-family": "tool-approval",
77
+ "data-slot": "body",
78
+ className: cn("min-w-0", className),
79
+ ...props
80
+ });
81
+ }
82
+ function ToolApprovalHeader({ className, ...props }) {
83
+ return /* @__PURE__ */ jsx("div", {
84
+ "data-control-ui": "tool-approval",
85
+ "data-control-family": "tool-approval",
86
+ "data-slot": "header",
87
+ className: cn("flex items-start gap-2", className),
88
+ ...props
89
+ });
90
+ }
91
+ function ToolApprovalIcon({ className, children, ...props }) {
92
+ return /* @__PURE__ */ jsx("span", {
93
+ "data-control-ui": "tool-approval",
94
+ "data-control-family": "tool-approval",
95
+ "data-slot": "icon",
96
+ "aria-hidden": "true",
97
+ className: cn("inline-flex size-5 shrink-0 items-center justify-center [&_svg]:size-4", className),
98
+ ...props,
99
+ children: children ?? /* @__PURE__ */ jsx(ShieldAlert, {})
100
+ });
101
+ }
102
+ function ToolApprovalTitle({ render, className, ...props }) {
103
+ const { titleId } = useToolApprovalContext();
104
+ return useRender({
105
+ defaultTagName: "div",
106
+ render,
107
+ props: {
108
+ ...props,
109
+ id: titleId,
110
+ "data-control-ui": "tool-approval",
111
+ "data-control-family": "tool-approval",
112
+ "data-slot": "title",
113
+ className: cn("min-w-0 flex-1 font-medium", className)
114
+ }
115
+ });
116
+ }
117
+ const riskColors = {
118
+ low: "neutral",
119
+ medium: "yellow",
120
+ high: "red"
121
+ };
122
+ const riskLabels = {
123
+ low: "Low risk",
124
+ medium: "Medium risk",
125
+ high: "High risk"
126
+ };
127
+ function ToolApprovalRisk({ children, ...props }) {
128
+ const { state, risk } = useToolApprovalContext();
129
+ if (state !== "pending") return null;
130
+ return /* @__PURE__ */ jsx(Badge, {
131
+ "data-control-ui": "tool-approval",
132
+ "data-slot": "risk",
133
+ size: "sm",
134
+ color: riskColors[risk],
135
+ ...props,
136
+ children: children ?? riskLabels[risk]
137
+ });
138
+ }
139
+ const decisionLabels = {
140
+ approved: "Approved",
141
+ denied: "Denied"
142
+ };
143
+ function ToolApprovalStatus({ className, children, ...props }) {
144
+ const { state } = useToolApprovalContext();
145
+ if (state === "pending") return null;
146
+ const StatusIcon = state === "approved" ? Check : X;
147
+ return /* @__PURE__ */ jsxs("div", {
148
+ "data-control-ui": "tool-approval",
149
+ "data-control-family": "tool-approval",
150
+ "data-slot": "status",
151
+ className: cn("shrink-0", className),
152
+ ...props,
153
+ children: [/* @__PURE__ */ jsx("span", {
154
+ "data-control-ui": "tool-approval",
155
+ "data-control-family": "tool-approval",
156
+ "data-slot": "status-icon",
157
+ "aria-hidden": "true",
158
+ children: /* @__PURE__ */ jsx(StatusIcon, { className: "size-3.5" })
159
+ }), children ?? decisionLabels[state]]
160
+ });
161
+ }
162
+ function ToolApprovalDescription({ className, ...props }) {
163
+ const { state } = useToolApprovalContext();
164
+ if (state !== "pending") return null;
165
+ return /* @__PURE__ */ jsx("p", {
166
+ "data-control-ui": "tool-approval",
167
+ "data-control-family": "tool-approval",
168
+ "data-slot": "description",
169
+ className,
170
+ ...props
171
+ });
172
+ }
173
+ function ToolApprovalPreview({ className, ...props }) {
174
+ const { state } = useToolApprovalContext();
175
+ if (state !== "pending") return null;
176
+ return /* @__PURE__ */ jsx("dl", {
177
+ "data-control-ui": "tool-approval",
178
+ "data-control-family": "tool-approval",
179
+ "data-slot": "preview",
180
+ className: cn("min-w-0", className),
181
+ ...props
182
+ });
183
+ }
184
+ function ToolApprovalField({ label, children, className, ...props }) {
185
+ return /* @__PURE__ */ jsxs("div", {
186
+ "data-control-ui": "tool-approval",
187
+ "data-control-family": "tool-approval",
188
+ "data-slot": "field",
189
+ className,
190
+ ...props,
191
+ children: [/* @__PURE__ */ jsx("dt", {
192
+ "data-control-ui": "tool-approval",
193
+ "data-control-family": "tool-approval",
194
+ "data-slot": "field-label",
195
+ children: label
196
+ }), /* @__PURE__ */ jsx("dd", {
197
+ "data-control-ui": "tool-approval",
198
+ "data-control-family": "tool-approval",
199
+ "data-slot": "field-value",
200
+ className: "min-w-0 break-words",
201
+ children
202
+ })]
203
+ });
204
+ }
205
+ function ToolApprovalFooter({ className, ...props }) {
206
+ const { state } = useToolApprovalContext();
207
+ if (state !== "pending") return null;
208
+ return /* @__PURE__ */ jsx("div", {
209
+ "data-control-ui": "tool-approval",
210
+ "data-control-family": "tool-approval",
211
+ "data-slot": "footer",
212
+ className,
213
+ ...props
214
+ });
215
+ }
216
+ function ToolApprovalDeny({ children, onClick, ...props }) {
217
+ const { deny } = useToolApprovalContext();
218
+ function handleClick(event) {
219
+ onClick?.(event);
220
+ if (!event.defaultPrevented) deny();
221
+ }
222
+ return /* @__PURE__ */ jsx(Button, {
223
+ "data-control-ui": "tool-approval",
224
+ "data-slot": "deny",
225
+ type: "button",
226
+ variant: "quiet",
227
+ size: "xs",
228
+ "aria-keyshortcuts": "Escape",
229
+ onClick: handleClick,
230
+ ...props,
231
+ children: children ?? /* @__PURE__ */ jsxs(Fragment$1, { children: ["Deny", /* @__PURE__ */ jsx(Kbd, {
232
+ "aria-hidden": "true",
233
+ children: "Esc"
234
+ })] })
235
+ });
236
+ }
237
+ function ToolApprovalApprove({ children, onClick, ...props }) {
238
+ const { approve } = useToolApprovalContext();
239
+ function handleClick(event) {
240
+ onClick?.(event);
241
+ if (!event.defaultPrevented) approve();
242
+ }
243
+ return /* @__PURE__ */ jsx(Button, {
244
+ "data-control-ui": "tool-approval",
245
+ "data-slot": "approve",
246
+ type: "button",
247
+ variant: "solid",
248
+ tone: "primary",
249
+ size: "xs",
250
+ "aria-keyshortcuts": "Meta+Enter Control+Enter",
251
+ onClick: handleClick,
252
+ ...props,
253
+ children: children ?? /* @__PURE__ */ jsxs(Fragment$1, { children: ["Approve", /* @__PURE__ */ jsx(Kbd, {
254
+ "aria-hidden": "true",
255
+ children: "⌘⏎"
256
+ })] })
257
+ });
258
+ }
259
+ //#endregion
260
+ export { ToolApproval, ToolApprovalApprove, ToolApprovalBody, ToolApprovalDeny, ToolApprovalDescription, ToolApprovalField, ToolApprovalFooter, ToolApprovalHeader, ToolApprovalIcon, ToolApprovalPreview, ToolApprovalRisk, ToolApprovalStatus, ToolApprovalTitle };
@@ -53,7 +53,7 @@ function AlertDialogContent({ className, children, ...props }) {
53
53
  "data-control-family": "popup",
54
54
  "data-popup-part": "surface",
55
55
  "data-surface": "modal",
56
- className: cn("fixed left-1/2 top-[12vh] z-(--z-modal) grid w-[calc(100%-2rem)] max-w-md -translate-x-1/2", className),
56
+ className: cn("fixed left-1/2 top-[12vh] z-(--z-modal) grid w-[calc(100%-2rem)] -translate-x-1/2", className),
57
57
  ...props,
58
58
  children
59
59
  })] });
package/dist/ui/badge.js CHANGED
@@ -27,7 +27,7 @@ function Badge({ variant = "default", size = "md", color, render, className, chi
27
27
  "data-variant": variant,
28
28
  "data-size": size,
29
29
  "data-color": resolvedColor,
30
- className: cn("inline-flex w-fit shrink-0 items-center justify-center overflow-hidden whitespace-nowrap border font-medium [&>svg]:pointer-events-none [&>svg]:size-3", className),
30
+ className: cn("inline-flex w-fit shrink-0 items-center justify-center overflow-hidden whitespace-nowrap [&>svg]:pointer-events-none [&>svg]:size-3", className),
31
31
  children
32
32
  }
33
33
  });
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
  import { cn } from "../lib/cn.js";
3
+ import { useSkin } from "../skin-provider.js";
3
4
  import { useEffect, useRef } from "react";
4
5
  import { jsx } from "react/jsx-runtime";
5
6
  import { CaptionLabel, Day, DayPicker, Month, MonthCaption, MonthGrid, Months, Nav, Weekday } from "react-day-picker";
@@ -12,7 +13,8 @@ const chevronPathByOrientation = {
12
13
  up: "M3 10 8 5.5 13 10",
13
14
  down: "M3 6 8 10.5 13 6"
14
15
  };
15
- function Calendar({ className, showOutsideDays = true, style, ...props }) {
16
+ function Calendar({ className, showOutsideDays, style, ...props }) {
17
+ const skin = useSkin();
16
18
  return /* @__PURE__ */ jsx("div", {
17
19
  "data-control-ui": "calendar",
18
20
  "data-control-family": "calendar",
@@ -20,7 +22,7 @@ function Calendar({ className, showOutsideDays = true, style, ...props }) {
20
22
  className: cn("w-fit", className),
21
23
  style,
22
24
  children: /* @__PURE__ */ jsx(DayPicker, {
23
- showOutsideDays,
25
+ showOutsideDays: showOutsideDays ?? skin.calendarShowOutsideDays ?? true,
24
26
  components: {
25
27
  Chevron: CalendarChevron,
26
28
  Months: CalendarMonths,
@@ -111,12 +113,15 @@ function CalendarWeekday({ className, ...props }) {
111
113
  ...props
112
114
  });
113
115
  }
114
- function CalendarDay({ className, ...props }) {
116
+ function CalendarDay({ className, day, ...props }) {
117
+ const dayOfWeek = day.date.getDay();
115
118
  return /* @__PURE__ */ jsx(Day, {
116
119
  "data-control-ui": "calendar",
117
120
  "data-control-family": "calendar",
118
121
  "data-slot": "day-cell",
119
- className: cn("p-0 align-middle", className),
122
+ "data-weekend": dayOfWeek === 0 || dayOfWeek === 6 ? true : void 0,
123
+ className: cn("align-middle", className),
124
+ day,
120
125
  ...props
121
126
  });
122
127
  }
package/dist/ui/card.d.ts CHANGED
@@ -3,10 +3,12 @@ import { CardKnobStyle } from "../knob-contracts/card-knobs.js";
3
3
  import { CSSProperties, ComponentProps } from "react";
4
4
  //#region src/ui/card.d.ts
5
5
  export type CardVariant = "default" | "sectioned";
6
+ export type CardSize = "default" | "sm";
6
7
  export type CardProps = Omit<ComponentProps<"div">, "style"> & {
7
8
  style?: CSSProperties & CardKnobStyle;
8
9
  } & {
9
10
  variant?: CardVariant;
11
+ size?: CardSize;
10
12
  };
11
13
  export type CardHeaderProps = ComponentProps<"div"> & {
12
14
  style?: CSSProperties & CardKnobStyle;
@@ -27,7 +29,7 @@ export type CardContentProps = ComponentProps<"div"> & {
27
29
  export type CardFooterProps = ComponentProps<"div"> & {
28
30
  style?: CSSProperties & CardKnobStyle;
29
31
  };
30
- export declare function Card({ variant, className, ...props }: CardProps): import("react").JSX.Element;
32
+ export declare function Card({ variant, size, className, ...props }: CardProps): import("react").JSX.Element;
31
33
  export declare function CardHeader({ className, ...props }: CardHeaderProps): import("react").JSX.Element;
32
34
  export declare function CardTitle({ render, ...props }: CardTitleProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
33
35
  export declare function CardDescription({ className, ...props }: CardDescriptionProps): import("react").JSX.Element;
package/dist/ui/card.js CHANGED
@@ -3,13 +3,14 @@ import { cn } from "../lib/cn.js";
3
3
  import { useRender } from "@base-ui/react/use-render";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  //#region src/ui/card.tsx
6
- function Card({ variant = "default", className, ...props }) {
6
+ function Card({ variant = "default", size = "default", className, ...props }) {
7
7
  return /* @__PURE__ */ jsx("div", {
8
8
  "data-control-ui": "card",
9
9
  "data-control-family": "card",
10
10
  "data-slot": "root",
11
11
  "data-surface": "panel",
12
12
  "data-variant": variant,
13
+ "data-size": size,
13
14
  className: cn("flex flex-col", className),
14
15
  ...props
15
16
  });
package/dist/ui/code.js CHANGED
@@ -3,6 +3,7 @@ import { useCopyToClipboard } from "../hooks/use-copy-to-clipboard.js";
3
3
  import { cn } from "../lib/cn.js";
4
4
  import { Button } from "./button.js";
5
5
  import { LiveStatus } from "./live-status.js";
6
+ import { Swap, SwapItem } from "./swap.js";
6
7
  import { ScrollArea } from "./scroll-area.js";
7
8
  import { highlightToTokens } from "../lib/code-tokens.js";
8
9
  import { Tooltip, TooltipContent, TooltipTrigger } from "./tooltip.js";
@@ -99,9 +100,18 @@ function CodeCopy({ value, copiedLabel, copiedAriaLabel = "Copied to clipboard",
99
100
  className,
100
101
  ...props,
101
102
  onClick: handleCopy,
102
- children: status === "copied" ? copied : children ?? /* @__PURE__ */ jsx(CopyIcon, {
103
- "aria-hidden": "true",
104
- className: "size-3.5"
103
+ children: /* @__PURE__ */ jsxs(Swap, {
104
+ value: status === "copied" ? "copied" : "idle",
105
+ children: [/* @__PURE__ */ jsx(SwapItem, {
106
+ value: "idle",
107
+ children: children ?? /* @__PURE__ */ jsx(CopyIcon, {
108
+ "aria-hidden": "true",
109
+ className: "size-3.5"
110
+ })
111
+ }), /* @__PURE__ */ jsx(SwapItem, {
112
+ value: "copied",
113
+ children: copied
114
+ })]
105
115
  })
106
116
  });
107
117
  if (!isIconOnly) return /* @__PURE__ */ jsxs(Fragment$1, { children: [button, liveStatus] });
@@ -61,6 +61,7 @@ function CommandInput({ className, ...props }) {
61
61
  "data-slot": "input-wrapper",
62
62
  "data-control-family": "popup",
63
63
  "data-control": "true",
64
+ "data-focus-ring": "none",
64
65
  "data-size": "lg",
65
66
  className: "flex items-center",
66
67
  children: [/* @__PURE__ */ jsxs("svg", {
package/dist/ui/dialog.js CHANGED
@@ -54,7 +54,7 @@ function DialogContent({ className, children, showCloseButton = true, closeLabel
54
54
  "data-control-family": "popup",
55
55
  "data-popup-part": "surface",
56
56
  "data-surface": "modal",
57
- className: cn("fixed left-1/2 top-[12vh] z-(--z-modal) grid w-[calc(100%-2rem)] max-w-lg -translate-x-1/2", className),
57
+ className: cn("fixed left-1/2 top-[12vh] z-(--z-modal) grid w-[calc(100%-2rem)] -translate-x-1/2", className),
58
58
  ...props,
59
59
  children: [
60
60
  skinAdornment(skin, "dialog", "titlebar", {}),
@@ -35,7 +35,7 @@ export type DropdownMenuLabelProps = Omit<ComponentProps<"div">, "style"> & {
35
35
  style?: CSSProperties & PopupKnobStyle;
36
36
  };
37
37
  export declare function DropdownMenu({ children, ...props }: DropdownMenuProps): import("react").JSX.Element;
38
- export declare function DropdownMenuTrigger({ size, iconOnly, variant, className, children, disabled, ...props }: DropdownMenuTriggerProps): import("react").JSX.Element;
38
+ export declare function DropdownMenuTrigger({ size, iconOnly, variant, className, ...props }: DropdownMenuTriggerProps): import("react").JSX.Element;
39
39
  export declare function DropdownMenuContent({ className, children, side, sideOffset, align, alignOffset, collisionBoundary, collisionPadding, collisionAvoidance, ...props }: DropdownMenuContentProps): import("react").JSX.Element;
40
40
  export declare function DropdownMenuItem({ className, ...props }: DropdownMenuItemProps): import("react").JSX.Element;
41
41
  export declare function DropdownMenuSeparator({ className, ...props }: DropdownMenuSeparatorProps): import("react").JSX.Element;
@@ -4,6 +4,7 @@ import { controlEffectsAttribute } from "../skin.js";
4
4
  import { useSkin } from "../skin-provider.js";
5
5
  import { popupItemFocusProps } from "../lib/popup-item-focus.js";
6
6
  import { popupItemStructureClasses } from "../surface-variants.js";
7
+ import { isValidElement } from "react";
7
8
  import { jsx, jsxs } from "react/jsx-runtime";
8
9
  import { mergeProps } from "@base-ui/react/merge-props";
9
10
  import { Menu } from "@base-ui/react/menu";
@@ -15,21 +16,37 @@ function DropdownMenu({ children, ...props }) {
15
16
  children
16
17
  });
17
18
  }
18
- function DropdownMenuTrigger({ size = "sm", iconOnly = false, variant = "surface", className, children, disabled, ...props }) {
19
+ function explicitAppearance({ size, variant, iconOnly }) {
20
+ const attributes = {};
21
+ if (size) attributes["data-size"] = size;
22
+ if (variant) attributes["data-variant"] = variant;
23
+ if (iconOnly) attributes["data-icon-only"] = "true";
24
+ return attributes;
25
+ }
26
+ function DropdownMenuTrigger({ size, iconOnly, variant, className, ...props }) {
27
+ if (props.render !== void 0 && !(isValidElement(props.render) && typeof props.render.type === "string")) return /* @__PURE__ */ jsx(Menu.Trigger, {
28
+ "data-control-ui": "dropdown-menu",
29
+ "data-slot": "trigger",
30
+ ...explicitAppearance({
31
+ size,
32
+ variant,
33
+ iconOnly
34
+ }),
35
+ className,
36
+ ...props
37
+ });
19
38
  return /* @__PURE__ */ jsx(Menu.Trigger, {
20
39
  "data-control-ui": "dropdown-menu",
21
40
  "data-control-family": "button",
22
41
  "data-slot": "trigger",
23
42
  "data-control": "true",
24
- "data-size": size,
43
+ "data-size": size ?? "sm",
25
44
  "data-icon-only": iconOnly ? "true" : void 0,
26
- "data-variant": variant,
45
+ "data-variant": variant ?? "surface",
27
46
  "data-tone": "neutral",
28
47
  "data-shape": "default",
29
48
  className: cn("relative isolate inline-flex shrink-0 items-center justify-center overflow-visible", className),
30
- disabled,
31
- ...props,
32
- children
49
+ ...props
33
50
  });
34
51
  }
35
52
  function DropdownMenuContent({ className, children, side, sideOffset = 6, align = "start", alignOffset, collisionBoundary, collisionPadding, collisionAvoidance, ...props }) {
@@ -1,12 +1,12 @@
1
1
  "use client";
2
2
  import { cn } from "../lib/cn.js";
3
3
  import { Button } from "./button.js";
4
+ import { Item, ItemActions, ItemContent, ItemDescription, ItemMedia, ItemTitle } from "./item.js";
4
5
  import { DropzoneErrorCode, formatDropzoneFileSize } from "../lib/dropzone-validation.js";
5
6
  import { useDropzone } from "../hooks/use-dropzone.js";
6
- import { Item, ItemActions, ItemContent, ItemDescription, ItemMedia, ItemTitle } from "./item.js";
7
7
  import { createContext, useContext, useEffect, useState } from "react";
8
8
  import { jsx, jsxs } from "react/jsx-runtime";
9
- import { CircleAlert, CloudUpload, FileIcon, LoaderCircle, Search, XIcon } from "lucide-react";
9
+ import { CircleAlertIcon, CloudUpload, FileIcon, LoaderCircle, Search, XIcon } from "lucide-react";
10
10
  //#region src/ui/dropzone.tsx
11
11
  const DropzoneContext = createContext(null);
12
12
  const DropzoneFocusContext = createContext(null);
@@ -300,7 +300,7 @@ function DropzoneFeedback({ state }) {
300
300
  icon = /* @__PURE__ */ jsx(CloudUpload, { "aria-hidden": "true" });
301
301
  message = "Release to add files.";
302
302
  } else if (state === "reject") {
303
- icon = /* @__PURE__ */ jsx(CircleAlert, { "aria-hidden": "true" });
303
+ icon = /* @__PURE__ */ jsx(CircleAlertIcon, { "aria-hidden": "true" });
304
304
  message = "Some files are not accepted.";
305
305
  } else if (state === "unknown") {
306
306
  icon = /* @__PURE__ */ jsx(Search, { "aria-hidden": "true" });
@@ -341,19 +341,18 @@ function DefaultFile({ file }) {
341
341
  ]
342
342
  });
343
343
  }
344
+ const rejectedItemStyle = {
345
+ "--cui-item-media-foreground": "var(--destructive-text)",
346
+ "--cui-item-description-foreground": "var(--destructive-text)"
347
+ };
344
348
  function DefaultRejection({ rejection }) {
345
349
  return /* @__PURE__ */ jsxs(Item, {
346
350
  variant: "muted",
347
- children: [/* @__PURE__ */ jsx(ItemMedia, {
348
- "data-dropzone-invalid": "",
349
- children: /* @__PURE__ */ jsx(CircleAlert, { "aria-hidden": "true" })
350
- }), /* @__PURE__ */ jsxs(ItemContent, { children: [/* @__PURE__ */ jsx(ItemTitle, {
351
+ style: rejectedItemStyle,
352
+ children: [/* @__PURE__ */ jsx(ItemMedia, { children: /* @__PURE__ */ jsx(CircleAlertIcon, { "aria-hidden": "true" }) }), /* @__PURE__ */ jsxs(ItemContent, { children: [/* @__PURE__ */ jsx(ItemTitle, {
351
353
  className: "wrap-anywhere",
352
354
  children: rejection.file.name
353
- }), rejection.errors.map((error) => /* @__PURE__ */ jsx(ItemDescription, {
354
- "data-dropzone-invalid": "",
355
- children: error.message
356
- }, `${error.code}-${error.message}`))] })]
355
+ }), rejection.errors.map((error) => /* @__PURE__ */ jsx(ItemDescription, { children: error.message }, `${error.code}-${error.message}`))] })]
357
356
  });
358
357
  }
359
358
  function getDropzoneStatusMessage(context) {
@@ -31,7 +31,9 @@ export type FieldErrorProps = Omit<ComponentProps<"div">, "style"> & {
31
31
  match?: FieldErrorMatch;
32
32
  style?: CSSProperties & FieldKnobStyle;
33
33
  };
34
+ export type FieldGroupVariant = "default" | "card";
34
35
  export type FieldGroupProps = ComponentProps<"div"> & {
36
+ variant?: FieldGroupVariant;
35
37
  style?: CSSProperties & FieldKnobStyle;
36
38
  };
37
39
  export type FieldSeparatorProps = Omit<ComponentProps<"div">, "style"> & {
@@ -44,7 +46,9 @@ export type FieldItemProps = ComponentProps<"div"> & {
44
46
  export type FieldSetProps = Omit<ComponentProps<"fieldset">, "style"> & {
45
47
  style?: CSSProperties & FieldKnobStyle;
46
48
  };
49
+ export type FieldLegendVariant = "default" | "section";
47
50
  export type FieldLegendProps = Omit<ComponentProps<"div">, "style"> & {
51
+ variant?: FieldLegendVariant;
48
52
  style?: CSSProperties & FieldKnobStyle;
49
53
  };
50
54
  export declare function Field({ className, orientation, ...props }: FieldProps): import("react").JSX.Element;
@@ -55,9 +59,9 @@ type RefinedFieldControlProps = FieldControlProps & Pick<ComponentProps<typeof F
55
59
  export declare function FieldControl({ className, render, ...props }: RefinedFieldControlProps): import("react").JSX.Element;
56
60
  export declare function FieldDescription({ className, ...props }: FieldDescriptionProps): import("react").JSX.Element;
57
61
  export declare function FieldError({ className, ...props }: FieldErrorProps): import("react").JSX.Element;
58
- export declare function FieldGroup({ className, ...props }: FieldGroupProps): import("react").JSX.Element;
62
+ export declare function FieldGroup({ className, variant, ...props }: FieldGroupProps): import("react").JSX.Element;
59
63
  export declare function FieldSeparator({ children, className, ...props }: FieldSeparatorProps): import("react").JSX.Element;
60
64
  export declare function FieldItem({ className, ...props }: FieldItemProps): import("react").JSX.Element;
61
65
  export declare function FieldSet({ className, ...props }: FieldSetProps): import("react").JSX.Element;
62
- export declare function FieldLegend({ className, ...props }: FieldLegendProps): import("react").JSX.Element;
66
+ export declare function FieldLegend({ className, variant, ...props }: FieldLegendProps): import("react").JSX.Element;
63
67
  //#endregion
package/dist/ui/field.js CHANGED
@@ -103,12 +103,13 @@ function FieldError({ className, ...props }) {
103
103
  })
104
104
  });
105
105
  }
106
- function FieldGroup({ className, ...props }) {
106
+ function FieldGroup({ className, variant = "default", ...props }) {
107
107
  return /* @__PURE__ */ jsx("div", {
108
108
  "data-control-ui": "field",
109
109
  "data-control-family": "field",
110
110
  "data-field-kind": "field",
111
111
  "data-slot": "group",
112
+ "data-variant": variant,
112
113
  className: cn("group/field-group @container/field-group flex flex-col", className),
113
114
  ...props
114
115
  });
@@ -152,12 +153,13 @@ function FieldSet({ className, ...props }) {
152
153
  ...props
153
154
  });
154
155
  }
155
- function FieldLegend({ className, ...props }) {
156
+ function FieldLegend({ className, variant = "default", ...props }) {
156
157
  return /* @__PURE__ */ jsx(Fieldset.Legend, {
157
158
  "data-control-ui": "field",
158
159
  "data-control-family": "field",
159
160
  "data-field-kind": "field",
160
161
  "data-slot": "legend",
162
+ "data-variant": variant,
161
163
  className,
162
164
  ...props
163
165
  });
@@ -1,31 +1,24 @@
1
+ import { Button } from "./button.js";
1
2
  import { InfiniteCanvasKnobStyle } from "../knob-contracts/infinite-canvas-knobs.js";
3
+ import { InfiniteCanvasBounds, InfiniteCanvasPoint, InfiniteCanvasTransform } from "../lib/infinite-canvas-camera.js";
4
+ import { InfiniteCanvasCamera, InfiniteCanvasFitOptions, InfiniteCanvasMoveDetails, InfiniteCanvasMoveOptions, InfiniteCanvasMoveReason, InfiniteCanvasRevealOptions, InfiniteCanvasTransformUpdate, InfiniteCanvasZoomOptions } from "../lib/infinite-canvas-camera-store.js";
5
+ import { InfiniteCanvasPanOnDrag } from "../lib/infinite-canvas-navigation.js";
2
6
  import { CSSProperties, ComponentProps } from "react";
3
7
  //#region src/ui/infinite-canvas.d.ts
4
- export type InfiniteCanvasTransform = {
5
- x: number;
6
- y: number;
7
- scale: number;
8
- };
9
- export type InfiniteCanvasMoveReason = "pointer" | "wheel" | "keyboard" | "control";
10
- export type InfiniteCanvasMoveDetails = {
11
- reason: InfiniteCanvasMoveReason;
12
- };
13
- export type InfiniteCanvasProps = Omit<ComponentProps<"section">, "onChange" | "onWheel" | "ref" | "style"> & {
8
+ export type InfiniteCanvasProps = Omit<ComponentProps<"section">, "onChange" | "onWheel" | "style"> & {
14
9
  transform?: InfiniteCanvasTransform;
15
10
  defaultTransform?: InfiniteCanvasTransform;
16
11
  onTransformChange?: (transform: InfiniteCanvasTransform, details: InfiniteCanvasMoveDetails) => void;
17
12
  minScale?: number;
18
13
  maxScale?: number;
14
+ panOnDrag?: InfiniteCanvasPanOnDrag;
15
+ keyboardNavigation?: boolean;
19
16
  onWheel?: (event: WheelEvent) => void;
20
17
  style?: CSSProperties & InfiniteCanvasKnobStyle;
21
18
  };
22
- export type InfiniteCanvasContentProps = ComponentProps<"div"> & {
19
+ export type InfiniteCanvasContentProps = Omit<ComponentProps<"div">, "ref" | "style"> & {
23
20
  style?: CSSProperties & InfiniteCanvasKnobStyle;
24
21
  };
25
- export type InfiniteCanvasPoint = {
26
- x: number;
27
- y: number;
28
- };
29
22
  export type InfiniteCanvasItemProps = Omit<ComponentProps<"div">, "style"> & {
30
23
  x: number;
31
24
  y: number;
@@ -33,19 +26,23 @@ export type InfiniteCanvasItemProps = Omit<ComponentProps<"div">, "style"> & {
33
26
  movableItemLabel?: string;
34
27
  style?: CSSProperties & InfiniteCanvasKnobStyle;
35
28
  };
29
+ export type InfiniteCanvasItemHandleProps = ComponentProps<typeof Button> & {
30
+ onPositionChange: (position: InfiniteCanvasPoint) => void;
31
+ };
36
32
  export type InfiniteCanvasControlsProps = Omit<ComponentProps<"div">, "children" | "style"> & {
37
33
  style?: CSSProperties & InfiniteCanvasKnobStyle;
38
34
  };
39
- type InfiniteCanvasContextValue = {
40
- transform: InfiniteCanvasTransform;
35
+ export type InfiniteCanvasContextValue = InfiniteCanvasCamera & {
41
36
  minScale: number;
42
37
  maxScale: number;
43
- reset: (reason: InfiniteCanvasMoveReason) => void;
44
- zoomBy: (factor: number, reason: InfiniteCanvasMoveReason) => void;
45
38
  };
46
39
  export declare function useInfiniteCanvas(): InfiniteCanvasContextValue;
47
- export declare function InfiniteCanvas({ transform: controlledTransform, defaultTransform, onTransformChange, minScale: minScaleProp, maxScale: maxScaleProp, className, children, style, onPointerDown, onPointerMove, onPointerUp, onPointerCancel, onWheel, onKeyDown, "aria-label": ariaLabel, "aria-keyshortcuts": ariaKeyShortcuts, ...props }: InfiniteCanvasProps): import("react").JSX.Element;
40
+ export declare function useInfiniteCanvasTransform(): InfiniteCanvasTransform;
41
+ export declare function useInfiniteCanvasTransform<Selected>(select: (transform: InfiniteCanvasTransform) => Selected): Selected;
42
+ export declare function InfiniteCanvas({ transform, defaultTransform, onTransformChange, minScale: minScaleProp, maxScale: maxScaleProp, panOnDrag, keyboardNavigation, ref, className, children, style, onPointerDown, onWheel, onKeyDown, "aria-label": ariaLabel, "aria-keyshortcuts": ariaKeyShortcuts, ...props }: InfiniteCanvasProps): import("react").JSX.Element;
48
43
  export declare function InfiniteCanvasContent({ className, style, ...props }: InfiniteCanvasContentProps): import("react").JSX.Element;
49
- export declare function InfiniteCanvasItem({ x, y, onPositionChange, movableItemLabel, className, style, onPointerDown, onPointerMove, onPointerUp, onPointerCancel, onKeyDown, ...props }: InfiniteCanvasItemProps): import("react").JSX.Element;
44
+ export declare function InfiniteCanvasItem({ x, y, onPositionChange, movableItemLabel, className, style, onPointerDown, onPointerMove, onPointerUp, onPointerCancel, onLostPointerCapture, onKeyDown, ...props }: InfiniteCanvasItemProps): import("react").JSX.Element;
45
+ export declare function InfiniteCanvasItemHandle({ onPositionChange, className, children, onPointerDown, onPointerMove, onPointerUp, onPointerCancel, onLostPointerCapture, onKeyDown, "aria-label": ariaLabel, ...props }: InfiniteCanvasItemHandleProps): import("react").JSX.Element;
50
46
  export declare function InfiniteCanvasControls({ className, ...props }: InfiniteCanvasControlsProps): import("react").JSX.Element;
51
- //#endregion
47
+ //#endregion
48
+ export type { InfiniteCanvasBounds, InfiniteCanvasCamera, InfiniteCanvasFitOptions, InfiniteCanvasMoveDetails, InfiniteCanvasMoveOptions, InfiniteCanvasMoveReason, InfiniteCanvasPanOnDrag, InfiniteCanvasPoint, InfiniteCanvasRevealOptions, InfiniteCanvasTransform, InfiniteCanvasTransformUpdate, InfiniteCanvasZoomOptions };