@resira/ui 0.4.19 → 0.4.20

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/dist/index.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React from 'react';
3
- import { Product, WeightedBaseUrl, Resira, RefundRule, TimeSlotAvailability, DurationPrice, PublicResource, ValidatePromoCodeResponse, Reservation, AvailabilityParams, Availability, CheckoutSession, Dish, PaymentIntentResponse, CreatePaymentIntentRequest, CreateReservationRequest } from '@resira/sdk';
3
+ import { Product, WeightedBaseUrl, Resira, RefundRule, TimeSlotAvailability, DurationPrice, PublicResource, ValidatePromoCodeResponse, Reservation, AvailabilityParams, Availability, CheckoutSession, Dish, PaymentIntentResponse, CreatePaymentIntentRequest, CreateReservationRequest, SlotHoldResponse } from '@resira/sdk';
4
4
  export { CheckoutConfig, CheckoutSession, CheckoutSessionResponse, ConfirmPaymentRequest, ConfirmPaymentResponse, CreateCheckoutSessionRequest, CreateCheckoutSessionResponse, CreatePaymentIntentRequest, Dish, DishListResponse, DishModel, DishResponse, DurationPrice, PaymentIntentResponse, PricingModel, Product, ProductCategory, ProductImage, ProductListResponse, ProductVariant, PublicResource, ResourceListResponse, RiderTierPrice } from '@resira/sdk';
5
5
 
6
6
  type ResiraDomain = "rental" | "restaurant" | "watersport" | "service";
@@ -190,6 +190,12 @@ interface ResiraLocale {
190
190
  reserveTable?: string;
191
191
  /** @default "Reservation for" */
192
192
  reservationFor?: string;
193
+ /** @default "Reserved for you" */
194
+ slotHoldReserved?: string;
195
+ /** @default "This slot just sold out. Pick another time." */
196
+ slotSoldOut?: string;
197
+ /** @default "Your hold expired. Please choose a time again." */
198
+ slotHoldExpired?: string;
193
199
  }
194
200
  /** Default English locale. */
195
201
  declare const DEFAULT_LOCALE: Required<ResiraLocale>;
@@ -332,6 +338,11 @@ interface ResiraProviderConfig {
332
338
  onError?: (code: string, message: string) => void;
333
339
  /** Promoter mode configuration for fast in-person bookings. */
334
340
  promoterMode?: PromoterModeConfig;
341
+ /**
342
+ * When true (default), watersport/service flows create a short-lived slot hold after time selection.
343
+ * Disable on APIs that do not yet expose `POST /v2/public/products/.../slot-holds`.
344
+ */
345
+ slotHoldsEnabled?: boolean;
335
346
  }
336
347
  /** Props for the ResiraProvider component. */
337
348
  interface ResiraProviderProps {
@@ -421,6 +432,8 @@ interface ResiraContextValue {
421
432
  checkoutSessionToken?: string;
422
433
  /** Resolved promoter-mode behavior flags. */
423
434
  promoterMode: Required<PromoterModeConfig>;
435
+ /** Slot soft-hold API enabled (watersport/service). @default true */
436
+ slotHoldsEnabled: boolean;
424
437
  }
425
438
  /** Steps in the booking flow. */
426
439
  type BookingStep = "resource" | "availability" | "details" | "terms" | "payment" | "confirmation" | "checkout";
@@ -963,6 +976,48 @@ declare function resolveTheme(overrides?: ResiraTheme): Required<ResiraTheme>;
963
976
  */
964
977
  declare function themeToCSS(theme: Required<ResiraTheme>): Record<string, string>;
965
978
 
979
+ /** Known hold / slot conflict signals from API error text or `body.code`. */
980
+ type SlotHoldErrorCode = "SLOT_UNAVAILABLE" | "HOLD_EXPIRED" | "HOLD_MISMATCH" | "HOLD_NOT_FOUND" | "HOLD_NOT_ACTIVE" | "UNKNOWN";
981
+ declare function parseSlotHoldError(err: unknown): {
982
+ code: SlotHoldErrorCode;
983
+ message: string;
984
+ };
985
+ interface UseSlotHoldOptions {
986
+ client: Resira;
987
+ /** Master switch (false = no API calls; use for legacy APIs). */
988
+ enabled: boolean;
989
+ productId: string | undefined;
990
+ startTime: string | undefined;
991
+ durationMinutes: number | undefined;
992
+ partySize: number | undefined;
993
+ resourceId: string | undefined;
994
+ sessionToken?: string | undefined;
995
+ /** When hold cannot be placed or slot is gone. */
996
+ onSlotUnavailable?: () => void;
997
+ /** When countdown reaches zero. */
998
+ onHoldExpired?: () => void;
999
+ }
1000
+ interface UseSlotHoldReturn {
1001
+ holdId: string | null;
1002
+ holdExpiresAt: string | null;
1003
+ heldResourceId: string | null;
1004
+ /** Seconds left; null when no active hold. */
1005
+ remainingSeconds: number | null;
1006
+ /** True while POST /slot-holds is in flight. */
1007
+ creating: boolean;
1008
+ /** User-facing error message. */
1009
+ error: string | null;
1010
+ parsedErrorCode: SlotHoldErrorCode | null;
1011
+ /** Whether the user can leave the slot step (hold succeeded or holds disabled). */
1012
+ holdReady: boolean;
1013
+ /** Best-effort release (e.g. on unmount). */
1014
+ release: () => Promise<void>;
1015
+ serverNow: string | null;
1016
+ /** Full last hold response for debugging/UI. */
1017
+ lastHold: SlotHoldResponse | null;
1018
+ }
1019
+ declare function useSlotHold(options: UseSlotHoldOptions): UseSlotHoldReturn;
1020
+
966
1021
  interface IconProps {
967
1022
  size?: number;
968
1023
  className?: string;
@@ -989,4 +1044,4 @@ declare function TagIcon({ size, className }: IconProps): react_jsx_runtime.JSX.
989
1044
  declare function CubeIcon({ size, className }: IconProps): react_jsx_runtime.JSX.Element;
990
1045
  declare function ViewfinderIcon({ size, className }: IconProps): react_jsx_runtime.JSX.Element;
991
1046
 
992
- export { AlertCircleIcon, BookingCalendar, BookingModal, type BookingSelection, type BookingStep, CalendarIcon, CheckCircleIcon, CheckIcon, type CheckoutSessionErrorCode, ChevronLeftIcon, ChevronRightIcon, ClockIcon, ConfirmationView, CreditCardIcon, CubeIcon, DEFAULT_LOCALE, DEFAULT_THEME, type DeeplinkGuest, type DeeplinkSelection, DishShowcase, type DishShowcaseProps, type DomainConfig, GuestForm, type GuestFormErrors, type GuestFormValues, LockIcon, MailIcon, MinusIcon, NoteIcon, PaymentForm, PhoneIcon, PlusIcon, ProductSelector, type PromoterModeConfig, ResiraBookingWidget, type ResiraClassNames, type ResiraContextValue, type ResiraDomain, type ResiraLocale, ResiraProvider, type ResiraProviderConfig, type ResiraProviderProps, type ResiraTheme, type ResolveServicePriceParams, type ResolvedServicePrice, ResourcePicker, type Service, type ServiceLayout, type ServiceOption, ShieldIcon, SummaryPreview, TagIcon, TimeSlotPicker, type UseServicesReturn, UserIcon, UsersIcon, ViewfinderIcon, WaiverConsent, XIcon, fetchServices, resolveServicePrice, resolveTheme, themeToCSS, useAvailability, useCheckoutSession, useDish, useDishes, usePaymentIntent, useProducts, useReservation, useResira, useResources, useServices, validateGuestForm };
1047
+ export { AlertCircleIcon, BookingCalendar, BookingModal, type BookingSelection, type BookingStep, CalendarIcon, CheckCircleIcon, CheckIcon, type CheckoutSessionErrorCode, ChevronLeftIcon, ChevronRightIcon, ClockIcon, ConfirmationView, CreditCardIcon, CubeIcon, DEFAULT_LOCALE, DEFAULT_THEME, type DeeplinkGuest, type DeeplinkSelection, DishShowcase, type DishShowcaseProps, type DomainConfig, GuestForm, type GuestFormErrors, type GuestFormValues, LockIcon, MailIcon, MinusIcon, NoteIcon, PaymentForm, PhoneIcon, PlusIcon, ProductSelector, type PromoterModeConfig, ResiraBookingWidget, type ResiraClassNames, type ResiraContextValue, type ResiraDomain, type ResiraLocale, ResiraProvider, type ResiraProviderConfig, type ResiraProviderProps, type ResiraTheme, type ResolveServicePriceParams, type ResolvedServicePrice, ResourcePicker, type Service, type ServiceLayout, type ServiceOption, ShieldIcon, type SlotHoldErrorCode, SummaryPreview, TagIcon, TimeSlotPicker, type UseServicesReturn, type UseSlotHoldOptions, type UseSlotHoldReturn, UserIcon, UsersIcon, ViewfinderIcon, WaiverConsent, XIcon, fetchServices, parseSlotHoldError, resolveServicePrice, resolveTheme, themeToCSS, useAvailability, useCheckoutSession, useDish, useDishes, usePaymentIntent, useProducts, useReservation, useResira, useResources, useServices, useSlotHold, validateGuestForm };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React from 'react';
3
- import { Product, WeightedBaseUrl, Resira, RefundRule, TimeSlotAvailability, DurationPrice, PublicResource, ValidatePromoCodeResponse, Reservation, AvailabilityParams, Availability, CheckoutSession, Dish, PaymentIntentResponse, CreatePaymentIntentRequest, CreateReservationRequest } from '@resira/sdk';
3
+ import { Product, WeightedBaseUrl, Resira, RefundRule, TimeSlotAvailability, DurationPrice, PublicResource, ValidatePromoCodeResponse, Reservation, AvailabilityParams, Availability, CheckoutSession, Dish, PaymentIntentResponse, CreatePaymentIntentRequest, CreateReservationRequest, SlotHoldResponse } from '@resira/sdk';
4
4
  export { CheckoutConfig, CheckoutSession, CheckoutSessionResponse, ConfirmPaymentRequest, ConfirmPaymentResponse, CreateCheckoutSessionRequest, CreateCheckoutSessionResponse, CreatePaymentIntentRequest, Dish, DishListResponse, DishModel, DishResponse, DurationPrice, PaymentIntentResponse, PricingModel, Product, ProductCategory, ProductImage, ProductListResponse, ProductVariant, PublicResource, ResourceListResponse, RiderTierPrice } from '@resira/sdk';
5
5
 
6
6
  type ResiraDomain = "rental" | "restaurant" | "watersport" | "service";
@@ -190,6 +190,12 @@ interface ResiraLocale {
190
190
  reserveTable?: string;
191
191
  /** @default "Reservation for" */
192
192
  reservationFor?: string;
193
+ /** @default "Reserved for you" */
194
+ slotHoldReserved?: string;
195
+ /** @default "This slot just sold out. Pick another time." */
196
+ slotSoldOut?: string;
197
+ /** @default "Your hold expired. Please choose a time again." */
198
+ slotHoldExpired?: string;
193
199
  }
194
200
  /** Default English locale. */
195
201
  declare const DEFAULT_LOCALE: Required<ResiraLocale>;
@@ -332,6 +338,11 @@ interface ResiraProviderConfig {
332
338
  onError?: (code: string, message: string) => void;
333
339
  /** Promoter mode configuration for fast in-person bookings. */
334
340
  promoterMode?: PromoterModeConfig;
341
+ /**
342
+ * When true (default), watersport/service flows create a short-lived slot hold after time selection.
343
+ * Disable on APIs that do not yet expose `POST /v2/public/products/.../slot-holds`.
344
+ */
345
+ slotHoldsEnabled?: boolean;
335
346
  }
336
347
  /** Props for the ResiraProvider component. */
337
348
  interface ResiraProviderProps {
@@ -421,6 +432,8 @@ interface ResiraContextValue {
421
432
  checkoutSessionToken?: string;
422
433
  /** Resolved promoter-mode behavior flags. */
423
434
  promoterMode: Required<PromoterModeConfig>;
435
+ /** Slot soft-hold API enabled (watersport/service). @default true */
436
+ slotHoldsEnabled: boolean;
424
437
  }
425
438
  /** Steps in the booking flow. */
426
439
  type BookingStep = "resource" | "availability" | "details" | "terms" | "payment" | "confirmation" | "checkout";
@@ -963,6 +976,48 @@ declare function resolveTheme(overrides?: ResiraTheme): Required<ResiraTheme>;
963
976
  */
964
977
  declare function themeToCSS(theme: Required<ResiraTheme>): Record<string, string>;
965
978
 
979
+ /** Known hold / slot conflict signals from API error text or `body.code`. */
980
+ type SlotHoldErrorCode = "SLOT_UNAVAILABLE" | "HOLD_EXPIRED" | "HOLD_MISMATCH" | "HOLD_NOT_FOUND" | "HOLD_NOT_ACTIVE" | "UNKNOWN";
981
+ declare function parseSlotHoldError(err: unknown): {
982
+ code: SlotHoldErrorCode;
983
+ message: string;
984
+ };
985
+ interface UseSlotHoldOptions {
986
+ client: Resira;
987
+ /** Master switch (false = no API calls; use for legacy APIs). */
988
+ enabled: boolean;
989
+ productId: string | undefined;
990
+ startTime: string | undefined;
991
+ durationMinutes: number | undefined;
992
+ partySize: number | undefined;
993
+ resourceId: string | undefined;
994
+ sessionToken?: string | undefined;
995
+ /** When hold cannot be placed or slot is gone. */
996
+ onSlotUnavailable?: () => void;
997
+ /** When countdown reaches zero. */
998
+ onHoldExpired?: () => void;
999
+ }
1000
+ interface UseSlotHoldReturn {
1001
+ holdId: string | null;
1002
+ holdExpiresAt: string | null;
1003
+ heldResourceId: string | null;
1004
+ /** Seconds left; null when no active hold. */
1005
+ remainingSeconds: number | null;
1006
+ /** True while POST /slot-holds is in flight. */
1007
+ creating: boolean;
1008
+ /** User-facing error message. */
1009
+ error: string | null;
1010
+ parsedErrorCode: SlotHoldErrorCode | null;
1011
+ /** Whether the user can leave the slot step (hold succeeded or holds disabled). */
1012
+ holdReady: boolean;
1013
+ /** Best-effort release (e.g. on unmount). */
1014
+ release: () => Promise<void>;
1015
+ serverNow: string | null;
1016
+ /** Full last hold response for debugging/UI. */
1017
+ lastHold: SlotHoldResponse | null;
1018
+ }
1019
+ declare function useSlotHold(options: UseSlotHoldOptions): UseSlotHoldReturn;
1020
+
966
1021
  interface IconProps {
967
1022
  size?: number;
968
1023
  className?: string;
@@ -989,4 +1044,4 @@ declare function TagIcon({ size, className }: IconProps): react_jsx_runtime.JSX.
989
1044
  declare function CubeIcon({ size, className }: IconProps): react_jsx_runtime.JSX.Element;
990
1045
  declare function ViewfinderIcon({ size, className }: IconProps): react_jsx_runtime.JSX.Element;
991
1046
 
992
- export { AlertCircleIcon, BookingCalendar, BookingModal, type BookingSelection, type BookingStep, CalendarIcon, CheckCircleIcon, CheckIcon, type CheckoutSessionErrorCode, ChevronLeftIcon, ChevronRightIcon, ClockIcon, ConfirmationView, CreditCardIcon, CubeIcon, DEFAULT_LOCALE, DEFAULT_THEME, type DeeplinkGuest, type DeeplinkSelection, DishShowcase, type DishShowcaseProps, type DomainConfig, GuestForm, type GuestFormErrors, type GuestFormValues, LockIcon, MailIcon, MinusIcon, NoteIcon, PaymentForm, PhoneIcon, PlusIcon, ProductSelector, type PromoterModeConfig, ResiraBookingWidget, type ResiraClassNames, type ResiraContextValue, type ResiraDomain, type ResiraLocale, ResiraProvider, type ResiraProviderConfig, type ResiraProviderProps, type ResiraTheme, type ResolveServicePriceParams, type ResolvedServicePrice, ResourcePicker, type Service, type ServiceLayout, type ServiceOption, ShieldIcon, SummaryPreview, TagIcon, TimeSlotPicker, type UseServicesReturn, UserIcon, UsersIcon, ViewfinderIcon, WaiverConsent, XIcon, fetchServices, resolveServicePrice, resolveTheme, themeToCSS, useAvailability, useCheckoutSession, useDish, useDishes, usePaymentIntent, useProducts, useReservation, useResira, useResources, useServices, validateGuestForm };
1047
+ export { AlertCircleIcon, BookingCalendar, BookingModal, type BookingSelection, type BookingStep, CalendarIcon, CheckCircleIcon, CheckIcon, type CheckoutSessionErrorCode, ChevronLeftIcon, ChevronRightIcon, ClockIcon, ConfirmationView, CreditCardIcon, CubeIcon, DEFAULT_LOCALE, DEFAULT_THEME, type DeeplinkGuest, type DeeplinkSelection, DishShowcase, type DishShowcaseProps, type DomainConfig, GuestForm, type GuestFormErrors, type GuestFormValues, LockIcon, MailIcon, MinusIcon, NoteIcon, PaymentForm, PhoneIcon, PlusIcon, ProductSelector, type PromoterModeConfig, ResiraBookingWidget, type ResiraClassNames, type ResiraContextValue, type ResiraDomain, type ResiraLocale, ResiraProvider, type ResiraProviderConfig, type ResiraProviderProps, type ResiraTheme, type ResolveServicePriceParams, type ResolvedServicePrice, ResourcePicker, type Service, type ServiceLayout, type ServiceOption, ShieldIcon, type SlotHoldErrorCode, SummaryPreview, TagIcon, TimeSlotPicker, type UseServicesReturn, type UseSlotHoldOptions, type UseSlotHoldReturn, UserIcon, UsersIcon, ViewfinderIcon, WaiverConsent, XIcon, fetchServices, parseSlotHoldError, resolveServicePrice, resolveTheme, themeToCSS, useAvailability, useCheckoutSession, useDish, useDishes, usePaymentIntent, useProducts, useReservation, useResira, useResources, useServices, useSlotHold, validateGuestForm };