@ctrl-ui/react 0.9.2 → 0.9.4

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.
@@ -66,7 +66,7 @@ function AudioDeviceSelect({ devices, kind = "input", value, defaultValue, onVal
66
66
  "data-control-ui": "audio-device-select",
67
67
  "data-control-family": "audio-device-select",
68
68
  "data-slot": "root",
69
- className: cn("grid min-w-0 gap-2", className),
69
+ className: cn("grid min-w-0 grid-cols-[minmax(0,1fr)] gap-2", className),
70
70
  children: /* @__PURE__ */ jsx(Select, {
71
71
  value: current,
72
72
  onValueChange: handleValueChange,
@@ -1,4 +1,6 @@
1
1
  import { ChatLayout } from "../chat-layout.js";
2
+ import { SidebarProviderProps } from "../ui/sidebar-provider.js";
3
+ import "../ui/sidebar.js";
2
4
  import { ComponentProps, ReactNode } from "react";
3
5
  //#region src/blocks/coding-agent.d.ts
4
6
  export type CodingAgentNavigationItem = {
@@ -19,7 +21,7 @@ export type CodingAgentProject = {
19
21
  tasks: readonly CodingAgentTask[];
20
22
  open?: boolean;
21
23
  };
22
- export type CodingAgentBlockProps = Omit<ComponentProps<"div">, "children"> & {
24
+ export type CodingAgentBlockProps = Omit<ComponentProps<"div">, "children"> & Pick<SidebarProviderProps, "persistOpen" | "keyboardShortcut"> & {
23
25
  appName?: string;
24
26
  brand?: ReactNode;
25
27
  sidebarTop?: ReactNode;
@@ -1,7 +1,9 @@
1
+ import { SidebarProviderProps } from "../ui/sidebar-provider.js";
2
+ import "../ui/sidebar.js";
1
3
  import { FileExplorerBreadcrumb, FileExplorerColumn, FileExplorerEntry, FileExplorerEntryDetail, FileExplorerLocation, FileExplorerResolution, FileExplorerSearchResult } from "./file-explorer-data.js";
2
4
  import { ComponentProps, ReactNode } from "react";
3
5
  //#region src/blocks/file-explorer.d.ts
4
- export type FileExplorerBlockProps = Omit<ComponentProps<"div">, "children" | "defaultValue" | "onChange"> & {
6
+ export type FileExplorerBlockProps = Omit<ComponentProps<"div">, "children" | "defaultValue" | "onChange"> & Pick<SidebarProviderProps, "persistOpen" | "keyboardShortcut"> & {
5
7
  locations: readonly FileExplorerLocation[];
6
8
  activeLocationId?: string;
7
9
  defaultActiveLocationId?: string;
@@ -27,6 +29,6 @@ export type FileExplorerBlockProps = Omit<ComponentProps<"div">, "children" | "d
27
29
  detailsLabel?: string;
28
30
  layout?: "viewport" | "contained";
29
31
  };
30
- export declare function FileExplorerBlock({ locations, activeLocationId, defaultActiveLocationId, selectedPath, defaultSelectedPath, searchValue, defaultSearchValue, onActiveLocationChange, onSelectedPathChange, onSearchValueChange, onOpenEntry, sidebarTop, sidebarFooter, headerActions, headerMenuItems, searchPlaceholder, searchLabel, clearSearchLabel, searchResultsLabel, searchStatusLabel, backLabel, moreActionsLabel, detailsLabel, layout, className, style, ...props }: FileExplorerBlockProps): import("react").JSX.Element;
32
+ export declare function FileExplorerBlock({ locations, activeLocationId, defaultActiveLocationId, selectedPath, defaultSelectedPath, searchValue, defaultSearchValue, onActiveLocationChange, onSelectedPathChange, onSearchValueChange, onOpenEntry, sidebarTop, sidebarFooter, headerActions, headerMenuItems, searchPlaceholder, searchLabel, clearSearchLabel, searchResultsLabel, searchStatusLabel, backLabel, moreActionsLabel, detailsLabel, layout, persistOpen, keyboardShortcut, className, style, ...props }: FileExplorerBlockProps): import("react").JSX.Element;
31
33
  //#endregion
32
34
  export type { FileExplorerBreadcrumb, FileExplorerColumn, FileExplorerEntry, FileExplorerEntryDetail, FileExplorerLocation, FileExplorerResolution, FileExplorerSearchResult };
@@ -23,7 +23,7 @@ function defaultSearchStatusLabel(count, query) {
23
23
  if (count === 0) return `No results for “${query}”`;
24
24
  return count === 1 ? "1 result" : `${count} results`;
25
25
  }
26
- function FileExplorerBlock({ locations, activeLocationId, defaultActiveLocationId, selectedPath, defaultSelectedPath = [], searchValue, defaultSearchValue = "", onActiveLocationChange, onSelectedPathChange, onSearchValueChange, onOpenEntry, sidebarTop, sidebarFooter, headerActions, headerMenuItems, searchPlaceholder = "Search files", searchLabel = "Search files", clearSearchLabel = "Clear search", searchResultsLabel = "Search results", searchStatusLabel = defaultSearchStatusLabel, backLabel = "Go back", moreActionsLabel = "More actions", detailsLabel = "Details", layout = "viewport", className, style, ...props }) {
26
+ function FileExplorerBlock({ locations, activeLocationId, defaultActiveLocationId, selectedPath, defaultSelectedPath = [], searchValue, defaultSearchValue = "", onActiveLocationChange, onSelectedPathChange, onSearchValueChange, onOpenEntry, sidebarTop, sidebarFooter, headerActions, headerMenuItems, searchPlaceholder = "Search files", searchLabel = "Search files", clearSearchLabel = "Clear search", searchResultsLabel = "Search results", searchStatusLabel = defaultSearchStatusLabel, backLabel = "Go back", moreActionsLabel = "More actions", detailsLabel = "Details", layout = "viewport", persistOpen, keyboardShortcut, className, style, ...props }) {
27
27
  const [internalLocationId, setInternalLocationId] = useState(defaultActiveLocationId ?? locations[0]?.id);
28
28
  const [internalSelectedPath, setInternalSelectedPath] = useState(defaultSelectedPath);
29
29
  const [internalSearchValue, setInternalSearchValue] = useState(defaultSearchValue);
@@ -68,6 +68,8 @@ function FileExplorerBlock({ locations, activeLocationId, defaultActiveLocationI
68
68
  };
69
69
  return /* @__PURE__ */ jsxs(SidebarProvider, {
70
70
  layout,
71
+ persistOpen,
72
+ keyboardShortcut,
71
73
  className: cn("bg-background text-foreground", !contained && "h-svh overflow-hidden", className),
72
74
  style: providerStyle,
73
75
  ...props,
@@ -1,8 +1,10 @@
1
1
  import { Button } from "../ui/button.js";
2
+ import { SidebarProviderProps } from "../ui/sidebar-provider.js";
3
+ import "../ui/sidebar.js";
2
4
  import { SettingDefinition, SettingsControlProps, SettingsPageDefinition, SettingsSectionDefinition } from "./settings-data.js";
3
5
  import { ComponentProps, ReactNode } from "react";
4
6
  //#region src/blocks/settings.d.ts
5
- export type SettingsBlockProps = Omit<ComponentProps<"div">, "children"> & {
7
+ export type SettingsBlockProps = Omit<ComponentProps<"div">, "children"> & Pick<SidebarProviderProps, "persistOpen" | "keyboardShortcut"> & {
6
8
  pages: readonly SettingsPageDefinition[];
7
9
  activePageId?: string;
8
10
  defaultActivePageId?: string;
@@ -1,4 +1,4 @@
1
1
  //#region src/knob-contracts/range-knobs.d.ts
2
- export declare const rangeKnobs: readonly ["--cui-range-level-warning-background", "--cui-range-level-clip-background", "--cui-range-level-size", "--cui-range-level-scale-foreground", "--cui-range-indeterminate-size", "--cui-range-track-radius", "--cui-range-track-background", "--cui-range-indicator-radius", "--cui-range-indicator-background", "--cui-range-thumb-radius", "--cui-range-thumb-background", "--cui-range-thumb-border-color", "--cui-range-thumb-shadow"];
2
+ export declare const rangeKnobs: readonly ["--cui-range-level-warning-background", "--cui-range-level-clip-background", "--cui-range-level-muted-background", "--cui-range-level-size", "--cui-range-level-scale-foreground", "--cui-range-indeterminate-size", "--cui-range-track-radius", "--cui-range-track-background", "--cui-range-indicator-radius", "--cui-range-indicator-background", "--cui-range-thumb-radius", "--cui-range-thumb-background", "--cui-range-thumb-border-color", "--cui-range-thumb-shadow"];
3
3
  export type RangeKnobStyle = Partial<Record<(typeof rangeKnobs)[number], string>>;
4
4
  //#endregion
@@ -2,6 +2,7 @@
2
2
  const rangeKnobs = [
3
3
  "--cui-range-level-warning-background",
4
4
  "--cui-range-level-clip-background",
5
+ "--cui-range-level-muted-background",
5
6
  "--cui-range-level-size",
6
7
  "--cui-range-level-scale-foreground",
7
8
  "--cui-range-indeterminate-size",
@@ -2,6 +2,7 @@
2
2
  :where([data-control-family="range"][data-range-kind="level-meter"][data-slot="root"]) {
3
3
  --cui-range-level-warning-background: var(--warning);
4
4
  --cui-range-level-clip-background: var(--destructive);
5
+ --cui-range-level-muted-background: var(--muted-foreground);
5
6
  --cui-range-level-size: calc(var(--spacing) * 2);
6
7
  --cui-range-level-scale-foreground: var(--muted-foreground);
7
8
  --_range-level-peak-size: 2px;
@@ -96,6 +97,13 @@
96
97
  );
97
98
  }
98
99
 
100
+ :where(
101
+ [data-range-kind="level-meter"][data-slot="root"][data-muted]
102
+ [data-control-family="range"][data-range-kind="level-meter"]:is([data-slot="bar"], [data-slot="peak"])
103
+ ) {
104
+ background: var(--cui-range-level-muted-background);
105
+ }
106
+
99
107
  :where([data-control-family="range"][data-range-kind="level-meter"][data-slot="bar"]) {
100
108
  clip-path: inset(0 calc((1 - var(--_range-level, 0)) * 100%) 0 0 round var(--cui-range-indicator-radius));
101
109
  }
@@ -145,6 +153,12 @@
145
153
  initial-value: transparent;
146
154
  }
147
155
 
156
+ @property --cui-range-level-muted-background {
157
+ syntax: "<color>";
158
+ inherits: true;
159
+ initial-value: transparent;
160
+ }
161
+
148
162
  @property --cui-range-level-size {
149
163
  syntax: "<length-percentage>";
150
164
  inherits: true;
@@ -6,6 +6,7 @@ import { jsx } from "react/jsx-runtime";
6
6
  const ChannelStripTitleIdContext = createContext(null);
7
7
  function Mixer({ className, ...props }) {
8
8
  return /* @__PURE__ */ jsx("div", {
9
+ role: "group",
9
10
  "data-control-ui": "channel-strip",
10
11
  "data-control-family": "channel-strip",
11
12
  "data-slot": "mixer",
@@ -41,12 +42,12 @@ function ChannelStripHeader({ className, ...props }) {
41
42
  function ChannelStripTitle({ className, ...props }) {
42
43
  const titleId = use(ChannelStripTitleIdContext);
43
44
  return /* @__PURE__ */ jsx("span", {
44
- id: titleId ?? void 0,
45
45
  "data-control-ui": "channel-strip",
46
46
  "data-control-family": "channel-strip",
47
47
  "data-slot": "title",
48
48
  className: cn("min-w-0 flex-1 truncate text-caption", className),
49
- ...props
49
+ ...props,
50
+ id: titleId ?? void 0
50
51
  });
51
52
  }
52
53
  function ChannelStripActions({ className, ...props }) {
@@ -12,6 +12,7 @@ export type LevelMeterProps = Omit<ComponentProps<"div">, "style"> & {
12
12
  maxDb?: number;
13
13
  warningDb?: number;
14
14
  clipDb?: number;
15
+ muted?: boolean;
15
16
  orientation?: LevelMeterOrientation;
16
17
  style?: CSSProperties & RangeKnobStyle;
17
18
  };
@@ -28,7 +29,7 @@ export type LevelMeterScaleProps = Omit<ComponentProps<"div">, "style" | "childr
28
29
  ticks?: readonly number[];
29
30
  style?: CSSProperties & RangeKnobStyle;
30
31
  };
31
- export declare function LevelMeter({ value, source, minDb, maxDb, warningDb, clipDb, orientation, className, style, children, ref, ...props }: LevelMeterProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
32
+ export declare function LevelMeter({ value, source, minDb, maxDb, warningDb, clipDb, muted, orientation, className, style, children, ref, ...props }: LevelMeterProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
32
33
  export declare function LevelMeterTrack({ className, ...props }: LevelMeterTrackProps): import("react").JSX.Element;
33
34
  export declare function LevelMeterBar({ className, ...props }: LevelMeterBarProps): import("react").JSX.Element;
34
35
  export declare function LevelMeterPeak({ className, ...props }: LevelMeterPeakProps): import("react").JSX.Element;
@@ -77,7 +77,7 @@ function createLevelMeterPainter() {
77
77
  }
78
78
  };
79
79
  }
80
- function LevelMeter({ value, source, minDb = -60, maxDb = 0, warningDb = -18, clipDb = -6, orientation = "horizontal", className, style, children, ref, ...props }) {
80
+ function LevelMeter({ value, source, minDb = -60, maxDb = 0, warningDb = -18, clipDb = -6, muted = false, orientation = "horizontal", className, style, children, ref, ...props }) {
81
81
  const [painter] = useState(createLevelMeterPainter);
82
82
  const rootRef = useRef(null);
83
83
  const labelled = Boolean(props["aria-label"] || props["aria-labelledby"]);
@@ -130,6 +130,7 @@ function LevelMeter({ value, source, minDb = -60, maxDb = 0, warningDb = -18, cl
130
130
  "data-range-kind": "level-meter",
131
131
  "data-slot": "root",
132
132
  "data-orientation": orientation,
133
+ "data-muted": muted || void 0,
133
134
  className: cn("grid", className),
134
135
  style: zoneStyle,
135
136
  children: /* @__PURE__ */ jsx(LevelMeterScaleContext, {
package/dist/ui/toggle.js CHANGED
@@ -76,7 +76,7 @@ function ToggleGroup({ className, orientation = "horizontal", indicator, childre
76
76
  "data-orientation": orientation,
77
77
  "data-track": resolvedIndicator,
78
78
  orientation,
79
- className: cn(buttonTrackStructureClasses, "inline-flex items-center data-[track=hover]:gap-0", orientation === "vertical" && "flex-col", className),
79
+ className: cn(buttonTrackStructureClasses, "inline-flex items-center", orientation === "vertical" && "flex-col", className),
80
80
  ...props,
81
81
  children: [children, tracksHover ? /* @__PURE__ */ jsx(TrackHighlight, { className: "z-0" }) : null]
82
82
  })
package/package.json CHANGED
@@ -1,7 +1,25 @@
1
1
  {
2
2
  "name": "@ctrl-ui/react",
3
- "version": "0.9.2",
4
- "description": "Control UI components, blocks, and primitives with neutral defaults and consumer-owned themes.",
3
+ "version": "0.9.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
+ "keywords": [
6
+ "react",
7
+ "react-components",
8
+ "component-library",
9
+ "ui-components",
10
+ "shadcn",
11
+ "shadcn-ui",
12
+ "tailwindcss",
13
+ "design-system",
14
+ "base-ui",
15
+ "nextjs",
16
+ "color-picker",
17
+ "emoji-picker",
18
+ "tree-view",
19
+ "markdown-editor",
20
+ "ai-chat",
21
+ "chat-ui"
22
+ ],
5
23
  "license": "MIT",
6
24
  "repository": {
7
25
  "type": "git",