# OpenSpec Change: enterprise-r3f-booking - **Change ID**: enterprise-r3f-booking - **Package**: `@suaveplan/r3f-booking` - **Category**: r3f/commerce - **Target path**: `r3f/commerce/r3f-booking` - **Status**: PROPOSED - **Date**: 2026-04-24 - **Reference spec**: `/mnt/s/web/suaveplan/enterprise/r3f-booking.md` --- ## Summary Deliver `@suaveplan/r3f-booking` on the genesis branch from scratch at enterprise quality. The package provides interactive 3D venue maps for seat/space booking — concert halls, stadiums, offices, conference rooms. It ships ``, ``, ``, ``, and a `useVenueSelection` hook. Seats have availability states (available/reserved/selected/disabled), animated selection feedback, accessible keyboard navigation, and a JSON venue schema for data-driven layout. Storybook stories for every component; Vitest + `@testing-library/react` tests. --- ## Current-state audit (genesis) Does not exist on genesis — fresh build. --- ## Available workspace deps on genesis Same R3F + React stack as `enterprise-r3f-earth`, plus no additional deps. --- ## Public API surface ```tsx function VenueMap(props: VenueMapProps): JSX.Element function VenueFloorPlan(props: VenueFloorPlanProps): JSX.Element function VenueSection(props: VenueSectionProps): JSX.Element function VenueSeat(props: VenueSeatProps): JSX.Element function useVenueSelection(options: UseVenueSelectionOptions): VenueSelectionState interface VenueMapProps { venue: VenueDefinition selectedSeats?: string[] onSeatSelect?: (seatId: string) => void onSeatDeselect?: (seatId: string) => void maxSelectable?: number colorScheme?: VenueColorScheme cameraControls?: boolean } interface VenueDefinition { id: string name: string sections: SectionDefinition[] } interface SectionDefinition { id: string label: string rows: RowDefinition[] color?: string position: { x: number; y: number; z: number } rotation?: number } interface RowDefinition { id: string label: string seats: SeatDefinition[] } interface SeatDefinition { id: string label: string status: 'available' | 'reserved' | 'disabled' category?: string price?: number } type VenueSelectionState = { selected: string[] select: (seatId: string) => void deselect: (seatId: string) => void clear: () => void isSelected: (seatId: string) => boolean } ``` --- ## File layout ```text r3f/commerce/r3f-booking/ package.json tsconfig.json vitest.config.ts src/ index.ts error-codes.ts types/ r3f-booking.types.ts r3f-booking.types.md components/ venue-map/ (tsx + md + types + test + stories + index) venue-floor-plan/ ... venue-section/ ... venue-seat/ ... hooks/ use-venue-selection/ use-venue-selection.ts / .md / .test.ts / index.ts schemas/ venue-schema/ venue-schema.ts / venue-schema.md / venue-schema.test.ts / index.ts ``` --- ## Impact Downstream: booking UI, event ticketing, office space booking. **Prerequisites on Verdaccio**: `@suaveplan/error`, `@suaveplan/types`, `@suaveplan/logger`.