@voyant-travel/bookings-react 0.162.1 → 0.163.0

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.
@@ -2,7 +2,7 @@
2
2
  "use client";
3
3
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
4
4
  import { useQueryClient } from "@tanstack/react-query";
5
- import { useAdminNavigate, useOperatorAdminMessages } from "@voyant-travel/admin";
5
+ import { useAdminNavigate, useLocale, useOperatorAdminMessages } from "@voyant-travel/admin";
6
6
  import { legalQueryKeys, useLegalContractAttachments, useLegalContracts, useVoyantLegalContext, } from "@voyant-travel/legal-react";
7
7
  import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, Badge, Button, } from "@voyant-travel/ui/components";
8
8
  import { DataTable } from "@voyant-travel/ui/components/data-table";
@@ -177,6 +177,7 @@ function TravelerStatusCell({ doc, messages, }) {
177
177
  return (_jsx(StatusBadge, { status: isExpired ? "expired" : "active", children: isExpired ? messages.travelerStatusExpired : messages.travelerStatusOnFile }));
178
178
  }
179
179
  function ContractDateCell({ contract, messages, }) {
180
+ const { resolvedLocale } = useLocale();
180
181
  const generationFailure = resolveContractGenerationFailure(contract);
181
182
  const attachmentsQuery = useLegalContractAttachments({ contractId: contract.id });
182
183
  const attachments = (attachmentsQuery.data ?? []).filter((a) => a.kind === "document");
@@ -189,14 +190,15 @@ function ContractDateCell({ contract, messages, }) {
189
190
  : messages.contractPendingSinceLabel;
190
191
  if (!dateIso)
191
192
  return _jsx("span", { className: "text-muted-foreground text-xs", children: "\u2014" });
192
- return (_jsxs("span", { className: "text-muted-foreground text-xs", children: [_jsxs("span", { className: "opacity-60", children: [dateLabel, " "] }), formatDate(dateIso)] }));
193
+ return (_jsxs("span", { className: "text-muted-foreground text-xs", children: [_jsxs("span", { className: "opacity-60", children: [dateLabel, " "] }), formatDate(dateIso, resolvedLocale)] }));
193
194
  }
194
195
  function TravelerDateCell({ doc, messages, }) {
196
+ const { resolvedLocale } = useLocale();
195
197
  const dateIso = doc.expiresAt ?? doc.createdAt ?? null;
196
198
  const dateLabel = doc.expiresAt ? messages.travelerExpiresLabel : messages.travelerUploadedLabel;
197
199
  if (!dateIso)
198
200
  return _jsx("span", { className: "text-muted-foreground text-xs", children: "\u2014" });
199
- return (_jsxs("span", { className: "text-muted-foreground text-xs", children: [_jsxs("span", { className: "opacity-60", children: [dateLabel, " "] }), formatDate(dateIso)] }));
201
+ return (_jsxs("span", { className: "text-muted-foreground text-xs", children: [_jsxs("span", { className: "opacity-60", children: [dateLabel, " "] }), formatDate(dateIso, resolvedLocale)] }));
200
202
  }
201
203
  function ContractActionsCell({ contract, messages, }) {
202
204
  const queryClient = useQueryClient();
@@ -246,12 +248,12 @@ function formatBytes(bytes) {
246
248
  return `${Math.round(bytes / 1024)} KB`;
247
249
  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
248
250
  }
249
- function formatDate(iso) {
251
+ function formatDate(iso, locale) {
250
252
  try {
251
253
  const d = new Date(iso);
252
254
  if (!Number.isFinite(d.getTime()))
253
255
  return iso;
254
- return d.toLocaleDateString(undefined, { day: "numeric", month: "short", year: "numeric" });
256
+ return d.toLocaleDateString(locale, { day: "numeric", month: "short", year: "numeric" });
255
257
  }
256
258
  catch {
257
259
  return iso;
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useLocale } from "@voyant-travel/admin";
3
4
  import { useSlots } from "@voyant-travel/operations-react/availability";
4
5
  import { Combobox, ComboboxCollection, ComboboxContent, ComboboxEmpty, ComboboxInput, ComboboxItem, ComboboxList, } from "@voyant-travel/ui/components/combobox";
5
6
  import { DatePicker } from "@voyant-travel/ui/components/date-picker";
@@ -7,23 +8,13 @@ import { Label } from "@voyant-travel/ui/components/label";
7
8
  import { useEffect, useMemo, useState } from "react";
8
9
  import { getBookableDepartureSlots } from "../components/booking-create-utils.js";
9
10
  import { useBookingsUiMessagesOrDefault } from "../i18n/provider.js";
10
- /**
11
- * Admin departure picker for the booking journey's `"departure"`
12
- * sub-step. Loads the owned product's scheduled departures from
13
- * availability and lets the operator pick a real one (filtered by the
14
- * chosen product option). When the product has no scheduled
15
- * departures, it falls back to a free date so non-scheduled
16
- * products can still be booked.
17
- *
18
- * Wired into `<BookingJourneyHost />` via the journey's
19
- * `renderDeparturePicker` slot.
20
- */
21
- const dateFormatter = new Intl.DateTimeFormat(undefined, {
22
- year: "numeric",
23
- month: "short",
24
- day: "numeric",
25
- });
26
11
  export function JourneyDeparturePicker({ productId, optionId, slotId, departureDate, onChange, lockDeparture = false, }) {
12
+ const { resolvedLocale } = useLocale();
13
+ const dateFormatter = useMemo(() => new Intl.DateTimeFormat(resolvedLocale, {
14
+ year: "numeric",
15
+ month: "short",
16
+ day: "numeric",
17
+ }), [resolvedLocale]);
27
18
  const messages = useBookingsUiMessagesOrDefault().bookingCreateDialog;
28
19
  // Stable "now" so the slot query + future filter don't churn every render.
29
20
  const [nowIso] = useState(() => new Date().toISOString());
@@ -6,23 +6,24 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
6
6
  * redeemed); they never need to know the exact code, unlike storefront
7
7
  * customers. Wired into `<BookingJourneyHost />` via `renderTravelCreditPicker`.
8
8
  */
9
- import { useOperatorAdminMessages } from "@voyant-travel/admin";
9
+ import { useLocale, useOperatorAdminMessages } from "@voyant-travel/admin";
10
10
  import { useTravelCredits } from "@voyant-travel/finance-react";
11
11
  import { Combobox, ComboboxCollection, ComboboxContent, ComboboxEmpty, ComboboxInput, ComboboxItem, ComboboxList, } from "@voyant-travel/ui/components/combobox";
12
12
  import { Label } from "@voyant-travel/ui/components/label";
13
13
  import { useEffect, useState } from "react";
14
- function formatMoney(cents, currency) {
14
+ function formatMoney(cents, currency, locale) {
15
15
  try {
16
- return new Intl.NumberFormat(undefined, { style: "currency", currency }).format(cents / 100);
16
+ return new Intl.NumberFormat(locale, { style: "currency", currency }).format(cents / 100);
17
17
  }
18
18
  catch {
19
19
  return `${(cents / 100).toFixed(2)} ${currency}`;
20
20
  }
21
21
  }
22
- function travelCreditLabel(travelCredit) {
23
- return `${travelCredit.code} · ${formatMoney(travelCredit.remainingAmountCents, travelCredit.currency)}`;
22
+ function travelCreditLabel(travelCredit, locale) {
23
+ return `${travelCredit.code} · ${formatMoney(travelCredit.remainingAmountCents, travelCredit.currency, locale)}`;
24
24
  }
25
25
  export function JourneyTravelCreditPicker({ value, onApply, }) {
26
+ const { resolvedLocale } = useLocale();
26
27
  const t = useOperatorAdminMessages().bookings.detail.bookingJourney;
27
28
  const [inputValue, setInputValue] = useState("");
28
29
  const [search, setSearch] = useState("");
@@ -39,12 +40,12 @@ export function JourneyTravelCreditPicker({ value, onApply, }) {
39
40
  // Reflect a pre-selected Travel Credit's label once its record loads.
40
41
  useEffect(() => {
41
42
  if (selectedId && byId.has(selectedId)) {
42
- setInputValue(travelCreditLabel(byId.get(selectedId)));
43
+ setInputValue(travelCreditLabel(byId.get(selectedId), resolvedLocale));
43
44
  }
44
- }, [selectedId, byId]);
45
+ }, [selectedId, byId, resolvedLocale]);
45
46
  return (_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { children: t.travelCreditPickerLabel }), _jsxs(Combobox, { items: travelCredits.map((travelCredit) => travelCredit.id), value: selectedId, inputValue: inputValue, autoHighlight: true, itemToStringLabel: (id) => {
46
47
  const v = byId.get(id);
47
- return v ? travelCreditLabel(v) : id;
48
+ return v ? travelCreditLabel(v, resolvedLocale) : id;
48
49
  }, itemToStringValue: (id) => id, onInputValueChange: (next) => {
49
50
  setInputValue(next);
50
51
  setSearch(next);
@@ -60,12 +61,12 @@ export function JourneyTravelCreditPicker({ value, onApply, }) {
60
61
  const v = byId.get(id);
61
62
  if (v) {
62
63
  onApply({ travelCreditId: v.id, amountCents: v.remainingAmountCents });
63
- setInputValue(travelCreditLabel(v));
64
+ setInputValue(travelCreditLabel(v, resolvedLocale));
64
65
  }
65
66
  }, children: [_jsx(ComboboxInput, { placeholder: t.travelCreditSearchPlaceholder, showClear: !!selectedId }), _jsxs(ComboboxContent, { children: [_jsx(ComboboxEmpty, { children: t.travelCreditEmpty }), _jsx(ComboboxList, { children: _jsx(ComboboxCollection, { children: (id) => {
66
67
  const v = byId.get(id);
67
68
  if (!v)
68
69
  return null;
69
- return (_jsx(ComboboxItem, { value: v.id, children: _jsxs("div", { className: "flex min-w-0 flex-col", children: [_jsx("span", { className: "truncate font-medium", children: v.code }), _jsx("span", { className: "truncate text-muted-foreground text-xs", children: formatMoney(v.remainingAmountCents, v.currency) })] }) }, v.id));
70
+ return (_jsx(ComboboxItem, { value: v.id, children: _jsxs("div", { className: "flex min-w-0 flex-col", children: [_jsx("span", { className: "truncate font-medium", children: v.code }), _jsx("span", { className: "truncate text-muted-foreground text-xs", children: formatMoney(v.remainingAmountCents, v.currency, resolvedLocale) })] }) }, v.id));
70
71
  } }) })] })] })] }));
71
72
  }
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useAdminNavigate, useOperatorAdminMessages } from "@voyant-travel/admin";
3
+ import { useAdminNavigate, useLocale, useOperatorAdminMessages } from "@voyant-travel/admin";
4
4
  import { Badge } from "@voyant-travel/ui/components/badge";
5
5
  import { Skeleton } from "@voyant-travel/ui/components/skeleton";
6
6
  import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@voyant-travel/ui/components/table";
@@ -15,6 +15,7 @@ import { bookingStatusBadgeVariant, useBookings } from "../index.js";
15
15
  * semantic `booking.detail` destination.
16
16
  */
17
17
  export function PersonBookingsWidget({ personId }) {
18
+ const { resolvedLocale } = useLocale();
18
19
  const adminMessages = useOperatorAdminMessages();
19
20
  const messages = adminMessages.bookings.list;
20
21
  const navigateTo = useAdminNavigate();
@@ -35,14 +36,14 @@ export function PersonBookingsWidget({ personId }) {
35
36
  const extraItems = Math.max((booking.items?.length ?? 0) - 1, 0);
36
37
  return (_jsxs(TableRow, { onClick: () => navigateTo("booking.detail", { bookingId: booking.id }), className: "cursor-pointer", children: [_jsx(TableCell, { className: "font-medium", children: booking.bookingNumber }), _jsx(TableCell, { children: _jsxs("div", { className: "max-w-[280px] truncate", title: itemLabel, children: [itemLabel, extraItems > 0 ? (_jsxs("span", { className: "ml-1 text-muted-foreground text-xs", children: ["+", extraItems] })) : null] }) }), _jsx(TableCell, { children: _jsx(Badge, { variant: bookingStatusBadgeVariant[booking.status], children: booking.status }) }), _jsx(TableCell, { children: booking.sellAmountCents == null
37
38
  ? "—"
38
- : `${(booking.sellAmountCents / 100).toFixed(2)} ${booking.sellCurrency}` }), _jsx(TableCell, { children: booking.pax ?? "—" }), _jsx(TableCell, { children: formatBookingDate(booking.startsAt ?? booking.startDate) })] }, booking.id));
39
+ : `${(booking.sellAmountCents / 100).toFixed(2)} ${booking.sellCurrency}` }), _jsx(TableCell, { children: booking.pax ?? "—" }), _jsx(TableCell, { children: formatBookingDate(booking.startsAt ?? booking.startDate, resolvedLocale) })] }, booking.id));
39
40
  }) })] }) }));
40
41
  }
41
- function formatBookingDate(value) {
42
+ function formatBookingDate(value, locale) {
42
43
  if (!value)
43
44
  return "—";
44
45
  const date = new Date(/^\d{4}-\d{2}-\d{2}$/.test(value) ? `${value}T00:00:00` : value);
45
46
  if (Number.isNaN(date.getTime()))
46
47
  return "—";
47
- return date.toLocaleDateString();
48
+ return date.toLocaleDateString(locale);
48
49
  }
@@ -15,11 +15,11 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "
15
15
  import { ListFilter, X } from "lucide-react";
16
16
  import * as React from "react";
17
17
  import { BOOKING_STATUS_ALL } from "../booking-list-constants.js";
18
- import { useBookingsUiMessagesOrDefault } from "../i18n/provider.js";
18
+ import { useBookingsUiI18nOrDefault } from "../i18n/provider.js";
19
19
  import { bookingStatuses } from "../index.js";
20
20
  export { BOOKING_STATUS_ALL };
21
21
  export function BookingListFiltersPopover({ open, onOpenChange, activeFilterCount, status, onStatusChange, productId, onProductIdChange, optionId, onOptionIdChange, availabilitySlotId, onAvailabilitySlotIdChange, supplierId, onSupplierIdChange, productCategoryId, onProductCategoryIdChange, personId, onPersonIdChange, organizationId, onOrganizationIdChange, dateRange, onDateRangeChange, paxMin, onPaxMinChange, paxMax, onPaxMaxChange, onFiltersChanged, hasActiveFilters, onClearFilters, }) {
22
- const messages = useBookingsUiMessagesOrDefault();
22
+ const { locale, messages } = useBookingsUiI18nOrDefault();
23
23
  const filterMessages = messages.bookingList.filters;
24
24
  const statusLabels = messages.common.bookingStatusLabels;
25
25
  const [selectedProduct, setSelectedProduct] = React.useState(null);
@@ -115,7 +115,7 @@ export function BookingListFiltersPopover({ open, onOpenChange, activeFilterCoun
115
115
  setSelectedSlot(match);
116
116
  }
117
117
  markChanged();
118
- }, items: slots, selectedItem: selectedSlot, getKey: (slot) => slot.id, getLabel: (slot) => formatSlotLabel(slot), getSecondary: (slot) => slot.status, placeholder: filterMessages.departure, emptyText: productId ? filterMessages.departureEmpty : filterMessages.departureNeedsProduct, disabled: productId === null })] }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { htmlFor: "bookings-filter-category", children: filterMessages.categoryLabel }), _jsx(AsyncCombobox, { value: productCategoryId, onChange: (value) => {
118
+ }, items: slots, selectedItem: selectedSlot, getKey: (slot) => slot.id, getLabel: (slot) => formatSlotLabel(slot, locale), getSecondary: (slot) => slot.status, placeholder: filterMessages.departure, emptyText: productId ? filterMessages.departureEmpty : filterMessages.departureNeedsProduct, disabled: productId === null })] }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { htmlFor: "bookings-filter-category", children: filterMessages.categoryLabel }), _jsx(AsyncCombobox, { value: productCategoryId, onChange: (value) => {
119
119
  onProductCategoryIdChange(value);
120
120
  if (!value)
121
121
  setSelectedProductCategory(null);
@@ -175,9 +175,9 @@ function formatPersonName(person) {
175
175
  * in the slot's own timezone so the operator sees what the customer
176
176
  * sees, not whatever the admin's browser locale converts it to.
177
177
  */
178
- function formatSlotLabel(slot) {
178
+ function formatSlotLabel(slot, locale) {
179
179
  try {
180
- const formatter = new Intl.DateTimeFormat(undefined, {
180
+ const formatter = new Intl.DateTimeFormat(locale, {
181
181
  day: "numeric",
182
182
  month: "short",
183
183
  year: "numeric",
@@ -31,7 +31,7 @@ export function BookingPaymentsSummary({ bookingId, variant = "public", onInvoic
31
31
  const publicQuery = usePublicBookingPayments(bookingId, { enabled: variant === "public" });
32
32
  const adminQuery = useAdminBookingPayments(bookingId, { enabled: variant === "admin" });
33
33
  const data = variant === "admin" ? adminQuery.data : publicQuery.data;
34
- const { formatDateTime } = useBookingsUiI18nOrDefault();
34
+ const { formatDateTime, locale } = useBookingsUiI18nOrDefault();
35
35
  const messages = useBookingsUiMessagesOrDefault();
36
36
  const card = messages.bookingPaymentsSummary;
37
37
  const payments = data?.data?.payments ?? [];
@@ -91,7 +91,7 @@ export function BookingPaymentsSummary({ bookingId, variant = "public", onInvoic
91
91
  {
92
92
  accessorKey: "amountCents",
93
93
  header: card.columns.amount,
94
- cell: ({ row }) => (_jsx("span", { className: "font-mono font-medium", children: formatMoney(row.original.amountCents, row.original.currency) })),
94
+ cell: ({ row }) => (_jsx("span", { className: "font-mono font-medium", children: formatMoney(row.original.amountCents, row.original.currency, locale) })),
95
95
  },
96
96
  {
97
97
  id: "fx",
@@ -103,7 +103,7 @@ export function BookingPaymentsSummary({ bookingId, variant = "public", onInvoic
103
103
  baseCurrency.toUpperCase() === currency.toUpperCase()) {
104
104
  return _jsx("span", { className: "text-muted-foreground", children: "\u2014" });
105
105
  }
106
- return (_jsxs("span", { className: "font-mono text-xs", children: ["\u2248 ", formatMoney(baseAmountCents, baseCurrency)] }));
106
+ return (_jsxs("span", { className: "font-mono text-xs", children: ["\u2248 ", formatMoney(baseAmountCents, baseCurrency, locale)] }));
107
107
  },
108
108
  },
109
109
  {
@@ -170,6 +170,7 @@ export function BookingPaymentsSummary({ bookingId, variant = "public", onInvoic
170
170
  }, [
171
171
  card,
172
172
  formatDateTime,
173
+ locale,
173
174
  getInvoiceHref,
174
175
  onInvoiceOpen,
175
176
  onConvertProforma,
@@ -182,18 +183,18 @@ export function BookingPaymentsSummary({ bookingId, variant = "public", onInvoic
182
183
  if (!next && !deletePending)
183
184
  setDeleteTarget(null);
184
185
  }, children: _jsxs(AlertDialogContent, { size: "sm", children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: card.deleteConfirm.title }), _jsx(AlertDialogDescription, { children: deleteTarget
185
- ? card.deleteConfirm.description.replace("{amount}", formatMoney(deleteTarget.amountCents, deleteTarget.currency))
186
+ ? card.deleteConfirm.description.replace("{amount}", formatMoney(deleteTarget.amountCents, deleteTarget.currency, locale))
186
187
  : "" })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { disabled: deletePending, children: card.deleteConfirm.cancel }), _jsx(AlertDialogAction, { variant: "destructive", disabled: deletePending, onClick: () => void handleDeleteConfirm(), children: card.deleteConfirm.confirm })] })] }) })) : null] }));
187
188
  }
188
- function formatMoney(cents, currency) {
189
+ function formatMoney(cents, currency, locale) {
189
190
  if (!currency) {
190
- return new Intl.NumberFormat(undefined, {
191
+ return new Intl.NumberFormat(locale, {
191
192
  minimumFractionDigits: 2,
192
193
  maximumFractionDigits: 2,
193
194
  }).format(cents / 100);
194
195
  }
195
196
  try {
196
- return new Intl.NumberFormat(undefined, { style: "currency", currency }).format(cents / 100);
197
+ return new Intl.NumberFormat(locale, { style: "currency", currency }).format(cents / 100);
197
198
  }
198
199
  catch {
199
200
  return `${(cents / 100).toFixed(2)} ${currency}`;
@@ -7,7 +7,7 @@ import { DataTable } from "@voyant-travel/ui/components/data-table";
7
7
  import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, } from "@voyant-travel/ui/components/sheet";
8
8
  import { Eye, EyeOff, Loader2, Pencil, Plus, Trash2, Users } from "lucide-react";
9
9
  import * as React from "react";
10
- import { formatMessage, useBookingsUiMessagesOrDefault } from "../i18n/provider.js";
10
+ import { formatMessage, useBookingsUiI18nOrDefault, useBookingsUiMessagesOrDefault, } from "../i18n/provider.js";
11
11
  import { useBookingTravelerDocuments, useRevealTraveler, useTravelerMutation, useTravelers, } from "../index.js";
12
12
  import { IconActionButton } from "./icon-action-button.js";
13
13
  import { TravelerDialog } from "./traveler-dialog.js";
@@ -179,11 +179,11 @@ function TravelerDobCell({ bookingId, traveler, revealed, }) {
179
179
  const person = usePerson(traveler.personId ?? undefined, {
180
180
  enabled: Boolean(traveler.personId),
181
181
  }).data;
182
- const messages = useBookingsUiMessagesOrDefault();
182
+ const { locale, messages } = useBookingsUiI18nOrDefault();
183
183
  if (loading)
184
184
  return _jsx(RowLoading, {});
185
185
  const dob = travelDetails?.dateOfBirth ?? person?.dateOfBirth ?? null;
186
- return _jsx(_Fragment, { children: formatDobAge(dob, messages.travelerList.values.fieldUnavailable) });
186
+ return _jsx(_Fragment, { children: formatDobAge(dob, messages.travelerList.values.fieldUnavailable, locale) });
187
187
  }
188
188
  function RolePills({ traveler }) {
189
189
  const messages = useBookingsUiMessagesOrDefault();
@@ -220,7 +220,7 @@ function getTravelDocumentLabel(travelDetails, messages) {
220
220
  return messages.travelerDialog.documentTypeLabels[documentType];
221
221
  }
222
222
  function TravelerSnapshotBody({ bookingId, traveler, documents, }) {
223
- const messages = useBookingsUiMessagesOrDefault();
223
+ const { locale, messages } = useBookingsUiI18nOrDefault();
224
224
  const labels = messages.travelerList.snapshot;
225
225
  const empty = labels.empty;
226
226
  const { display, travelDetails, loading } = useRevealed(bookingId, traveler, true);
@@ -243,9 +243,9 @@ function TravelerSnapshotBody({ bookingId, traveler, documents, }) {
243
243
  if (display.travelerCategory) {
244
244
  roles.push(messages.travelerDialog.travelerCategoryLabels[display.travelerCategory] ?? display.travelerCategory);
245
245
  }
246
- return (_jsxs("div", { className: "flex-1 overflow-y-auto px-4 pb-4", children: [loading ? (_jsx("div", { className: "py-4", children: _jsx(RowLoading, {}) })) : null, _jsxs(SnapshotSection, { title: labels.sectionContact, children: [_jsx(SnapshotRow, { label: labels.nameLabel, value: fullName }), _jsx(SnapshotRow, { label: labels.emailLabel, value: email }), _jsx(SnapshotRow, { label: labels.phoneLabel, value: phone }), _jsx(SnapshotRow, { label: labels.languageLabel, value: display.preferredLanguage || empty }), _jsx(SnapshotRow, { label: labels.roleLabel, value: roles.length > 0 ? (_jsx("div", { className: "flex flex-wrap gap-1.5", children: roles.map((label) => (_jsx(MiniPill, { children: label }, label))) })) : (empty) })] }), _jsxs(SnapshotSection, { title: labels.sectionTravel, children: [_jsx(SnapshotRow, { label: labels.dobLabel, value: formatDobAge(dob, empty) }), _jsx(SnapshotRow, { label: labels.nationalityLabel, value: travelDetails?.nationality || empty }), _jsx(SnapshotRow, { label: labels.documentLabel, value: documentValue }), _jsx(SnapshotRow, { label: labels.documentExpiryLabel, value: formatDateValue(travelDetails?.documentExpiry) ?? empty }), _jsx(SnapshotRow, { label: labels.dietaryLabel, value: travelDetails?.dietaryRequirements || empty, multiline: true }), _jsx(SnapshotRow, { label: labels.accessibilityLabel, value: travelDetails?.accessibilityNeeds || empty, multiline: true }), _jsx(SnapshotRow, { label: labels.specialRequestsLabel, value: display.specialRequests || empty, multiline: true }), _jsx(SnapshotRow, { label: labels.notesLabel, value: display.notes || empty, multiline: true })] }), _jsx(SnapshotSection, { title: labels.sectionDocuments, children: documents.length === 0 ? (_jsx("div", { className: "px-3 py-3 text-sm text-muted-foreground", children: labels.noDocuments })) : (documents.map((document) => (_jsx(SnapshotRow, { label: formatMessage(messages.travelerList.context.documentLabel, {
246
+ return (_jsxs("div", { className: "flex-1 overflow-y-auto px-4 pb-4", children: [loading ? (_jsx("div", { className: "py-4", children: _jsx(RowLoading, {}) })) : null, _jsxs(SnapshotSection, { title: labels.sectionContact, children: [_jsx(SnapshotRow, { label: labels.nameLabel, value: fullName }), _jsx(SnapshotRow, { label: labels.emailLabel, value: email }), _jsx(SnapshotRow, { label: labels.phoneLabel, value: phone }), _jsx(SnapshotRow, { label: labels.languageLabel, value: display.preferredLanguage || empty }), _jsx(SnapshotRow, { label: labels.roleLabel, value: roles.length > 0 ? (_jsx("div", { className: "flex flex-wrap gap-1.5", children: roles.map((label) => (_jsx(MiniPill, { children: label }, label))) })) : (empty) })] }), _jsxs(SnapshotSection, { title: labels.sectionTravel, children: [_jsx(SnapshotRow, { label: labels.dobLabel, value: formatDobAge(dob, empty, locale) }), _jsx(SnapshotRow, { label: labels.nationalityLabel, value: travelDetails?.nationality || empty }), _jsx(SnapshotRow, { label: labels.documentLabel, value: documentValue }), _jsx(SnapshotRow, { label: labels.documentExpiryLabel, value: formatDateValue(travelDetails?.documentExpiry, locale) ?? empty }), _jsx(SnapshotRow, { label: labels.dietaryLabel, value: travelDetails?.dietaryRequirements || empty, multiline: true }), _jsx(SnapshotRow, { label: labels.accessibilityLabel, value: travelDetails?.accessibilityNeeds || empty, multiline: true }), _jsx(SnapshotRow, { label: labels.specialRequestsLabel, value: display.specialRequests || empty, multiline: true }), _jsx(SnapshotRow, { label: labels.notesLabel, value: display.notes || empty, multiline: true })] }), _jsx(SnapshotSection, { title: labels.sectionDocuments, children: documents.length === 0 ? (_jsx("div", { className: "px-3 py-3 text-sm text-muted-foreground", children: labels.noDocuments })) : (documents.map((document) => (_jsx(SnapshotRow, { label: formatMessage(messages.travelerList.context.documentLabel, {
247
247
  type: document.type.replaceAll("_", " "),
248
- }), value: document.fileName }, document.id)))) }), _jsxs(SnapshotSection, { title: labels.sectionMeta, children: [_jsx(SnapshotRow, { label: labels.createdAtLabel, value: formatTimestamp(traveler.createdAt) ?? empty }), _jsx(SnapshotRow, { label: labels.updatedAtLabel, value: formatTimestamp(traveler.updatedAt) ?? empty })] })] }));
248
+ }), value: document.fileName }, document.id)))) }), _jsxs(SnapshotSection, { title: labels.sectionMeta, children: [_jsx(SnapshotRow, { label: labels.createdAtLabel, value: formatTimestamp(traveler.createdAt, locale) ?? empty }), _jsx(SnapshotRow, { label: labels.updatedAtLabel, value: formatTimestamp(traveler.updatedAt, locale) ?? empty })] })] }));
249
249
  }
250
250
  function SnapshotSection({ title, children }) {
251
251
  return (_jsxs("section", { className: "mb-6", children: [_jsx("h3", { className: "mb-2 text-xs font-medium uppercase tracking-wide text-muted-foreground", children: title }), _jsx("dl", { className: "divide-y divide-border rounded-md border", children: children })] }));
@@ -260,14 +260,14 @@ function RowLoading() {
260
260
  function MiniPill({ children }) {
261
261
  return (_jsx("span", { className: "inline-flex h-5 items-center rounded-full border px-2 text-[11px] capitalize text-muted-foreground", children: children }));
262
262
  }
263
- function formatTimestamp(iso) {
263
+ function formatTimestamp(iso, locale) {
264
264
  if (!iso)
265
265
  return null;
266
266
  const d = new Date(iso);
267
267
  if (!Number.isFinite(d.getTime()))
268
268
  return null;
269
269
  try {
270
- return d.toLocaleString(undefined, {
270
+ return d.toLocaleString(locale, {
271
271
  day: "numeric",
272
272
  month: "short",
273
273
  year: "numeric",
@@ -279,7 +279,7 @@ function formatTimestamp(iso) {
279
279
  return d.toISOString();
280
280
  }
281
281
  }
282
- function formatDobAge(value, unavailable) {
282
+ function formatDobAge(value, unavailable, locale) {
283
283
  if (!value)
284
284
  return unavailable;
285
285
  const date = new Date(value);
@@ -291,15 +291,15 @@ function formatDobAge(value, unavailable) {
291
291
  (today.getMonth() === date.getMonth() && today.getDate() >= date.getDate());
292
292
  if (!birthdayPassed)
293
293
  age -= 1;
294
- return `${formatDateValue(value)} · ${age}`;
294
+ return `${formatDateValue(value, locale)} · ${age}`;
295
295
  }
296
- function formatDateValue(value) {
296
+ function formatDateValue(value, locale) {
297
297
  if (!value)
298
298
  return null;
299
299
  const date = new Date(value);
300
300
  if (Number.isNaN(date.getTime()))
301
301
  return value;
302
- return date.toLocaleDateString(undefined, { month: "short", day: "numeric", year: "numeric" });
302
+ return date.toLocaleDateString(locale, { month: "short", day: "numeric", year: "numeric" });
303
303
  }
304
304
  /**
305
305
  * Heuristic check for redaction markers used by `redactTravelerIdentity`
@@ -114,9 +114,10 @@ export declare function getExtrasUiI18n({ locale, overrides, }: {
114
114
  locale?: string | null | undefined;
115
115
  overrides?: ExtrasUiMessageOverrides | null;
116
116
  }): PackageI18nValue<ExtrasUiMessages>;
117
- export declare function ExtrasUiMessagesProvider({ children, locale, overrides, }: {
117
+ export declare function ExtrasUiMessagesProvider({ children, locale, timeZone, overrides, }: {
118
118
  children: ReactNode;
119
119
  locale: string | null | undefined;
120
+ timeZone?: string | null;
120
121
  overrides?: ExtrasUiMessageOverrides | null;
121
122
  }): import("react").JSX.Element;
122
123
  export declare const useExtrasUiI18n: () => PackageI18nValue<ExtrasUiMessages>;
@@ -31,8 +31,8 @@ export function getExtrasUiI18n({ locale, overrides, }) {
31
31
  ...createLocaleFormatters(resolvedLocale),
32
32
  };
33
33
  }
34
- export function ExtrasUiMessagesProvider({ children, locale, overrides, }) {
35
- return (_jsx(extrasUiContext.ResolvedMessagesProvider, { definitions: extrasUiMessageDefinitions, fallbackLocale: fallbackLocale, locale: locale, overrides: overrides, children: children }));
34
+ export function ExtrasUiMessagesProvider({ children, locale, timeZone, overrides, }) {
35
+ return (_jsx(extrasUiContext.ResolvedMessagesProvider, { definitions: extrasUiMessageDefinitions, fallbackLocale: fallbackLocale, locale: locale, timeZone: timeZone, overrides: overrides, children: children }));
36
36
  }
37
37
  export const useExtrasUiI18n = extrasUiContext.useI18n;
38
38
  export const useExtrasUiMessages = extrasUiContext.useMessages;
@@ -3218,9 +3218,10 @@ export declare function getBookingsUiI18n({ locale, overrides, }: {
3218
3218
  locale?: string | null | undefined;
3219
3219
  overrides?: BookingsUiMessageOverrides | null;
3220
3220
  }): PackageI18nValue<BookingsUiMessages>;
3221
- export declare function BookingsUiMessagesProvider({ children, locale, overrides, }: {
3221
+ export declare function BookingsUiMessagesProvider({ children, locale, timeZone, overrides, }: {
3222
3222
  children: ReactNode;
3223
3223
  locale: string | null | undefined;
3224
+ timeZone?: string | null;
3224
3225
  overrides?: BookingsUiMessageOverrides | null;
3225
3226
  }): import("react").JSX.Element;
3226
3227
  export declare const useBookingsUiI18n: () => PackageI18nValue<BookingsUiMessages>;
@@ -31,8 +31,8 @@ export function getBookingsUiI18n({ locale, overrides, }) {
31
31
  ...createLocaleFormatters(resolvedLocale),
32
32
  };
33
33
  }
34
- export function BookingsUiMessagesProvider({ children, locale, overrides, }) {
35
- return (_jsx(bookingsUiContext.ResolvedMessagesProvider, { definitions: bookingsUiMessageDefinitions, fallbackLocale: fallbackLocale, locale: locale, overrides: overrides, children: children }));
34
+ export function BookingsUiMessagesProvider({ children, locale, timeZone, overrides, }) {
35
+ return (_jsx(bookingsUiContext.ResolvedMessagesProvider, { definitions: bookingsUiMessageDefinitions, fallbackLocale: fallbackLocale, locale: locale, timeZone: timeZone, overrides: overrides, children: children }));
36
36
  }
37
37
  export const useBookingsUiI18n = bookingsUiContext.useI18n;
38
38
  export const useBookingsUiMessages = bookingsUiContext.useMessages;
@@ -13,4 +13,4 @@ export declare function PriceSidePanel({ pricing, isQuoting, invalidReason, enti
13
13
  * pricing, where they're most in context. */
14
14
  pricingExtras?: React.ReactNode;
15
15
  }): React.ReactElement;
16
- export declare function stepHeadline(step: JourneyStep, draft: NonNullable<SidePanelState["draft"]>, messages: ReturnType<typeof useBookingsUiMessagesOrDefault>): string;
16
+ export declare function stepHeadline(step: JourneyStep, draft: NonNullable<SidePanelState["draft"]>, messages: ReturnType<typeof useBookingsUiMessagesOrDefault>, locale: string): string;
@@ -4,7 +4,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
4
4
  import { Accordion, AccordionContent, AccordionItem, AccordionTrigger, } from "@voyant-travel/ui/components/accordion";
5
5
  import { Card, CardContent } from "@voyant-travel/ui/components/card";
6
6
  import { Skeleton } from "@voyant-travel/ui/components/skeleton";
7
- import { formatMessage, useBookingsUiMessagesOrDefault } from "../../i18n/index.js";
7
+ import { formatMessage, useBookingsUiI18nOrDefault, useBookingsUiMessagesOrDefault, } from "../../i18n/index.js";
8
8
  /**
9
9
  * Right-rail summary panel. Shows what's being booked, an
10
10
  * accordion-per-step recap of the user's input, and the live
@@ -13,7 +13,7 @@ import { formatMessage, useBookingsUiMessagesOrDefault } from "../../i18n/index.
13
13
  * they've filled in elsewhere.
14
14
  */
15
15
  export function PriceSidePanel({ pricing, isQuoting, invalidReason, entitySummary, currentStep, steps, shape, draft, className, pricingExtras, }) {
16
- const messages = useBookingsUiMessagesOrDefault();
16
+ const { locale, messages } = useBookingsUiI18nOrDefault();
17
17
  // Only surface pricing once the user has configured what actually drives
18
18
  // the price — otherwise the quote's baseline shows a misleading total
19
19
  // (e.g. a per-pax "from" price before any room is picked). Room products
@@ -30,8 +30,8 @@ export function PriceSidePanel({ pricing, isQuoting, invalidReason, entitySummar
30
30
  : messages.bookingJourney.sidePanel.pricingHint;
31
31
  // Departure shows directly under the product title — it's the most-glanced
32
32
  // fact, so it doesn't belong buried in the recap accordion.
33
- const departureText = draft ? stepHeadline("departure", draft, messages) : "";
34
- return (_jsxs(Card, { className: className, children: [entitySummary?.heroImageUrl ? (_jsx("img", { src: entitySummary.heroImageUrl, alt: entitySummary.name, className: "aspect-video w-full object-cover" })) : null, entitySummary ? (_jsx(EntityHeader, { summary: entitySummary, departureText: departureText })) : null, _jsxs(CardContent, { className: "space-y-4", children: [steps && steps.length > 0 && currentStep && draft ? (_jsx(StepRecap, { steps: steps, currentStep: currentStep, draft: draft })) : null, invalidReason ? _jsx("p", { className: "text-destructive text-sm", children: invalidReason }) : null, !showPricing ? (_jsx("p", { className: "border-t pt-4 text-muted-foreground text-sm", children: pricingHint })) : isQuoting && !pricing ? (_jsxs("div", { className: "space-y-2 border-t pt-4", children: [_jsx(Skeleton, { className: "h-4 w-24" }), _jsx(Skeleton, { className: "h-4 w-32" }), _jsx(Skeleton, { className: "h-4 w-20" })] })) : null, showPricing && pricing ? (_jsxs("div", { className: "space-y-2 border-t pt-4", children: [_jsx("ul", { className: "space-y-1 text-sm", children: pricing.lines.map((line) => (_jsxs("li", { className: "flex justify-between", children: [_jsxs("span", { children: [line.label, line.quantity ? (_jsxs("span", { className: "text-muted-foreground", children: [" \u00D7 ", line.quantity] })) : null] }), _jsx("span", { children: formatMoney(line.totalAmount, pricing.currency) })] }, `${line.kind}-${line.label}-${line.totalAmount}`))) }), pricing.taxes.length > 0 ? (_jsx("ul", { className: "space-y-1 border-t pt-2 text-sm text-muted-foreground", children: pricing.taxes.map((tax) => (_jsxs("li", { className: "flex justify-between", children: [_jsxs("span", { children: [tax.label, tax.rate > 0 ? ` (${formatTaxRate(tax.rate)})` : ""] }), _jsx("span", { children: formatMoney(tax.amount, pricing.currency) })] }, tax.code))) })) : null, _jsxs("div", { className: "flex justify-between border-t pt-2 font-medium", children: [_jsx("span", { children: messages.bookingJourney.sidePanel.total }), _jsx("span", { children: formatMoney(pricing.total, pricing.currency) })] })] })) : null, pricingExtras ? _jsx("div", { className: "border-t pt-4", children: pricingExtras }) : null] })] }));
33
+ const departureText = draft ? stepHeadline("departure", draft, messages, locale) : "";
34
+ return (_jsxs(Card, { className: className, children: [entitySummary?.heroImageUrl ? (_jsx("img", { src: entitySummary.heroImageUrl, alt: entitySummary.name, className: "aspect-video w-full object-cover" })) : null, entitySummary ? (_jsx(EntityHeader, { summary: entitySummary, departureText: departureText })) : null, _jsxs(CardContent, { className: "space-y-4", children: [steps && steps.length > 0 && currentStep && draft ? (_jsx(StepRecap, { steps: steps, currentStep: currentStep, draft: draft })) : null, invalidReason ? _jsx("p", { className: "text-destructive text-sm", children: invalidReason }) : null, !showPricing ? (_jsx("p", { className: "border-t pt-4 text-muted-foreground text-sm", children: pricingHint })) : isQuoting && !pricing ? (_jsxs("div", { className: "space-y-2 border-t pt-4", children: [_jsx(Skeleton, { className: "h-4 w-24" }), _jsx(Skeleton, { className: "h-4 w-32" }), _jsx(Skeleton, { className: "h-4 w-20" })] })) : null, showPricing && pricing ? (_jsxs("div", { className: "space-y-2 border-t pt-4", children: [_jsx("ul", { className: "space-y-1 text-sm", children: pricing.lines.map((line) => (_jsxs("li", { className: "flex justify-between", children: [_jsxs("span", { children: [line.label, line.quantity ? (_jsxs("span", { className: "text-muted-foreground", children: [" \u00D7 ", line.quantity] })) : null] }), _jsx("span", { children: formatMoney(line.totalAmount, pricing.currency, locale) })] }, `${line.kind}-${line.label}-${line.totalAmount}`))) }), pricing.taxes.length > 0 ? (_jsx("ul", { className: "space-y-1 border-t pt-2 text-sm text-muted-foreground", children: pricing.taxes.map((tax) => (_jsxs("li", { className: "flex justify-between", children: [_jsxs("span", { children: [tax.label, tax.rate > 0 ? ` (${formatTaxRate(tax.rate)})` : ""] }), _jsx("span", { children: formatMoney(tax.amount, pricing.currency, locale) })] }, tax.code))) })) : null, _jsxs("div", { className: "flex justify-between border-t pt-2 font-medium", children: [_jsx("span", { children: messages.bookingJourney.sidePanel.total }), _jsx("span", { children: formatMoney(pricing.total, pricing.currency, locale) })] })] })) : null, pricingExtras ? _jsx("div", { className: "border-t pt-4", children: pricingExtras }) : null] })] }));
35
35
  }
36
36
  function EntityHeader({ summary, departureText, }) {
37
37
  // Text block only — the hero image is rendered as a direct Card child above.
@@ -52,21 +52,21 @@ function StepRecap({ steps, currentStep, draft, }) {
52
52
  return (_jsx(Accordion, { defaultValue: [currentStep], multiple: true, children: recapSteps.map((step) => (_jsxs(AccordionItem, { value: step, children: [_jsx(AccordionTrigger, { className: "py-3", children: _jsxs("div", { className: "flex flex-1 flex-col text-left", children: [_jsx("span", { className: step === currentStep ? "font-semibold" : "text-muted-foreground font-medium", children: stepLabel(step, messages) }), _jsx(StepSummaryLine, { step: step, draft: draft })] }) }), _jsx(AccordionContent, { children: _jsx(StepDetails, { step: step, draft: draft }) })] }, step))) }, currentStep));
53
53
  }
54
54
  function StepSummaryLine({ step, draft, }) {
55
- const messages = useBookingsUiMessagesOrDefault();
56
- const text = stepHeadline(step, draft, messages);
55
+ const { locale, messages } = useBookingsUiI18nOrDefault();
56
+ const text = stepHeadline(step, draft, messages, locale);
57
57
  if (!text)
58
58
  return null;
59
59
  return _jsx("span", { className: "text-muted-foreground text-xs", children: text });
60
60
  }
61
- export function stepHeadline(step, draft, messages) {
61
+ export function stepHeadline(step, draft, messages, locale) {
62
62
  switch (step) {
63
63
  case "departure": {
64
64
  const range = draft.configure?.dateRange;
65
65
  if (range?.checkIn && range?.checkOut)
66
- return `${formatConfigureDate(range.checkIn)} → ${formatConfigureDate(range.checkOut)}`;
66
+ return `${formatConfigureDate(range.checkIn, locale)} → ${formatConfigureDate(range.checkOut, locale)}`;
67
67
  // Never surface the raw slot id — show the departure date.
68
68
  return draft.configure?.departureDate
69
- ? formatConfigureDate(draft.configure.departureDate)
69
+ ? formatConfigureDate(draft.configure.departureDate, locale)
70
70
  : "";
71
71
  }
72
72
  case "options": {
@@ -146,10 +146,10 @@ function StepDetails({ step, draft, }) {
146
146
  }
147
147
  }
148
148
  function DepartureDetails({ draft, }) {
149
- const messages = useBookingsUiMessagesOrDefault();
149
+ const { locale, messages } = useBookingsUiI18nOrDefault();
150
150
  const cfg = draft.configure ?? {};
151
151
  const range = cfg.dateRange;
152
- return (_jsxs("dl", { className: "space-y-1 text-xs", children: [cfg.departureDate ? (_jsx(Row, { label: messages.bookingJourney.sidePanel.departure, value: formatConfigureDate(cfg.departureDate) })) : null, range?.checkIn ? (_jsx(Row, { label: messages.bookingJourney.sidePanel.checkIn, value: formatConfigureDate(range.checkIn) })) : null, range?.checkOut ? (_jsx(Row, { label: messages.bookingJourney.sidePanel.checkOut, value: formatConfigureDate(range.checkOut) })) : null] }));
152
+ return (_jsxs("dl", { className: "space-y-1 text-xs", children: [cfg.departureDate ? (_jsx(Row, { label: messages.bookingJourney.sidePanel.departure, value: formatConfigureDate(cfg.departureDate, locale) })) : null, range?.checkIn ? (_jsx(Row, { label: messages.bookingJourney.sidePanel.checkIn, value: formatConfigureDate(range.checkIn, locale) })) : null, range?.checkOut ? (_jsx(Row, { label: messages.bookingJourney.sidePanel.checkOut, value: formatConfigureDate(range.checkOut, locale) })) : null] }));
153
153
  }
154
154
  function OptionsDetails({ draft, }) {
155
155
  const messages = useBookingsUiMessagesOrDefault();
@@ -221,9 +221,9 @@ function stepLabel(step, messages) {
221
221
  return messages.bookingJourney.steps.billingAndContact;
222
222
  return messages.bookingJourney.steps[step];
223
223
  }
224
- function formatMoney(cents, currency) {
224
+ function formatMoney(cents, currency, locale) {
225
225
  try {
226
- return new Intl.NumberFormat(undefined, { style: "currency", currency }).format(cents / 100);
226
+ return new Intl.NumberFormat(locale, { style: "currency", currency }).format(cents / 100);
227
227
  }
228
228
  catch {
229
229
  return `${(cents / 100).toFixed(2)} ${currency}`;
@@ -235,14 +235,14 @@ function formatTaxRate(rate) {
235
235
  }
236
236
  /** Format an ISO date (YYYY-MM-DD or full ISO) for the recap, falling back
237
237
  * to the raw value when unparseable. Never surfaces a raw slot id. */
238
- function formatConfigureDate(iso) {
238
+ function formatConfigureDate(iso, locale) {
239
239
  const date = new Date(iso);
240
240
  if (Number.isNaN(date.getTime()))
241
241
  return iso;
242
242
  // Date-only strings parse as UTC midnight; render them in UTC so the
243
243
  // calendar date is not shifted for viewers in timezones west of UTC.
244
244
  const timeZone = /^\d{4}-\d{2}-\d{2}$/.test(iso) ? "UTC" : undefined;
245
- return new Intl.DateTimeFormat(undefined, {
245
+ return new Intl.DateTimeFormat(locale, {
246
246
  year: "numeric",
247
247
  month: "short",
248
248
  day: "numeric",
@@ -1,113 +1,113 @@
1
1
  export declare const SELECT_TYPES: Set<string>;
2
2
  export declare const QUESTION_TARGETS: readonly [{
3
3
  readonly value: "booking";
4
- readonly label: "Booking";
4
+ readonly label: string;
5
5
  }, {
6
6
  readonly value: "traveler";
7
- readonly label: "Traveler";
7
+ readonly label: string;
8
8
  }, {
9
9
  readonly value: "lead_traveler";
10
- readonly label: "Lead traveler";
10
+ readonly label: string;
11
11
  }, {
12
12
  readonly value: "booker";
13
- readonly label: "Booker";
13
+ readonly label: string;
14
14
  }, {
15
15
  readonly value: "extra";
16
- readonly label: "Extra";
16
+ readonly label: string;
17
17
  }, {
18
18
  readonly value: "service";
19
- readonly label: "Service";
19
+ readonly label: string;
20
20
  }];
21
21
  export declare const QUESTION_FIELD_TYPES: readonly [{
22
22
  readonly value: "text";
23
- readonly label: "Text";
23
+ readonly label: string;
24
24
  }, {
25
25
  readonly value: "textarea";
26
- readonly label: "Long text";
26
+ readonly label: string;
27
27
  }, {
28
28
  readonly value: "number";
29
- readonly label: "Number";
29
+ readonly label: string;
30
30
  }, {
31
31
  readonly value: "email";
32
- readonly label: "Email";
32
+ readonly label: string;
33
33
  }, {
34
34
  readonly value: "phone";
35
- readonly label: "Phone";
35
+ readonly label: string;
36
36
  }, {
37
37
  readonly value: "date";
38
- readonly label: "Date";
38
+ readonly label: string;
39
39
  }, {
40
40
  readonly value: "datetime";
41
- readonly label: "Date & time";
41
+ readonly label: string;
42
42
  }, {
43
43
  readonly value: "boolean";
44
- readonly label: "Yes / no";
44
+ readonly label: string;
45
45
  }, {
46
46
  readonly value: "single_select";
47
- readonly label: "Single select";
47
+ readonly label: string;
48
48
  }, {
49
49
  readonly value: "multi_select";
50
- readonly label: "Multi select";
50
+ readonly label: string;
51
51
  }, {
52
52
  readonly value: "file";
53
- readonly label: "File upload";
53
+ readonly label: string;
54
54
  }, {
55
55
  readonly value: "country";
56
- readonly label: "Country";
56
+ readonly label: string;
57
57
  }, {
58
58
  readonly value: "other";
59
- readonly label: "Other";
59
+ readonly label: string;
60
60
  }];
61
61
  export declare const CONTACT_FIELDS: readonly [{
62
62
  readonly value: "first_name";
63
- readonly label: "First name";
63
+ readonly label: string;
64
64
  }, {
65
65
  readonly value: "last_name";
66
- readonly label: "Last name";
66
+ readonly label: string;
67
67
  }, {
68
68
  readonly value: "email";
69
- readonly label: "Email";
69
+ readonly label: string;
70
70
  }, {
71
71
  readonly value: "phone";
72
- readonly label: "Phone";
72
+ readonly label: string;
73
73
  }, {
74
74
  readonly value: "date_of_birth";
75
- readonly label: "Date of birth";
75
+ readonly label: string;
76
76
  }, {
77
77
  readonly value: "nationality";
78
- readonly label: "Nationality";
78
+ readonly label: string;
79
79
  }, {
80
80
  readonly value: "passport_number";
81
- readonly label: "Passport number";
81
+ readonly label: string;
82
82
  }, {
83
83
  readonly value: "passport_expiry";
84
- readonly label: "Passport expiry";
84
+ readonly label: string;
85
85
  }, {
86
86
  readonly value: "dietary_requirements";
87
- readonly label: "Dietary requirements";
87
+ readonly label: string;
88
88
  }, {
89
89
  readonly value: "accessibility_needs";
90
- readonly label: "Accessibility needs";
90
+ readonly label: string;
91
91
  }, {
92
92
  readonly value: "special_requests";
93
- readonly label: "Special requests";
93
+ readonly label: string;
94
94
  }, {
95
95
  readonly value: "address";
96
- readonly label: "Address";
96
+ readonly label: string;
97
97
  }, {
98
98
  readonly value: "other";
99
- readonly label: "Other";
99
+ readonly label: string;
100
100
  }];
101
101
  export declare const CONTACT_SCOPES: readonly [{
102
102
  readonly value: "booking";
103
- readonly label: "Booking";
103
+ readonly label: string;
104
104
  }, {
105
105
  readonly value: "lead_traveler";
106
- readonly label: "Lead traveler";
106
+ readonly label: string;
107
107
  }, {
108
108
  readonly value: "traveler";
109
- readonly label: "Traveler";
109
+ readonly label: string;
110
110
  }, {
111
111
  readonly value: "booker";
112
- readonly label: "Booker";
112
+ readonly label: string;
113
113
  }];
@@ -1,45 +1,47 @@
1
+ import { bookingRequirementsUiEn } from "./i18n/en.js";
2
+ const labels = bookingRequirementsUiEn.common;
1
3
  export const SELECT_TYPES = new Set(["single_select", "multi_select"]);
2
4
  export const QUESTION_TARGETS = [
3
- { value: "booking", label: "Booking" },
4
- { value: "traveler", label: "Traveler" },
5
- { value: "lead_traveler", label: "Lead traveler" },
6
- { value: "booker", label: "Booker" },
7
- { value: "extra", label: "Extra" },
8
- { value: "service", label: "Service" },
5
+ { value: "booking", label: labels.questionTargetLabels.booking },
6
+ { value: "traveler", label: labels.questionTargetLabels.traveler },
7
+ { value: "lead_traveler", label: labels.questionTargetLabels.lead_traveler },
8
+ { value: "booker", label: labels.questionTargetLabels.booker },
9
+ { value: "extra", label: labels.questionTargetLabels.extra },
10
+ { value: "service", label: labels.questionTargetLabels.service },
9
11
  ];
10
12
  export const QUESTION_FIELD_TYPES = [
11
- { value: "text", label: "Text" },
12
- { value: "textarea", label: "Long text" },
13
- { value: "number", label: "Number" },
14
- { value: "email", label: "Email" },
15
- { value: "phone", label: "Phone" },
16
- { value: "date", label: "Date" },
17
- { value: "datetime", label: "Date & time" },
18
- { value: "boolean", label: "Yes / no" },
19
- { value: "single_select", label: "Single select" },
20
- { value: "multi_select", label: "Multi select" },
21
- { value: "file", label: "File upload" },
22
- { value: "country", label: "Country" },
23
- { value: "other", label: "Other" },
13
+ { value: "text", label: labels.questionFieldTypeLabels.text },
14
+ { value: "textarea", label: labels.questionFieldTypeLabels.textarea },
15
+ { value: "number", label: labels.questionFieldTypeLabels.number },
16
+ { value: "email", label: labels.questionFieldTypeLabels.email },
17
+ { value: "phone", label: labels.questionFieldTypeLabels.phone },
18
+ { value: "date", label: labels.questionFieldTypeLabels.date },
19
+ { value: "datetime", label: labels.questionFieldTypeLabels.datetime },
20
+ { value: "boolean", label: labels.questionFieldTypeLabels.boolean },
21
+ { value: "single_select", label: labels.questionFieldTypeLabels.single_select },
22
+ { value: "multi_select", label: labels.questionFieldTypeLabels.multi_select },
23
+ { value: "file", label: labels.questionFieldTypeLabels.file },
24
+ { value: "country", label: labels.questionFieldTypeLabels.country },
25
+ { value: "other", label: labels.questionFieldTypeLabels.other },
24
26
  ];
25
27
  export const CONTACT_FIELDS = [
26
- { value: "first_name", label: "First name" },
27
- { value: "last_name", label: "Last name" },
28
- { value: "email", label: "Email" },
29
- { value: "phone", label: "Phone" },
30
- { value: "date_of_birth", label: "Date of birth" },
31
- { value: "nationality", label: "Nationality" },
32
- { value: "passport_number", label: "Passport number" },
33
- { value: "passport_expiry", label: "Passport expiry" },
34
- { value: "dietary_requirements", label: "Dietary requirements" },
35
- { value: "accessibility_needs", label: "Accessibility needs" },
36
- { value: "special_requests", label: "Special requests" },
37
- { value: "address", label: "Address" },
38
- { value: "other", label: "Other" },
28
+ { value: "first_name", label: labels.fieldKeyLabels.first_name },
29
+ { value: "last_name", label: labels.fieldKeyLabels.last_name },
30
+ { value: "email", label: labels.fieldKeyLabels.email },
31
+ { value: "phone", label: labels.fieldKeyLabels.phone },
32
+ { value: "date_of_birth", label: labels.fieldKeyLabels.date_of_birth },
33
+ { value: "nationality", label: labels.fieldKeyLabels.nationality },
34
+ { value: "passport_number", label: labels.fieldKeyLabels.passport_number },
35
+ { value: "passport_expiry", label: labels.fieldKeyLabels.passport_expiry },
36
+ { value: "dietary_requirements", label: labels.fieldKeyLabels.dietary_requirements },
37
+ { value: "accessibility_needs", label: labels.fieldKeyLabels.accessibility_needs },
38
+ { value: "special_requests", label: labels.fieldKeyLabels.special_requests },
39
+ { value: "address", label: labels.fieldKeyLabels.address },
40
+ { value: "other", label: labels.fieldKeyLabels.other },
39
41
  ];
40
42
  export const CONTACT_SCOPES = [
41
- { value: "booking", label: "Booking" },
42
- { value: "lead_traveler", label: "Lead traveler" },
43
- { value: "traveler", label: "Traveler" },
44
- { value: "booker", label: "Booker" },
43
+ { value: "booking", label: labels.scopeLabels.booking },
44
+ { value: "lead_traveler", label: labels.scopeLabels.lead_traveler },
45
+ { value: "traveler", label: labels.scopeLabels.traveler },
46
+ { value: "booker", label: labels.scopeLabels.booker },
45
47
  ];
@@ -10,7 +10,7 @@ export declare function useBookingQuestions(options?: UseBookingQuestionsOptions
10
10
  label: string;
11
11
  description: string | null;
12
12
  target: "extra" | "service" | "traveler" | "booking" | "lead_traveler" | "booker";
13
- fieldType: "number" | "boolean" | "date" | "other" | "file" | "email" | "phone" | "textarea" | "text" | "single_select" | "multi_select" | "datetime" | "country";
13
+ fieldType: "number" | "boolean" | "date" | "other" | "file" | "email" | "phone" | "textarea" | "text" | "datetime" | "single_select" | "multi_select" | "country";
14
14
  placeholder: string | null;
15
15
  helpText: string | null;
16
16
  isRequired: boolean;
@@ -198,9 +198,10 @@ export declare function getBookingRequirementsUiI18n({ locale, overrides, }: {
198
198
  locale?: string | null | undefined;
199
199
  overrides?: BookingRequirementsUiMessageOverrides | null;
200
200
  }): PackageI18nValue<BookingRequirementsUiMessages>;
201
- export declare function BookingRequirementsUiMessagesProvider({ children, locale, overrides, }: {
201
+ export declare function BookingRequirementsUiMessagesProvider({ children, locale, timeZone, overrides, }: {
202
202
  children: ReactNode;
203
203
  locale: string | null | undefined;
204
+ timeZone?: string | null;
204
205
  overrides?: BookingRequirementsUiMessageOverrides | null;
205
206
  }): import("react").JSX.Element;
206
207
  export declare const useBookingRequirementsUiI18n: () => PackageI18nValue<BookingRequirementsUiMessages>;
@@ -31,8 +31,8 @@ export function getBookingRequirementsUiI18n({ locale, overrides, }) {
31
31
  ...createLocaleFormatters(resolvedLocale),
32
32
  };
33
33
  }
34
- export function BookingRequirementsUiMessagesProvider({ children, locale, overrides, }) {
35
- return (_jsx(bookingRequirementsUiContext.ResolvedMessagesProvider, { definitions: bookingRequirementsUiMessageDefinitions, fallbackLocale: fallbackLocale, locale: locale, overrides: overrides, children: children }));
34
+ export function BookingRequirementsUiMessagesProvider({ children, locale, timeZone, overrides, }) {
35
+ return (_jsx(bookingRequirementsUiContext.ResolvedMessagesProvider, { definitions: bookingRequirementsUiMessageDefinitions, fallbackLocale: fallbackLocale, locale: locale, timeZone: timeZone, overrides: overrides, children: children }));
36
36
  }
37
37
  export const useBookingRequirementsUiI18n = bookingRequirementsUiContext.useI18n;
38
38
  export const useBookingRequirementsUiMessages = bookingRequirementsUiContext.useMessages;
@@ -132,7 +132,7 @@ export declare function getBookingQuestionsQueryOptions(client: FetchWithValidat
132
132
  label: string;
133
133
  description: string | null;
134
134
  target: "extra" | "service" | "traveler" | "booking" | "lead_traveler" | "booker";
135
- fieldType: "number" | "boolean" | "date" | "other" | "file" | "email" | "phone" | "textarea" | "text" | "single_select" | "multi_select" | "datetime" | "country";
135
+ fieldType: "number" | "boolean" | "date" | "other" | "file" | "email" | "phone" | "textarea" | "text" | "datetime" | "single_select" | "multi_select" | "country";
136
136
  placeholder: string | null;
137
137
  helpText: string | null;
138
138
  isRequired: boolean;
@@ -150,7 +150,7 @@ export declare function getBookingQuestionsQueryOptions(client: FetchWithValidat
150
150
  label: string;
151
151
  description: string | null;
152
152
  target: "extra" | "service" | "traveler" | "booking" | "lead_traveler" | "booker";
153
- fieldType: "number" | "boolean" | "date" | "other" | "file" | "email" | "phone" | "textarea" | "text" | "single_select" | "multi_select" | "datetime" | "country";
153
+ fieldType: "number" | "boolean" | "date" | "other" | "file" | "email" | "phone" | "textarea" | "text" | "datetime" | "single_select" | "multi_select" | "country";
154
154
  placeholder: string | null;
155
155
  helpText: string | null;
156
156
  isRequired: boolean;
@@ -169,7 +169,7 @@ export declare function getBookingQuestionsQueryOptions(client: FetchWithValidat
169
169
  label: string;
170
170
  description: string | null;
171
171
  target: "extra" | "service" | "traveler" | "booking" | "lead_traveler" | "booker";
172
- fieldType: "number" | "boolean" | "date" | "other" | "file" | "email" | "phone" | "textarea" | "text" | "single_select" | "multi_select" | "datetime" | "country";
172
+ fieldType: "number" | "boolean" | "date" | "other" | "file" | "email" | "phone" | "textarea" | "text" | "datetime" | "single_select" | "multi_select" | "country";
173
173
  placeholder: string | null;
174
174
  helpText: string | null;
175
175
  isRequired: boolean;
@@ -190,7 +190,7 @@ export declare function getBookingQuestionsQueryOptions(client: FetchWithValidat
190
190
  label: string;
191
191
  description: string | null;
192
192
  target: "extra" | "service" | "traveler" | "booking" | "lead_traveler" | "booker";
193
- fieldType: "number" | "boolean" | "date" | "other" | "file" | "email" | "phone" | "textarea" | "text" | "single_select" | "multi_select" | "datetime" | "country";
193
+ fieldType: "number" | "boolean" | "date" | "other" | "file" | "email" | "phone" | "textarea" | "text" | "datetime" | "single_select" | "multi_select" | "country";
194
194
  placeholder: string | null;
195
195
  helpText: string | null;
196
196
  isRequired: boolean;
@@ -26,9 +26,9 @@ export declare const questionFieldTypeSchema: z.ZodEnum<{
26
26
  phone: "phone";
27
27
  textarea: "textarea";
28
28
  text: "text";
29
+ datetime: "datetime";
29
30
  single_select: "single_select";
30
31
  multi_select: "multi_select";
31
- datetime: "datetime";
32
32
  country: "country";
33
33
  }>;
34
34
  export declare const bookingQuestionSchema: z.ZodObject<{
@@ -55,9 +55,9 @@ export declare const bookingQuestionSchema: z.ZodObject<{
55
55
  phone: "phone";
56
56
  textarea: "textarea";
57
57
  text: "text";
58
+ datetime: "datetime";
58
59
  single_select: "single_select";
59
60
  multi_select: "multi_select";
60
- datetime: "datetime";
61
61
  country: "country";
62
62
  }>;
63
63
  placeholder: z.ZodNullable<z.ZodString>;
@@ -166,9 +166,9 @@ export declare const bookingQuestionListResponse: z.ZodObject<{
166
166
  phone: "phone";
167
167
  textarea: "textarea";
168
168
  text: "text";
169
+ datetime: "datetime";
169
170
  single_select: "single_select";
170
171
  multi_select: "multi_select";
171
- datetime: "datetime";
172
172
  country: "country";
173
173
  }>;
174
174
  placeholder: z.ZodNullable<z.ZodString>;
@@ -3,6 +3,7 @@ import { useQuery } from "@tanstack/react-query";
3
3
  import { useStorefrontUi } from "@voyant-travel/storefront-react/storefront";
4
4
  import { useMemo } from "react";
5
5
  import { z } from "zod";
6
+ import { useBookingsUiI18nOrDefault } from "../i18n/provider.js";
6
7
  import { StorefrontBookingJourney, } from "./storefront-booking-journey.js";
7
8
  export const storefrontBookingSearchSchema = z.object({
8
9
  departureSlotId: z.string().optional(),
@@ -76,6 +77,7 @@ function buildInitialAccommodation(search) {
76
77
  };
77
78
  }
78
79
  function useEntityContent(apiUrl, entityModule, entityId, search) {
80
+ const { locale } = useBookingsUiI18nOrDefault();
79
81
  const url = entityContentUrl(apiUrl, entityModule, entityId);
80
82
  const { data } = useQuery({
81
83
  queryKey: ["public-entity-summary", entityModule, entityId],
@@ -93,7 +95,7 @@ function useEntityContent(apiUrl, entityModule, entityId, search) {
93
95
  });
94
96
  const content = data?.content ?? null;
95
97
  const source = useMemo(() => resolveEntitySource(entityModule, data?.provenance, content), [entityModule, data?.provenance, content]);
96
- const summary = useMemo(() => resolveEntitySummary(entityModule, content, search), [content, entityModule, search]);
98
+ const summary = useMemo(() => resolveEntitySummary(entityModule, content, search, locale), [content, entityModule, search, locale]);
97
99
  return { summary, source };
98
100
  }
99
101
  function entityContentUrl(apiUrl, entityModule, entityId) {
@@ -107,19 +109,19 @@ function entityContentUrl(apiUrl, entityModule, entityId) {
107
109
  return `${apiUrl}/v1/public/products/${encodedId}/content`;
108
110
  return null;
109
111
  }
110
- function resolveEntitySummary(entityModule, content, search) {
112
+ function resolveEntitySummary(entityModule, content, search, locale) {
111
113
  if (!content)
112
114
  return undefined;
113
115
  if (entityModule === "products")
114
- return resolveProductSummary(content, search);
116
+ return resolveProductSummary(content, search, locale);
115
117
  if (entityModule === "cruises")
116
- return resolveCruiseSummary(content, search);
118
+ return resolveCruiseSummary(content, search, locale);
117
119
  if (entityModule === "accommodations") {
118
- return resolveAccommodationSummary(content, search);
120
+ return resolveAccommodationSummary(content, search, locale);
119
121
  }
120
122
  return undefined;
121
123
  }
122
- function resolveProductSummary(content, search) {
124
+ function resolveProductSummary(content, search, locale) {
123
125
  const subtitle = [
124
126
  content.product.duration_days
125
127
  ? `${content.product.duration_days} day${content.product.duration_days === 1 ? "" : "s"}`
@@ -132,14 +134,14 @@ function resolveProductSummary(content, search) {
132
134
  subtitle: subtitle.join(" · ") || undefined,
133
135
  heroImageUrl: content.product.hero_image_url ?? content.media?.[0]?.url ?? undefined,
134
136
  vertical: "products",
135
- whenLabel: departure ? formatDate(departure.starts_at) : undefined,
137
+ whenLabel: departure ? formatDate(departure.starts_at, locale) : undefined,
136
138
  locationLabel: content.product.departure_city ?? content.product.country ?? undefined,
137
139
  startDate: departure?.starts_at ?? undefined,
138
140
  endDate: departure?.ends_at ?? undefined,
139
141
  destination: content.product.country ?? content.product.departure_city ?? undefined,
140
142
  };
141
143
  }
142
- function resolveCruiseSummary(content, search) {
144
+ function resolveCruiseSummary(content, search, locale) {
143
145
  const sailing = content.sailings.find((item) => item.id === search.departureSlotId);
144
146
  const subtitle = [
145
147
  content.cruise.duration_nights
@@ -157,14 +159,14 @@ function resolveCruiseSummary(content, search) {
157
159
  subtitle: subtitle.join(" · ") || undefined,
158
160
  heroImageUrl: content.cruise.hero_image_url ?? undefined,
159
161
  vertical: "cruises",
160
- whenLabel: sailing ? formatDate(sailing.start_date) : undefined,
162
+ whenLabel: sailing ? formatDate(sailing.start_date, locale) : undefined,
161
163
  locationLabel: route ?? undefined,
162
164
  startDate: sailing?.start_date ?? undefined,
163
165
  endDate: sailing?.end_date ?? undefined,
164
166
  destination: route ?? undefined,
165
167
  };
166
168
  }
167
- function resolveAccommodationSummary(content, search) {
169
+ function resolveAccommodationSummary(content, search, locale) {
168
170
  const stars = content.hotel.star_rating ? "★".repeat(Math.floor(content.hotel.star_rating)) : null;
169
171
  return {
170
172
  name: content.hotel.name,
@@ -172,7 +174,7 @@ function resolveAccommodationSummary(content, search) {
172
174
  heroImageUrl: content.hotel.hero_image_url ?? undefined,
173
175
  vertical: "accommodations",
174
176
  whenLabel: search.checkIn && search.checkOut
175
- ? `${formatDate(search.checkIn)} → ${formatDate(search.checkOut)}`
177
+ ? `${formatDate(search.checkIn, locale)} → ${formatDate(search.checkOut, locale)}`
176
178
  : undefined,
177
179
  startDate: search.checkIn ?? undefined,
178
180
  endDate: search.checkOut ?? undefined,
@@ -192,9 +194,9 @@ function resolveEntitySource(entityModule, provenance, content) {
192
194
  supplier: { id: "", name: supplierName },
193
195
  };
194
196
  }
195
- function formatDate(iso) {
197
+ function formatDate(iso, locale) {
196
198
  try {
197
- return new Date(iso).toLocaleDateString(undefined, {
199
+ return new Date(iso).toLocaleDateString(locale, {
198
200
  weekday: "short",
199
201
  day: "numeric",
200
202
  month: "short",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voyant-travel/bookings-react",
3
- "version": "0.162.1",
3
+ "version": "0.163.0",
4
4
  "license": "Apache-2.0",
5
5
  "repository": {
6
6
  "type": "git",
@@ -150,24 +150,24 @@
150
150
  "react-dom": "^19.0.0",
151
151
  "react-hook-form": "^7.80.0",
152
152
  "zod": "^4.0.0",
153
- "@voyant-travel/accommodations": "^0.122.0",
154
- "@voyant-travel/admin": "^0.126.0",
155
- "@voyant-travel/bookings": "^0.162.1",
156
- "@voyant-travel/catalog": "^0.160.0",
157
- "@voyant-travel/catalog-react": "^0.160.0",
158
- "@voyant-travel/distribution-react": "^0.152.0",
159
- "@voyant-travel/relationships-react": "^0.162.0",
160
- "@voyant-travel/finance": "^0.162.1",
161
- "@voyant-travel/finance-react": "^0.162.1",
162
- "@voyant-travel/identity-react": "^0.162.0",
163
- "@voyant-travel/legal-react": "^0.162.1",
164
- "@voyant-travel/commerce-react": "^0.44.0",
165
- "@voyant-travel/cruises": "^0.161.0",
166
- "@voyant-travel/inventory-react": "^0.44.0",
167
- "@voyant-travel/inventory": "^0.12.1",
168
- "@voyant-travel/storefront-react": "^0.164.0",
153
+ "@voyant-travel/accommodations": "^0.123.0",
154
+ "@voyant-travel/admin": "^0.126.1",
155
+ "@voyant-travel/bookings": "^0.163.0",
156
+ "@voyant-travel/catalog": "^0.161.0",
157
+ "@voyant-travel/catalog-react": "^0.161.0",
158
+ "@voyant-travel/distribution-react": "^0.153.0",
159
+ "@voyant-travel/relationships-react": "^0.163.0",
160
+ "@voyant-travel/finance": "^0.163.0",
161
+ "@voyant-travel/finance-react": "^0.163.0",
162
+ "@voyant-travel/identity-react": "^0.163.0",
163
+ "@voyant-travel/legal-react": "^0.163.0",
164
+ "@voyant-travel/commerce-react": "^0.45.0",
165
+ "@voyant-travel/cruises": "^0.162.0",
166
+ "@voyant-travel/inventory-react": "^0.45.0",
167
+ "@voyant-travel/inventory": "^0.13.0",
168
+ "@voyant-travel/storefront-react": "^0.165.0",
169
169
  "@voyant-travel/ui": "^0.109.2",
170
- "@voyant-travel/operations-react": "^0.43.0"
170
+ "@voyant-travel/operations-react": "^0.44.0"
171
171
  },
172
172
  "peerDependenciesMeta": {
173
173
  "@tanstack/react-table": {
@@ -234,7 +234,7 @@
234
234
  "dependencies": {
235
235
  "sonner": "^2.0.7",
236
236
  "@voyant-travel/catalog-contracts": "^0.111.1",
237
- "@voyant-travel/i18n": "^0.111.2",
237
+ "@voyant-travel/i18n": "^0.111.3",
238
238
  "@voyant-travel/react": "^0.104.2",
239
239
  "@voyant-travel/types": "^0.109.2"
240
240
  },
@@ -251,26 +251,26 @@
251
251
  "typescript": "^6.0.3",
252
252
  "vitest": "^4.1.9",
253
253
  "zod": "^4.4.3",
254
- "@voyant-travel/accommodations": "^0.122.0",
255
- "@voyant-travel/admin": "^0.126.0",
256
- "@voyant-travel/bookings": "^0.162.1",
257
- "@voyant-travel/catalog": "^0.160.0",
258
- "@voyant-travel/catalog-react": "^0.160.0",
259
- "@voyant-travel/distribution-react": "^0.152.0",
260
- "@voyant-travel/relationships-react": "^0.162.0",
261
- "@voyant-travel/finance": "^0.162.1",
262
- "@voyant-travel/finance-react": "^0.162.1",
263
- "@voyant-travel/identity-react": "^0.162.0",
264
- "@voyant-travel/legal-react": "^0.162.1",
265
- "@voyant-travel/commerce-react": "^0.44.0",
266
- "@voyant-travel/cruises": "^0.161.0",
267
- "@voyant-travel/inventory-react": "^0.44.0",
268
- "@voyant-travel/inventory": "^0.12.1",
254
+ "@voyant-travel/accommodations": "^0.123.0",
255
+ "@voyant-travel/admin": "^0.126.1",
256
+ "@voyant-travel/bookings": "^0.163.0",
257
+ "@voyant-travel/catalog": "^0.161.0",
258
+ "@voyant-travel/catalog-react": "^0.161.0",
259
+ "@voyant-travel/distribution-react": "^0.153.0",
260
+ "@voyant-travel/relationships-react": "^0.163.0",
261
+ "@voyant-travel/finance": "^0.163.0",
262
+ "@voyant-travel/finance-react": "^0.163.0",
263
+ "@voyant-travel/identity-react": "^0.163.0",
264
+ "@voyant-travel/legal-react": "^0.163.0",
265
+ "@voyant-travel/commerce-react": "^0.45.0",
266
+ "@voyant-travel/cruises": "^0.162.0",
267
+ "@voyant-travel/inventory-react": "^0.45.0",
268
+ "@voyant-travel/inventory": "^0.13.0",
269
269
  "@voyant-travel/react": "^0.104.2",
270
- "@voyant-travel/storefront-react": "^0.164.0",
270
+ "@voyant-travel/storefront-react": "^0.165.0",
271
271
  "@voyant-travel/ui": "^0.109.2",
272
272
  "@voyant-travel/voyant-typescript-config": "^0.1.0",
273
- "@voyant-travel/operations-react": "^0.43.0"
273
+ "@voyant-travel/operations-react": "^0.44.0"
274
274
  },
275
275
  "files": [
276
276
  "dist",