Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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
16 changes: 16 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,22 @@ Install the project dependencies:
pnpm install
```

### Start the dev server

For the standard data table and data grid demos:

```shell
pnpm dev
```

For the multiplayer demo (requires PartyKit):

```shell
pnpm dev:multiplayer
```

This starts both the Next.js server and the PartyKit WebSocket server concurrently.

### Create a branch

Create and check out your feature branch:
Expand Down
42 changes: 29 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ See the [documentation](https://diceui.com/docs/components/data-table) to get st

## Running Locally

### Quick Setup (with docker)
### Quick Setup (with Docker)

1. **Clone the repository**

Expand Down Expand Up @@ -83,31 +83,47 @@ See the [documentation](https://diceui.com/docs/components/data-table) to get st
**Option A: Use Docker PostgreSQL**

```bash
# Start PostgreSQL container
pnpm db:start

# Set up database schema and seed data
pnpm db:setup

# Start development server
pnpm dev
pnpm db:start # start the PostgreSQL container
pnpm db:setup # push schema and seed data
pnpm dev # start the Next.js dev server
```

**Option B: Use existing PostgreSQL database**

```bash
# Update .env with your database URL
# Then set up database schema and seed data
# Update .env with your DATABASE_URL, then:
pnpm db:setup

# Start development server
pnpm dev
```

## Scripts

| Script | Description |
| --- | --- |
| `pnpm dev` | Start the Next.js dev server |
| `pnpm dev:multiplayer` | Start Next.js + PartyKit dev servers together |
| `pnpm dev:docker` | Start Docker PostgreSQL then Next.js |
| `pnpm build` | Production build |
| `pnpm check` | Run Biome lint + TypeScript type-check |
| `pnpm lint` | Lint with Biome |
| `pnpm lint:fix` | Lint and auto-fix |
| `pnpm typecheck` | TypeScript type-check only |
| `pnpm test` | Run tests with Vitest |
| `pnpm db:start` | Start the Docker PostgreSQL container |
| `pnpm db:stop` | Stop the Docker PostgreSQL container |
| `pnpm db:setup` | Push schema + seed the database |
| `pnpm db:reset` | Wipe and re-seed the database |
| `pnpm db:generate` | Generate Drizzle migrations |
| `pnpm db:migrate` | Run pending migrations |
| `pnpm build:registry` | Build the shadcn component registry |
| `pnpm ollie` | Full first-time setup (install + db:start + db:setup) |

## How do I deploy this?

Follow the deployment guides for [Vercel](https://create.t3.gg/en/deployment/vercel), [Netlify](https://create.t3.gg/en/deployment/netlify) and [Docker](https://create.t3.gg/en/deployment/docker) for more information.

The multiplayer demo uses [PartyKit](https://partykit.io) as a separate deployment. Run `pnpm dlx partykit deploy` from the project root and set `NEXT_PUBLIC_PARTYKIT_HOST` in your Vercel environment variables.

## Credits

- [shadcn/ui](https://github.com/shadcn-ui/ui/tree/main/apps/v4/app/(app)/examples/tasks) - For the initial implementation of the data table.
59 changes: 59 additions & 0 deletions party/constants.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,62 @@
export const ADJECTIVES = [
"Swift",
"Bold",
"Calm",
"Daring",
"Eager",
"Fierce",
"Gentle",
"Happy",
"Icy",
"Jolly",
"Kind",
"Lively",
"Merry",
"Noble",
"Odd",
"Proud",
"Quiet",
"Rapid",
"Silly",
"Tiny",
] as const;

export const ANIMALS = [
"Badger",
"Bear",
"Crane",
"Deer",
"Eagle",
"Fox",
"Goat",
"Hawk",
"Ibis",
"Jay",
"Kite",
"Lamb",
"Mink",
"Newt",
"Otter",
"Puma",
"Quail",
"Raven",
"Seal",
"Tiger",
] as const;

export const COLORS = [
"#ef4444",
"#f97316",
"#eab308",
"#22c55e",
"#06b6d4",
"#3b82f6",
"#8b5cf6",
"#ec4899",
"#14b8a6",
"#f59e0b",
] as const;

export const STANCES = ["regular", "goofy"] as const;

export const STYLES = [
Expand Down
70 changes: 8 additions & 62 deletions party/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// Each room seeds from party/seeds.ts on first use and stores mutations from there.

import type * as Party from "partykit/server";
import { ADJECTIVES, ANIMALS, COLORS } from "./constants";
import { seedRows } from "./seeds";
import type {
ClientMessage,
Expand All @@ -11,65 +12,6 @@ import type {
UserPresence,
} from "./types";

const ADJECTIVES = [
"Swift",
"Bold",
"Calm",
"Daring",
"Eager",
"Fierce",
"Gentle",
"Happy",
"Icy",
"Jolly",
"Kind",
"Lively",
"Merry",
"Noble",
"Odd",
"Proud",
"Quiet",
"Rapid",
"Silly",
"Tiny",
];

const ANIMALS = [
"Badger",
"Bear",
"Crane",
"Deer",
"Eagle",
"Fox",
"Goat",
"Hawk",
"Ibis",
"Jay",
"Kite",
"Lamb",
"Mink",
"Newt",
"Otter",
"Puma",
"Quail",
"Raven",
"Seal",
"Tiger",
];

const COLORS = [
"#ef4444",
"#f97316",
"#eab308",
"#22c55e",
"#06b6d4",
"#3b82f6",
"#8b5cf6",
"#ec4899",
"#14b8a6",
"#f59e0b",
];

interface RoomState {
users: Record<string, UserPresence>;
usedColors: string[];
Expand Down Expand Up @@ -115,11 +57,15 @@ export default class SkaterRoom implements Party.Server {
}

onConnect(conn: Party.Connection) {
const color = pickColor(this.state.usedColors);
this.state.usedColors.push(color);
const url = new URL(conn.uri);
const name = url.searchParams.get("name") ?? generateUserName();
const color =
url.searchParams.get("color") ?? pickColor(this.state.usedColors);
if (!this.state.usedColors.includes(color))
this.state.usedColors.push(color);

const user: UserPresence = {
name: generateUserName(),
name,
color,
activeCell: { rowId: null, columnId: null },
};
Expand Down
2 changes: 1 addition & 1 deletion public/r/data-grid.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion public/r/data-table-filter-list.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion public/r/data-table-filter-menu.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion public/r/data-table-sort-list.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/app/components/feature-flags-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ export function FeatureFlagsProvider({ children }: FeatureFlagsProviderProps) {
<Tooltip key={flag.value} delayDuration={700}>
<ToggleGroupItem
value={flag.value}
className="whitespace-nowrap px-3 text-xs data-[state=on]:bg-accent/70 data-[state=on]:hover:bg-accent/90"
className="whitespace-nowrap not-first:not-last:rounded-none not-first:border-l-0 px-3 text-xs first:rounded-r-none last:rounded-l-none data-[state=on]:bg-accent/70 data-[state=on]:hover:bg-accent/90"
asChild
>
<TooltipTrigger>
Expand Down
13 changes: 8 additions & 5 deletions src/components/data-grid/data-grid-cell-variants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectTrigger,
SelectValue,
Expand Down Expand Up @@ -978,11 +979,13 @@ export function SelectCell<TData>({
sideOffset={-8}
className="min-w-[calc(var(--radix-select-trigger-width)+16px)]"
>
{options.map((option) => (
<SelectItem key={option.value} value={option.value}>
{option.label}
</SelectItem>
))}
<SelectGroup>
{options.map((option) => (
<SelectItem key={option.value} value={option.value}>
{option.label}
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>
) : displayLabel ? (
Expand Down
39 changes: 23 additions & 16 deletions src/components/data-table/data-table-filter-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import {
import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectTrigger,
SelectValue,
Expand Down Expand Up @@ -415,11 +416,13 @@ function DataTableFilterItem<TData>({
position="popper"
className="min-w-(--radix-select-trigger-width) lowercase"
>
{dataTableConfig.joinOperators.map((joinOperator) => (
<SelectItem key={joinOperator} value={joinOperator}>
{joinOperator}
</SelectItem>
))}
<SelectGroup>
{dataTableConfig.joinOperators.map((joinOperator) => (
<SelectItem key={joinOperator} value={joinOperator}>
{joinOperator}
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>
) : (
Expand Down Expand Up @@ -508,15 +511,17 @@ function DataTableFilterItem<TData>({
</div>
</SelectTrigger>
<SelectContent id={operatorListboxId}>
{filterOperators.map((operator) => (
<SelectItem
key={operator.value}
value={operator.value}
className="lowercase"
>
{operator.label}
</SelectItem>
))}
<SelectGroup>
{filterOperators.map((operator) => (
<SelectItem
key={operator.value}
value={operator.value}
className="lowercase"
>
{operator.label}
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>
<div className="min-w-36 max-w-60 flex-1">
Expand Down Expand Up @@ -650,8 +655,10 @@ function onFilterInputRender<TData>({
<SelectValue placeholder={filter.value ? "True" : "False"} />
</SelectTrigger>
<SelectContent id={inputListboxId}>
<SelectItem value="true">True</SelectItem>
<SelectItem value="false">False</SelectItem>
<SelectGroup>
<SelectItem value="true">True</SelectItem>
<SelectItem value="false">False</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
);
Expand Down
Loading
Loading