@ga-components/drawer-seat
v1.0.3
Published
> A production-ready, reusable **Seat Selection Drawer** component for flight booking applications — built with React 19, TypeScript, and Material UI v5.
Downloads
50
Readme
@ga-components/drawer-seat
A production-ready, reusable Seat Selection Drawer component for flight booking applications — built with React 19, TypeScript, and Material UI v5.
Overview
@ga-components/drawer-seat is a private scoped NPM package extracted from the internal flight booking system (ga-web). It provides a fully-featured, responsive seat selection UI that works seamlessly across desktop (right-anchored drawer) and mobile (full-screen drawer) layouts.
This package follows a true reuse strategy — not copy-paste — enabling multiple repositories to consume the same versioned component with consistent behavior and UI.
Features
- ✈️ Flight tab navigation — switch between multiple flight segments
- 👤 Passenger card — display and select seat per passenger
- 🗺️ Interactive seat map — visual seat grid with dynamic row/column rendering
- 🏷️ Seat legend — compact mobile legend + bottom drawer, full desktop legend
- 💰 Fare comparison — modal fare comparison per cabin class
- 📋 Terms dialog — seat selection terms & conditions
- 📱 Fully responsive — dedicated mobile & desktop layouts
- 💄 SCSS auto-injected — styles injected to DOM via
esbuild-sass-plugin - 🖼️ Inline assets — images & SVGs bundled as base64 dataURL
Requirements
| Peer Dependency | Version |
|---|---|
| react | ^18.2.0 |
| react-dom | ^18.2.0 |
| @mui/material | ^5.2.1 |
| @mui/icons-material | ^5.2.1 |
| @mui/lab | ^5.0.0-alpha.175 |
| @mui/x-date-pickers | ^6.17.0 |
| swiper | ^12.1.4 |
⚠️ All peer dependencies must be installed in the consuming repository. This package does not bundle them.
Installation
# npm
npm install @ga-components/drawer-seat --legacy-peer-deps
# yarn
yarn add @ga-components/drawer-seat --ignore-enginesUsage
import { DrawerSeat } from "@ga-components/drawer-seat";
<DrawerSeat
open={isDrawerOpen}
onClose={handleClose}
responseData={seatResponseData}
bookingData={bookingData}
cartData={cartData}
seatSelections={seatSelections}
savedSeatSelections={savedSeatSelections}
calculatedPrice={calculatedPrice}
currency="IDR"
isCalculating={false}
adapter={adapter}
t={translations}
getPassengerDesc={getPassengerDesc}
onChooseSeat={handleChooseSeat}
/>Props
| Prop | Type | Required | Description |
|---|---|---|---|
| open | boolean | ✅ | Controls drawer open/close state |
| onClose | () => void | ✅ | Callback when drawer is closed |
| responseData | SeatResponseData | ✅ | Seat availability data per flight & passenger |
| bookingData | BookingResponse | ✅ | Booking information (flight routes, passengers) |
| cartData | CartData | ✅ | Cart & pricing data |
| seatSelections | SeatSelection[] | ✅ | Current seat selections |
| savedSeatSelections | SeatSelection[] | ✅ | Previously saved seat selections |
| calculatedPrice | CalculatedPrice | ✅ | Calculated price breakdown |
| currency | string | ✅ | Currency code (e.g. "IDR", "USD") |
| isCalculating | boolean | ✅ | Loading state for price calculation |
| adapter | DrawerSeatAdapter | ✅ | Adapter config for data transformation |
| t | DrawerSeatTranslations | ✅ | Translation strings |
| getPassengerDesc | (travellerId: string) => { name: string; desc: string } | ✅ | Passenger display info resolver |
| onChooseSeat | (params: ChooseSeatParams) => void | ✅ | Callback when a seat is selected |
Type Definitions
All types are exported from the package entry point:
import type {
DrawerSeatProps,
DrawerSeatAdapter,
DrawerSeatConfig,
DrawerSeatTranslations,
SeatSelection,
CalculatedPrice,
} from "@ga-components/drawer-seat";Architecture
src/
├── types/ # All TypeScript type definitions
├── utils/ # Utility functions (formatCurrency, etc.)
├── hooks/
│ └── useDrawerSeat.ts # All business logic — no logic in components
├── components/
│ └── drawer-seat/
│ ├── index.tsx # Desktop & mobile layout entry
│ ├── styled.tsx # Styled components & sx styles
│ └── components/
│ ├── SeatFlightTabs/
│ ├── SeatPassengerCard/
│ ├── SeatMapSection/
│ ├── SeatDialogTerms/
│ ├── SeatInfo/
│ └── fare-comparison/
├── shared/
│ ├── legend/ # SeatLegendComponents (compact mobile + drawer)
│ ├── summary/
│ ├── footer/
│ └── display-seat/
└── config/
├── theme.tsx
└── primitives.tsxKey principle: All business logic lives in
useDrawerSeathook. Components are purely presentational.
Build
This package is bundled with tsup v8.5.1 targeting ESM (Vite-compatible).
# Build
npm run build
# Watch mode
npm run dev
# Clean dist
npm run cleantsup config highlights
- Format:
esmonly (CJS excluded — not compatible with Vite ESM) - SCSS: auto-injected via
esbuild-sass-pluginwithtype: "style" - Images: inlined as
base64dataURL (.png,.svg,.jpg, etc.) splitting: true— code splitting enabled for optimal chunking
Publishing
# Bump version
npm version patch # 1.0.0 → 1.0.1
npm version minor # 1.0.0 → 1.1.0
npm version major # 1.0.0 → 2.0.0
# Build & publish
npm run build
npm publish --access publicRequires membership in the
@ga-componentsNPM organization and 2FA enabled on your NPM account.
Important Constraints
| Rule | Reason |
|---|---|
| Do NOT import from barrel index files | Use specific imports to avoid circular deps |
| Do NOT add CJS-only libraries | Package targets ESM (Vite compatibility) |
| Do NOT put libraries in dependencies | They will be bundled into dist — use peerDependencies |
| Do NOT place business logic in components | All logic belongs in useDrawerSeat hook |
| Always run rm -rf node_modules/.vite after install | Clears Vite cache in consuming repo |
| Always install with --legacy-peer-deps (npm) or --ignore-engines (yarn) | Node v16 compatibility in consuming repos |
Changelog
1.0.1
- Fix:
exportsfield — move"types"before"import"and"require"to resolve esbuild warning - Fix: Remove
@andrydharmawan/bgs-componentdependency — replacedbgsModalwith MUIDialog - Fix: Mobile footer sticky — restructured
MobileDrawerto flex column layout - Fix:
SeatPassengerCardmobile grid wrap — replaced MUI Grid xs withflex: 1+flexWrap: nowrap - Fix:
DisplaySeatLayoutrow number wrap — replaced MUI Grid with Box flex - Fix: Desktop seat map clipped by legend — legend fixed to
300px, seat map usesflex: 1
1.0.0
- Initial release —
DrawerSeatcomponent extracted fromga-web
License
Internal use only — @ga-components organization members.
© PT Garuda Indonesia. All rights reserved.
