@alexgorbatchev/shadcn 0.0.45 → 0.0.47

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
@@ -71,7 +71,7 @@ Import shared controls and providers from `@alexgorbatchev/shadcn`. Import the f
71
71
  | `/file-upload` | FileUpload selection and validation | `bun add react-dropzone@^20.1.4` |
72
72
  | `/color-picker` | ColorPicker | `bun add react-colorful@^5.8.1` |
73
73
  | `/image-crop` | ImageCrop and native export helpers | `bun add react-image-crop@^11.1.2` |
74
- | `/tree` | Tree, native hooks and features | `bun add @headless-tree/core@^1.8.0 @headless-tree/react@^1.8.0` |
74
+ | `/tree` | Tree, native hooks and features | `bun add @headless-tree/core@^1.8.0 @headless-tree/react@^1.8.0`; patched runtimes are bundled |
75
75
  | `/editor` | RichTextEditor, native Tiptap hooks and StarterKit | `bun add @tiptap/core@^3.32.0 @tiptap/react@^3.32.0 @tiptap/pm@^3.32.0 @tiptap/starter-kit@^3.32.0` |
76
76
  | `/event-calendar` | EventCalendar, EventForm and native calendar APIs | `bun add date-fns@^4.4.0`; TypeScript: `bun add -d @types/react-big-calendar@^1.16.3` |
77
77
  | `/gantt` | Gantt and Roadmap | `bun add date-fns@^4.4.0 @date-fns/tz@^1.5.0` |
@@ -86,7 +86,7 @@ import { ChartContainer, type ChartConfig } from "@alexgorbatchev/shadcn/chart";
86
86
  import { Carousel, CarouselContent, CarouselItem } from "@alexgorbatchev/shadcn/carousel";
87
87
  ```
88
88
 
89
- A production install of this package adds no third-party packages: every library is an optional peer that consumers install themselves, or is bundled into the package. Core peers are listed under Installation; feature peers are listed per entry point above. The patched `sonner`, `input-otp`, and `@shadcn/react` runtimes, and the calendar with its patched `uncontrollable` wrapper, are bundled so consumers receive the fixes even when their package manager does not apply Bun patches; consumers of those three entry points still install the upstream packages for the types the declarations reference; the calendar runtime stays isolated behind `/event-calendar`. Install `@base-ui/utils` at the exact version `@base-ui/react` requires, so the portal components share Base UI's own ref merging without a second copy. Shared providers work across entry points.
89
+ A production install of this package adds no third-party packages: every library is an optional peer that consumers install themselves, or is bundled into the package. Core peers are listed under Installation; feature peers are listed per entry point above. The patched `sonner`, `input-otp`, `@shadcn/react`, and Headless Tree runtimes, and the calendar with its patched `uncontrollable` wrapper, are bundled so consumers receive the fixes even when their package manager does not apply Bun patches. Install their upstream peers for the types the declarations reference; the tree runtime stays behind `/tree` and the calendar runtime behind `/event-calendar`. Import tree hooks and features from this package's `/tree` entry point so they use the bundled native implementation. Install `@base-ui/utils` at the exact version `@base-ui/react` requires, so the portal components share Base UI's own ref merging without a second copy. Shared providers work across entry points.
90
90
 
91
91
  The optional assistant-ui catalog provides presentational families under `/assistant-ui/<family>` and runtime adapters under `/assistant-ui/native/<family>`. For example, import `ApprovalCard` from `@alexgorbatchev/shadcn/assistant-ui/approval-card`. Add `@alexgorbatchev/shadcn/assistant-ui.css` to your stylesheet. Native threads require an actual assistant-ui runtime and the selected family's optional peers. See the [assistant-ui reference](./docs/internal/assistant-ui.md) for imports, dependency-bearing styles, source inventory, and the SelectionToolbar isolation limitation.
92
92
 
@@ -368,6 +368,14 @@ Compose `QuestionnaireItem`, `QuestionnaireTitle`, and answer controls inside `Q
368
368
 
369
369
  Column `meta.filter` offers a column in `DataGridFilters`, hidden columns included. A `range` filter edits `[min, max]` bounds, `null` for an open end, for `filterFn: "inNumberRange"`; its inputs suggest the range of the rows the other filters leave, formatted through the filter's `Intl.NumberFormatOptions`. An `options` filter chooses among labelled string values, one or several, listed in its `options` or, when they depend on runtime data, in the `options` prop of `DataGridFilters` and `DataGridFilterSummary` keyed by column ID, for `filterFn: "arrHas"` (one value per row), `"arrIncludesSome"` (an array per row), or a custom `filterFn`; each option counts the rows the other filters leave with that value, so a column whose rows hold several values or values in another form supplies them through `getUniqueValues`. Column filters combine with each other and with the global filter. `DataGridFilterSummary` lists the active filters with buttons that remove them, and both controls clear every column filter at once.
370
370
 
371
+ Import `DataGridSelectHeader` and `DataGridSelectCell` from `@alexgorbatchev/shadcn/data-grid`. Pass the current `useTable` result as `table` to both controls, and pass `row` and an accessible `label` to each cell. The header selects selectable filtered rows across all pages and preserves selections hidden by filters. It shows a mixed state when some of those rows are selected and disables itself when none are selectable. Its default label is "Select all filtered rows"; provide `label` to name the scope in your application. Cells follow native row selection rules, including disabled rows and partially selected parents. The controls observe selection changes without requiring the parent table selector to include selection state.
372
+
373
+ `TreeItem linkProps` places the registered tree item, roving focus, and native drag handlers on an anchor. Pass `href` and anchor events directly, or compose a router link through `linkProps.render`. The outer `render` and `ref` remain available for row overlays; disclosure and `endEnhancer` controls remain siblings of the link. Enter and modified clicks retain native link behavior, while tree arrows retain navigation and expansion behavior. Optional `dropHint={{ content, open, side }}` displays caller-controlled drag feedback without adding a focus target.
374
+
375
+ Embedded actions, links, menus, editable fields, and media controls retain their own keyboard behavior. Registered anchor and button rows still participate in tree navigation; rename and search inputs retain their completion and cancellation shortcuts.
376
+
377
+ `PageHeader` accepts an optional `eyebrow` above its single page title. It accepts any React content without introducing another heading. Breadcrumbs, description, actions, and density remain independent slots; long action content wraps within narrow layouts.
378
+
371
379
  `StarRating` takes a controlled numeric `value` from 0 to 5, `onValueChange`, and an accessible `label`. Its native radio buttons support keyboard selection and an Unrated option to clear the rating. Set `disabled` while saving. `Avatar shape="square"` displays square artwork with matching image, fallback, and border corners.
372
380
 
373
381
  `DialogContent size="wide"` uses a desktop maximum width of 576px; `size="narrow"` uses 192px, and the default uses 384px. Dialogs remain bounded by the viewport. `FieldGroup columns={2}` arranges fields in two columns on desktop and one on mobile.
@@ -3140,7 +3140,7 @@ function AppShell2({
3140
3140
  }
3141
3141
  // src/components/PageHeader.tsx
3142
3142
  import { jsx as jsx32, jsxs as jsxs19 } from "react/jsx-runtime";
3143
- function PageHeader2({ title, description, breadcrumbs, actions, density }) {
3143
+ function PageHeader2({ title, eyebrow, description, breadcrumbs, actions, density }) {
3144
3144
  return /* @__PURE__ */ jsxs19("header", {
3145
3145
  "data-density": density,
3146
3146
  "data-slot": "page-header",
@@ -3154,6 +3154,10 @@ function PageHeader2({ title, description, breadcrumbs, actions, density }) {
3154
3154
  /* @__PURE__ */ jsxs19("div", {
3155
3155
  className: "min-w-0",
3156
3156
  children: [
3157
+ eyebrow != null && /* @__PURE__ */ jsx32("div", {
3158
+ className: "mb-2 text-xs font-medium tracking-widest text-muted-foreground",
3159
+ children: eyebrow
3160
+ }),
3157
3161
  /* @__PURE__ */ jsx32("h1", {
3158
3162
  className: "text-xl font-semibold text-foreground",
3159
3163
  children: title
@@ -3165,7 +3169,7 @@ function PageHeader2({ title, description, breadcrumbs, actions, density }) {
3165
3169
  ]
3166
3170
  }),
3167
3171
  actions && /* @__PURE__ */ jsx32("div", {
3168
- className: "flex shrink-0 flex-wrap items-center gap-control-gap",
3172
+ className: "flex min-w-0 max-w-full flex-wrap items-center gap-control-gap wrap-anywhere",
3169
3173
  children: actions
3170
3174
  })
3171
3175
  ]
@@ -7,7 +7,7 @@ import {
7
7
 
8
8
  // src/components/Checkbox.tsx
9
9
  import { Checkbox as CheckboxPrimitive } from "@base-ui/react/checkbox";
10
- import { CheckIcon } from "lucide-react";
10
+ import { CheckIcon, MinusIcon } from "lucide-react";
11
11
  import { jsx } from "react/jsx-runtime";
12
12
  function Checkbox2({ analytics, density, className, ...props }) {
13
13
  const trackedOnCheckedChange = useAnalyticsCallback("Checkbox", analytics, { name: "ui.change-request" }, props.onCheckedChange);
@@ -20,7 +20,14 @@ function Checkbox2({ analytics, density, className, ...props }) {
20
20
  children: /* @__PURE__ */ jsx(CheckboxPrimitive.Indicator, {
21
21
  "data-slot": "checkbox-indicator",
22
22
  className: "grid place-content-center text-current transition-none [&>svg]:size-3.5",
23
- children: /* @__PURE__ */ jsx(CheckIcon, {})
23
+ render: (indicatorProps, state) => /* @__PURE__ */ jsx("span", {
24
+ ...indicatorProps,
25
+ children: state.indeterminate ? /* @__PURE__ */ jsx(MinusIcon, {
26
+ "data-slot": "checkbox-mixed-indicator"
27
+ }) : /* @__PURE__ */ jsx(CheckIcon, {
28
+ "data-slot": "checkbox-checked-indicator"
29
+ })
30
+ })
24
31
  })
25
32
  });
26
33
  }
@@ -9,7 +9,7 @@ import {
9
9
  } from "./chunk-1xncv9gb.js";
10
10
  import {
11
11
  Checkbox2
12
- } from "./chunk-9w9berq8.js";
12
+ } from "./chunk-caz81rnv.js";
13
13
  import {
14
14
  useReceiptFocus
15
15
  } from "./chunk-vxvaaptq.js";
@@ -6,7 +6,7 @@ import {
6
6
  } from "./chunk-vxvaaptq.js";
7
7
  import {
8
8
  OptionList2
9
- } from "./chunk-k455qwx2.js";
9
+ } from "./chunk-dy4ghe9p.js";
10
10
 
11
11
  // src/components/assistant-ui/elements/QuestionFlow.tsx
12
12
  import { useCallback, useId, useLayoutEffect, useRef, useState } from "react";
@@ -2,10 +2,12 @@ import type { ReactElement, ReactNode } from "react";
2
2
  import type { IDensityProps } from "../density/types.js";
3
3
  type PageHeaderProps = IDensityProps & {
4
4
  title: string;
5
+ /** Context above the page title without introducing another heading. */
6
+ eyebrow?: ReactNode;
5
7
  description?: ReactNode;
6
8
  breadcrumbs?: ReactNode;
7
9
  actions?: ReactNode;
8
10
  };
9
- declare function PageHeader({ title, description, breadcrumbs, actions, density }: PageHeaderProps): ReactElement;
11
+ declare function PageHeader({ title, eyebrow, description, breadcrumbs, actions, density }: PageHeaderProps): ReactElement;
10
12
  export { PageHeader };
11
13
  export type { PageHeaderProps };
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  OptionList2
3
- } from "../../../chunk-k455qwx2.js";
3
+ } from "../../../chunk-dy4ghe9p.js";
4
4
  import"../../../chunk-71efbr5n.js";
5
5
  import"../../../chunk-vxvaaptq.js";
6
6
  import"../../../chunk-1xncv9gb.js";
7
- import"../../../chunk-9w9berq8.js";
7
+ import"../../../chunk-caz81rnv.js";
8
8
  import"../../../chunk-38301e40.js";
9
9
  import"../../../chunk-x90xmrba.js";
10
10
  import"../../../chunk-jpvw9xqy.js";
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  QuestionFlow2
3
- } from "../../../chunk-55s7v2mw.js";
4
- import"../../../chunk-k455qwx2.js";
3
+ } from "../../../chunk-mqea74ex.js";
4
+ import"../../../chunk-dy4ghe9p.js";
5
5
  import"../../../chunk-71efbr5n.js";
6
6
  import"../../../chunk-vxvaaptq.js";
7
7
  import"../../../chunk-1xncv9gb.js";
8
- import"../../../chunk-9w9berq8.js";
8
+ import"../../../chunk-caz81rnv.js";
9
9
  import"../../../chunk-38301e40.js";
10
10
  import"../../../chunk-x90xmrba.js";
11
11
  import"../../../chunk-jpvw9xqy.js";
@@ -427,13 +427,13 @@ import {
427
427
  OpenAILogo2
428
428
  } from "../../chunk-pa07b92f.js";
429
429
  import"../../chunk-1xncv9gb.js";
430
- import"../../chunk-9w9berq8.js";
430
+ import"../../chunk-caz81rnv.js";
431
431
  import {
432
432
  OptionText2
433
433
  } from "../../chunk-71efbr5n.js";
434
434
  import {
435
435
  OptionList2
436
- } from "../../chunk-k455qwx2.js";
436
+ } from "../../chunk-dy4ghe9p.js";
437
437
  import {
438
438
  PermissionGrant2
439
439
  } from "../../chunk-8jnfvgvk.js";
@@ -442,7 +442,7 @@ import {
442
442
  } from "../../chunk-10t1w38s.js";
443
443
  import {
444
444
  QuestionFlow2
445
- } from "../../chunk-55s7v2mw.js";
445
+ } from "../../chunk-mqea74ex.js";
446
446
  import {
447
447
  QuotaBanner2
448
448
  } from "../../chunk-zp3wrbve.js";
@@ -0,0 +1,12 @@
1
+ import { type RowData } from "@tanstack/react-table";
2
+ import type { ReactElement } from "react";
3
+ import type { IDensityProps } from "../../density/types.js";
4
+ import type { DataGridRow, IDataGridControlProps } from "./DataGrid.js";
5
+ interface DataGridSelectCellProps<T extends RowData> extends IDensityProps, IDataGridControlProps<T> {
6
+ row: DataGridRow<T>;
7
+ /** Names this row's selection control, such as "Select project Atlas". */
8
+ label: string;
9
+ }
10
+ /** Uses the row's native selection rules, including disabled and partially selected parent rows. */
11
+ export declare function DataGridSelectCell<T extends RowData>({ row, table, label, density, }: DataGridSelectCellProps<T>): ReactElement;
12
+ export type { DataGridSelectCellProps };
@@ -0,0 +1,8 @@
1
+ import { type RowData } from "@tanstack/react-table";
2
+ import type { ReactElement } from "react";
3
+ import type { IDensityProps } from "../../density/types.js";
4
+ import type { IDataGridControlProps } from "./DataGrid.js";
5
+ type DataGridSelectHeaderProps<T extends RowData> = IDataGridControlProps<T> & IDensityProps;
6
+ /** Selects the selectable filtered rows across every page, preserving selections hidden by filters. */
7
+ export declare function DataGridSelectHeader<T extends RowData>({ table, label, density, }: DataGridSelectHeaderProps<T>): ReactElement;
8
+ export type { DataGridSelectHeaderProps };
@@ -3,3 +3,7 @@ export type { DataGridColumn, DataGridColumnFilter, DataGridFeatures, DataGridPr
3
3
  export { DataGridColumnOptions } from "./DataGridColumnOptions.js";
4
4
  export { DataGridFilters } from "./DataGridFilters.js";
5
5
  export { DataGridFilterSummary } from "./DataGridFilterSummary.js";
6
+ export { DataGridSelectHeader } from "./DataGridSelectHeader.js";
7
+ export type { DataGridSelectHeaderProps } from "./DataGridSelectHeader.js";
8
+ export { DataGridSelectCell } from "./DataGridSelectCell.js";
9
+ export type { DataGridSelectCellProps } from "./DataGridSelectCell.js";
@@ -22,7 +22,7 @@ import {
22
22
  } from "../../chunk-77xfccfq.js";
23
23
  import {
24
24
  Checkbox2
25
- } from "../../chunk-9w9berq8.js";
25
+ } from "../../chunk-caz81rnv.js";
26
26
  import {
27
27
  Label2
28
28
  } from "../../chunk-jcxxjkqx.js";
@@ -514,6 +514,56 @@ function DataGridFilterSummary({
514
514
  }
515
515
  });
516
516
  }
517
+ // src/components/data-grid/DataGridSelectHeader.tsx
518
+ import { Subscribe as Subscribe4 } from "@tanstack/react-table";
519
+ import { jsx as jsx4 } from "react/jsx-runtime";
520
+ function DataGridSelectHeader({
521
+ table,
522
+ label = "Select all filtered rows",
523
+ density
524
+ }) {
525
+ return /* @__PURE__ */ jsx4(Subscribe4, {
526
+ source: table.store,
527
+ selector: (state) => ({
528
+ selection: state.rowSelection,
529
+ filters: state.columnFilters,
530
+ filter: state.globalFilter
531
+ }),
532
+ children: () => {
533
+ const rows = table.getFilteredRowModel().flatRows.filter((row) => row.getCanSelect() && row.getParentRows().every((parent) => parent.getCanSelectSubRows()));
534
+ const selected = rows.filter((row) => row.getIsSelected()).length;
535
+ return /* @__PURE__ */ jsx4(Checkbox2, {
536
+ "aria-label": label,
537
+ density,
538
+ disabled: rows.length === 0,
539
+ checked: rows.length > 0 && selected === rows.length,
540
+ indeterminate: selected > 0 && selected < rows.length,
541
+ onCheckedChange: (checked) => table.toggleAllRowsSelected(checked)
542
+ });
543
+ }
544
+ });
545
+ }
546
+ // src/components/data-grid/DataGridSelectCell.tsx
547
+ import { Subscribe as Subscribe5 } from "@tanstack/react-table";
548
+ import { jsx as jsx5 } from "react/jsx-runtime";
549
+ function DataGridSelectCell({
550
+ row,
551
+ table,
552
+ label,
553
+ density
554
+ }) {
555
+ return /* @__PURE__ */ jsx5(Subscribe5, {
556
+ source: table.atoms.rowSelection,
557
+ children: () => /* @__PURE__ */ jsx5(Checkbox2, {
558
+ "aria-label": label,
559
+ density,
560
+ checked: row.getIsSelected(),
561
+ indeterminate: row.getIsSomeSelected(),
562
+ disabled: !row.getCanSelect(),
563
+ onCheckedChange: (checked) => row.toggleSelected(checked)
564
+ })
565
+ });
566
+ }
517
567
  export {
518
568
  DataGrid2 as DataGrid,
519
569
  DataGridCells2 as DataGridCells,
@@ -523,5 +573,7 @@ export {
523
573
  DataGridFilterSummary,
524
574
  DataGridFilters,
525
575
  DataGridPagination2 as DataGridPagination,
576
+ DataGridSelectCell,
577
+ DataGridSelectHeader,
526
578
  dataGridFeatures2 as dataGridFeatures
527
579
  };
@@ -22,7 +22,7 @@ import {
22
22
  } from "../../chunk-0fmrwsgp.js";
23
23
  import {
24
24
  Checkbox2
25
- } from "../../chunk-9w9berq8.js";
25
+ } from "../../chunk-caz81rnv.js";
26
26
  import {
27
27
  Spinner2
28
28
  } from "../../chunk-1xncv9gb.js";
@@ -36,7 +36,7 @@ import {
36
36
  DrawerHeader2,
37
37
  DrawerTitle2,
38
38
  DrawerDescription2
39
- } from "../../chunk-pp0qdx0f.js";
39
+ } from "../../chunk-0qgd06td.js";
40
40
  import {
41
41
  DropdownMenu2,
42
42
  DropdownMenuTrigger2,
@@ -105,7 +105,7 @@ import {
105
105
  import"../../chunk-9de1htr5.js";
106
106
  import {
107
107
  Checkbox2
108
- } from "../../chunk-9w9berq8.js";
108
+ } from "../../chunk-caz81rnv.js";
109
109
  import"../../chunk-1j2hz3w9.js";
110
110
  import"../../chunk-k99h6evz.js";
111
111
  import {
@@ -17,7 +17,15 @@ type TreeItemProps<T> = useRender.ComponentProps<"div", TreeItemState> & IDensit
17
17
  expandOn?: "click" | "doubleClick" | "disclosure";
18
18
  isEditing?: boolean;
19
19
  isDropTarget?: boolean;
20
+ /** The registered native link owns row focus; disclosure and actions remain siblings. */
21
+ linkProps?: useRender.ComponentProps<"a", TreeItemState>;
22
+ /** Domain-controlled drag feedback; omitted rows have no tooltip wrapper. */
23
+ dropHint?: {
24
+ content: ReactNode;
25
+ open: boolean;
26
+ side?: "top" | "right" | "bottom" | "left";
27
+ };
20
28
  };
21
29
  /** Registered tree row; compose menus with render and place counts/actions in endEnhancer. */
22
- export declare function TreeItem<T>({ analytics, item, children, startEnhancer, endEnhancer, expandOn, isEditing, isDropTarget, density, render, ref, ...props }: TreeItemProps<T>): ReactElement;
30
+ export declare function TreeItem<T>({ analytics, item, children, startEnhancer, endEnhancer, expandOn, isEditing, isDropTarget, linkProps, dropHint, density, render, ref, ...props }: TreeItemProps<T>): ReactElement;
23
31
  export type { TreeItemProps };