@alexgorbatchev/shadcn 0.0.43 → 0.0.45

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.
package/README.md CHANGED
@@ -270,6 +270,10 @@ The npm package includes the same index at `llms.txt` in its root and its linked
270
270
 
271
271
  Use the composed parts exported from the package root, such as `DialogTrigger`, `DialogContent`, and `DialogTitle`. Storybook provides working compositions, variants, disabled states, and action callbacks. The local preview starts with `bun run storybook` and binds to `127.0.0.1:6006`.
272
272
 
273
+ Set `wrap` on `ItemTitle` to keep complete titles visible in narrow items, including long names without spaces. The default title presentation remains unchanged.
274
+
275
+ `ToggleGroup` supports optional single selection by default and independent selections with `multiple`. Set `required` for a single selection that stays pressed when activated again by pointer, Space, or Enter. Required groups accept exactly one initial item through the controlled `value` or uncontrolled `defaultValue` tuple and cannot use `multiple`. Empty selection requests are canceled through Base UI before consumer callbacks or analytics run; accepted changes retain the native array value and event-details API. This selection rule does not add form submission or validation behavior.
276
+
273
277
  `ScrollArea` supplies a native scroll viewport and one vertical `ScrollBar` by default. Set `scrollbars={<ScrollBar orientation="horizontal" />}` for a wide horizontal layout, or supply a fragment containing vertical and horizontal parts for both axes. The tracks stay outside the viewport and reserve their shared corner. `keepMounted` belongs to `ScrollBar`; root and track className callbacks receive native overflow/scroll state. Focus the viewport for native keyboard scrolling.
274
278
 
275
279
  Scrolling is intentional: cards, panels, dialogs, sheets, and floating surfaces carry `data-scroll="none"`. Put long content in a nested `ScrollArea` or an explicitly styled native scroll viewport; the outer surface stays stationary. `DialogContent` bounds its height to the viewport and uses a flex column, so give a nested `ScrollArea` `className="min-h-0"` to let it shrink within the dialog. Headers and footers stay outside that scroll area when they need to remain visible.
@@ -4,7 +4,7 @@ import {
4
4
  import {
5
5
  ToggleGroup2,
6
6
  ToggleGroupItem2
7
- } from "./chunk-w9s21aj0.js";
7
+ } from "./chunk-q606kj28.js";
8
8
 
9
9
  // src/components/assistant-ui/elements/MessageActions.tsx
10
10
  import { CheckIcon, CopyIcon, EllipsisIcon, RefreshCwIcon, ThumbsDownIcon, ThumbsUpIcon } from "lucide-react";
@@ -19,7 +19,7 @@ import {
19
19
  import {
20
20
  ToggleGroup2,
21
21
  ToggleGroupItem2
22
- } from "./chunk-w9s21aj0.js";
22
+ } from "./chunk-q606kj28.js";
23
23
 
24
24
  // src/components/assistant-ui/elements/FeedbackDialog.tsx
25
25
  import { useId } from "react";
@@ -7,7 +7,7 @@ import {
7
7
  import {
8
8
  ToggleGroup2,
9
9
  ToggleGroupItem2
10
- } from "./chunk-w9s21aj0.js";
10
+ } from "./chunk-q606kj28.js";
11
11
  import {
12
12
  pct,
13
13
  announced
@@ -1333,11 +1333,11 @@ function ItemContent2({ density, className, ...props }) {
1333
1333
  ...props
1334
1334
  });
1335
1335
  }
1336
- function ItemTitle2({ density, className, ...props }) {
1336
+ function ItemTitle2({ density, className, wrap = false, ...props }) {
1337
1337
  return /* @__PURE__ */ jsx14("div", {
1338
1338
  "data-density": density,
1339
1339
  "data-slot": "item-title",
1340
- className: cn2("line-clamp-1 flex w-fit items-center gap-2 text-sm leading-snug font-medium underline-offset-4", className),
1340
+ className: cn2(!wrap && "line-clamp-1", "flex w-fit items-center gap-2 text-sm leading-snug font-medium underline-offset-4", wrap && "min-w-0 max-w-full wrap-anywhere", className),
1341
1341
  ...props
1342
1342
  });
1343
1343
  }
@@ -62,6 +62,7 @@ function ToggleGroup2({
62
62
  orientation = "horizontal",
63
63
  children,
64
64
  style,
65
+ required = false,
65
66
  ...props
66
67
  }) {
67
68
  const trackedOnValueChange = useAnalyticsCallback("ToggleGroup", analytics, { name: "ui.change-request" }, props.onValueChange);
@@ -78,7 +79,13 @@ function ToggleGroup2({
78
79
  }),
79
80
  className: (state) => cn2("group/toggle-group flex w-fit flex-row items-center rounded-sm data-[orientation=vertical]:flex-col data-[orientation=vertical]:items-stretch", typeof className === "function" ? className(state) : className),
80
81
  ...props,
81
- onValueChange: trackedOnValueChange,
82
+ onValueChange: (value, details) => {
83
+ if (required && value.length === 0) {
84
+ details.cancel();
85
+ return;
86
+ }
87
+ trackedOnValueChange(value, details);
88
+ },
82
89
  children: /* @__PURE__ */ jsx2(ToggleGroupContext.Provider, {
83
90
  value: { variant, size, spacing },
84
91
  children
@@ -19,8 +19,11 @@ type ItemMediaProps = ComponentProps<"div"> & VariantProps<typeof itemMediaVaria
19
19
  declare function ItemMedia({ density, className, variant, ...props }: ItemMediaProps): ReactElement;
20
20
  type ItemContentProps = ComponentProps<"div"> & IDensityProps;
21
21
  declare function ItemContent({ density, className, ...props }: ItemContentProps): ReactElement;
22
- type ItemTitleProps = ComponentProps<"div"> & IDensityProps;
23
- declare function ItemTitle({ density, className, ...props }: ItemTitleProps): ReactElement;
22
+ type ItemTitleProps = ComponentProps<"div"> & IDensityProps & {
23
+ /** Keep the complete title visible, including long unbroken names. */
24
+ wrap?: boolean;
25
+ };
26
+ declare function ItemTitle({ density, className, wrap, ...props }: ItemTitleProps): ReactElement;
24
27
  type ItemDescriptionProps = ComponentProps<"p"> & IDensityProps;
25
28
  declare function ItemDescription({ density, className, ...props }: ItemDescriptionProps): ReactElement;
26
29
  type ItemActionsProps = ComponentProps<"div"> & IDensityProps;
@@ -4,10 +4,24 @@ import { ToggleGroup as ToggleGroupPrimitive } from "@base-ui/react/toggle-group
4
4
  import type { VariantProps } from "class-variance-authority";
5
5
  import type { IDensityProps } from "../density/types.js";
6
6
  import { toggleVariants, type ToggleProps } from "./Toggle.js";
7
- export type ToggleGroupProps = IAnalyticsProps & ToggleGroupPrimitive.Props & VariantProps<typeof toggleVariants> & IDensityProps & IToggleGroupLayout;
7
+ export type ToggleGroupProps = IAnalyticsProps & Omit<ToggleGroupPrimitive.Props, "multiple" | "value" | "defaultValue"> & VariantProps<typeof toggleVariants> & IDensityProps & IToggleGroupLayout & (OptionalToggleGroupSelection | RequiredToggleGroupSelection);
8
+ type OptionalToggleGroupSelection = Pick<ToggleGroupPrimitive.Props, "multiple" | "value" | "defaultValue"> & {
9
+ required?: false;
10
+ };
11
+ type RequiredToggleGroupSelection = {
12
+ /** Keep one toggle pressed. Supply exactly one initial value. */
13
+ required: true;
14
+ multiple?: false;
15
+ } & ({
16
+ value: [string];
17
+ defaultValue?: [string];
18
+ } | {
19
+ value?: undefined;
20
+ defaultValue: [string];
21
+ });
8
22
  interface IToggleGroupLayout {
9
23
  spacing?: number;
10
24
  }
11
- export declare function ToggleGroup({ analytics, density, className, variant, size, spacing, orientation, children, style, ...props }: ToggleGroupProps): ReactElement;
25
+ export declare function ToggleGroup({ analytics, density, className, variant, size, spacing, orientation, children, style, required, ...props }: ToggleGroupProps): ReactElement;
12
26
  export declare function ToggleGroupItem({ density, className, variant, size, ...props }: ToggleProps): ReactElement;
13
27
  export {};
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  FeedbackDialog2
3
- } from "../../../chunk-0ybh8xre.js";
3
+ } from "../../../chunk-79vgr8w9.js";
4
4
  import"../../../chunk-6jpz5geq.js";
5
- import"../../../chunk-w9s21aj0.js";
5
+ import"../../../chunk-q606kj28.js";
6
6
  import"../../../chunk-bygq5yqf.js";
7
7
  import"../../../chunk-jcxxjkqx.js";
8
8
  import"../../../chunk-tq0pfv5h.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  MessageActions2
3
- } from "../../../chunk-634pk1cg.js";
4
- import"../../../chunk-w9s21aj0.js";
3
+ } from "../../../chunk-6475gsta.js";
4
+ import"../../../chunk-q606kj28.js";
5
5
  import"../../../chunk-38301e40.js";
6
6
  import"../../../chunk-x90xmrba.js";
7
7
  import"../../../chunk-jpvw9xqy.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  ReasoningEffort2
3
- } from "../../../chunk-3c35ysaq.js";
4
- import"../../../chunk-w9s21aj0.js";
3
+ } from "../../../chunk-dhmtrz6f.js";
4
+ import"../../../chunk-q606kj28.js";
5
5
  import"../../../chunk-5j39rehg.js";
6
6
  import"../../../chunk-5mydsjp3.js";
7
7
  import"../../../chunk-8ssktt4b.js";
@@ -259,10 +259,10 @@ import"../../chunk-f6rbv5gf.js";
259
259
  import {
260
260
  EveAskQuestion2
261
261
  } from "../../chunk-vg2j5044.js";
262
- import"../../chunk-w9s21aj0.js";
262
+ import"../../chunk-q606kj28.js";
263
263
  import {
264
264
  FeedbackDialog2
265
- } from "../../chunk-0ybh8xre.js";
265
+ } from "../../chunk-79vgr8w9.js";
266
266
  import {
267
267
  FileRoot2,
268
268
  FileIconDisplay2,
@@ -351,7 +351,7 @@ import {
351
351
  } from "../../chunk-1t959882.js";
352
352
  import {
353
353
  MessageActions2
354
- } from "../../chunk-634pk1cg.js";
354
+ } from "../../chunk-6475gsta.js";
355
355
  import {
356
356
  MessageAttachments2
357
357
  } from "../../chunk-wpa484a6.js";
@@ -461,7 +461,7 @@ import {
461
461
  } from "../../chunk-qv3b2jvc.js";
462
462
  import {
463
463
  ReasoningEffort2
464
- } from "../../chunk-3c35ysaq.js";
464
+ } from "../../chunk-dhmtrz6f.js";
465
465
  import {
466
466
  SwapLabel2
467
467
  } from "../../chunk-wgxs6b5t.js";
@@ -36,7 +36,7 @@ import {
36
36
  DrawerHeader2,
37
37
  DrawerTitle2,
38
38
  DrawerDescription2
39
- } from "../../chunk-3r0q02k6.js";
39
+ } from "../../chunk-pp0qdx0f.js";
40
40
  import {
41
41
  DropdownMenu2,
42
42
  DropdownMenuTrigger2,
@@ -112,7 +112,7 @@ import {
112
112
  Toggle2,
113
113
  ToggleGroup2,
114
114
  ToggleGroupItem2
115
- } from "../../chunk-w9s21aj0.js";
115
+ } from "../../chunk-q606kj28.js";
116
116
  import {
117
117
  Alert2,
118
118
  AlertTitle2,
package/dist/index.js CHANGED
@@ -178,7 +178,7 @@ import {
178
178
  StatusTracker2,
179
179
  DashboardLayout2,
180
180
  BillingUsage2
181
- } from "./chunk-3r0q02k6.js";
181
+ } from "./chunk-pp0qdx0f.js";
182
182
  import {
183
183
  Tabs2,
184
184
  tabsListVariants2,
@@ -301,7 +301,7 @@ import {
301
301
  Toggle2,
302
302
  ToggleGroup2,
303
303
  ToggleGroupItem2
304
- } from "./chunk-w9s21aj0.js";
304
+ } from "./chunk-q606kj28.js";
305
305
  import {
306
306
  Spinner2
307
307
  } from "./chunk-1xncv9gb.js";
package/dist/prototype.js CHANGED
@@ -2051,7 +2051,7 @@ var program = new Command;
2051
2051
  // package.json
2052
2052
  var package_default = {
2053
2053
  name: "@alexgorbatchev/shadcn",
2054
- version: "0.0.43",
2054
+ version: "0.0.45",
2055
2055
  description: "Sharp, monospace React components with compact and comfortable densities.",
2056
2056
  license: "MIT",
2057
2057
  repository: {
@@ -8,7 +8,8 @@ Source: src/components/stories/actions/ToggleGroup.stories.tsx
8
8
  ## Public imports
9
9
 
10
10
  ```tsx
11
- import { ToggleGroup, ToggleGroupItem, DirectionProvider, Field, FieldLabel, FieldDescription } from "@alexgorbatchev/shadcn";
11
+ import { ToggleGroup, ToggleGroupItem, DirectionProvider, Field, FieldLabel, FieldDescription, Button } from "@alexgorbatchev/shadcn";
12
+ import { AnalyticsProvider } from "@alexgorbatchev/shadcn/analytics";
12
13
  ```
13
14
 
14
15
  ## Supporting imports
@@ -61,6 +62,52 @@ Storybook CSF excerpts. Default args and render apply unless overridden. Local h
61
62
  {}
62
63
  ```
63
64
 
65
+ ### RequiredSingle
66
+
67
+ ```tsx
68
+ {
69
+ args: { required: true, defaultValue: ["bold"], variant: "outline", analytics: { id: "required-format" } },
70
+ beforeEach: () => {
71
+ trackRequiredChange.mockClear();
72
+ },
73
+ decorators: [
74
+ (Story) => (<AnalyticsProvider transport={{ track: trackRequiredChange }}>
75
+ <Story />
76
+ </AnalyticsProvider>),
77
+ ]
78
+ }
79
+ ```
80
+
81
+ ### RequiredControlled
82
+
83
+ ```tsx
84
+ {
85
+ beforeEach: () => {
86
+ submitRequiredForm.mockClear();
87
+ },
88
+ render: function Render(args) {
89
+ const [value, setValue] = useState<[
90
+ string
91
+ ]>(["bold"]);
92
+ return (<form onSubmit={(event) => {
93
+ event.preventDefault();
94
+ submitRequiredForm(value);
95
+ }}>
96
+ <ToggleGroup {...args} required multiple={false} value={value} defaultValue={undefined} onValueChange={(values, details) => {
97
+ const next = values[0];
98
+ if (next !== undefined)
99
+ setValue([next]);
100
+ args.onValueChange?.(values, details);
101
+ }}>
102
+ <ToggleGroupItem value="bold">Bold</ToggleGroupItem>
103
+ <ToggleGroupItem value="italic">Italic</ToggleGroupItem>
104
+ </ToggleGroup>
105
+ <Button type="submit">Apply formatting</Button>
106
+ </form>);
107
+ }
108
+ }
109
+ ```
110
+
64
111
  ### Multiple
65
112
 
66
113
  ```tsx
@@ -190,6 +190,45 @@ Storybook CSF excerpts. Default args and render apply unless overridden. Local h
190
190
  }
191
191
  ```
192
192
 
193
+ ### TitleMedia
194
+
195
+ ```tsx
196
+ {
197
+ render: (args) => (<Item {...args}>
198
+ <ItemContent>
199
+ <ItemTitle>
200
+ <ItemMedia>
201
+ <FileIcon data-testid="title-icon" aria-hidden="true"/>
202
+ </ItemMedia>
203
+ <span>Document title</span>
204
+ </ItemTitle>
205
+ </ItemContent>
206
+ </Item>)
207
+ }
208
+ ```
209
+
210
+ ### WrappedTitle
211
+
212
+ ```tsx
213
+ {
214
+ render: (args) => (<div data-testid="title-container" className="w-56">
215
+ <Item {...args} render={<dl />}>
216
+ <ItemContent>
217
+ <dt>
218
+ <ItemTitle wrap>
219
+ <ItemMedia>
220
+ <FileIcon aria-hidden="true"/>
221
+ </ItemMedia>
222
+ A long saved title with repeated details and a verylongunbrokenmarkertitlethatmustremainreadable
223
+ </ItemTitle>
224
+ </dt>
225
+ <dd>Saved item details</dd>
226
+ </ItemContent>
227
+ </Item>
228
+ </div>)
229
+ }
230
+ ```
231
+
193
232
  ### NativeSeparatorCallback
194
233
 
195
234
  ```tsx
package/llms/setup.md CHANGED
@@ -270,6 +270,10 @@ The npm package includes the same index at `llms.txt` in its root and its linked
270
270
 
271
271
  Use the composed parts exported from the package root, such as `DialogTrigger`, `DialogContent`, and `DialogTitle`. Storybook provides working compositions, variants, disabled states, and action callbacks. The local preview starts with `bun run storybook` and binds to `127.0.0.1:6006`.
272
272
 
273
+ Set `wrap` on `ItemTitle` to keep complete titles visible in narrow items, including long names without spaces. The default title presentation remains unchanged.
274
+
275
+ `ToggleGroup` supports optional single selection by default and independent selections with `multiple`. Set `required` for a single selection that stays pressed when activated again by pointer, Space, or Enter. Required groups accept exactly one initial item through the controlled `value` or uncontrolled `defaultValue` tuple and cannot use `multiple`. Empty selection requests are canceled through Base UI before consumer callbacks or analytics run; accepted changes retain the native array value and event-details API. This selection rule does not add form submission or validation behavior.
276
+
273
277
  `ScrollArea` supplies a native scroll viewport and one vertical `ScrollBar` by default. Set `scrollbars={<ScrollBar orientation="horizontal" />}` for a wide horizontal layout, or supply a fragment containing vertical and horizontal parts for both axes. The tracks stay outside the viewport and reserve their shared corner. `keepMounted` belongs to `ScrollBar`; root and track className callbacks receive native overflow/scroll state. Focus the viewport for native keyboard scrolling.
274
278
 
275
279
  Scrolling is intentional: cards, panels, dialogs, sheets, and floating surfaces carry `data-scroll="none"`. Put long content in a nested `ScrollArea` or an explicitly styled native scroll viewport; the outer surface stays stationary. `DialogContent` bounds its height to the viewport and uses a flex column, so give a nested `ScrollArea` `className="min-h-0"` to let it shrink within the dialog. Headers and footers stay outside that scroll area when they need to remain visible.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alexgorbatchev/shadcn",
3
- "version": "0.0.43",
3
+ "version": "0.0.45",
4
4
  "description": "Sharp, monospace React components with compact and comfortable densities.",
5
5
  "license": "MIT",
6
6
  "repository": {