chore(format): apply prettier auto-formatting

Pre-commit hook reformatted these files after the substantive commits.
No semantic changes — markdown table alignment, list indentation, and
emphasis style normalisation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-09 04:11:54 +02:00
parent aad514a3bd
commit 502455ac04
6 changed files with 165 additions and 161 deletions

View File

@@ -15,20 +15,20 @@ message order where possible.
## Quick status snapshot — 2026-05-08 23:00
| Wave | Topic | Status |
| --- | --- | --- |
| 1 | Small confident fixes | ✅ Done |
| 2 | Country dropdown unification + cmdk scroll | ✅ Done (country/nationality split deferred) |
| 3 | Berth field overhaul (NocoDB enums) | ✅ Done |
| 4 | Currency platform-wide | 🔴 Not started |
| 5 | Configurable enums (admin Vocabularies) | 🔴 Not started |
| 6 | Notes unification (aggregate-on-read) | 🔴 Not started |
| 7 | Clients / yachts / companies misc | 🟡 Partial (small bits done; large items deferred) |
| 8 | Expenses revisit | 🔴 Not started |
| 9 | Interests + notifications | ✅ Done |
| 10 | Settings polish | ✅ Done (small bits) — schema-blocked items deferred |
| 11 | DEFERRED — group-discussion items | 🟣 Awaiting alignment |
| **Bonus** | **Public berth feed (website map)** | ✅ Map data backfilled (117 rows). Field-parity gaps remain — see § Bonus. |
| Wave | Topic | Status |
| --------- | ------------------------------------------ | -------------------------------------------------------------------------- |
| 1 | Small confident fixes | ✅ Done |
| 2 | Country dropdown unification + cmdk scroll | ✅ Done (country/nationality split deferred) |
| 3 | Berth field overhaul (NocoDB enums) | ✅ Done |
| 4 | Currency platform-wide | 🔴 Not started |
| 5 | Configurable enums (admin Vocabularies) | 🔴 Not started |
| 6 | Notes unification (aggregate-on-read) | 🔴 Not started |
| 7 | Clients / yachts / companies misc | 🟡 Partial (small bits done; large items deferred) |
| 8 | Expenses revisit | 🔴 Not started |
| 9 | Interests + notifications | ✅ Done |
| 10 | Settings polish | ✅ Done (small bits) — schema-blocked items deferred |
| 11 | DEFERRED — group-discussion items | 🟣 Awaiting alignment |
| **Bonus** | **Public berth feed (website map)** | ✅ Map data backfilled (117 rows). Field-parity gaps remain — see § Bonus. |
Test status: `pnpm exec vitest run`**1185/1185 pass**.
TS check: `pnpm exec tsc --noEmit`**clean**.
@@ -83,7 +83,7 @@ Git: 23 files modified, 2 new files (no commits yet).
below (pipeline funnel, occupancy timeline, revenue breakdown,
lead source) and the activity feed remain.
File: `src/components/dashboard/dashboard-shell.tsx`.
3. **Per-dock color stripe on mobile berth cards** — was the *status*
3. **Per-dock color stripe on mobile berth cards** — was the _status_
color, which made every same-dock berth different. Now uses
`mooringLetterDot()` so the stripe groups by dock letter; status
conveyed by the existing pill below.
@@ -114,20 +114,20 @@ Git: 23 files modified, 2 new files (no commits yet).
Files: `src/components/layout/sidebar.tsx`,
`src/components/layout/mobile/more-sheet.tsx`.
10. **"Other" comm-channel UX hint** — when a contact's channel is
`'other'`, the inline `Label` field switches its label/placeholder
to "Specify" / "e.g. Telegram, Signal".
File: `src/components/clients/client-form.tsx:289-302`.
`'other'`, the inline `Label` field switches its label/placeholder
to "Specify" / "e.g. Telegram, Signal".
File: `src/components/clients/client-form.tsx:289-302`.
11. **End Membership wording** — renamed to "Remove from company" in
the company members tab dropdown.
File: `src/components/companies/company-members-tab.tsx:249`.
the company members tab dropdown.
File: `src/components/companies/company-members-tab.tsx:249`.
12. **Berth area filter → letter dropdown** — was free-text; now a
`<Select>` constrained to `A / B / C / D / E`. Label changed to
"Dock" to match how the user refers to it.
File: `src/components/berths/berth-filters.tsx`.
`<Select>` constrained to `A / B / C / D / E`. Label changed to
"Dock" to match how the user refers to it.
File: `src/components/berths/berth-filters.tsx`.
13. **Yacht flag → CountryCombobox** — was a free-text 2-letter input
(`placeholder="e.g. MT"`); now uses the same country picker as
client / residential.
File: `src/components/yachts/yacht-form.tsx`.
(`placeholder="e.g. MT"`); now uses the same country picker as
client / residential.
File: `src/components/yachts/yacht-form.tsx`.
### Wave 2 — country dropdown unification
@@ -149,7 +149,7 @@ Git: 23 files modified, 2 new files (no commits yet).
floors so wide triggers get wide popovers.
6. **DEFERRED: country/nationality split** on the client form — needs
a Drizzle migration (`alter table clients add column country_iso
text`) plus a copy-on-migrate of existing `nationality_iso` values.
text`) plus a copy-on-migrate of existing `nationality_iso` values.
See § Wave 11 / pending — large.
### Wave 3 — berth field overhaul (NocoDB enums)
@@ -210,6 +210,7 @@ Triggered by user prompt "ensure we are properly wired up to replace
the NocoDB table as the source of truth for the berth map".
**State before audit:**
- API endpoints existed (`/api/public/berths`,
`/api/public/berths/[mooringNumber]`) — wiring fine.
- `src/lib/services/public-berths.ts` mapped the response shape to
@@ -220,8 +221,9 @@ the NocoDB table as the source of truth for the berth map".
has no shapes to render.
**Action taken:**
- Ran `pnpm tsx scripts/import-berths-from-nocodb.ts --apply
--port-slug port-nimara` (after a clean dry-run). Result:
--port-slug port-nimara` (after a clean dry-run). Result:
117 berths updated, 117 `berth_map_data` rows inserted.
- Spot-checked the public API: `GET /api/public/berths` returns the
correct shape with `Map Data` populated, byte-for-byte identical
@@ -288,14 +290,16 @@ User chose option 1 ("aggregate on read") from the brainstorm. The
yacht notes into a single feed with `source` metadata.
Symmetric extensions to add:
- `listForYachtAggregated` — yacht own notes + owner client notes
+ linked interest notes.
- linked interest notes.
- `listForCompanyAggregated` — company own notes + owned yacht notes
+ linked interest notes.
- linked interest notes.
- `listForResidentialClientAggregated` — residential client notes
+ residential interest notes.
- residential interest notes.
UI:
- `<NotesList entityType="…">` should render the source-label badge
(already implemented for clients — copy the pattern).
- Convert single-textarea spots to entry-list pattern: the
@@ -310,11 +314,13 @@ UI:
### Wave 7: clients / yachts / companies misc
Done in this session:
- **Yacht flag** → CountryCombobox (Wave 1).
- **End Membership** → "Remove from company" (Wave 1).
- **Berth Documents tab** explainer paragraph.
Pending:
- **Status change modal — prospect picker**: when user changes berth
status to `under_offer` or `sold`, surface an interest/prospect
selector below the reason dropdown so the recorded reason can link
@@ -338,8 +344,8 @@ Pending:
Chromium. User reported "doesn't open" on macOS — possibly a focus
/ window issue or a content-blocking extension. Need a real-machine
repro to diagnose. The hidden `<input type="file" ref={fileInputRef}>`
+ `fileInputRef.current?.click()` wiring is at
`user-settings.tsx:247-258`.
- `fileInputRef.current?.click()` wiring is at
`user-settings.tsx:247-258`.
- **Display name + first / last name fields** — current schema only
has `displayName`. Adding first/last requires a Drizzle migration on
`users` or `user_profiles` plus migration of existing data (split
@@ -351,24 +357,24 @@ Pending:
### Wave Bonus follow-up — public berth feed field parity
Map data is now wired. Field gaps the website *might* consume but we
Map data is now wired. Field gaps the website _might_ consume but we
don't expose:
| NocoDB field | Currently in PublicBerth? | DB has it? | Notes |
| --- | --- | --- | --- |
| `Price` | ❌ | ✅ `berths.price` | Pricing-public is a policy decision. **Open question (#4)** |
| `Berth Approved` | ❌ | ✅ `berths.berth_approved` | Boolean. Often used to gate "Sold" display |
| `Water Depth` | ❌ | ✅ `berths.water_depth` | Sometimes shown in tooltip |
| `Width Is Minimum` | ❌ | ✅ `berths.width_is_minimum` | Modifier for "Width" display |
| `Water Depth Is Minimum` | ❌ | ✅ `berths.water_depth_is_minimum` | ditto |
| `Length (Metric)` | ❌ | ✅ `berths.length_m` | Derivable. Website may consume |
| `Width (Metric)` | ❌ | ✅ `berths.width_m` | ditto |
| `Draft (Metric)` | ❌ | ✅ `berths.draft_m` | ditto |
| `Water Depth (Metric)` | ❌ | ✅ `berths.water_depth_m` | ditto |
| `Nominal Boat Size (Metric)` | ❌ | ✅ `berths.nominal_boat_size_m` | ditto |
| `CreatedAt` / `UpdatedAt` | ❌ | ✅ timestamps | Cache invalidation hints |
| `Interests` (count) | ❌ | derivable | Probably internal-only |
| `Interested Parties` (count) | ❌ | derivable | Probably internal-only |
| NocoDB field | Currently in PublicBerth? | DB has it? | Notes |
| ---------------------------- | ------------------------- | ---------------------------------- | ----------------------------------------------------------- |
| `Price` | ❌ | ✅ `berths.price` | Pricing-public is a policy decision. **Open question (#4)** |
| `Berth Approved` | ❌ | ✅ `berths.berth_approved` | Boolean. Often used to gate "Sold" display |
| `Water Depth` | ❌ | ✅ `berths.water_depth` | Sometimes shown in tooltip |
| `Width Is Minimum` | ❌ | ✅ `berths.width_is_minimum` | Modifier for "Width" display |
| `Water Depth Is Minimum` | ❌ | ✅ `berths.water_depth_is_minimum` | ditto |
| `Length (Metric)` | ❌ | ✅ `berths.length_m` | Derivable. Website may consume |
| `Width (Metric)` | ❌ | ✅ `berths.width_m` | ditto |
| `Draft (Metric)` | ❌ | ✅ `berths.draft_m` | ditto |
| `Water Depth (Metric)` | ❌ | ✅ `berths.water_depth_m` | ditto |
| `Nominal Boat Size (Metric)` | ❌ | ✅ `berths.nominal_boat_size_m` | ditto |
| `CreatedAt` / `UpdatedAt` | ❌ | ✅ timestamps | Cache invalidation hints |
| `Interests` (count) | ❌ | derivable | Probably internal-only |
| `Interested Parties` (count) | ❌ | derivable | Probably internal-only |
**Plan once questions are answered:** Add the chosen fields to
`PublicBerth` interface in `src/lib/services/public-berths.ts`, the
@@ -376,6 +382,7 @@ don't expose:
by which fields the website actually uses.
**Other public-feed concerns to flag**:
- **No archive flag**: when a berth is retired the public feed will
still serve it. Need a `berths.archived_at` column + filter on the
route. Plan §4.5 hinted at this. Not urgent.
@@ -404,6 +411,7 @@ berths inline (without leaving the form), plus a mini-recommender for
picking a berth at create time.
Scope:
- "Existing yacht / new yacht" picker.
- "Existing company / new company" picker.
- "Open an interest with this client" affordance that wires through
@@ -417,6 +425,7 @@ Estimate fully before starting (likely 23 days).
### B. Documents section overhaul
User wants:
- Folders (create / delete / nested).
- Sort + filter (by date, type, owner).
- Wider file-type allowlist (PDF + Office + image is current; expand).
@@ -433,6 +442,7 @@ Refactor of `documents.service.ts` plus a new folders schema
### C. Reports system
User asked for:
- Defined report types (Pipeline summary / Revenue / Activity log /
Berth occupancy) with documented data shape per type.
- Test fixtures for visual QA.
@@ -453,11 +463,13 @@ PDF pages via `pdf-lib.copyPages`. Depends on Wave 8 expense form work.
### E. Country / Nationality split on Client form
Client schema has only `nationalityIso`. User wants:
- New `country_iso` column for *country of residence* (visible
- New `country_iso` column for _country of residence_ (visible
/ primary).
- Keep `nationality_iso` as an *optional* secondary field.
- Keep `nationality_iso` as an _optional_ secondary field.
Requires:
- Drizzle migration (`alter table clients add column country_iso text`).
- Migrate existing data: copy `nationality_iso → country_iso` for
every client (current value is more often country of residence in
@@ -494,7 +506,7 @@ implementation. They're ordered by what unblocks the most work.
**Recommendation: one new page, grouped by domain.** Easier to
discover, cleaner schema for the editor.
2. **Notification preferences placement (Wave 10)** — keep both the
user-settings notifications panel *and* `/notifications/preferences`,
user-settings notifications panel _and_ `/notifications/preferences`,
or collapse to one? **Recommendation: collapse to user-settings
only**, since that's where every other personal preference lives.
Keep the dedicated route as a redirect for back-compat links.
@@ -543,7 +555,7 @@ implementation. They're ordered by what unblocks the most work.
every berth (NocoDB does). Confirmation that the live import we
ran today populated mooring_type for all 117 records. (Spot-
checked: yes — the SQL traces show `mooring_type = "Side Pier /
Med Mooring"` etc.)
Med Mooring"` etc.)
---
@@ -551,55 +563,55 @@ implementation. They're ordered by what unblocks the most work.
### Berth-related
| Concern | File(s) |
| --- | --- |
| Canonical berth enums | `src/lib/constants.ts` (search `BERTH_`) |
| Berth list ordering SQL | `src/lib/services/berths.service.ts:69-72` |
| Berth detail inline edit | `src/components/berths/berth-tabs.tsx` |
| Berth modal form | `src/components/berths/berth-form.tsx` |
| Berth area filter | `src/components/berths/berth-filters.tsx` |
| Berth detail header / status modal | `src/components/berths/berth-detail-header.tsx:90` |
| Berth Documents tab | `src/components/berths/berth-documents-tab.tsx` |
| Berth list query + sort | `src/lib/services/berths.service.ts:25-140` |
| Berth import script | `scripts/import-berths-from-nocodb.ts` |
| Berth import service / parsers | `src/lib/services/berth-import.ts` |
| Public berth API route | `src/app/api/public/berths/route.ts` |
| Public berth single route | `src/app/api/public/berths/[mooringNumber]/route.ts` |
| Public berth mapper | `src/lib/services/public-berths.ts` |
| Public berth tests | `tests/unit/services/public-berths.test.ts` |
| Berth seed snapshot | `src/lib/db/seed-data/berths.json` |
| Berth schema | `src/lib/db/schema/berths.ts` (incl. `berthMapData`) |
| Concern | File(s) |
| ---------------------------------- | ---------------------------------------------------- |
| Canonical berth enums | `src/lib/constants.ts` (search `BERTH_`) |
| Berth list ordering SQL | `src/lib/services/berths.service.ts:69-72` |
| Berth detail inline edit | `src/components/berths/berth-tabs.tsx` |
| Berth modal form | `src/components/berths/berth-form.tsx` |
| Berth area filter | `src/components/berths/berth-filters.tsx` |
| Berth detail header / status modal | `src/components/berths/berth-detail-header.tsx:90` |
| Berth Documents tab | `src/components/berths/berth-documents-tab.tsx` |
| Berth list query + sort | `src/lib/services/berths.service.ts:25-140` |
| Berth import script | `scripts/import-berths-from-nocodb.ts` |
| Berth import service / parsers | `src/lib/services/berth-import.ts` |
| Public berth API route | `src/app/api/public/berths/route.ts` |
| Public berth single route | `src/app/api/public/berths/[mooringNumber]/route.ts` |
| Public berth mapper | `src/lib/services/public-berths.ts` |
| Public berth tests | `tests/unit/services/public-berths.test.ts` |
| Berth seed snapshot | `src/lib/db/seed-data/berths.json` |
| Berth schema | `src/lib/db/schema/berths.ts` (incl. `berthMapData`) |
### Other domains
| Concern | File(s) |
| --- | --- |
| Interest stage colors / legend | `src/components/interests/stage-legend.tsx` + `src/lib/constants.ts:STAGE_DOT` |
| Mobile kanban toggle / fallback | `src/components/interests/interest-list.tsx` |
| Country / timezone autoset | `src/components/clients/client-form.tsx` + `src/components/settings/user-settings.tsx` |
| Phone input | `src/components/shared/phone-input.tsx` |
| Country combobox + scroll patch | `src/components/shared/country-combobox.tsx` + `src/components/ui/command.tsx` |
| Sidebar Umami gate | `src/components/layout/sidebar.tsx` (search `umamiRequired`) |
| Mobile More-sheet | `src/components/layout/mobile/more-sheet.tsx` |
| Notes service (aggregate-on-read) | `src/lib/services/notes.service.ts:130-242` |
| Notes UI | `src/components/shared/notes-list.tsx` |
| Settings manager (admin) | `src/components/admin/settings/settings-manager.tsx` |
| User settings page | `src/components/settings/user-settings.tsx` |
| Status change dialog | `src/components/berths/berth-detail-header.tsx:90` |
| Companies members tab | `src/components/companies/company-members-tab.tsx` |
| Yacht form | `src/components/yachts/yacht-form.tsx` |
| Client form | `src/components/clients/client-form.tsx` |
| Concern | File(s) |
| --------------------------------- | -------------------------------------------------------------------------------------- |
| Interest stage colors / legend | `src/components/interests/stage-legend.tsx` + `src/lib/constants.ts:STAGE_DOT` |
| Mobile kanban toggle / fallback | `src/components/interests/interest-list.tsx` |
| Country / timezone autoset | `src/components/clients/client-form.tsx` + `src/components/settings/user-settings.tsx` |
| Phone input | `src/components/shared/phone-input.tsx` |
| Country combobox + scroll patch | `src/components/shared/country-combobox.tsx` + `src/components/ui/command.tsx` |
| Sidebar Umami gate | `src/components/layout/sidebar.tsx` (search `umamiRequired`) |
| Mobile More-sheet | `src/components/layout/mobile/more-sheet.tsx` |
| Notes service (aggregate-on-read) | `src/lib/services/notes.service.ts:130-242` |
| Notes UI | `src/components/shared/notes-list.tsx` |
| Settings manager (admin) | `src/components/admin/settings/settings-manager.tsx` |
| User settings page | `src/components/settings/user-settings.tsx` |
| Status change dialog | `src/components/berths/berth-detail-header.tsx:90` |
| Companies members tab | `src/components/companies/company-members-tab.tsx` |
| Yacht form | `src/components/yachts/yacht-form.tsx` |
| Client form | `src/components/clients/client-form.tsx` |
### Infrastructure
| Concern | File(s) |
| --- | --- |
| Drizzle config / migrations | `drizzle.config.ts`, `src/lib/db/migrations/` |
| `system_settings` table | `src/lib/db/schema/system.ts:128-147` |
| Permissions / `withAuth` / `withPermission` | `src/lib/api/helpers.ts` |
| Body parsing (always use `parseBody`) | `src/lib/api/route-helpers.ts` |
| Storage backend abstraction | `src/lib/storage/` |
| Logger (pino) | `src/lib/logger.ts` |
| Concern | File(s) |
| ------------------------------------------- | --------------------------------------------- |
| Drizzle config / migrations | `drizzle.config.ts`, `src/lib/db/migrations/` |
| `system_settings` table | `src/lib/db/schema/system.ts:128-147` |
| Permissions / `withAuth` / `withPermission` | `src/lib/api/helpers.ts` |
| Body parsing (always use `parseBody`) | `src/lib/api/route-helpers.ts` |
| Storage backend abstraction | `src/lib/storage/` |
| Logger (pino) | `src/lib/logger.ts` |
---

View File

@@ -163,10 +163,9 @@ export function BerthDocumentsTab({ berthId }: { berthId: string }) {
return (
<div className="space-y-6">
<p className="text-sm text-muted-foreground">
Berth-spec PDF: the dimensional drawing or surveyor sheet for this slip.
Versioned so a misparse can be rolled back. For documents tied to a
prospect on this berth (EOI, contract, etc.), open the matching deal
in the Interests tab.
Berth-spec PDF: the dimensional drawing or surveyor sheet for this slip. Versioned so a
misparse can be rolled back. For documents tied to a prospect on this berth (EOI, contract,
etc.), open the matching deal in the Interests tab.
</p>
<Card>
<CardHeader className="flex flex-row items-center justify-between pb-3">

View File

@@ -245,7 +245,11 @@ function OverviewTab({ berth }: { berth: BerthData }) {
/>
<SpecRow
label="Nominal Boat Size (m)"
value={formatNominalBoatSize(berth.nominalBoatSize, berth.nominalBoatSizeM)?.split(' / ')[1] ?? null}
value={
formatNominalBoatSize(berth.nominalBoatSize, berth.nominalBoatSizeM)?.split(
' / ',
)[1] ?? null
}
/>
<EditableSpec
label="Water Depth (ft)"

View File

@@ -4,12 +4,7 @@ import { Info } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
import {
PIPELINE_STAGES,
STAGE_LABELS,
stageDotClass,
type PipelineStage,
} from '@/lib/constants';
import { PIPELINE_STAGES, STAGE_LABELS, stageDotClass, type PipelineStage } from '@/lib/constants';
/**
* Small popover that decodes the colored stripe on each interest card to

View File

@@ -276,7 +276,11 @@ export function UserSettings() {
<Label htmlFor="settings-phone">Phone</Label>
<PhoneInput
id="settings-phone"
value={phone ? ({ e164: phone, country: (country as never) ?? 'US' } as PhoneInputValue) : null}
value={
phone
? ({ e164: phone, country: (country as never) ?? 'US' } as PhoneInputValue)
: null
}
onChange={(next) => setPhone(next.e164 ?? '')}
placeholder="555 0123"
/>

View File

@@ -1,12 +1,12 @@
"use client"
'use client';
import * as React from "react"
import { type DialogProps } from "@radix-ui/react-dialog"
import { Command as CommandPrimitive } from "cmdk"
import { Search } from "lucide-react"
import * as React from 'react';
import { type DialogProps } from '@radix-ui/react-dialog';
import { Command as CommandPrimitive } from 'cmdk';
import { Search } from 'lucide-react';
import { cn } from "@/lib/utils"
import { Dialog, DialogContent } from "@/components/ui/dialog"
import { cn } from '@/lib/utils';
import { Dialog, DialogContent } from '@/components/ui/dialog';
const Command = React.forwardRef<
React.ElementRef<typeof CommandPrimitive>,
@@ -15,13 +15,13 @@ const Command = React.forwardRef<
<CommandPrimitive
ref={ref}
className={cn(
"flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground",
className
'flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground',
className,
)}
{...props}
/>
))
Command.displayName = CommandPrimitive.displayName
));
Command.displayName = CommandPrimitive.displayName;
const CommandDialog = ({ children, ...props }: DialogProps) => {
return (
@@ -32,8 +32,8 @@ const CommandDialog = ({ children, ...props }: DialogProps) => {
</Command>
</DialogContent>
</Dialog>
)
}
);
};
const CommandInput = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Input>,
@@ -44,15 +44,15 @@ const CommandInput = React.forwardRef<
<CommandPrimitive.Input
ref={ref}
className={cn(
"flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
className
'flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50',
className,
)}
{...props}
/>
</div>
))
));
CommandInput.displayName = CommandPrimitive.Input.displayName
CommandInput.displayName = CommandPrimitive.Input.displayName;
const CommandList = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.List>,
@@ -64,30 +64,26 @@ const CommandList = React.forwardRef<
// event ourselves so the list scrolls regardless of focus state.
<CommandPrimitive.List
ref={ref}
className={cn("max-h-[300px] overflow-y-auto overflow-x-hidden overscroll-contain", className)}
className={cn('max-h-[300px] overflow-y-auto overflow-x-hidden overscroll-contain', className)}
onWheel={(event) => {
onWheel?.(event)
if (event.defaultPrevented) return
event.currentTarget.scrollTop += event.deltaY
onWheel?.(event);
if (event.defaultPrevented) return;
event.currentTarget.scrollTop += event.deltaY;
}}
{...props}
/>
))
));
CommandList.displayName = CommandPrimitive.List.displayName
CommandList.displayName = CommandPrimitive.List.displayName;
const CommandEmpty = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Empty>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>
>((props, ref) => (
<CommandPrimitive.Empty
ref={ref}
className="py-6 text-center text-sm"
{...props}
/>
))
<CommandPrimitive.Empty ref={ref} className="py-6 text-center text-sm" {...props} />
));
CommandEmpty.displayName = CommandPrimitive.Empty.displayName
CommandEmpty.displayName = CommandPrimitive.Empty.displayName;
const CommandGroup = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Group>,
@@ -96,14 +92,14 @@ const CommandGroup = React.forwardRef<
<CommandPrimitive.Group
ref={ref}
className={cn(
"overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground",
className
'overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground',
className,
)}
{...props}
/>
))
));
CommandGroup.displayName = CommandPrimitive.Group.displayName
CommandGroup.displayName = CommandPrimitive.Group.displayName;
const CommandSeparator = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Separator>,
@@ -111,11 +107,11 @@ const CommandSeparator = React.forwardRef<
>(({ className, ...props }, ref) => (
<CommandPrimitive.Separator
ref={ref}
className={cn("-mx-1 h-px bg-border", className)}
className={cn('-mx-1 h-px bg-border', className)}
{...props}
/>
))
CommandSeparator.displayName = CommandPrimitive.Separator.displayName
));
CommandSeparator.displayName = CommandPrimitive.Separator.displayName;
const CommandItem = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Item>,
@@ -124,30 +120,24 @@ const CommandItem = React.forwardRef<
<CommandPrimitive.Item
ref={ref}
className={cn(
"relative flex cursor-default gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled=true]:pointer-events-none data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
className
'relative flex cursor-default gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled=true]:pointer-events-none data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
className,
)}
{...props}
/>
))
));
CommandItem.displayName = CommandPrimitive.Item.displayName
CommandItem.displayName = CommandPrimitive.Item.displayName;
const CommandShortcut = ({
className,
...props
}: React.HTMLAttributes<HTMLSpanElement>) => {
const CommandShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => {
return (
<span
className={cn(
"ml-auto text-xs tracking-widest text-muted-foreground",
className
)}
className={cn('ml-auto text-xs tracking-widest text-muted-foreground', className)}
{...props}
/>
)
}
CommandShortcut.displayName = "CommandShortcut"
);
};
CommandShortcut.displayName = 'CommandShortcut';
export {
Command,
@@ -159,4 +149,4 @@ export {
CommandItem,
CommandShortcut,
CommandSeparator,
}
};