@hotelcard/ui 0.0.13 → 0.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -29,36 +29,61 @@ npm install react react-dom
29
29
  ## Quick Start
30
30
 
31
31
  ```tsx
32
- import { Button, Card, Badge } from '@hotelcard/ui';
32
+ import { HotelCardUIProvider, Button, HotelCard } from '@hotelcard/ui';
33
33
 
34
34
  // Import styles (required - do this once in your app entry)
35
- import '@hotelcard/ui/dist/index.css';
35
+ import '@hotelcard/ui/styles.css';
36
36
 
37
37
  function App() {
38
38
  return (
39
- <div>
39
+ <HotelCardUIProvider locale="de" currency="CHF">
40
40
  <Button variant="primary" onClick={() => alert('Clicked!')}>
41
41
  Book Now
42
42
  </Button>
43
43
 
44
- <Card
45
- image="https://example.com/hotel.jpg"
46
- title="Hotel Schweizerhof"
47
- location="Luzern, Switzerland"
48
- stars={5}
49
- price="CHF 195"
50
- originalPrice="CHF 390"
51
- onClick={() => console.log('Card clicked')}
52
- >
53
- <Badge color="primary" size="small">-50%</Badge>
54
- </Card>
55
- </div>
44
+ <HotelCard
45
+ hotel={hotelData}
46
+ onFavoriteClick={() => toggleFavorite()}
47
+ onContentClick={() => navigate('/hotel/123')}
48
+ />
49
+ </HotelCardUIProvider>
56
50
  );
57
51
  }
58
52
  ```
59
53
 
60
54
  ---
61
55
 
56
+ ## Context Provider (Required for Translations)
57
+
58
+ Wrap your app with `HotelCardUIProvider` to enable translations and configuration:
59
+
60
+ ```tsx
61
+ import { HotelCardUIProvider } from '@hotelcard/ui';
62
+
63
+ <HotelCardUIProvider
64
+ locale="de" // 'de' | 'en' | 'fr' | 'it'
65
+ currency="CHF" // Currency code
66
+ isDesktop={false} // Responsive mode
67
+ >
68
+ <App />
69
+ </HotelCardUIProvider>
70
+ ```
71
+
72
+ ### Translations
73
+
74
+ The package includes built-in translations for `de`, `en`, `fr`, and `it` locales. These are automatically applied based on the `locale` prop. Components like `HotelCard`, `GuestContent`, and `WhenContent` use these translations internally.
75
+
76
+ **Custom translations** (optional):
77
+
78
+ ```tsx
79
+ <HotelCardUIProvider
80
+ locale="de"
81
+ t={(key, fallback) => myI18n.t(key) || fallback} // Custom translation function
82
+ >
83
+ ```
84
+
85
+ ---
86
+
62
87
  ## Available Components
63
88
 
64
89
  ### UI Components
@@ -77,7 +102,13 @@ function App() {
77
102
  | `Dropdown` | Select dropdown |
78
103
  | `Modal` | Modal dialog |
79
104
  | `SectionHeader` | Section title with "Show all" button |
80
- | `WhenContent` | Date/month picker for search (accepts labels as props) |
105
+ | `Block` | Content block with title and optional icon |
106
+ | `ReviewCard` | Guest review card with rating and text |
107
+ | `FAQ` | Expandable FAQ accordion |
108
+ | `Benefits` | Benefits list with icons |
109
+ | `Pin` | Location pin marker |
110
+ | `DateSelector` | Date selector container component |
111
+ | `WhenContent` | Date/month picker for search |
81
112
  | `DualCalendar` | Calendar component for date range selection |
82
113
  | `GuestContent` | Guest selector with adults, children (with ages), and pet toggle |
83
114
  | `HotelCard` | Hotel card for search results with image carousel, rating, and pricing |
@@ -189,18 +220,11 @@ import { WhenContent } from '@hotelcard/ui';
189
220
  variant="dropdown"
190
221
  showApplyButton={true}
191
222
  onApply={() => closeDropdown()}
192
- labels={{
193
- dates: 'Dates', // Tab label
194
- flexible: 'Flexible', // Tab label
195
- anytime: 'Anytime', // Button label
196
- selectMonths: 'When do you want to travel?',
197
- apply: 'Apply', // Button label
198
- }}
199
223
  locale="de" // Optional: 'de', 'en', 'fr', 'it'
200
224
  />
201
225
  ```
202
226
 
203
- **Note**: All text labels are passed as props. The consuming app provides translated strings.
227
+ Translations (dates, flexible, anytime, etc.) are handled automatically via `HotelCardUIProvider`.
204
228
 
205
229
  ### GuestContent (Guest Selector)
206
230
 
@@ -220,22 +244,10 @@ const [petFilter, setPetFilter] = useState(0);
220
244
  petFilter={petFilter}
221
245
  onPetChange={setPetFilter}
222
246
  showPetToggle={true}
223
- labels={{
224
- adults: 'Adults',
225
- children: 'Children',
226
- pet: 'Pet',
227
- ageOfChild: 'Age of child',
228
- age: 'Age',
229
- decreaseAdults: 'Decrease adults',
230
- increaseAdults: 'Increase adults',
231
- decreaseChildren: 'Decrease children',
232
- increaseChildren: 'Increase children',
233
- togglePets: 'Toggle pets',
234
- }}
235
247
  />
236
248
  ```
237
249
 
238
- **Note**: All text labels are passed as props. The consuming app provides translated strings.
250
+ Translations (Adults, Children, Pet, etc.) are handled automatically via `HotelCardUIProvider`.
239
251
 
240
252
  ### HotelCard
241
253
 
@@ -271,24 +283,10 @@ const hotel: HotelCardHotel = {
271
283
  hotel={hotel}
272
284
  onFavoriteClick={() => toggleFavorite(hotel.id)}
273
285
  onContentClick={() => navigate(`/hotel/${hotel.slug}`)}
274
- labels={{
275
- priceFrom: t('hotel.priceFrom'),
276
- notAvailable: t('hotel.notAvailable'),
277
- ratingExcellent: t('rating.excellent'),
278
- ratingVeryGood: t('rating.veryGood'),
279
- ratingGood: t('rating.good'),
280
- ratingFair: t('rating.fair'),
281
- rating: t('rating.rating'),
282
- swissLodge: t('hotel.swissLodge'),
283
- removeFromFavorites: t('favorites.remove'),
284
- addToFavorites: t('favorites.add'),
285
- previousImage: t('navigation.previous'),
286
- nextImage: t('navigation.next'),
287
- }}
288
286
  />
289
287
  ```
290
288
 
291
- **Note**: All text labels are passed as props. The consuming app provides translated strings. Navigation and favorite logic are handled by the consuming app via callbacks.
289
+ Translations (rating labels, price text, etc.) are handled automatically via `HotelCardUIProvider`.
292
290
 
293
291
  ### Checkbox & RadioButton
294
292
 
@@ -330,19 +328,33 @@ import type {
330
328
  RatingProps,
331
329
  DividerProps,
332
330
  SectionHeaderProps,
331
+ BlockProps,
332
+ ReviewCardProps,
333
+ FAQProps,
334
+ FAQItem,
335
+ BenefitsProps,
336
+ BenefitItem,
337
+ PinProps,
338
+ DateSelectorProps,
333
339
  WhenContentProps,
334
- WhenContentLabels,
335
340
  DateRange,
336
341
  GuestContentProps,
337
- GuestContentLabels,
338
342
  GuestCounts,
339
343
  ChildAgeError,
340
344
  HotelCardProps,
341
- HotelCardLabels,
342
345
  HotelCardHotel,
343
346
  HotelCardImageProps,
344
347
  HotelCardContentProps,
345
348
 
349
+ // Context Types
350
+ UIContextValue,
351
+ HotelCardUIProviderProps,
352
+ TranslateFunction,
353
+
354
+ // Translation Types
355
+ Locale,
356
+ TranslationKeys,
357
+
346
358
  // Data Types
347
359
  Hotel,
348
360
  Booking,
@@ -359,7 +371,7 @@ import type {
359
371
  ## Hooks
360
372
 
361
373
  ```typescript
362
- import { useDebounce, useResponsive, useWindowData } from '@hotelcard/ui';
374
+ import { useDebounce, useResponsive, useWindowData, useUIContext } from '@hotelcard/ui';
363
375
 
364
376
  // Debounce a value
365
377
  const debouncedSearch = useDebounce(searchTerm, 300);
@@ -369,6 +381,10 @@ const { isDesktop } = useResponsive(); // >= 1024px
369
381
 
370
382
  // Window/context data
371
383
  const { locale, currency } = useWindowData();
384
+
385
+ // UI Context with translation function
386
+ const { locale, currency, isDesktop, t } = useUIContext();
387
+ t('label.rating-excellent', 'Excellent'); // Returns translated string
372
388
  ```
373
389
 
374
390
  ---
@@ -393,20 +409,18 @@ calculateDiscount(400, 200); // 50
393
409
 
394
410
  ---
395
411
 
396
- ## Context Provider (Optional)
412
+ ## Translations
397
413
 
398
- For apps that need shared configuration:
414
+ The package exports bundled translations that can be used directly:
399
415
 
400
- ```tsx
401
- import { HotelCardUIProvider } from '@hotelcard/ui';
416
+ ```typescript
417
+ import { translations } from '@hotelcard/ui';
402
418
 
403
- <HotelCardUIProvider
404
- locale="de"
405
- currency="CHF"
406
- isDesktop={false}
407
- >
408
- <App />
409
- </HotelCardUIProvider>
419
+ // Access translations for a specific locale
420
+ console.log(translations.de.form.adults); // "Erwachsene"
421
+ console.log(translations.en.form.adults); // "Adults"
422
+ console.log(translations.fr.form.adults); // "Adultes"
423
+ console.log(translations.it.form.adults); // "Adulti"
410
424
  ```
411
425
 
412
426
  ---
@@ -417,7 +431,7 @@ Components use CSS variables for theming. Import the styles once in your app ent
417
431
 
418
432
  ```tsx
419
433
  // main.tsx or App.tsx
420
- import '@hotelcard/ui/dist/index.css';
434
+ import '@hotelcard/ui/styles.css';
421
435
  ```
422
436
 
423
437
  ### Customizing with CSS Variables
@@ -457,6 +471,45 @@ Components have built-in fallback values, so they work without custom CSS variab
457
471
 
458
472
  ---
459
473
 
474
+ ## Platform Safeguards
475
+
476
+ This package is designed to work in both web (Next.js) and mobile (Ionic/Capacitor) environments. To maintain platform-agnosticism, the following safeguards are in place:
477
+
478
+ ### Forbidden Imports
479
+
480
+ ESLint and pre-publish checks will block:
481
+
482
+ | Import | Reason |
483
+ |--------|--------|
484
+ | `next/router`, `next/image` | Web-only Next.js APIs |
485
+ | `@ionic/react`, `@capacitor/*` | Mobile-only Ionic/Capacitor APIs |
486
+ | `@/*` path aliases | App-specific configuration |
487
+ | `react-native` | Mobile-only framework |
488
+
489
+ ### Forbidden Patterns
490
+
491
+ | Pattern | Reason | Alternative |
492
+ |---------|--------|-------------|
493
+ | `localStorage.*` | Not available everywhere | Use callback props |
494
+ | `window.location` | Web-only | Use `onNavigate` callback |
495
+ | `useRouter()` | Platform-specific | Use `onClick` callback |
496
+ | `useNavigate()` | Platform-specific | Use `onClick` callback |
497
+
498
+ ### Running Checks
499
+
500
+ ```bash
501
+ pnpm check-imports # Scan for forbidden patterns
502
+ pnpm lint # Run ESLint
503
+ ```
504
+
505
+ These checks run automatically before `pnpm publish`.
506
+
507
+ ### Contributing
508
+
509
+ See [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines on keeping components platform-agnostic.
510
+
511
+ ---
512
+
460
513
  ## License
461
514
 
462
515
  MIT