@nickkupriyanov/slotline-react 0.1.1 → 0.2.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.
package/dist/index.d.cts CHANGED
@@ -1,21 +1,32 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode, ComponentPropsWithoutRef } from 'react';
3
- import { BookingAdapter, BuiltInLocale, SlotlineMessages, SlotlineTheme, BookingResult, BookingRequest, SlotlineClassSlot, FlowState, DayAvailability, FieldErrors, TimeSlot, ClassValue } from '@nickkupriyanov/slotline-core';
4
- export { AvailabilityQuery, BookingAdapter, BookingDetails, BookingRequest, BookingResult, DayAvailability, FLOW_STEPS, FieldErrors, FlowAction, FlowState, LoadStatus, MockAdapterOptions, SLOT_CLASS, SlotlineClassSlot, SlotlineMessages, SlotlineStep, SlotlineTheme, SlotsQuery, TimeSlot, addDays, addMonths, buildMonthGrid, compareDayKeys, countSlots, createFlowState, createMockAdapter, cx, dayKeyOf, dayKeyOfInstant, defaultMessages, flowReducer, format, formatFullDay, formatMonthYear, formatTime, formatTimeZoneName, isDayKey, monthKeyOf, resolveMessages, stepIndex, todayKey, validateDetails } from '@nickkupriyanov/slotline-core';
3
+ import { DefaultBookingValues, BookingAdapter, AvailabilityAdapter, BookingChangeMetadata, BuiltInLocale, SlotlineMessages, SlotlineTheme, TimeFormat, BookingContext, InitialBookingAttempt, BookingResult, BookingRequest, BookingError, BookingErrorContext, SlotlineClassSlot, BookingSnapshot, BookingControllerActions, ClassValue } from '@nickkupriyanov/slotline-core';
4
+ export { AvailabilityAdapter, AvailabilityQuery, BOOKING_ERROR_CODES, BookingAction, BookingAdapter, BookingAttemptOutcome, BookingAttemptState, BookingCapabilities, BookingChangeMetadata, BookingClock, BookingConfig, BookingConfigInput, BookingConfigOverrides, BookingContext, BookingController, BookingControllerActions, BookingControllerHandlers, BookingControllerInputs, BookingControllerOptions, BookingDetails, BookingError, BookingErrorCode, BookingErrorContext, BookingFieldConfig, BookingFieldOption, BookingFieldType, BookingInvitation, BookingRequest, BookingResult, BookingSnapshot, BookingState, BookingTimeAnchor, BookingValues, BookingView, DEFAULT_BOOKING_CONTEXT, DEFAULT_BOOKING_FIELDS, DEFAULT_CONTEXT_KEY, DEFAULT_DURATION_OPTIONS, DEFAULT_TIME_FORMAT, DayAvailability, DefaultBookingValues, FALLBACK_LOCALE, FALLBACK_TIME_ZONE, FLOW_STEP_ORDER, InitialBookingAttempt, InstantLike, LoadStatus, MockAdapterOptions, MockFailure, ResolvedBookingField, SLOT_CLASS, SelectionChangeReason, SelectionStatus, SlotlineClassSlot, SlotlineMessages, SlotlineStep, SlotlineTheme, SlotsQuery, SubmitStatus, TimeFormat, TimeSlot, addDays, addMonths, bookingReducer, buildMonthGrid, clampDayKey, compareDayKeys, contextKeyOf, countSlots, createBookingController, createBookingState, createEmptyValues, createIdempotencyKey, createMockAdapter, createTimeAnchor, cx, dayKeyOf, dayKeyOfInstant, defaultMessages, deriveBookingView, detectLocale, endOf, format, formatFullDay, formatMonthYear, formatTime, formatTimeZoneName, formatUtcOffset, guaranteesNotCreated, instantOf, instantOfZonedTime, isAbortError, isBookingError, isBookingErrorCode, isDayKey, isRepeatedLocalTime, isRetrySafe, midnightAfter, monthKeyOf, resolveBookingConfig, resolveBookingFields, resolveMessages, resolveTimeZone, retryWindowClosesAt, soonestBoundary, systemClock, timeAnchorKey, toBookingError, todayKey, unmappedFieldNames, userSteps, validateBookingValues, visibleFieldErrors, wallKeyOf, zoneOffsetMs } from '@nickkupriyanov/slotline-core';
5
5
 
6
- interface SlotlineProps {
7
- /** Availability + booking persistence. See {@link BookingAdapter}. */
8
- adapter: BookingAdapter;
6
+ /** Component props. `TValues` is inferred from the adapter, so a custom form keeps its own type. */
7
+ interface SlotlineProps<TValues = DefaultBookingValues> {
8
+ /**
9
+ * The adapter the flow works against.
10
+ *
11
+ * A `selection` needs availability and slots; a `booking` also persists them, and
12
+ * the controller enforces the pairing. Typing the two shapes loosely here keeps
13
+ * the props readable for the common booking case — an application that selects
14
+ * only never has to write a `createBooking` stub.
15
+ */
16
+ adapter: BookingAdapter<TValues> | AvailabilityAdapter<TValues>;
9
17
  /** Duration options in minutes. Default: `[15, 30, 60]`. */
10
18
  durations?: number[];
11
19
  /** Controlled duration, in minutes. */
12
20
  duration?: number;
13
21
  /** Uncontrolled initial duration. Default: first entry of `durations`. */
14
22
  defaultDuration?: number;
15
- /** Called whenever the user picks a different duration. */
16
- onDurationChange?: (duration: number) => void;
23
+ /** Called whenever the duration changes, however it changed. */
24
+ onDurationChange?: (duration: number, metadata: BookingChangeMetadata) => void;
17
25
  /** IANA time zone used for every date and time rendered. Default: the browser zone. */
26
+ /** IANA time zone used for every date and time rendered, and for calendar queries. */
18
27
  timeZone?: string;
28
+ /** Uncontrolled initial time zone. Default: the browser zone. */
29
+ defaultTimeZone?: string;
19
30
  /** Built-in locale (`en`, `ru`) or any tag understood by `Intl`. Default: browser. */
20
31
  locale?: BuiltInLocale | (string & {});
21
32
  /** Per-string overrides merged on top of the locale defaults. */
@@ -30,13 +41,31 @@ interface SlotlineProps {
30
41
  maxDate?: string | Date;
31
42
  /** First column of the calendar. `0` = Sunday (default), `1` = Monday. */
32
43
  weekStartsOn?: 0 | 1;
44
+ /** `24h` (default) or a 12-hour cycle. */
45
+ timeFormat?: TimeFormat;
46
+ /** Uncontrolled initial hour cycle. */
47
+ defaultTimeFormat?: TimeFormat;
48
+ /** Called when the hour cycle changes. */
49
+ onTimeFormatChange?: (timeFormat: TimeFormat, metadata: BookingChangeMetadata) => void;
50
+ /** The schedule the widget works against. Default: a single implicit one. */
51
+ context?: BookingContext;
52
+ /** Called when the schedule changes. */
53
+ onContextChange?: (context: BookingContext, metadata: BookingChangeMetadata) => void;
54
+ /**
55
+ * An attempt the application restored after a reload. It opens on the attempt
56
+ * screen, resolved, so nothing is repeated by accident.
57
+ */
58
+ attempt?: InitialBookingAttempt | null;
59
+ /** Asks the application to look up the outcome of an unresolved attempt. */
60
+ onCheckStatus?: () => void;
33
61
  /**
34
62
  * Called after the adapter persisted the booking — even when the user has
35
- * already moved on, in which case the UI does not jump to the confirmation.
63
+ * already moved on, in which case the UI does not jump to the confirmation. An
64
+ * exception thrown here never turns a created booking into a failure.
36
65
  */
37
- onBooked?: (result: BookingResult, request: BookingRequest) => void;
38
- /** Called on any adapter failure; the widget also renders the message inline. */
39
- onError?: (error: Error) => void;
66
+ onBooked?: (result: BookingResult, request: BookingRequest<TValues>) => void;
67
+ /** Called on any adapter failure, with the phase it happened in. */
68
+ onError?: (error: BookingError, context: BookingErrorContext) => void;
40
69
  /** Renders a back button on the first step that calls this instead of leaving it out. */
41
70
  onDismiss?: () => void;
42
71
  /** Extra class on the outermost element. */
@@ -50,9 +79,9 @@ interface SlotlineProps {
50
79
  /** Replace the built-in animation kit (see `@nickkupriyanov/slotline-react/motion`). */
51
80
  animations?: AnimationKit;
52
81
  }
53
- interface SlotlineProviderProps extends SlotlineProps {
82
+ type SlotlineProviderProps<TValues = DefaultBookingValues> = SlotlineProps<TValues> & {
54
83
  children: ReactNode;
55
- }
84
+ };
56
85
  /**
57
86
  * Animation primitives the widget renders through. The default kit is pure CSS;
58
87
  * `@nickkupriyanov/slotline-react/motion` swaps in spring-based variants.
@@ -81,16 +110,19 @@ interface HeightProps {
81
110
  }
82
111
 
83
112
  /**
84
- * Provides the booking flow to any UI. Use it directly to build a custom
85
- * widget on top of `useSlotlineContext()`.
113
+ * Provides the booking flow to any UI. Use it directly to build a custom widget
114
+ * on top of `useSlotlineContext()`.
115
+ *
116
+ * The provider owns exactly one controller: it is created here, kept in step with
117
+ * the props, started after mounting and stopped on unmount.
86
118
  */
87
- declare function SlotlineProvider(props: SlotlineProviderProps): react.JSX.Element;
119
+ declare function SlotlineProvider<TValues = DefaultBookingValues>(props: SlotlineProviderProps<TValues>): react.JSX.Element;
88
120
  /**
89
121
  * Builds a `Slotline` bound to a specific animation kit — used by
90
122
  * `@nickkupriyanov/slotline-react/motion` and available for custom kits.
91
123
  */
92
124
  declare function createSlotline(animations: AnimationKit): {
93
- (props: SlotlineProps): react.JSX.Element;
125
+ <TValues = DefaultBookingValues>(props: SlotlineProps<TValues>): react.JSX.Element;
94
126
  displayName: string;
95
127
  };
96
128
  /**
@@ -104,89 +136,56 @@ declare function createSlotline(animations: AnimationKit): {
104
136
  * ```
105
137
  */
106
138
  declare const Slotline: {
107
- (props: SlotlineProps): react.JSX.Element;
139
+ <TValues = DefaultBookingValues>(props: SlotlineProps<TValues>): react.JSX.Element;
108
140
  displayName: string;
109
141
  };
110
142
 
111
143
  /** The full widget: card, header, progress, panel, footer. */
112
144
  declare function SlotlineView(): react.JSX.Element;
113
145
 
146
+ /** What the flow hands to a binding: one immutable snapshot and the actions. */
114
147
  interface UseBookingFlowResult {
115
- state: FlowState;
116
- /** Merged copy for the active locale. */
117
- messages: SlotlineMessages;
118
- /** Locale used for `Intl` formatting. */
119
- locale: string;
120
- timeZone: string;
121
- /** Short zone hint, e.g. `GMT+2`. */
122
- timeZoneName?: string;
123
- theme: Exclude<SlotlineTheme, 'system'>;
124
- /** Header title for the current step. */
125
- title: string;
126
- durations: number[];
127
- weekStartsOn: 0 | 1;
128
- minDate?: string;
129
- maxDate?: string;
130
- /** The 42 day keys of the visible month view. */
131
- monthGrid: string[];
132
- /** Short weekday headers, rotated to `weekStartsOn`. */
133
- weekdayHeaders: string[];
134
- /** Long weekday names for accessible headers, rotated to `weekStartsOn`. */
135
- weekdayLongNames: string[];
136
- monthLabel: string;
137
- selectedDateLabel: string;
138
- selectedTimeLabel: string;
139
- durationLabel: string;
140
- /** Availability for one day, if the adapter knows about it. */
141
- availabilityOf: (dayKey: string) => DayAvailability | undefined;
142
- isDayBookable: (dayKey: string) => boolean;
143
- canGoBack: boolean;
144
- fieldErrors: FieldErrors;
145
- shownFieldErrors: FieldErrors;
146
- /** `true` when the details form can be submitted. */
147
- detailsValid: boolean;
148
- actions: {
149
- selectDate: (dayKey: string) => void;
150
- selectSlot: (slot: TimeSlot) => void;
151
- setDuration: (minutes: number) => void;
152
- setDetails: (details: Partial<{
153
- name: string;
154
- email: string;
155
- notes: string;
156
- }>) => void;
157
- /** Marks a field as touched so its validation message becomes visible. */
158
- touchField: (field: 'name' | 'email') => void;
159
- back: () => void;
160
- submit: () => Promise<void>;
161
- reset: () => void;
162
- goToMonth: (monthKey: string) => void;
163
- previousMonth: () => void;
164
- nextMonth: () => void;
165
- reloadAvailability: () => void;
166
- reloadSlots: () => void;
167
- };
148
+ snapshot: BookingSnapshot;
149
+ actions: BookingControllerActions;
168
150
  }
169
- declare function useBookingFlow(props: SlotlineProps): UseBookingFlowResult;
170
-
171
- declare const FlowContext: react.Context<UseBookingFlowResult | null>;
172
151
  /**
173
152
  * Reads the booking flow from the nearest `<Slotline>` / `<SlotlineProvider>`.
174
153
  * This is the hook to build a fully custom UI on top of.
175
154
  */
176
155
  declare function useSlotlineContext(): UseBookingFlowResult;
156
+ /**
157
+ * Presentation values shared by the built-in parts. Copy and locale live here
158
+ * rather than in the view model: they are how the application asked the widget to
159
+ * speak, not something derived from the flow.
160
+ */
177
161
  interface SlotlineUIContextValue {
178
162
  animations: AnimationKit;
179
163
  classNames?: Partial<Record<SlotlineClassSlot, string>>;
164
+ className?: string;
180
165
  autoFocus: boolean;
181
166
  trapFocus: boolean;
182
- className?: string;
167
+ /** Whether the application supplied a dismiss handler. */
168
+ canDismiss: boolean;
169
+ /** Asks the application to look up the outcome of an unresolved attempt. */
170
+ onCheckStatus?: (() => void) | undefined;
171
+ messages: SlotlineMessages;
172
+ locale: string;
173
+ theme: Exclude<SlotlineTheme, 'system'>;
183
174
  }
184
- declare const UIContext: react.Context<SlotlineUIContextValue>;
185
175
  declare function useUI(): SlotlineUIContextValue;
186
176
  declare function useAnimations(): AnimationKit;
187
177
  /** `classes('day', isToday && 'is-today')` → `"sl-day is-today <consumer class>"`. */
188
178
  declare function useClassNames(): (slot: SlotlineClassSlot, ...extra: ClassValue[]) => string;
189
179
 
180
+ /**
181
+ * The headless widget: the whole flow, no markup.
182
+ *
183
+ * ```tsx
184
+ * const { snapshot, actions } = useBookingFlow({ adapter });
185
+ * ```
186
+ */
187
+ declare function useBookingFlow<TValues = DefaultBookingValues>(props: SlotlineProps<TValues>): UseBookingFlowResult;
188
+
190
189
  /**
191
190
  * The default kit: no runtime, no dependencies. Every transition is a CSS
192
191
  * animation or transition, and all of them collapse under
@@ -194,4 +193,4 @@ declare function useClassNames(): (slot: SlotlineClassSlot, ...extra: ClassValue
194
193
  */
195
194
  declare const cssAnimations: AnimationKit;
196
195
 
197
- export { type AnimationKit, FlowContext, type HeightProps, Slotline, type SlotlineProps, SlotlineProvider, type SlotlineProviderProps, type SlotlineUIContextValue, SlotlineView, type StaggerItemProps, type StepHostProps, UIContext, type UseBookingFlowResult, createSlotline, cssAnimations, useAnimations, useBookingFlow, useClassNames, useSlotlineContext, useUI };
196
+ export { type AnimationKit, type HeightProps, Slotline, type SlotlineProps, SlotlineProvider, type SlotlineProviderProps, type SlotlineUIContextValue, SlotlineView, type StaggerItemProps, type StepHostProps, type UseBookingFlowResult, createSlotline, cssAnimations, useAnimations, useBookingFlow, useClassNames, useSlotlineContext, useUI };
package/dist/index.d.ts CHANGED
@@ -1,21 +1,32 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode, ComponentPropsWithoutRef } from 'react';
3
- import { BookingAdapter, BuiltInLocale, SlotlineMessages, SlotlineTheme, BookingResult, BookingRequest, SlotlineClassSlot, FlowState, DayAvailability, FieldErrors, TimeSlot, ClassValue } from '@nickkupriyanov/slotline-core';
4
- export { AvailabilityQuery, BookingAdapter, BookingDetails, BookingRequest, BookingResult, DayAvailability, FLOW_STEPS, FieldErrors, FlowAction, FlowState, LoadStatus, MockAdapterOptions, SLOT_CLASS, SlotlineClassSlot, SlotlineMessages, SlotlineStep, SlotlineTheme, SlotsQuery, TimeSlot, addDays, addMonths, buildMonthGrid, compareDayKeys, countSlots, createFlowState, createMockAdapter, cx, dayKeyOf, dayKeyOfInstant, defaultMessages, flowReducer, format, formatFullDay, formatMonthYear, formatTime, formatTimeZoneName, isDayKey, monthKeyOf, resolveMessages, stepIndex, todayKey, validateDetails } from '@nickkupriyanov/slotline-core';
3
+ import { DefaultBookingValues, BookingAdapter, AvailabilityAdapter, BookingChangeMetadata, BuiltInLocale, SlotlineMessages, SlotlineTheme, TimeFormat, BookingContext, InitialBookingAttempt, BookingResult, BookingRequest, BookingError, BookingErrorContext, SlotlineClassSlot, BookingSnapshot, BookingControllerActions, ClassValue } from '@nickkupriyanov/slotline-core';
4
+ export { AvailabilityAdapter, AvailabilityQuery, BOOKING_ERROR_CODES, BookingAction, BookingAdapter, BookingAttemptOutcome, BookingAttemptState, BookingCapabilities, BookingChangeMetadata, BookingClock, BookingConfig, BookingConfigInput, BookingConfigOverrides, BookingContext, BookingController, BookingControllerActions, BookingControllerHandlers, BookingControllerInputs, BookingControllerOptions, BookingDetails, BookingError, BookingErrorCode, BookingErrorContext, BookingFieldConfig, BookingFieldOption, BookingFieldType, BookingInvitation, BookingRequest, BookingResult, BookingSnapshot, BookingState, BookingTimeAnchor, BookingValues, BookingView, DEFAULT_BOOKING_CONTEXT, DEFAULT_BOOKING_FIELDS, DEFAULT_CONTEXT_KEY, DEFAULT_DURATION_OPTIONS, DEFAULT_TIME_FORMAT, DayAvailability, DefaultBookingValues, FALLBACK_LOCALE, FALLBACK_TIME_ZONE, FLOW_STEP_ORDER, InitialBookingAttempt, InstantLike, LoadStatus, MockAdapterOptions, MockFailure, ResolvedBookingField, SLOT_CLASS, SelectionChangeReason, SelectionStatus, SlotlineClassSlot, SlotlineMessages, SlotlineStep, SlotlineTheme, SlotsQuery, SubmitStatus, TimeFormat, TimeSlot, addDays, addMonths, bookingReducer, buildMonthGrid, clampDayKey, compareDayKeys, contextKeyOf, countSlots, createBookingController, createBookingState, createEmptyValues, createIdempotencyKey, createMockAdapter, createTimeAnchor, cx, dayKeyOf, dayKeyOfInstant, defaultMessages, deriveBookingView, detectLocale, endOf, format, formatFullDay, formatMonthYear, formatTime, formatTimeZoneName, formatUtcOffset, guaranteesNotCreated, instantOf, instantOfZonedTime, isAbortError, isBookingError, isBookingErrorCode, isDayKey, isRepeatedLocalTime, isRetrySafe, midnightAfter, monthKeyOf, resolveBookingConfig, resolveBookingFields, resolveMessages, resolveTimeZone, retryWindowClosesAt, soonestBoundary, systemClock, timeAnchorKey, toBookingError, todayKey, unmappedFieldNames, userSteps, validateBookingValues, visibleFieldErrors, wallKeyOf, zoneOffsetMs } from '@nickkupriyanov/slotline-core';
5
5
 
6
- interface SlotlineProps {
7
- /** Availability + booking persistence. See {@link BookingAdapter}. */
8
- adapter: BookingAdapter;
6
+ /** Component props. `TValues` is inferred from the adapter, so a custom form keeps its own type. */
7
+ interface SlotlineProps<TValues = DefaultBookingValues> {
8
+ /**
9
+ * The adapter the flow works against.
10
+ *
11
+ * A `selection` needs availability and slots; a `booking` also persists them, and
12
+ * the controller enforces the pairing. Typing the two shapes loosely here keeps
13
+ * the props readable for the common booking case — an application that selects
14
+ * only never has to write a `createBooking` stub.
15
+ */
16
+ adapter: BookingAdapter<TValues> | AvailabilityAdapter<TValues>;
9
17
  /** Duration options in minutes. Default: `[15, 30, 60]`. */
10
18
  durations?: number[];
11
19
  /** Controlled duration, in minutes. */
12
20
  duration?: number;
13
21
  /** Uncontrolled initial duration. Default: first entry of `durations`. */
14
22
  defaultDuration?: number;
15
- /** Called whenever the user picks a different duration. */
16
- onDurationChange?: (duration: number) => void;
23
+ /** Called whenever the duration changes, however it changed. */
24
+ onDurationChange?: (duration: number, metadata: BookingChangeMetadata) => void;
17
25
  /** IANA time zone used for every date and time rendered. Default: the browser zone. */
26
+ /** IANA time zone used for every date and time rendered, and for calendar queries. */
18
27
  timeZone?: string;
28
+ /** Uncontrolled initial time zone. Default: the browser zone. */
29
+ defaultTimeZone?: string;
19
30
  /** Built-in locale (`en`, `ru`) or any tag understood by `Intl`. Default: browser. */
20
31
  locale?: BuiltInLocale | (string & {});
21
32
  /** Per-string overrides merged on top of the locale defaults. */
@@ -30,13 +41,31 @@ interface SlotlineProps {
30
41
  maxDate?: string | Date;
31
42
  /** First column of the calendar. `0` = Sunday (default), `1` = Monday. */
32
43
  weekStartsOn?: 0 | 1;
44
+ /** `24h` (default) or a 12-hour cycle. */
45
+ timeFormat?: TimeFormat;
46
+ /** Uncontrolled initial hour cycle. */
47
+ defaultTimeFormat?: TimeFormat;
48
+ /** Called when the hour cycle changes. */
49
+ onTimeFormatChange?: (timeFormat: TimeFormat, metadata: BookingChangeMetadata) => void;
50
+ /** The schedule the widget works against. Default: a single implicit one. */
51
+ context?: BookingContext;
52
+ /** Called when the schedule changes. */
53
+ onContextChange?: (context: BookingContext, metadata: BookingChangeMetadata) => void;
54
+ /**
55
+ * An attempt the application restored after a reload. It opens on the attempt
56
+ * screen, resolved, so nothing is repeated by accident.
57
+ */
58
+ attempt?: InitialBookingAttempt | null;
59
+ /** Asks the application to look up the outcome of an unresolved attempt. */
60
+ onCheckStatus?: () => void;
33
61
  /**
34
62
  * Called after the adapter persisted the booking — even when the user has
35
- * already moved on, in which case the UI does not jump to the confirmation.
63
+ * already moved on, in which case the UI does not jump to the confirmation. An
64
+ * exception thrown here never turns a created booking into a failure.
36
65
  */
37
- onBooked?: (result: BookingResult, request: BookingRequest) => void;
38
- /** Called on any adapter failure; the widget also renders the message inline. */
39
- onError?: (error: Error) => void;
66
+ onBooked?: (result: BookingResult, request: BookingRequest<TValues>) => void;
67
+ /** Called on any adapter failure, with the phase it happened in. */
68
+ onError?: (error: BookingError, context: BookingErrorContext) => void;
40
69
  /** Renders a back button on the first step that calls this instead of leaving it out. */
41
70
  onDismiss?: () => void;
42
71
  /** Extra class on the outermost element. */
@@ -50,9 +79,9 @@ interface SlotlineProps {
50
79
  /** Replace the built-in animation kit (see `@nickkupriyanov/slotline-react/motion`). */
51
80
  animations?: AnimationKit;
52
81
  }
53
- interface SlotlineProviderProps extends SlotlineProps {
82
+ type SlotlineProviderProps<TValues = DefaultBookingValues> = SlotlineProps<TValues> & {
54
83
  children: ReactNode;
55
- }
84
+ };
56
85
  /**
57
86
  * Animation primitives the widget renders through. The default kit is pure CSS;
58
87
  * `@nickkupriyanov/slotline-react/motion` swaps in spring-based variants.
@@ -81,16 +110,19 @@ interface HeightProps {
81
110
  }
82
111
 
83
112
  /**
84
- * Provides the booking flow to any UI. Use it directly to build a custom
85
- * widget on top of `useSlotlineContext()`.
113
+ * Provides the booking flow to any UI. Use it directly to build a custom widget
114
+ * on top of `useSlotlineContext()`.
115
+ *
116
+ * The provider owns exactly one controller: it is created here, kept in step with
117
+ * the props, started after mounting and stopped on unmount.
86
118
  */
87
- declare function SlotlineProvider(props: SlotlineProviderProps): react.JSX.Element;
119
+ declare function SlotlineProvider<TValues = DefaultBookingValues>(props: SlotlineProviderProps<TValues>): react.JSX.Element;
88
120
  /**
89
121
  * Builds a `Slotline` bound to a specific animation kit — used by
90
122
  * `@nickkupriyanov/slotline-react/motion` and available for custom kits.
91
123
  */
92
124
  declare function createSlotline(animations: AnimationKit): {
93
- (props: SlotlineProps): react.JSX.Element;
125
+ <TValues = DefaultBookingValues>(props: SlotlineProps<TValues>): react.JSX.Element;
94
126
  displayName: string;
95
127
  };
96
128
  /**
@@ -104,89 +136,56 @@ declare function createSlotline(animations: AnimationKit): {
104
136
  * ```
105
137
  */
106
138
  declare const Slotline: {
107
- (props: SlotlineProps): react.JSX.Element;
139
+ <TValues = DefaultBookingValues>(props: SlotlineProps<TValues>): react.JSX.Element;
108
140
  displayName: string;
109
141
  };
110
142
 
111
143
  /** The full widget: card, header, progress, panel, footer. */
112
144
  declare function SlotlineView(): react.JSX.Element;
113
145
 
146
+ /** What the flow hands to a binding: one immutable snapshot and the actions. */
114
147
  interface UseBookingFlowResult {
115
- state: FlowState;
116
- /** Merged copy for the active locale. */
117
- messages: SlotlineMessages;
118
- /** Locale used for `Intl` formatting. */
119
- locale: string;
120
- timeZone: string;
121
- /** Short zone hint, e.g. `GMT+2`. */
122
- timeZoneName?: string;
123
- theme: Exclude<SlotlineTheme, 'system'>;
124
- /** Header title for the current step. */
125
- title: string;
126
- durations: number[];
127
- weekStartsOn: 0 | 1;
128
- minDate?: string;
129
- maxDate?: string;
130
- /** The 42 day keys of the visible month view. */
131
- monthGrid: string[];
132
- /** Short weekday headers, rotated to `weekStartsOn`. */
133
- weekdayHeaders: string[];
134
- /** Long weekday names for accessible headers, rotated to `weekStartsOn`. */
135
- weekdayLongNames: string[];
136
- monthLabel: string;
137
- selectedDateLabel: string;
138
- selectedTimeLabel: string;
139
- durationLabel: string;
140
- /** Availability for one day, if the adapter knows about it. */
141
- availabilityOf: (dayKey: string) => DayAvailability | undefined;
142
- isDayBookable: (dayKey: string) => boolean;
143
- canGoBack: boolean;
144
- fieldErrors: FieldErrors;
145
- shownFieldErrors: FieldErrors;
146
- /** `true` when the details form can be submitted. */
147
- detailsValid: boolean;
148
- actions: {
149
- selectDate: (dayKey: string) => void;
150
- selectSlot: (slot: TimeSlot) => void;
151
- setDuration: (minutes: number) => void;
152
- setDetails: (details: Partial<{
153
- name: string;
154
- email: string;
155
- notes: string;
156
- }>) => void;
157
- /** Marks a field as touched so its validation message becomes visible. */
158
- touchField: (field: 'name' | 'email') => void;
159
- back: () => void;
160
- submit: () => Promise<void>;
161
- reset: () => void;
162
- goToMonth: (monthKey: string) => void;
163
- previousMonth: () => void;
164
- nextMonth: () => void;
165
- reloadAvailability: () => void;
166
- reloadSlots: () => void;
167
- };
148
+ snapshot: BookingSnapshot;
149
+ actions: BookingControllerActions;
168
150
  }
169
- declare function useBookingFlow(props: SlotlineProps): UseBookingFlowResult;
170
-
171
- declare const FlowContext: react.Context<UseBookingFlowResult | null>;
172
151
  /**
173
152
  * Reads the booking flow from the nearest `<Slotline>` / `<SlotlineProvider>`.
174
153
  * This is the hook to build a fully custom UI on top of.
175
154
  */
176
155
  declare function useSlotlineContext(): UseBookingFlowResult;
156
+ /**
157
+ * Presentation values shared by the built-in parts. Copy and locale live here
158
+ * rather than in the view model: they are how the application asked the widget to
159
+ * speak, not something derived from the flow.
160
+ */
177
161
  interface SlotlineUIContextValue {
178
162
  animations: AnimationKit;
179
163
  classNames?: Partial<Record<SlotlineClassSlot, string>>;
164
+ className?: string;
180
165
  autoFocus: boolean;
181
166
  trapFocus: boolean;
182
- className?: string;
167
+ /** Whether the application supplied a dismiss handler. */
168
+ canDismiss: boolean;
169
+ /** Asks the application to look up the outcome of an unresolved attempt. */
170
+ onCheckStatus?: (() => void) | undefined;
171
+ messages: SlotlineMessages;
172
+ locale: string;
173
+ theme: Exclude<SlotlineTheme, 'system'>;
183
174
  }
184
- declare const UIContext: react.Context<SlotlineUIContextValue>;
185
175
  declare function useUI(): SlotlineUIContextValue;
186
176
  declare function useAnimations(): AnimationKit;
187
177
  /** `classes('day', isToday && 'is-today')` → `"sl-day is-today <consumer class>"`. */
188
178
  declare function useClassNames(): (slot: SlotlineClassSlot, ...extra: ClassValue[]) => string;
189
179
 
180
+ /**
181
+ * The headless widget: the whole flow, no markup.
182
+ *
183
+ * ```tsx
184
+ * const { snapshot, actions } = useBookingFlow({ adapter });
185
+ * ```
186
+ */
187
+ declare function useBookingFlow<TValues = DefaultBookingValues>(props: SlotlineProps<TValues>): UseBookingFlowResult;
188
+
190
189
  /**
191
190
  * The default kit: no runtime, no dependencies. Every transition is a CSS
192
191
  * animation or transition, and all of them collapse under
@@ -194,4 +193,4 @@ declare function useClassNames(): (slot: SlotlineClassSlot, ...extra: ClassValue
194
193
  */
195
194
  declare const cssAnimations: AnimationKit;
196
195
 
197
- export { type AnimationKit, FlowContext, type HeightProps, Slotline, type SlotlineProps, SlotlineProvider, type SlotlineProviderProps, type SlotlineUIContextValue, SlotlineView, type StaggerItemProps, type StepHostProps, UIContext, type UseBookingFlowResult, createSlotline, cssAnimations, useAnimations, useBookingFlow, useClassNames, useSlotlineContext, useUI };
196
+ export { type AnimationKit, type HeightProps, Slotline, type SlotlineProps, SlotlineProvider, type SlotlineProviderProps, type SlotlineUIContextValue, SlotlineView, type StaggerItemProps, type StepHostProps, type UseBookingFlowResult, createSlotline, cssAnimations, useAnimations, useBookingFlow, useClassNames, useSlotlineContext, useUI };