@v-office/website-chat 1.1.3 → 1.3.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/README.md CHANGED
@@ -28,6 +28,7 @@ Render `WebsiteChat` once in the layout as a client island; see `instructions/ve
28
28
  | `locale` | yes | `"de"` or `"en"` |
29
29
  | `searchPath` | yes | the site's search, for a rental without a page and when the chat is down |
30
30
  | `contactPath` | yes | the site's contact page |
31
+ | `privacyPath` | no | the site's privacy policy, linked at the step that starts the chat |
31
32
  | `theme` | no | `classic` (default), `soft` or `minimal`: shadows or borders, how round |
32
33
  | `colors` | no | `{ primary, secondary, accent }`, any CSS colour, over the site's tokens |
33
34
  | `position` | no | the entry pill and the panel on the `right` (default) or `left` |
@@ -41,8 +42,8 @@ It takes its colours and corners from the site's shadcn tokens (`--primary`,
41
42
  are square (`--radius: 0`) gets square buttons too.
42
43
 
43
44
  A site with a sticky header sets `--chat-top` (its height) on any element around the widget, such as
44
- `:root`: the dimmed page and the panel start below it. `--chat-width` widens the panel on wide screens
45
- (default `700px`).
45
+ `:root`: from 1024 px wide, the dimmed page and the panel start below it; narrower, the chat opens as a
46
+ full-height sheet over the header. `--chat-width` widens the panel on wide screens (default `700px`).
46
47
 
47
48
  The service places these components in replies: `RentalCard` (photo gallery, rating, the wishes the
48
49
  search that found it applied), `RentalCarousel`, `Compare`, `StayQuote`, `PriceBreakdown`,
@@ -28,67 +28,70 @@ const chatCatalog = defineCatalog(schema, {
28
28
  },
29
29
  RentalCarousel: {
30
30
  props: z.object({ items: z.array(offer).min(2).max(8) }),
31
- description: "Several rentals side by side, swipeable, each as a RentalCard. Use it for search results instead of several RentalCards."
31
+ description: "Several rentals side by side, swipeable, each as a RentalCard: search results, instead of several RentalCards. After a flexible search, each rental with its first period as its stayId."
32
32
  },
33
33
  StayQuote: {
34
- props: z.object({ stayId: id }),
35
- description: "One priced stay: the rental, the dates, the party, the total and a booking button."
34
+ props: z.object({
35
+ stayId: id,
36
+ handover: z.boolean().optional()
37
+ }),
38
+ description: "One priced stay: the rental, the dates, the party, the total and a booking button. Show it whenever the visitor asks what one stay costs, with the stayId from quote_stay or configure_stay. When the visitor decides on a stay ('we'll take it', 'how do we book'), show it again with handover true: it carries the booking button, so the reply need not say where the button is."
36
39
  },
37
40
  PriceBreakdown: {
38
41
  props: z.object({ stayId: id }),
39
- description: "What a quoted stay's total is made of (nights, cleaning, pets, …), line by line. Only for a stay from quote_stay."
42
+ description: "What a stay's total is made of (nights, cleaning, pets, …), line by line, when the visitor asks. Only for a stay from quote_stay or configure_stay."
40
43
  },
41
44
  AlternativeStays: {
42
45
  props: z.object({
43
46
  rentalId: id,
44
47
  stayIds: z.array(id).min(1).max(6)
45
48
  }),
46
- description: "Free periods of one rental as tappable choices with their prices: other dates when the asked ones are taken, or the periods a flexible search found."
49
+ description: "Other free periods of one rental as tappable choices with their prices, right after that rental's card: the rental the reply is about, the one taken on the asked dates, or a rental's further periods after a flexible search; never the stay its card shows. For a rental the visitor named, its RentalCard comes first (stayId null when taken). For several taken rentals use a RentalCarousel with each rental's first free period as its stayId, and say the dates differ. At most one AlternativeStays per reply."
47
50
  },
48
51
  AvailabilityCalendar: {
49
52
  props: z.object({
50
53
  rentalId: id,
51
54
  stayId: id.nullable()
52
55
  }),
53
- description: "A rental's month calendar of free and taken days, with a stay's dates marked when there is one. Only after get_availability."
56
+ description: "A rental's month calendar of free and taken days, with a stay's dates marked when there is one. Show it whenever the visitor asks when a rental is free, after get_availability."
54
57
  },
55
58
  PriceCalendar: {
56
59
  props: z.object({ rentalId: id }),
57
- description: "One rental's total for the same length of stay at the arrivals around the asked one, cheapest marked; tapping one asks for it. Only after price_calendar."
60
+ description: "One rental's total for the same length of stay at the arrivals around the asked one; tapping one asks for it. For other or cheaper arrival dates, only after price_calendar. Not what one stay costs: that is a StayQuote."
58
61
  },
59
62
  ReviewSummary: {
60
63
  props: z.object({ rentalId: id }),
61
- description: "A rental's guest rating as the booking system sums it up, its category ratings and a few review texts. Only after get_reviews."
64
+ description: "A rental's guest rating as the booking system sums it up, its category ratings and a few review texts, when the visitor asks how guests rate it. Only after get_reviews; sum up in a sentence, in your own words, what guests value."
62
65
  },
63
66
  RentalFacts: {
64
67
  props: z.object({
65
68
  rentalId: id,
66
69
  groups: z.array(z.string().trim().min(1).max(80)).min(1).max(4)
67
70
  }),
68
- description: "The facts of one rental in the groups get_rental listed (by their label, such as Haustiere or Lage), for a question about pets, the kitchen or the surroundings."
71
+ description: "The facts of one rental in the groups get_rental listed, by their label. Show it whenever the visitor asks what one rental has or allows (pets, kitchen, parking, surroundings), after get_rental; answer the question in your text as well."
69
72
  },
70
73
  RentalMap: {
71
74
  props: z.object({ rentalId: id }),
72
- description: "Where one rental is: a map the visitor loads with a tap, and a link to its page."
75
+ description: "Where one rental is, when the visitor asks: a map the visitor loads with a tap, and a link to its page."
73
76
  },
74
77
  Compare: {
75
78
  props: z.object({ items: z.array(offer).min(2).max(3) }),
76
- description: "Two or three rentals side by side: rating, rooms, highlights, the stay and its price."
79
+ description: "Two or three rentals side by side: rating, rooms, highlights, the stay and its price. Show it whenever the visitor weighs or compares two or three rentals, with stays of the same dates; a rental taken then gets stayId null."
77
80
  },
78
81
  StayLink: {
79
82
  props: z.object({
80
83
  rentalId: id,
81
84
  stayId: id.nullable()
82
85
  }),
83
- description: "A button to the rental's page on this website, with the stay filled in, to book there."
86
+ description: "A button to the rental's page on this website, with the stay filled in, to book there. Only for a rental or stay shown without one: cards, carousels, comparisons and quotes carry their own booking buttons."
84
87
  },
85
88
  ContactLink: {
86
89
  props: z.object({}),
87
- description: "A link to this website's contact page."
90
+ description: "A link to this website's contact page. Show it whenever you send the visitor to the agency; never only offer it."
88
91
  },
89
92
  QuickReplies: {
90
93
  props: z.object({ options: z.array(z.string().trim().min(1).max(40)).min(1).max(4) }),
91
- description: "Up to four short answers the visitor can tap to send as their next message (\"Nur mit Sauna\", \"Andere Termine\"). Never a fact or a price."
94
+ description: "Up to four short answers the visitor can tap, in the language of your reply (a date, a party size, a wish): with every question you ask. Never a fact or a price."
92
95
  }
93
96
  },
94
97
  actions: {}
@@ -145,6 +148,9 @@ const isAtLeast = (clientVersion, since) => {
145
148
  if (!client || from[0] !== client[0]) return false;
146
149
  return from[1] < client[1] || from[1] === client[1] && from[2] <= client[2];
147
150
  };
151
+ /** Whether a widget of `clientVersion` is `since` or newer within the same major, for the service's own
152
+ * version gates (what it retires, which words it uses); an unreadable version is neither. */
153
+ const versionAtLeast = isAtLeast;
148
154
  /** See {@link ComponentsFor}. */
149
155
  const componentsFor = (clientVersion) => PLACEABLE_COMPONENTS.filter((name) => isAtLeast(clientVersion, COMPONENT_SINCE[name]));
150
156
  /** Whether the widget shows the assistant's `**bold**` as bold text (1.1.0 and later); an older
@@ -187,4 +193,4 @@ const chatSpec = (items, state) => {
187
193
  };
188
194
  };
189
195
  //#endregion
190
- export { componentsFor as a, rendersBold as c, chatSpec as i, stateKey as l, PLACEABLE_COMPONENTS as n, handsOverStays as o, chatCatalog as r, parseItem as s, COMPONENT_SINCE as t, statePath as u };
196
+ export { componentsFor as a, rendersBold as c, statePath as d, chatSpec as i, versionAtLeast as l, PLACEABLE_COMPONENTS as n, handsOverStays as o, chatCatalog as r, parseItem as s, COMPONENT_SINCE as t, stateKey as u };
package/dist/catalog.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as ChatLocale, c as MAX_MESSAGE_CHARS, i as ChatEvent, l as SESSION_TTL_S, n as CHAT_PATH, o as ChatRequest, r as ChatAvailability, s as ChatUnavailableReason, t as CHAT_LOCALES } from "./protocol-Bmb_uxVQ.js";
1
+ import { a as ChatLocale, c as ChatUnavailableReason, i as ChatEvent, l as MAX_MESSAGE_CHARS, n as CHAT_PATH, o as ChatRequest, r as ChatAvailability, s as ChatStatusStep, t as CHAT_LOCALES, u as SESSION_TTL_S } from "./protocol-Dg1HZNWG.js";
2
2
  import { Spec } from "@json-render/core";
3
3
  import { z } from "zod";
4
4
  import { Party } from "@v-office/website-headless";
@@ -8,6 +8,9 @@ interface ChatImage {
8
8
  readonly src: string;
9
9
  /** The PMS's description; empty when it has none. */
10
10
  readonly alt: string;
11
+ /** The PMS's `srcset`, so the browser loads the size the screen needs; only on a card's first
12
+ * photos (1.3.0). */
13
+ readonly srcset?: string;
11
14
  }
12
15
  /** A rental as the chat shows it: facts from the PMS, never from the model. */
13
16
  interface ChatRental {
@@ -32,6 +35,23 @@ interface ChatRental {
32
35
  readonly lng: number;
33
36
  } | null;
34
37
  }
38
+ /** The discount the PMS applied to a stay's total (1.3.0). */
39
+ interface ChatDiscount {
40
+ /** The PMS's names of the applied discounts ("Frühbucher"); empty when it names none (v9). */
41
+ readonly labels: readonly string[];
42
+ /** What the visitor saves, as the PMS formats money ("112,30 €"); `null` when it is not one known
43
+ * amount. */
44
+ readonly saving: string | null;
45
+ }
46
+ /** What cancelling a stay costs under the rate the quote priced, from the PMS's policy (1.3.0):
47
+ * free until a day, or nothing refunded any more. */
48
+ type ChatCancellation = {
49
+ readonly kind: "free";
50
+ /** `YYYY-MM-DD`, the last day with a full refund. */
51
+ readonly until: string;
52
+ } | {
53
+ readonly kind: "none";
54
+ };
35
55
  /** A stay of one rental for one party, priced by the PMS. */
36
56
  interface ChatStay {
37
57
  readonly id: string;
@@ -59,7 +79,20 @@ interface ChatStay {
59
79
  readonly services?: readonly {
60
80
  readonly id: string;
61
81
  readonly count: number;
82
+ /** The extra's name as the PMS gives it (1.3.0). */
83
+ readonly label?: string;
62
84
  }[];
85
+ /** The discount in the total; absent or `null` without one (1.3.0). */
86
+ readonly discount?: ChatDiscount | null;
87
+ /** The cancellation terms of the quoted rate; absent or `null` when the PMS states none (a search
88
+ * result, v9) (1.3.0). */
89
+ readonly cancellation?: ChatCancellation | null;
90
+ /** The rate's own name where the agency named it ("Flexibler Tarif"); absent for the PMS's built-in
91
+ * rates (1.3.0). */
92
+ readonly rateName?: string | null;
93
+ /** A stay the PMS refused: the departures it allows from the same arrival, `YYYY-MM-DD`, ascending,
94
+ * at most four; absent when not asked (1.3.0). */
95
+ readonly departures?: readonly string[];
63
96
  }
64
97
  /** A day of a rental's calendar: bookable, taken, or outside what can be booked (past, closed). */
65
98
  type ChatDayStatus = "free" | "booked" | "closed";
@@ -71,6 +104,11 @@ interface ChatCalendar {
71
104
  readonly through: string;
72
105
  /** Every day from `from` through `through`. */
73
106
  readonly days: Readonly<Record<string, ChatDayStatus>>;
107
+ /** The free days a stay can start on, `YYYY-MM-DD`; absent when not known (1.3.0). */
108
+ readonly arrivals?: readonly string[];
109
+ /** A free day's night-price level among the calendar's priced days, 1 (cheaper) to 3, never an
110
+ * amount; absent for a day without a price, and altogether without prices (1.3.0). */
111
+ readonly levels?: Readonly<Record<string, 1 | 2 | 3>>;
74
112
  }
75
113
  /** One stay length's totals for the arrivals around the asked one, as the PMS priced them. */
76
114
  interface ChatPriceCalendar {
@@ -112,6 +150,36 @@ interface ChatFactGroup {
112
150
  readonly label: string;
113
151
  readonly items: readonly string[];
114
152
  }
153
+ /** What the latest search searched with, for the widget to show what the chat is working from
154
+ * (1.3.0). */
155
+ interface ChatTrip {
156
+ readonly party: Party;
157
+ /** The search assumed the party (two adults): the visitor named none. */
158
+ readonly partyAssumed: boolean;
159
+ /** Fixed dates, months (with a length of stay or weekends), or explicit windows; `null` without
160
+ * any. */
161
+ readonly period: {
162
+ readonly kind: "dates";
163
+ readonly start: string;
164
+ readonly end: string;
165
+ } | {
166
+ readonly kind: "months";
167
+ /** `YYYY-MM`. */
168
+ readonly months: readonly string[];
169
+ readonly nights: number | null;
170
+ readonly weekend: boolean;
171
+ } | {
172
+ readonly kind: "windows";
173
+ /** `YYYY-MM-DD` each. */
174
+ readonly windows: readonly {
175
+ readonly from: string;
176
+ readonly to: string;
177
+ }[];
178
+ readonly nights: number;
179
+ } | null;
180
+ /** The visitor's wishes the search applied, as the PMS labels its filters. */
181
+ readonly wishes: readonly string[];
182
+ }
115
183
  /** The state of one spec: everything its components read, keyed by the raw id. */
116
184
  interface ChatState {
117
185
  readonly rentals: Readonly<Record<string, ChatRental>>;
@@ -133,6 +201,11 @@ interface ChatState {
133
201
  * erlaubt"), as the PMS labels its filters, by rental id: the rental has each. With dates or
134
202
  * without; absent when that search applied none. */
135
203
  readonly wishes: Readonly<Record<string, readonly string[]>>;
204
+ /** What the latest search searched with; absent or `null` before any (1.3.0). */
205
+ readonly trip?: ChatTrip | null;
206
+ /** A flexible search's free periods of a rental, as ids of stays in `stays` (at most four, the
207
+ * card's own among them), by rental id; absent without a flexible search (1.3.0). */
208
+ readonly periods?: Readonly<Record<string, readonly string[]>>;
136
209
  }
137
210
  /** An id as one JSON Pointer token (RFC 6901): a v10 rental id may contain `/` or `~`, which would
138
211
  * otherwise change the path a component reads. State stays keyed by the raw id; only paths escape it. */
@@ -208,6 +281,7 @@ export declare const chatCatalog: import("@json-render/core").Catalog<{
208
281
  StayQuote: {
209
282
  props: z.ZodObject<{
210
283
  stayId: z.ZodString;
284
+ handover: z.ZodOptional<z.ZodBoolean>;
211
285
  }, z.core.$strip>;
212
286
  description: string;
213
287
  };
@@ -305,6 +379,12 @@ type ComponentsFor = (clientVersion: string) => PlaceableComponent[];
305
379
  type ParseItem = (item: unknown, allowed: readonly PlaceableComponent[]) => ChatItem | null;
306
380
  /** The spec of one reply: the items stacked under the service's root, and the state they read. */
307
381
  type ChatSpec = (items: readonly ChatItem[], state: ChatState) => Spec;
382
+ /** Whether a widget of `clientVersion` is `since` or newer within the same major; an unreadable
383
+ * version is neither. */
384
+ declare const isAtLeast: (clientVersion: string, since: string) => boolean;
385
+ /** Whether a widget of `clientVersion` is `since` or newer within the same major, for the service's own
386
+ * version gates (what it retires, which words it uses); an unreadable version is neither. */
387
+ export declare const versionAtLeast: typeof isAtLeast;
308
388
  /** See {@link ComponentsFor}. */
309
389
  export declare const componentsFor: ComponentsFor;
310
390
  /** Whether the widget shows the assistant's `**bold**` as bold text (1.1.0 and later); an older
@@ -319,4 +399,4 @@ export declare const parseItem: ParseItem;
319
399
  /** See {@link ChatSpec}. */
320
400
  export declare const chatSpec: ChatSpec;
321
401
  //#endregion
322
- export { CHAT_LOCALES, CHAT_PATH, type ChatAvailability, type ChatCalendar, type ChatDayStatus, type ChatEvent, type ChatFactGroup, type ChatImage, type ChatLocale, type ChatPriceCalendar, type ChatRental, type ChatRequest, type ChatReviews, type ChatState, type ChatStay, type ChatUnavailableReason, MAX_MESSAGE_CHARS, SESSION_TTL_S };
402
+ export { CHAT_LOCALES, CHAT_PATH, type ChatAvailability, type ChatCalendar, type ChatCancellation, type ChatDayStatus, type ChatDiscount, type ChatEvent, type ChatFactGroup, type ChatImage, type ChatLocale, type ChatPriceCalendar, type ChatRental, type ChatRequest, type ChatReviews, type ChatState, type ChatStatusStep, type ChatStay, type ChatTrip, type ChatUnavailableReason, MAX_MESSAGE_CHARS, SESSION_TTL_S };
package/dist/catalog.js CHANGED
@@ -1,3 +1,3 @@
1
1
  import { i as SESSION_TTL_S, n as CHAT_PATH, r as MAX_MESSAGE_CHARS, t as CHAT_LOCALES } from "./protocol-BuNqZAMt.js";
2
- import { a as componentsFor, c as rendersBold, i as chatSpec, l as stateKey, n as PLACEABLE_COMPONENTS, o as handsOverStays, r as chatCatalog, s as parseItem, t as COMPONENT_SINCE, u as statePath } from "./catalog-y3xQ2jXW.js";
3
- export { CHAT_LOCALES, CHAT_PATH, COMPONENT_SINCE, MAX_MESSAGE_CHARS, PLACEABLE_COMPONENTS, SESSION_TTL_S, chatCatalog, chatSpec, componentsFor, handsOverStays, parseItem, rendersBold, stateKey, statePath };
2
+ import { a as componentsFor, c as rendersBold, d as statePath, i as chatSpec, l as versionAtLeast, n as PLACEABLE_COMPONENTS, o as handsOverStays, r as chatCatalog, s as parseItem, t as COMPONENT_SINCE, u as stateKey } from "./catalog-Buxzskkg.js";
3
+ export { CHAT_LOCALES, CHAT_PATH, COMPONENT_SINCE, MAX_MESSAGE_CHARS, PLACEABLE_COMPONENTS, SESSION_TTL_S, chatCatalog, chatSpec, componentsFor, handsOverStays, parseItem, rendersBold, stateKey, statePath, versionAtLeast };
@@ -92,6 +92,8 @@ const loadConversation = (endpoint, now = Date.now()) => {
92
92
  return {
93
93
  sessionId: stored.sessionId ?? null,
94
94
  messages: stored.messages,
95
+ ...stored.selected && { selected: stored.selected },
96
+ ...stored.picked && { picked: stored.picked },
95
97
  savedAt: stored.savedAt
96
98
  };
97
99
  } catch {
@@ -146,6 +148,20 @@ const Check = () => /* @__PURE__ */ jsx(Svg, {
146
148
  size: 14,
147
149
  children: /* @__PURE__ */ jsx("path", { d: "M5 12.5l4.5 4.5L19 7.5" })
148
150
  });
151
+ /** A discount. */
152
+ const Tag = () => /* @__PURE__ */ jsx(Svg, { children: /* @__PURE__ */ jsx("path", { d: "M3 12V4h8l10 10-8 8zM7.5 8.5h.01" }) });
153
+ /** Free cancellation. */
154
+ const CircleCheck = () => /* @__PURE__ */ jsxs(Svg, { children: [/* @__PURE__ */ jsx("circle", {
155
+ cx: "12",
156
+ cy: "12",
157
+ r: "9"
158
+ }), /* @__PURE__ */ jsx("path", { d: "M8 12.5l2.5 2.5L16 9.5" })] });
159
+ /** Terms without a refund: a fact, not a warning. */
160
+ const CircleInfo = () => /* @__PURE__ */ jsxs(Svg, { children: [/* @__PURE__ */ jsx("circle", {
161
+ cx: "12",
162
+ cy: "12",
163
+ r: "9"
164
+ }), /* @__PURE__ */ jsx("path", { d: "M12 11v5M12 8h.01" })] });
149
165
  /** In a photo's place on a card without photos. */
150
166
  const House = () => /* @__PURE__ */ jsx(Svg, {
151
167
  size: 32,
@@ -171,7 +187,7 @@ const TOPICS = [
171
187
  },
172
188
  {
173
189
  topic: "people",
174
- words: /famili|kinder|zu zweit|personen|erwachsene|gruppe|family|kids|people|adults|couple/
190
+ words: /famili|kinder|zu zweit|personen|erwachsene|gruppe|family|kids|people|adults|couple|for two(?! weeks| nights)/
175
191
  },
176
192
  {
177
193
  topic: "date",
@@ -240,4 +256,4 @@ const TopicIcon = ({ text }) => {
240
256
  return /* @__PURE__ */ jsx(Svg, { children: TOPIC_PATHS[topic] });
241
257
  };
242
258
  //#endregion
243
- export { House as a, TopicIcon as c, saveConversation as d, chatAvailable as f, Cross as i, clearConversation as l, Check as n, Restart as o, sendMessage as p, Chevron as r, Spark as s, Arrow as t, loadConversation as u };
259
+ export { CircleInfo as a, Restart as c, TopicIcon as d, clearConversation as f, sendMessage as g, chatAvailable as h, CircleCheck as i, Spark as l, saveConversation as m, Check as n, Cross as o, loadConversation as p, Chevron as r, House as s, Arrow as t, Tag as u };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as ChatLocale, t as CHAT_LOCALES } from "./protocol-Bmb_uxVQ.js";
1
+ import { a as ChatLocale, s as ChatStatusStep, t as CHAT_LOCALES } from "./protocol-Dg1HZNWG.js";
2
2
  //#region src/copy.d.ts
3
3
  interface ChatCopy {
4
4
  /** The entry pill's invitation, under the title; on wide screens the pill's field says it. */
@@ -9,8 +9,15 @@ interface ChatCopy {
9
9
  /** The chat's name: over the entry pill and in the panel's head. */
10
10
  readonly title: string;
11
11
  readonly newConversation: string;
12
- /** The AI notice under the title (AI Act transparency); have its wording checked for the site. */
12
+ /** The AI notice under the title (AI Act transparency); have its wording checked for the site. Shown
13
+ * in full before the first message, then behind the ⓘ beside `noticeShort`. */
13
14
  readonly notice: string;
15
+ /** The mark beside the title that the chat is an AI, always shown. */
16
+ readonly aiBadge: string;
17
+ /** The notice's one line under the title once the conversation runs. */
18
+ readonly noticeShort: string;
19
+ /** The ⓘ button's name, which opens the full `notice`. */
20
+ readonly noticeMore: string;
14
21
  /** Shown before the first message. */
15
22
  readonly greeting: string;
16
23
  /** Tappable first messages, before the visitor wrote anything. */
@@ -19,6 +26,33 @@ interface ChatCopy {
19
26
  readonly send: string;
20
27
  /** Read out while a reply is on its way. */
21
28
  readonly thinking: string;
29
+ /** What the chat is doing while the visitor waits, by the service's step; `thinking` for any other. */
30
+ readonly status: Readonly<Record<ChatStatusStep, string>>;
31
+ /** Sends a message again that the chat could not answer (busy, failed). */
32
+ readonly retry: string;
33
+ /** The link to the site's privacy policy at the start step, where the site passes `privacyPath`. */
34
+ readonly privacyLink: string;
35
+ /** The bar over the input, for a screen reader: the stay in reach, or what the chat searched with. */
36
+ readonly yourPick: string;
37
+ readonly yourTrip: string;
38
+ /** Beside a party the search assumed because the visitor named none. */
39
+ readonly assumed: string;
40
+ /** People in a party, short: `{n}` is the count. */
41
+ readonly guests: Readonly<Partial<Record<Intl.LDMLPluralRule, string>>> & {
42
+ readonly other: string;
43
+ };
44
+ readonly adultsShort: Readonly<Partial<Record<Intl.LDMLPluralRule, string>>> & {
45
+ readonly other: string;
46
+ };
47
+ /** A search for weekends. */
48
+ readonly weekend: string;
49
+ /** What a tap on a part of the trip puts into the input, for the visitor to finish. */
50
+ readonly tripStarters: {
51
+ readonly party: string;
52
+ readonly period: string;
53
+ readonly nights: string;
54
+ readonly wishes: string;
55
+ };
22
56
  /** Over the message typed into the entry pill, at the start step that sends it. */
23
57
  readonly yourMessage: string;
24
58
  /** The consent step: what turning the chat on means. */
@@ -30,7 +64,7 @@ interface ChatCopy {
30
64
  readonly contactLink: string;
31
65
  readonly bookStay: string;
32
66
  readonly viewRental: string;
33
- /** A card's short button: book its stay, or see the rental without one. */
67
+ /** A card's and a quote's short button: book its stay, or see the rental without one. */
34
68
  readonly book: string;
35
69
  readonly view: string;
36
70
  /** @deprecated Not shown since 1.1.1: a card lists the wishes it matches instead. Kept so a site's
@@ -41,10 +75,36 @@ interface ChatCopy {
41
75
  readonly other: string;
42
76
  };
43
77
  readonly total: string;
78
+ /** Over a stay's total, what it covers; `{n}` is the nights. */
79
+ readonly totalForNights: Readonly<Partial<Record<Intl.LDMLPluralRule, string>>> & {
80
+ readonly other: string;
81
+ };
82
+ /** The disclosure with a quote's price lines. */
83
+ readonly priceDetails: string;
84
+ /** A discount the PMS applied without naming it. */
85
+ readonly dealFallback: string;
86
+ /** After a discount's name; `{amount}` is the saving as the PMS formats it. */
87
+ readonly youSave: string;
88
+ /** `{date}` is the last day with a full refund. */
89
+ readonly freeCancellation: string;
90
+ readonly nonRefundable: string;
91
+ /** Over the first and the last day in a hand-over card. */
92
+ readonly arrival: string;
93
+ readonly departure: string;
94
+ /** The hand-over card's button to the booking page. */
95
+ readonly continueToBooking: string;
96
+ /** Under that button: nothing is booked in the chat, and what the booking page asks next. */
97
+ readonly nothingBookedYet: string;
98
+ readonly handoverSteps: readonly string[];
44
99
  readonly notBookable: string;
45
100
  readonly photo: string;
101
+ /** A card's photo button, which opens the photos large; `{name}` is the rental's. */
102
+ readonly openPhotos: string;
103
+ readonly closePhotos: string;
46
104
  readonly previous: string;
47
105
  readonly next: string;
106
+ /** A carousel of found rentals, for a screen reader. */
107
+ readonly rentalsFound: string;
48
108
  /** `{n}` reviews, per plural form. */
49
109
  readonly reviews: Readonly<Partial<Record<Intl.LDMLPluralRule, string>>> & {
50
110
  readonly other: string;
@@ -56,6 +116,30 @@ interface ChatCopy {
56
116
  /** A day that is neither free nor taken: past, beyond the bookable range, or no arrival. */
57
117
  readonly closed: string;
58
118
  readonly yourStay: string;
119
+ /** A calendar day a stay can start on. */
120
+ readonly arrivalPossible: string;
121
+ /** The ends of the calendar's price levels, never an amount. */
122
+ readonly cheaper: string;
123
+ readonly dearer: string;
124
+ /** Asks for a stay's price: a tapped arrival, a stay length the booking system allows. */
125
+ readonly showPrice: string;
126
+ /** A tapped arrival, and the message that asks for its price; `{date}` is the day. */
127
+ readonly arrivalOn: string;
128
+ /** Over the stays a refused one could be instead; `{date}` is its arrival. */
129
+ readonly possibleFrom: string;
130
+ /** Under a stay length: its last day; `{date}` is the departure. */
131
+ readonly until: string;
132
+ /** Puts `otherArrivalStarter` into the input, for the visitor to name another arrival. */
133
+ readonly otherArrival: string;
134
+ readonly otherArrivalStarter: string;
135
+ /** Over a card's free periods, which switch its stay in place. */
136
+ readonly freePeriods: string;
137
+ /** Over free periods that all lie in one month, whose pills then leave the month out ("14.–21."). */
138
+ readonly freePeriodsIn: string;
139
+ /** Under a carousel whose stays have different dates. */
140
+ readonly datesDiffer: string;
141
+ /** A comparison's stay on other dates than the first one's. */
142
+ readonly otherDate: string;
59
143
  readonly compareRooms: string;
60
144
  readonly compareHighlights: string;
61
145
  readonly compareRating: string;
@@ -82,6 +166,10 @@ interface ChatCopy {
82
166
  readonly children: Readonly<Partial<Record<Intl.LDMLPluralRule, string>>> & {
83
167
  readonly other: string;
84
168
  };
169
+ /** The pets in a stay's party, after the people. */
170
+ readonly pets: Readonly<Partial<Record<Intl.LDMLPluralRule, string>>> & {
171
+ readonly other: string;
172
+ };
85
173
  }
86
174
  export declare const DEFAULT_COPY: Readonly<Record<ChatLocale, ChatCopy>>;
87
175
  //#endregion
@@ -112,6 +200,9 @@ interface WebsiteChatProps {
112
200
  readonly searchPath: string;
113
201
  /** The site's contact page: the chat links to it and has no form of its own. */
114
202
  readonly contactPath: string;
203
+ /** The site's privacy policy ("/datenschutz"): the start step links it next to what turning the
204
+ * chat on means. No link without it (1.3.0). */
205
+ readonly privacyPath?: string;
115
206
  readonly theme?: ChatTheme;
116
207
  readonly colors?: ChatColors;
117
208
  readonly position?: "right" | "left";