@ctrl-ui/react 0.8.18 → 0.8.20

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 (106) hide show
  1. package/README.md +7 -0
  2. package/dist/action-bar.js +2 -2
  3. package/dist/audio-device-select.js +5 -2
  4. package/dist/blocks/coding-agent.js +22 -12
  5. package/dist/blocks/design-canvas-inspector.js +6 -3
  6. package/dist/blocks/design-canvas.js +20 -10
  7. package/dist/blocks/discussion-markdown-input.d.ts +14 -0
  8. package/dist/blocks/discussion-markdown-input.js +36 -0
  9. package/dist/blocks/discussion.d.ts +9 -3
  10. package/dist/blocks/discussion.js +82 -16
  11. package/dist/blocks/file-explorer.js +46 -24
  12. package/dist/blocks/settings.js +10 -6
  13. package/dist/chat-composer-editor/extensions/mention.d.ts +1 -1
  14. package/dist/chat-message.d.ts +13 -0
  15. package/dist/chat-message.js +198 -3
  16. package/dist/filter-bar/editor.js +5 -2
  17. package/dist/knob-contracts/flow-knobs.d.ts +4 -0
  18. package/dist/knob-contracts/flow-knobs.js +32 -0
  19. package/dist/knob-contracts/item-knobs.d.ts +1 -1
  20. package/dist/knob-contracts/item-knobs.js +4 -1
  21. package/dist/knob-contracts/label-knobs.d.ts +4 -0
  22. package/dist/knob-contracts/label-knobs.js +4 -0
  23. package/dist/knob-contracts/markdown-editor-knobs.d.ts +4 -0
  24. package/dist/knob-contracts/markdown-editor-knobs.js +17 -0
  25. package/dist/knob-contracts/morphing-panel-knobs.d.ts +1 -1
  26. package/dist/knob-contracts/morphing-panel-knobs.js +2 -1
  27. package/dist/knob-contracts/resize-handle-knobs.d.ts +4 -0
  28. package/dist/knob-contracts/resize-handle-knobs.js +12 -0
  29. package/dist/knob-contracts/sidebar-knobs.d.ts +1 -1
  30. package/dist/knob-contracts/sidebar-knobs.js +10 -0
  31. package/dist/knob-contracts/switch-knobs.d.ts +1 -1
  32. package/dist/knob-contracts/switch-knobs.js +1 -0
  33. package/dist/lib/canvas-grid.d.ts +4 -0
  34. package/dist/lib/canvas-grid.js +5 -0
  35. package/dist/markdown-editor/context.d.ts +22 -0
  36. package/dist/markdown-editor/context.js +10 -0
  37. package/dist/markdown-editor/drag-handle.d.ts +6 -0
  38. package/dist/markdown-editor/drag-handle.js +126 -0
  39. package/dist/markdown-editor/extensions.d.ts +10 -0
  40. package/dist/markdown-editor/extensions.js +139 -0
  41. package/dist/markdown-editor/suggestions.d.ts +12 -0
  42. package/dist/markdown-editor/suggestions.js +235 -0
  43. package/dist/markdown-editor/toolbar.d.ts +9 -0
  44. package/dist/markdown-editor/toolbar.js +339 -0
  45. package/dist/markdown-editor/uploads.d.ts +23 -0
  46. package/dist/markdown-editor/uploads.js +32 -0
  47. package/dist/markdown-editor/use-image-uploads.d.ts +12 -0
  48. package/dist/markdown-editor/use-image-uploads.js +120 -0
  49. package/dist/markdown-editor.d.ts +27 -0
  50. package/dist/markdown-editor.js +202 -0
  51. package/dist/styles/index.css +9 -4
  52. package/dist/styles/recipes/chat-message-edit.css +105 -0
  53. package/dist/styles/recipes/code.css +4 -0
  54. package/dist/styles/recipes/field.css +1 -1
  55. package/dist/styles/recipes/flow.css +304 -0
  56. package/dist/styles/recipes/infinite-canvas.css +1 -1
  57. package/dist/styles/recipes/item.css +39 -2
  58. package/dist/styles/recipes/label.css +19 -0
  59. package/dist/styles/recipes/markdown-editor.css +234 -0
  60. package/dist/styles/recipes/morphing-panel.css +53 -12
  61. package/dist/styles/recipes/page-layout.css +11 -1
  62. package/dist/styles/recipes/resize-handle.css +126 -0
  63. package/dist/styles/recipes/sidebar-mobile.css +171 -0
  64. package/dist/styles/recipes/switch.css +17 -5
  65. package/dist/styles/recipes/toolbar.css +8 -1
  66. package/dist/styles/theme.css +1 -0
  67. package/dist/ui/autocomplete.js +1 -1
  68. package/dist/ui/code.js +1 -0
  69. package/dist/ui/color-picker.js +1 -1
  70. package/dist/ui/combobox.d.ts +1 -1
  71. package/dist/ui/combobox.js +1 -1
  72. package/dist/ui/dockable-panel.js +1 -1
  73. package/dist/ui/flow.d.ts +51 -0
  74. package/dist/ui/flow.js +153 -0
  75. package/dist/ui/infinite-canvas.js +3 -3
  76. package/dist/ui/item.d.ts +5 -3
  77. package/dist/ui/item.js +2 -1
  78. package/dist/ui/label.d.ts +8 -0
  79. package/dist/ui/label.js +14 -0
  80. package/dist/ui/markdown.d.ts +2 -1
  81. package/dist/ui/markdown.js +3 -3
  82. package/dist/ui/morphing-panel.d.ts +21 -4
  83. package/dist/ui/morphing-panel.js +152 -36
  84. package/dist/ui/resize-handle.d.ts +11 -0
  85. package/dist/ui/resize-handle.js +26 -0
  86. package/dist/ui/sidebar-mobile.d.ts +17 -0
  87. package/dist/ui/sidebar-mobile.js +70 -0
  88. package/dist/ui/sidebar-provider.d.ts +1 -0
  89. package/dist/ui/sidebar-provider.js +3 -0
  90. package/dist/ui/sidebar.d.ts +3 -1
  91. package/dist/ui/sidebar.js +101 -49
  92. package/dist/ui/toolbar.d.ts +3 -1
  93. package/dist/ui/toolbar.js +2 -1
  94. package/dist/ui/typography.d.ts +47 -0
  95. package/dist/ui/typography.js +61 -0
  96. package/dist/ui/use-switch-drag.js +1 -1
  97. package/package.json +41 -1
  98. package/dist/environment-variables.d.ts +0 -125
  99. package/dist/environment-variables.js +0 -512
  100. package/dist/hooks/use-environment-variables.d.ts +0 -50
  101. package/dist/hooks/use-environment-variables.js +0 -188
  102. package/dist/knob-contracts/environment-variables-knobs.d.ts +0 -4
  103. package/dist/knob-contracts/environment-variables-knobs.js +0 -12
  104. package/dist/lib/env-file.d.ts +0 -27
  105. package/dist/lib/env-file.js +0 -218
  106. package/dist/styles/recipes/environment-variables.css +0 -170
@@ -0,0 +1,171 @@
1
+ @layer components {
2
+ :where([data-control-family="sidebar"][data-slot="wrapper"]) {
3
+ --cui-sidebar-nav-height: 4.5rem;
4
+ --cui-sidebar-nav-background: var(--sidebar);
5
+ --cui-sidebar-nav-foreground: var(--sidebar-foreground);
6
+ --cui-sidebar-nav-border-color: var(--sidebar-border);
7
+ --cui-sidebar-nav-border-width: var(--control-rim-width);
8
+ --cui-sidebar-nav-shadow: var(--shadow-md);
9
+ --cui-sidebar-nav-item-radius: var(--radius-control);
10
+ --cui-sidebar-nav-item-active-background: var(--active-fill);
11
+ --cui-sidebar-nav-item-active-foreground: var(--foreground);
12
+ --cui-sidebar-nav-gap: calc(var(--spacing) * 3);
13
+ }
14
+
15
+ :where([data-control-family="sidebar"][data-slot="mobile-nav-container"]) {
16
+ --_sidebar-nav-space: calc(var(--cui-sidebar-nav-height) + env(safe-area-inset-bottom, 0px));
17
+ block-size: var(--_sidebar-nav-space);
18
+ }
19
+
20
+ :where([data-control-family="sidebar"][data-slot="mobile-nav"]) {
21
+ position: fixed;
22
+ inset-block-end: 0;
23
+ inset-inline: 0;
24
+ z-index: 30;
25
+ min-block-size: var(--_sidebar-nav-space);
26
+ gap: calc(var(--spacing) * 1);
27
+ padding: calc(var(--spacing) * 1) max(calc(var(--spacing) * 2), env(safe-area-inset-right, 0px))
28
+ calc(var(--spacing) * 1 + env(safe-area-inset-bottom, 0px)) max(calc(var(--spacing) * 2), env(safe-area-inset-left, 0px));
29
+ background-color: var(--cui-sidebar-nav-background);
30
+ color: var(--cui-sidebar-nav-foreground);
31
+ }
32
+
33
+ :where([data-control-family="sidebar"][data-slot="mobile-nav"][data-variant="bar"]) {
34
+ border-block-start: var(--cui-sidebar-nav-border-width) solid var(--cui-sidebar-nav-border-color);
35
+ }
36
+
37
+ :where([data-control-family="sidebar"][data-slot="mobile-nav-container"][data-layout="contained"] > [data-slot="mobile-nav"]) {
38
+ position: absolute;
39
+ }
40
+
41
+ :where([data-control-family="sidebar"][data-slot="mobile-nav"] [data-mobile-nav-item]) {
42
+ display: flex;
43
+ flex: 1 1 0;
44
+ flex-direction: column;
45
+ align-items: center;
46
+ justify-content: center;
47
+ gap: calc(var(--spacing) * 1);
48
+ min-inline-size: 48px;
49
+ min-block-size: 48px;
50
+ block-size: auto;
51
+ padding: calc(var(--spacing) * 1);
52
+ border-radius: var(--cui-sidebar-nav-item-radius);
53
+ background-color: transparent;
54
+ color: var(--cui-sidebar-nav-foreground);
55
+ font-size: var(--text-caption);
56
+ font-weight: var(--font-weight-medium);
57
+ text-decoration: none;
58
+ text-align: center;
59
+ }
60
+
61
+ :where([data-control-family="sidebar"][data-slot="mobile-nav"] [data-mobile-nav-item] > svg) {
62
+ inline-size: calc(var(--spacing) * 5);
63
+ block-size: calc(var(--spacing) * 5);
64
+ flex-shrink: 0;
65
+ }
66
+
67
+ :where([data-control-family="sidebar"][data-slot="mobile-nav"] [data-mobile-nav-item] > span) {
68
+ max-inline-size: 100%;
69
+ }
70
+
71
+ :where([data-control-family="sidebar"][data-slot="mobile-nav"] [data-mobile-nav-item][data-active]) {
72
+ background-color: var(--cui-sidebar-nav-item-active-background);
73
+ color: var(--cui-sidebar-nav-item-active-foreground);
74
+ }
75
+
76
+ :where([data-control-family="sidebar"][data-slot="mobile-nav"] [data-mobile-nav-item]:is(:disabled, [aria-disabled="true"])) {
77
+ pointer-events: none;
78
+ opacity: 0.5;
79
+ }
80
+
81
+ :where([data-control-family="sidebar"][data-slot="mobile-nav-container"][data-variant="floating"]) {
82
+ block-size: calc(var(--_sidebar-nav-space) + var(--cui-sidebar-nav-gap));
83
+ }
84
+
85
+ :where([data-control-family="sidebar"][data-slot="mobile-nav"][data-variant="floating"]) {
86
+ inset-inline-start: auto;
87
+ inset-inline-end: max(var(--cui-sidebar-nav-gap), env(safe-area-inset-right, 0px));
88
+ inset-block-end: calc(var(--cui-sidebar-nav-gap) + env(safe-area-inset-bottom, 0px));
89
+ min-block-size: 0;
90
+ padding: calc(var(--spacing) * 1);
91
+ border: var(--cui-sidebar-nav-border-width) solid var(--cui-sidebar-nav-border-color);
92
+ border-radius: var(--cui-sidebar-nav-item-radius);
93
+ box-shadow: var(--cui-sidebar-nav-shadow);
94
+ }
95
+
96
+ @media (width < 64rem) {
97
+ :where([data-control-family="sidebar"][data-slot="wrapper"]:has(> [data-slot="mobile-nav-container"])) {
98
+ flex-direction: column;
99
+ }
100
+
101
+ :where([data-control-family="sidebar"][data-slot="wrapper"]:has(> [data-slot="mobile-nav-container"]) > [data-slot="inset"]) {
102
+ scroll-padding-block-end: calc(var(--cui-sidebar-nav-height) + env(safe-area-inset-bottom, 0px));
103
+ }
104
+ }
105
+
106
+ @media (hover: hover) {
107
+ :where([data-control-family="sidebar"][data-slot="mobile-nav"] [data-mobile-nav-item]:hover) {
108
+ background-color: var(--cui-sidebar-nav-item-active-background);
109
+ color: var(--cui-sidebar-nav-item-active-foreground);
110
+ }
111
+ }
112
+ }
113
+
114
+ @property --cui-sidebar-nav-height {
115
+ syntax: "<length>";
116
+ inherits: true;
117
+ initial-value: 72px;
118
+ }
119
+
120
+ @property --cui-sidebar-nav-background {
121
+ syntax: "<color>";
122
+ inherits: true;
123
+ initial-value: transparent;
124
+ }
125
+
126
+ @property --cui-sidebar-nav-foreground {
127
+ syntax: "<color>";
128
+ inherits: true;
129
+ initial-value: transparent;
130
+ }
131
+
132
+ @property --cui-sidebar-nav-border-color {
133
+ syntax: "<color>";
134
+ inherits: true;
135
+ initial-value: transparent;
136
+ }
137
+
138
+ @property --cui-sidebar-nav-border-width {
139
+ syntax: "<length>";
140
+ inherits: true;
141
+ initial-value: 0px;
142
+ }
143
+
144
+ @property --cui-sidebar-nav-shadow {
145
+ syntax: "*";
146
+ inherits: true;
147
+ }
148
+
149
+ @property --cui-sidebar-nav-item-radius {
150
+ syntax: "<length-percentage>";
151
+ inherits: true;
152
+ initial-value: 0px;
153
+ }
154
+
155
+ @property --cui-sidebar-nav-item-active-background {
156
+ syntax: "<color>";
157
+ inherits: true;
158
+ initial-value: transparent;
159
+ }
160
+
161
+ @property --cui-sidebar-nav-item-active-foreground {
162
+ syntax: "<color>";
163
+ inherits: true;
164
+ initial-value: transparent;
165
+ }
166
+
167
+ @property --cui-sidebar-nav-gap {
168
+ syntax: "<length>";
169
+ inherits: true;
170
+ initial-value: 12px;
171
+ }
@@ -4,11 +4,13 @@
4
4
  --cui-switch-height: calc(var(--spacing) * 5);
5
5
  --cui-switch-padding: calc(var(--spacing) * 0.5);
6
6
  --cui-switch-thumb-inline-size: calc(var(--spacing) * 4);
7
- --cui-switch-thumb-press-scale: 1.25 1;
7
+ --cui-switch-thumb-press-inline-size: calc(var(--cui-switch-thumb-inline-size) * 1.25);
8
+ --cui-switch-thumb-press-scale: 1;
8
9
  --cui-switch-thumb-backdrop-filter: none;
9
10
  --_switch-direction: 1;
10
11
  --_switch-progress: 0;
11
- --_switch-travel: calc(var(--cui-switch-inline-size) - var(--cui-switch-padding) * 2 - var(--cui-switch-thumb-inline-size));
12
+ --_switch-thumb-inline-size: var(--cui-switch-thumb-inline-size);
13
+ --_switch-travel: calc(var(--cui-switch-inline-size) - var(--cui-switch-padding) * 2 - var(--_switch-thumb-inline-size));
12
14
  block-size: var(--cui-switch-height);
13
15
  inline-size: var(--cui-switch-inline-size);
14
16
  padding: var(--cui-switch-padding);
@@ -79,13 +81,13 @@
79
81
  border-radius: var(--cui-switch-thumb-radius);
80
82
  background: var(--cui-switch-thumb-background);
81
83
  box-shadow: var(--cui-switch-thumb-shadow);
82
- inline-size: var(--cui-switch-thumb-inline-size);
84
+ inline-size: var(--_switch-thumb-inline-size);
83
85
  block-size: calc(var(--cui-switch-height) - var(--cui-switch-padding) * 2);
84
86
  translate: calc(var(--_switch-direction) * var(--_switch-travel) * var(--_switch-progress)) 0;
85
87
  transform-origin: left center;
86
88
  -webkit-backdrop-filter: var(--cui-switch-thumb-backdrop-filter);
87
89
  backdrop-filter: var(--cui-switch-thumb-backdrop-filter);
88
- transition-property: translate, scale, background-color, box-shadow;
90
+ transition-property: translate, inline-size, scale, background-color, box-shadow;
89
91
  transition-duration: var(--duration-base);
90
92
  transition-timing-function: var(--ease-emphasized);
91
93
  }
@@ -136,6 +138,10 @@
136
138
  transform-origin: left center;
137
139
  }
138
140
 
141
+ :where([data-control-family="switch"][data-slot="root"]:is(:active, [data-dragging]):not([data-disabled], [data-readonly])) {
142
+ --_switch-thumb-inline-size: var(--cui-switch-thumb-press-inline-size);
143
+ }
144
+
139
145
  :where(
140
146
  [data-control-family="switch"][data-slot="root"]:is(:active, [data-dragging]):not([data-disabled], [data-readonly]) [data-slot="thumb"]
141
147
  ) {
@@ -157,7 +163,7 @@
157
163
  }
158
164
 
159
165
  :where([data-control-family="switch"][data-slot="root"][data-dragging] [data-slot="thumb"]) {
160
- transition-property: scale, background-color, box-shadow;
166
+ transition-property: inline-size, scale, background-color, box-shadow;
161
167
  }
162
168
  }
163
169
 
@@ -255,6 +261,12 @@
255
261
  initial-value: 16px;
256
262
  }
257
263
 
264
+ @property --cui-switch-thumb-press-inline-size {
265
+ syntax: "<length>";
266
+ inherits: true;
267
+ initial-value: 20px;
268
+ }
269
+
258
270
  @property --cui-switch-thumb-press-scale {
259
271
  syntax: "*";
260
272
  inherits: true;
@@ -32,6 +32,13 @@
32
32
  gap: calc(var(--spacing) * 1);
33
33
  }
34
34
 
35
+ :where([data-control-family="toolbar"][data-slot="root"][data-chrome="embedded"]) {
36
+ --cui-toolbar-background: transparent;
37
+ --cui-toolbar-border-width: 0px;
38
+ --cui-toolbar-radius: 0px;
39
+ --cui-toolbar-shadow: none;
40
+ }
41
+
35
42
  :where([data-control-family="toolbar"][data-slot="root"][data-variant="floating"]) {
36
43
  --cui-toolbar-background: transparent;
37
44
  --cui-toolbar-border-color: transparent;
@@ -112,7 +119,7 @@
112
119
  }
113
120
  }
114
121
 
115
- :where([data-control-family="toolbar"][data-slot="button"]:is([data-pressed], [data-active])),
122
+ :where([data-control-family="toolbar"][data-slot="button"]:is([data-pressed], [data-active], [aria-pressed="true"])),
116
123
  :where([data-control-family="toolbar"][data-slot="link"]:is([data-pressed], [data-active])) {
117
124
  background-color: var(--cui-toolbar-item-active-background);
118
125
  color: var(--cui-toolbar-item-active-foreground);
@@ -168,6 +168,7 @@
168
168
  --popover: var(--scale-neutral-1);
169
169
  --popover-foreground: var(--scale-neutral-12);
170
170
  --canvas: var(--scale-neutral-1);
171
+ --canvas-grid-dot: oklch(from var(--foreground) l c h / 0.16);
171
172
 
172
173
  --radius: 0px;
173
174
  --shadow-size: 0;
@@ -85,7 +85,7 @@ function AutocompleteContent({ className, children, sideOffset = 6, ...props })
85
85
  function AutocompleteList({ className, children, ...props }) {
86
86
  return /* @__PURE__ */ jsx(ScrollArea, {
87
87
  className: "w-full",
88
- viewportClassName: "overscroll-contain",
88
+ viewportClassName: "overscroll-y-contain",
89
89
  maxHeight: "min(18rem, var(--available-height))",
90
90
  lockAxis: "x",
91
91
  children: /* @__PURE__ */ jsx(Autocomplete$1.List, {
package/dist/ui/code.js CHANGED
@@ -112,6 +112,7 @@ function CodeCopy({ value, copiedLabel, copiedAriaLabel = "Copied to clipboard",
112
112
  }
113
113
  function CodeFloatingCopy({ className, ...props }) {
114
114
  return /* @__PURE__ */ jsx(CodeCopy, {
115
+ variant: "surface",
115
116
  "data-code-floating": "true",
116
117
  className: cn("absolute z-10", className),
117
118
  ...props
@@ -4,10 +4,10 @@ import { controlEffectsAttribute } from "../skin.js";
4
4
  import { useSkin } from "../skin-provider.js";
5
5
  import { Button } from "./button.js";
6
6
  import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./select.js";
7
- import { Input } from "./input.js";
8
7
  import { useColorArea } from "../hooks/use-color-area.js";
9
8
  import { formatColor, getChannels, hsvaToRgba, parseColor, pointToHueSat, pointToSaturationValue, setChannel } from "../lib/color.js";
10
9
  import { TARGET_RATIO, contrastOf, fixColorForContrast, formatContrastRatio, nextFixLevel, wcagLevels } from "../lib/contrast.js";
10
+ import { Input } from "./input.js";
11
11
  import { NumberField, NumberFieldGroup, NumberFieldInput } from "./number-field.js";
12
12
  import { createContext, useContext, useEffect, useId, useRef, useState, useSyncExternalStore } from "react";
13
13
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
@@ -4,7 +4,7 @@ import { PopupKnobStyle } from "../knob-contracts/popup-knobs.js";
4
4
  import { CSSProperties, ComponentProps, ReactNode } from "react";
5
5
  import { Combobox as Combobox$1 } from "@base-ui/react/combobox";
6
6
  //#region src/ui/combobox.d.ts
7
- export type ComboboxProps<Value = string, Multiple extends boolean | undefined = false> = Pick<Combobox$1.Root.Props<Value, Multiple>, "children" | "multiple" | "value" | "defaultValue" | "onValueChange" | "inputValue" | "defaultInputValue" | "onInputValueChange" | "open" | "defaultOpen" | "onOpenChange" | "disabled" | "readOnly" | "required" | "name" | "autoHighlight" | "itemToStringLabel" | "isItemEqualToValue" | "filter" | "modal"> & {
7
+ export type ComboboxProps<Value = string, Multiple extends boolean | undefined = false> = Pick<Combobox$1.Root.Props<Value, Multiple>, "children" | "multiple" | "value" | "defaultValue" | "onValueChange" | "inputValue" | "defaultInputValue" | "onInputValueChange" | "open" | "defaultOpen" | "onOpenChange" | "disabled" | "readOnly" | "required" | "name" | "autoHighlight" | "itemToStringLabel" | "isItemEqualToValue" | "filter" | "limit" | "modal"> & {
8
8
  items?: readonly Value[];
9
9
  };
10
10
  export type ComboboxInputProps = Omit<Omit<ComponentProps<"input">, "size">, "style"> & {
@@ -115,7 +115,7 @@ function ComboboxContent({ className, children, sideOffset = 6, anchor, ...props
115
115
  function ComboboxList({ className, children, ...props }) {
116
116
  return /* @__PURE__ */ jsx(ScrollArea, {
117
117
  className: "w-full",
118
- viewportClassName: "overscroll-contain",
118
+ viewportClassName: "overscroll-y-contain",
119
119
  maxHeight: "min(18rem, var(--available-height))",
120
120
  lockAxis: "x",
121
121
  children: /* @__PURE__ */ jsx(Combobox$1.List, {
@@ -3,8 +3,8 @@ import { cn } from "../lib/cn.js";
3
3
  import { Button } from "./button.js";
4
4
  import { LiveStatus } from "./live-status.js";
5
5
  import { ScrollArea } from "./scroll-area.js";
6
- import { useIsMobile } from "../hooks/use-mobile.js";
7
6
  import { Drawer, DrawerBody, DrawerContent } from "./drawer.js";
7
+ import { useIsMobile } from "../hooks/use-mobile.js";
8
8
  import { clampDockablePanelPosition, dockablePanelSideAt, dockablePanelSideForKey, oppositeDockablePanelSide } from "./dockable-panel-geometry.js";
9
9
  import { createContext, use, useEffect, useEffectEvent, useId, useRef, useState } from "react";
10
10
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
@@ -0,0 +1,51 @@
1
+ import { FlowKnobStyle } from "../knob-contracts/flow-knobs.js";
2
+ import { CSSProperties, ComponentProps } from "react";
3
+ import { BaseEdgeProps, Edge, FitViewOptions, Handle, Node, Panel, ReactFlowProps } from "@xyflow/react";
4
+ //#region src/ui/flow.d.ts
5
+ export type FlowProps<NodeType extends Node = Node, EdgeType extends Edge = Edge> = Omit<ReactFlowProps<NodeType, EdgeType>, "colorMode" | "style"> & {
6
+ style?: CSSProperties & FlowKnobStyle;
7
+ };
8
+ export type FlowBackgroundProps = {
9
+ id?: string;
10
+ className?: string;
11
+ };
12
+ export type FlowPanelProps = Omit<ComponentProps<typeof Panel>, "style"> & {
13
+ style?: CSSProperties & FlowKnobStyle;
14
+ };
15
+ export type FlowControlsProps = Omit<FlowPanelProps, "children"> & {
16
+ fitViewOptions?: FitViewOptions;
17
+ };
18
+ export type FlowNodeProps = Omit<ComponentProps<"div">, "style"> & {
19
+ selected?: boolean;
20
+ style?: CSSProperties & FlowKnobStyle;
21
+ };
22
+ export type FlowNodePartProps = Omit<ComponentProps<"div">, "style"> & {
23
+ style?: CSSProperties & FlowKnobStyle;
24
+ };
25
+ export type FlowHandleProps = Omit<ComponentProps<typeof Handle>, "style"> & {
26
+ style?: CSSProperties & FlowKnobStyle;
27
+ };
28
+ export type FlowEdgeProps = Omit<BaseEdgeProps, "style"> & {
29
+ dashed?: boolean;
30
+ style?: CSSProperties & FlowKnobStyle;
31
+ };
32
+ export type FlowEdgeLabelProps = Omit<ComponentProps<"div">, "style"> & {
33
+ x: number;
34
+ y: number;
35
+ style?: CSSProperties & FlowKnobStyle;
36
+ };
37
+ export type FlowEdgeLabelChipProps = Omit<ComponentProps<"span">, "style"> & {
38
+ style?: CSSProperties & FlowKnobStyle;
39
+ };
40
+ export declare function Flow<NodeType extends Node = Node, EdgeType extends Edge = Edge>(props: FlowProps<NodeType, EdgeType>): import("react").JSX.Element;
41
+ export declare function FlowBackground(props: FlowBackgroundProps): import("react").JSX.Element;
42
+ export declare function FlowPanel(props: FlowPanelProps): import("react").JSX.Element;
43
+ export declare function FlowControls({ position, fitViewOptions, className, ...props }: FlowControlsProps): import("react").JSX.Element;
44
+ export declare function FlowNode({ selected, className, ...props }: FlowNodeProps): import("react").JSX.Element;
45
+ export declare function FlowNodeHeader({ className, ...props }: FlowNodePartProps): import("react").JSX.Element;
46
+ export declare function FlowNodeBody({ className, ...props }: FlowNodePartProps): import("react").JSX.Element;
47
+ export declare function FlowHandle(props: FlowHandleProps): import("react").JSX.Element;
48
+ export declare function FlowEdge({ dashed, ...props }: FlowEdgeProps): import("react").JSX.Element;
49
+ export declare function FlowEdgeLabel({ x, y, className, style, ...props }: FlowEdgeLabelProps): import("react").JSX.Element;
50
+ export declare function FlowEdgeLabelChip({ className, ...props }: FlowEdgeLabelChipProps): import("react").JSX.Element;
51
+ //#endregion
@@ -0,0 +1,153 @@
1
+ "use client";
2
+ import { cn } from "../lib/cn.js";
3
+ import { Button } from "./button.js";
4
+ import { prefersReducedMotion, readDurationMs } from "../lib/motion.js";
5
+ import "../lib/canvas-grid.js";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ import { MaximizeIcon, MinusIcon, PlusIcon } from "lucide-react";
8
+ import { Background, BackgroundVariant, BaseEdge, EdgeLabelRenderer, Handle, Panel, ReactFlow, useReactFlow, useStore } from "@xyflow/react";
9
+ //#region src/ui/flow.tsx
10
+ function viewportTransitionMs(element) {
11
+ return prefersReducedMotion(element) ? 0 : readDurationMs(element, "--duration-base");
12
+ }
13
+ function Flow(props) {
14
+ return /* @__PURE__ */ jsx(ReactFlow, {
15
+ defaultMarkerColor: null,
16
+ ...props,
17
+ "data-control-ui": "flow",
18
+ "data-control-family": "flow",
19
+ "data-slot": "root"
20
+ });
21
+ }
22
+ function FlowBackground(props) {
23
+ return /* @__PURE__ */ jsx(Background, {
24
+ ...props,
25
+ variant: BackgroundVariant.Dots,
26
+ gap: 24,
27
+ size: 2
28
+ });
29
+ }
30
+ function FlowPanel(props) {
31
+ return /* @__PURE__ */ jsx(Panel, {
32
+ ...props,
33
+ "data-control-ui": "flow",
34
+ "data-control-family": "flow",
35
+ "data-slot": "panel"
36
+ });
37
+ }
38
+ function FlowControls({ position = "bottom-left", fitViewOptions, className, ...props }) {
39
+ const { zoomIn, zoomOut, fitView } = useReactFlow();
40
+ const atMinZoom = useStore((state) => state.transform[2] <= state.minZoom);
41
+ const atMaxZoom = useStore((state) => state.transform[2] >= state.maxZoom);
42
+ return /* @__PURE__ */ jsxs(Panel, {
43
+ ...props,
44
+ position,
45
+ "data-control-ui": "flow",
46
+ "data-control-family": "flow",
47
+ "data-slot": "controls",
48
+ className: cn("flex items-center", className),
49
+ children: [
50
+ /* @__PURE__ */ jsx(Button, {
51
+ type: "button",
52
+ size: "sm",
53
+ variant: "ghost",
54
+ iconOnly: true,
55
+ disabled: atMinZoom,
56
+ "aria-label": "Zoom out",
57
+ onClick: (event) => zoomOut({ duration: viewportTransitionMs(event.currentTarget) }),
58
+ children: /* @__PURE__ */ jsx(MinusIcon, {})
59
+ }),
60
+ /* @__PURE__ */ jsx(Button, {
61
+ type: "button",
62
+ size: "sm",
63
+ variant: "ghost",
64
+ iconOnly: true,
65
+ disabled: atMaxZoom,
66
+ "aria-label": "Zoom in",
67
+ onClick: (event) => zoomIn({ duration: viewportTransitionMs(event.currentTarget) }),
68
+ children: /* @__PURE__ */ jsx(PlusIcon, {})
69
+ }),
70
+ /* @__PURE__ */ jsx(Button, {
71
+ type: "button",
72
+ size: "sm",
73
+ variant: "ghost",
74
+ iconOnly: true,
75
+ "aria-label": "Fit view",
76
+ onClick: (event) => fitView({
77
+ ...fitViewOptions,
78
+ duration: viewportTransitionMs(event.currentTarget)
79
+ }),
80
+ children: /* @__PURE__ */ jsx(MaximizeIcon, {})
81
+ })
82
+ ]
83
+ });
84
+ }
85
+ function FlowNode({ selected, className, ...props }) {
86
+ return /* @__PURE__ */ jsx("div", {
87
+ ...props,
88
+ "data-control-ui": "flow",
89
+ "data-control-family": "flow",
90
+ "data-slot": "node",
91
+ "data-selected": selected || void 0,
92
+ className: cn("flex flex-col", className)
93
+ });
94
+ }
95
+ function FlowNodeHeader({ className, ...props }) {
96
+ return /* @__PURE__ */ jsx("div", {
97
+ ...props,
98
+ "data-control-ui": "flow",
99
+ "data-control-family": "flow",
100
+ "data-slot": "node-header",
101
+ className: cn("flex items-center", className)
102
+ });
103
+ }
104
+ function FlowNodeBody({ className, ...props }) {
105
+ return /* @__PURE__ */ jsx("div", {
106
+ ...props,
107
+ "data-control-ui": "flow",
108
+ "data-control-family": "flow",
109
+ "data-slot": "node-body",
110
+ className: cn("flex flex-col", className)
111
+ });
112
+ }
113
+ function FlowHandle(props) {
114
+ return /* @__PURE__ */ jsx(Handle, {
115
+ ...props,
116
+ "data-control-ui": "flow",
117
+ "data-control-family": "flow",
118
+ "data-slot": "handle"
119
+ });
120
+ }
121
+ function FlowEdge({ dashed, ...props }) {
122
+ return /* @__PURE__ */ jsx(BaseEdge, {
123
+ ...props,
124
+ "data-control-ui": "flow",
125
+ "data-control-family": "flow",
126
+ "data-slot": "edge",
127
+ "data-dashed": dashed || void 0
128
+ });
129
+ }
130
+ function FlowEdgeLabel({ x, y, className, style, ...props }) {
131
+ return /* @__PURE__ */ jsx(EdgeLabelRenderer, { children: /* @__PURE__ */ jsx("div", {
132
+ ...props,
133
+ "data-control-ui": "flow",
134
+ "data-control-family": "flow",
135
+ "data-slot": "edge-label",
136
+ className: cn("nodrag nopan pointer-events-auto absolute flex items-center", className),
137
+ style: {
138
+ ...style,
139
+ transform: `translate(-50%, -50%) translate(${x}px, ${y}px)`
140
+ }
141
+ }) });
142
+ }
143
+ function FlowEdgeLabelChip({ className, ...props }) {
144
+ return /* @__PURE__ */ jsx("span", {
145
+ ...props,
146
+ "data-control-ui": "flow",
147
+ "data-control-family": "flow",
148
+ "data-slot": "edge-label-chip",
149
+ className: cn("inline-flex max-w-40 items-center truncate", className)
150
+ });
151
+ }
152
+ //#endregion
153
+ export { Flow, FlowBackground, FlowControls, FlowEdge, FlowEdgeLabel, FlowEdgeLabelChip, FlowHandle, FlowNode, FlowNodeBody, FlowNodeHeader, FlowPanel };
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
  import { cn } from "../lib/cn.js";
3
3
  import { Button } from "./button.js";
4
+ import "../lib/canvas-grid.js";
4
5
  import { createContext, use, useEffect, useEffectEvent, useRef, useState } from "react";
5
6
  import { jsx, jsxs } from "react/jsx-runtime";
6
7
  import { MinusIcon, PlusIcon } from "lucide-react";
@@ -13,7 +14,6 @@ const DEFAULT_TRANSFORM = {
13
14
  const DEFAULT_MIN_SCALE = .35;
14
15
  const DEFAULT_MAX_SCALE = 2.5;
15
16
  const KEYBOARD_PAN_STEP = 32;
16
- const GRID_SIZE = 24;
17
17
  const WHEEL_ZOOM_SPEED = .004;
18
18
  const MAX_WHEEL_ZOOM_DELTA = 50;
19
19
  const CANVAS_KEY_SHORTCUTS = "ArrowLeft ArrowRight ArrowUp ArrowDown + - 0";
@@ -78,7 +78,7 @@ function useInfiniteCanvas() {
78
78
  return context;
79
79
  }
80
80
  function InfiniteCanvas({ transform: controlledTransform, defaultTransform = DEFAULT_TRANSFORM, onTransformChange, minScale: minScaleProp = DEFAULT_MIN_SCALE, maxScale: maxScaleProp = DEFAULT_MAX_SCALE, className, children, style, onPointerDown, onPointerMove, onPointerUp, onPointerCancel, onWheel, onKeyDown, "aria-label": ariaLabel = "Infinite canvas", "aria-keyshortcuts": ariaKeyShortcuts, ...props }) {
81
- const minScale = Math.max(.1, minScaleProp);
81
+ const minScale = minScaleProp > 0 ? minScaleProp : DEFAULT_MIN_SCALE;
82
82
  const maxScale = Math.max(minScale, maxScaleProp);
83
83
  const [uncontrolledTransform, setUncontrolledTransform] = useState(defaultTransform);
84
84
  const [panning, setPanning] = useState(false);
@@ -222,7 +222,7 @@ function InfiniteCanvas({ transform: controlledTransform, defaultTransform = DEF
222
222
  const canvasStyle = {
223
223
  ...style,
224
224
  backgroundPosition: `${transform.x}px ${transform.y}px`,
225
- backgroundSize: `${GRID_SIZE * transform.scale}px ${GRID_SIZE * transform.scale}px`
225
+ backgroundSize: `${24 * transform.scale}px ${24 * transform.scale}px`
226
226
  };
227
227
  return /* @__PURE__ */ jsx(InfiniteCanvasContext.Provider, {
228
228
  value: context,
package/dist/ui/item.d.ts CHANGED
@@ -27,6 +27,10 @@ export type ItemGroupProps = ComponentProps<"div"> & {
27
27
  style?: CSSProperties & ItemKnobStyle;
28
28
  };
29
29
  export type ItemSeparatorProps = ComponentProps<"div">;
30
+ export type ItemActionsProps = Omit<ComponentProps<"div">, "style"> & {
31
+ showOnHover?: boolean;
32
+ style?: CSSProperties & ItemKnobStyle;
33
+ };
30
34
  export declare function ItemGroup({ className, ...props }: ItemGroupProps): import("react").JSX.Element;
31
35
  export declare function ItemSeparator({ className, ...props }: ItemSeparatorProps): import("react").JSX.Element;
32
36
  export declare function Item({ variant, render, className, children, ...props }: ItemProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
@@ -36,9 +40,7 @@ export declare function ItemContent({ className, ...props }: ComponentProps<"div
36
40
  }): import("react").JSX.Element;
37
41
  export declare function ItemTitle({ render, className, ...props }: ItemTitleProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
38
42
  export declare function ItemDescription({ className, ...props }: ItemDescriptionProps): import("react").JSX.Element;
39
- export declare function ItemActions({ className, ...props }: ComponentProps<"div"> & {
40
- style?: CSSProperties & ItemKnobStyle;
41
- }): import("react").JSX.Element;
43
+ export declare function ItemActions({ showOnHover, className, ...props }: ItemActionsProps): import("react").JSX.Element;
42
44
  export declare function ItemHeader({ className, ...props }: ComponentProps<"div"> & {
43
45
  style?: CSSProperties & ItemKnobStyle;
44
46
  }): import("react").JSX.Element;
package/dist/ui/item.js CHANGED
@@ -83,11 +83,12 @@ function ItemDescription({ className, ...props }) {
83
83
  ...props
84
84
  });
85
85
  }
86
- function ItemActions({ className, ...props }) {
86
+ function ItemActions({ showOnHover, className, ...props }) {
87
87
  return /* @__PURE__ */ jsx("div", {
88
88
  "data-control-ui": "item",
89
89
  "data-control-family": "item",
90
90
  "data-slot": "actions",
91
+ "data-show-on-hover": showOnHover || void 0,
91
92
  className: cn("flex shrink-0 items-center", className),
92
93
  ...props
93
94
  });
@@ -0,0 +1,8 @@
1
+ import { LabelKnobStyle } from "../knob-contracts/label-knobs.js";
2
+ import { CSSProperties, ComponentProps } from "react";
3
+ //#region src/ui/label.d.ts
4
+ export type LabelProps = Omit<ComponentProps<"label">, "style"> & {
5
+ style?: CSSProperties & LabelKnobStyle;
6
+ };
7
+ export declare function Label({ htmlFor, children, ...props }: LabelProps): import("react").JSX.Element;
8
+ //#endregion
@@ -0,0 +1,14 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ //#region src/ui/label.tsx
3
+ function Label({ htmlFor, children, ...props }) {
4
+ return /* @__PURE__ */ jsx("label", {
5
+ ...props,
6
+ htmlFor,
7
+ "data-control-ui": "label",
8
+ "data-control-family": "label",
9
+ "data-slot": "root",
10
+ children
11
+ });
12
+ }
13
+ //#endregion
14
+ export { Label };
@@ -6,9 +6,10 @@ export type MarkdownRootProps = Omit<ComponentProps<"div">, "style"> & {
6
6
  };
7
7
  export type MarkdownProps = Omit<MarkdownRootProps, "children"> & {
8
8
  content: string;
9
+ mode?: "streaming" | "static";
9
10
  };
10
11
  export declare function MarkdownRoot({ className, ...props }: MarkdownRootProps): import("react").JSX.Element;
11
12
  export declare function MarkdownFlow(props: MarkdownRootProps): import("react").JSX.Element;
12
- export declare function Markdown({ content, className, ...props }: MarkdownProps): import("react").JSX.Element;
13
+ export declare function Markdown({ content, mode, className, ...props }: MarkdownProps): import("react").JSX.Element;
13
14
  export type MarkdownComponentProps = ComponentProps<typeof Markdown>;
14
15
  //#endregion
@@ -21,13 +21,13 @@ function MarkdownFlow(props) {
21
21
  ...props
22
22
  });
23
23
  }
24
- function Markdown({ content, className, ...props }) {
24
+ function Markdown({ content, mode = "streaming", className, ...props }) {
25
25
  return /* @__PURE__ */ jsx(MarkdownRoot, {
26
26
  className,
27
27
  ...props,
28
28
  children: /* @__PURE__ */ jsx(MarkdownFlow, { children: /* @__PURE__ */ jsx(Streamdown, {
29
- mode: "streaming",
30
- parseIncompleteMarkdown: true,
29
+ mode,
30
+ parseIncompleteMarkdown: mode === "streaming",
31
31
  controls: false,
32
32
  components: markdownComponents,
33
33
  className: "cui-markdown-streamdown [&>[data-control-family]]:[margin-block:revert-layer]",