Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 36 additions & 14 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,6 @@ Components are split across two entry points:

**Data Display:**

- **DataTable** - Advanced data table with virtualization, sorting, filtering
- **Avatar** - User avatar with image/initials fallback

**Navigation:**
Expand All @@ -251,6 +250,25 @@ Components are split across two entry points:
- **StatusBar** - VSCode-style status bar
- **Hero** - Hero section component

### DataTable (`baukasten-ui/data-table`)

- **DataTable** - Advanced data table with virtualization, sorting, filtering

DataTable has its own entry point because it is the only component that needs
`@tanstack/react-table`. Keeping it out of the `extra` and root barrels is what
makes that peer dependency genuinely optional: Rollup resolves re-exported
modules whether or not their exports are used, so a single re-export from a
barrel would force every consumer of that barrel to install the package.

```tsx
import { DataTable, type ColumnDef } from 'baukasten-ui/data-table';
```

The related helpers and types — `createSelectColumn`, `useDataTable`,
`useDataTableData`, `applyDataTransaction`, `mergeTransactions`, `ColumnDef`,
`SortingState`, `PaginationState`, `RowSelectionState`, `ColumnResizeMode`,
`Row` — are exported from the same entry.

## Key Technical Details

### Build System
Expand All @@ -262,28 +280,32 @@ Components are split across two entry points:

### Package Exports

Main package (`baukasten-ui`) provides three entry points:
Main package (`baukasten-ui`) provides four entry points:

- `baukasten-ui` (`.`) — All components and types (re-exports core + extra)
- `baukasten-ui` (`.`) — All components and types (re-exports core + extra; **not** DataTable)
- `baukasten-ui/core` (`./core`) — Fundamental primitives (Button, Input, Icon, Typography, etc.)
- `baukasten-ui/extra` (`./extra`) — Higher-level compositions (DataTable, Tabs, Menu, etc.)
- `baukasten-ui/styles` (`./styles`) — Design token utilities
- `baukasten-ui/extra` (`./extra`) — Higher-level compositions (Tabs, Menu, Tree, etc.)
- `baukasten-ui/data-table` (`./data-table`) — DataTable and its helpers/types

Design tokens and style utilities come from `baukasten-ui/core`, which re-exports all of `src/styles`. There is no separate `./styles` subpath — one was declared for a long time but never built, so it never resolved.

**Core components** (23 families): Icon, IconButton, Button, Input, TextArea, Checkbox, Radio/RadioGroup, Select, Slider, Label, FieldLabel, FormGroup, FormHelper, Typography (Heading/Text/Paragraph/Code/Link/Image), Badge, Tag, Table, Alert, Spinner, ProgressBar, Tooltip, Modal, Divider, Dropdown, PortalProvider, Styles, GlobalStyles

**Extra components** (14 families): DataTable, Tabs, Breadcrumbs, Pagination, Menu, ContextMenu, ButtonGroup, FileUpload, Accordion, SplitPane, StatusBar, Hero, Avatar
**Extra components**: Tabs, Breadcrumbs, Pagination, Menu, ContextMenu, ButtonGroup, FileUpload, Combobox, Drawer, Accordion, SplitPane, StatusBar, Hero, Avatar, Tree

`@tanstack/react-table` is a genuinely **optional peer dependency**, needed only if you import `baukasten-ui/data-table`. Nothing reachable from `.`, `./core` or `./extra` references it, so consumers who do not use DataTable never install it and never bundle it.

`@tanstack/react-table` is an **optional peer dependency** — only needed when importing DataTable from extra.
**Do not re-export DataTable from `extra.ts` or `index.ts`.** Rollup resolves re-exported modules regardless of whether their exports are used, so one re-export makes the peer dependency mandatory for every consumer of that barrel — which is exactly the bug the separate entry point fixes.

### Core / Extra Split Criteria

| Criterion | Core | Extra |
| ------------------------ | ----------------------------------------------------- | -------------------------------------------- |
| **Usage frequency** | Used in 80%+ of UIs | Used in specific scenarios |
| **Complexity** | Atomic / molecular | Composed from multiple core components |
| **External deps** | Only `clsx`, `@floating-ui/react`, `@vscode/codicons` | `@tanstack/react-table` or future heavy deps |
| **Cross-component deps** | May depend on Icon and styles only | May depend on any core component |
| **Self-contained** | Can work alone with just styles | Needs core components at runtime |
| Criterion | Core | Extra |
| ------------------------ | ----------------------------------------------------- | ------------------------------------------------------------------------------------------ |
| **Usage frequency** | Used in 80%+ of UIs | Used in specific scenarios |
| **Complexity** | Atomic / molecular | Composed from multiple core components |
| **External deps** | Only `clsx`, `@floating-ui/react`, `@vscode/codicons` | Same as core — a heavy optional dep earns its own entry point instead (see `./data-table`) |
| **Cross-component deps** | May depend on Icon and styles only | May depend on any core component |
| **Self-contained** | Can work alone with just styles | Needs core components at runtime |

**Key rule**: Extra can import from Core. Core **never** imports from Extra.

Expand Down
3 changes: 3 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 8 additions & 7 deletions packages/baukasten/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,29 @@
],
"license": "MIT",
"type": "module",
"main": "./dist/index.js",
"main": "./dist/index.cjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.js"
"require": "./dist/index.cjs"
},
"./core": {
"types": "./dist/core.d.ts",
"import": "./dist/core.mjs",
"require": "./dist/core.js"
"require": "./dist/core.cjs"
},
"./extra": {
"types": "./dist/extra.d.ts",
"import": "./dist/extra.mjs",
"require": "./dist/extra.js"
"require": "./dist/extra.cjs"
},
"./styles": {
"import": "./dist/styles.mjs",
"require": "./dist/styles.js"
"./data-table": {
"types": "./dist/data-table.d.ts",
"import": "./dist/data-table.mjs",
"require": "./dist/data-table.cjs"
},
"./dist/baukasten-base.css": "./dist/baukasten-base.css",
"./dist/baukasten-vscode.css": "./dist/baukasten-vscode.css",
Expand Down
34 changes: 7 additions & 27 deletions packages/baukasten/src/extra.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,33 +13,13 @@

// ─── Data ───────────────────────────────────────────────────────────────────

export {
DataTable,
createSelectColumn,
useDataTable,
useDataTableData,
applyDataTransaction,
mergeTransactions,
} from './components/DataTable';
export type {
AsyncTransactionsFlushedEvent,
DataTableProps,
DataTableVariant,
DataTableColumnAlign,
DataTableRef,
DataTableTransaction,
DataTableTransactionResult,
DataTableTransactionWarning,
UndoableDataTableTransactionResult,
UseDataTableDataOptions,
UseDataTableDataReturn,
ColumnDef,
SortingState,
PaginationState,
RowSelectionState,
ColumnResizeMode,
Row,
} from './components/DataTable';
// DataTable lives at "baukasten-ui/data-table", not here. It is the only
// component that needs @tanstack/react-table, and a re-export from this barrel
// forces every consumer of `extra` — or of the root entry, which re-exports
// this file — to resolve that package whether or not they use the table.
// Rollup resolves re-exported modules regardless of whether their exports are
// used, so the separate entry point is what makes the peer dependency
// genuinely optional.

// ─── Navigation ─────────────────────────────────────────────────────────────

Expand Down
16 changes: 15 additions & 1 deletion packages/baukasten/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,24 @@ export default defineConfig({
index: resolve(__dirname, 'src/index.ts'),
core: resolve(__dirname, 'src/core.ts'),
extra: resolve(__dirname, 'src/extra.ts'),
/**
* DataTable is the only code that touches @tanstack/react-table, and is
* deliberately NOT re-exported from `extra` or the root barrel: Rollup
* resolves re-exported modules whether or not their exports are used, so
* a single re-export would force every consumer of those barrels to
* install the package. Keeping it to its own entry is what makes the
* peer dependency genuinely optional.
*/
'data-table': resolve(__dirname, 'src/components/DataTable/index.ts'),
},
name: 'Baukasten',
formats: ['es', 'cjs'],
fileName: (format, entryName) => `${entryName}.${format === 'es' ? 'mjs' : 'js'}`,
// `.cjs`, not `.js`: package.json sets "type": "module", so Node parses any
// `.js` file in this package as ESM. Naming the CommonJS build `.js` made
// every require() of the package die with "exports is not defined" on its
// first statement. Vite names the shared chunks `.cjs` itself — only these
// entry files go through this callback, which is why the build looked right.
fileName: (format, entryName) => `${entryName}.${format === 'es' ? 'mjs' : 'cjs'}`,
cssFileName: 'baukasten-base',
},
rollupOptions: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { ColumnDef, Row } from '@tanstack/react-table'
import { Badge, DataTable } from 'baukasten-ui'
import { Badge } from 'baukasten-ui'
import { DataTable } from 'baukasten-ui/data-table'
import React, { useMemo } from 'react'
import { LOG_LEVEL_COLORS, LogEntry } from '../types/log'

Expand Down
1 change: 1 addition & 0 deletions packages/examples/vscode-db-explorer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"vite": "^6.0.0"
},
"dependencies": {
"@tanstack/react-table": "^8.21.3",
"baukasten-ui": "*",
"react": "^19.0.0",
"react-dom": "^19.0.0"
Expand Down
2 changes: 1 addition & 1 deletion packages/examples/vscode-db-explorer/src/webview/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ import {
Badge,
Tag,
Select,
DataTable,
StatusBar,
StatusBarSection,
StatusBarItem,
} from 'baukasten-ui';
import { DataTable } from 'baukasten-ui/data-table';
import './App.css';

// ─── Mock data ───────────────────────────────────────────────────────────────
Expand Down
1 change: 1 addition & 0 deletions packages/examples/vscode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"vite": "^6.0.0"
},
"dependencies": {
"@tanstack/react-table": "^8.21.3",
"baukasten-ui": "*",
"react": "^19.0.0",
"react-dom": "^19.0.0"
Expand Down
3 changes: 2 additions & 1 deletion packages/examples/vscode/src/webview/components/LogTable.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { ColumnDef, Row } from '@tanstack/react-table';
import { Badge, DataTable } from 'baukasten-ui';
import { Badge } from 'baukasten-ui';
import { DataTable } from 'baukasten-ui/data-table';
import React, { useMemo } from 'react';
import { LOG_LEVEL_COLORS, LogEntry } from '../types/log';

Expand Down
1 change: 1 addition & 0 deletions packages/website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"lint": "next lint"
},
"dependencies": {
"@tanstack/react-table": "^8.21.3",
"@types/flexsearch": "^0.7.6",
"baukasten-ui": "*",
"baukasten-ui-web-wrapper": "*",
Expand Down
22 changes: 11 additions & 11 deletions packages/website/src/app/components/datatable/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import { useState, useMemo, useRef } from 'react';
import PageLayout from '@/components/PageLayout';
import { Showcase, PropDefinition } from '@/components/ComponentShowcase';
import { Badge, Button, Heading } from 'baukasten-ui/core';
import { DataTable, createSelectColumn, useDataTableData } from 'baukasten-ui/extra';
import { DataTable, createSelectColumn, useDataTableData } from 'baukasten-ui/data-table';
import type {
ColumnDef,
SortingState,
PaginationState,
RowSelectionState,
DataTableRef,
} from 'baukasten-ui/extra';
} from 'baukasten-ui/data-table';

const dataTableProps: PropDefinition[] = [
{
Expand Down Expand Up @@ -661,8 +661,8 @@ export default function DataTablePage() {
title="Basic Usage"
description="Define columns using TanStack Table's column definition format, then pass your data and columns to the DataTable component."
preview={<DataTable data={sampleData.slice(0, 10)} columns={basicColumns} />}
code={`import { DataTable } from 'baukasten-ui/extra';
import type { ColumnDef } from 'baukasten-ui/extra';
code={`import { DataTable } from 'baukasten-ui/data-table';
import type { ColumnDef } from 'baukasten-ui/data-table';

interface User {
id: number;
Expand Down Expand Up @@ -738,8 +738,8 @@ function App() {
description="Use createSelectColumn() to add a checkbox column for row selection. Track selected rows with rowSelection state."
preview={<RowSelectionExample />}
code={`import { useState, useMemo } from 'react';
import { DataTable, createSelectColumn } from 'baukasten-ui/extra';
import type { RowSelectionState } from 'baukasten-ui/extra';
import { DataTable, createSelectColumn } from 'baukasten-ui/data-table';
import type { RowSelectionState } from 'baukasten-ui/data-table';

function App() {
const [rowSelection, setRowSelection] = useState<RowSelectionState>({});
Expand Down Expand Up @@ -797,8 +797,8 @@ function App() {
description="Control sorting state externally for integration with external state management or URL parameters."
preview={<ControlledSortingExample />}
code={`import { useState } from 'react';
import { DataTable } from 'baukasten-ui/extra';
import type { SortingState } from 'baukasten-ui/extra';
import { DataTable } from 'baukasten-ui/data-table';
import type { SortingState } from 'baukasten-ui/data-table';

function App() {
const [sorting, setSorting] = useState<SortingState>([]);
Expand Down Expand Up @@ -1137,8 +1137,8 @@ function App() {
description="Use initialData instead of data to enable managed mode. The table manages its own state and exposes a transaction API via ref. Use ref.applyTransaction() to add, update, or remove rows."
preview={<ManagedModeExample />}
code={`import { useRef } from 'react';
import { DataTable } from 'baukasten-ui/extra';
import type { DataTableRef } from 'baukasten-ui/extra';
import { DataTable } from 'baukasten-ui/data-table';
import type { DataTableRef } from 'baukasten-ui/data-table';

function App() {
const tableRef = useRef<DataTableRef<Person>>(null);
Expand Down Expand Up @@ -1237,7 +1237,7 @@ tableRef.current?.flushAsyncTransactions();
title="External Hook (useDataTableData)"
description="Use the useDataTableData hook externally when you need to share transaction state across multiple components, or prefer lifting state out of the table. Pass data as a prop for controlled mode."
preview={<ExternalHookExample />}
code={`import { DataTable, useDataTableData } from 'baukasten-ui/extra';
code={`import { DataTable, useDataTableData } from 'baukasten-ui/data-table';

function App() {
const { data, applyTransaction, applyTransactionAsync } = useDataTableData<Person>({
Expand Down
Loading
Loading