glitchgrab 1.59.0 → 1.59.1

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
@@ -1037,6 +1037,25 @@ interface CallsOptions {
1037
1037
  }
1038
1038
  ```
1039
1039
 
1040
+ ## How do I do something once a visitor books a demo?
1041
+
1042
+ Open the dialog yourself and pass `onBooked`. `intro` puts one line of your own
1043
+ above the dialog's title, so the visitor knows why you are asking.
1044
+
1045
+ ```tsx
1046
+ const { openBookingDialog } = useGlitchgrab();
1047
+
1048
+ openBookingDialog({
1049
+ intro: "Book a short call — the live demo opens the moment you're booked.",
1050
+ onBooked: ({ bookingId }) => {
1051
+ // Runs once, after the phone code when one is asked. The details come from
1052
+ // the browser: look `bookingId` up with listBookings() on your server
1053
+ // before you trust it.
1054
+ startDemo(bookingId);
1055
+ },
1056
+ });
1057
+ ```
1058
+
1040
1059
  ## How do I change demo booking settings from my admin panel?
1041
1060
 
1042
1061
  The same server key reads and writes the project's demo booking settings —
package/dist/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { f as GlitchgrabProviderProps, U as UseGlitchgrabReturn, R as ReportButtonProps, F as FeedbackButtonProps, g as GlitchgrabSession, C as CaptureErrorOptions, e as GlitchgrabFeedback, a as BreadcrumbType, B as Breadcrumb, b as CapturedContext, D as DeviceInfo, c as FeedbackPayload, d as FeedbackResult, L as LeadInput, h as LeadResult, i as ReportPayload, j as ReportResult } from './types-BpTLWJ1y.mjs';
3
- export { G as GlitchgrabConfig, k as ReportSeverity, l as ReportType, m as RuntimeInfo } from './types-BpTLWJ1y.mjs';
2
+ import { h as GlitchgrabProviderProps, U as UseGlitchgrabReturn, R as ReportButtonProps, B as BookedDemo, F as FeedbackButtonProps, i as GlitchgrabSession, C as CaptureErrorOptions, g as GlitchgrabFeedback, c as BreadcrumbType, b as Breadcrumb, d as CapturedContext, D as DeviceInfo, e as FeedbackPayload, f as FeedbackResult, L as LeadInput, j as LeadResult, k as ReportPayload, l as ReportResult } from './types-BlMF6wzX.mjs';
3
+ export { a as BookingDialogOptions, G as GlitchgrabConfig, m as ReportSeverity, n as ReportType, o as RuntimeInfo } from './types-BlMF6wzX.mjs';
4
4
  import * as React from 'react';
5
5
  import { ReactNode } from 'react';
6
6
 
@@ -81,7 +81,7 @@ declare function BookDemoButton({ label, className, children, }: {
81
81
  }) => ReactNode;
82
82
  }): react_jsx_runtime.JSX.Element;
83
83
 
84
- declare function BookingDialog({ token, baseUrl, open, onClose, preview, availabilityUrl, }: {
84
+ declare function BookingDialog({ token, baseUrl, open, onClose, preview, availabilityUrl, intro, onBooked, }: {
85
85
  token: string;
86
86
  baseUrl: string;
87
87
  open: boolean;
@@ -97,6 +97,10 @@ declare function BookingDialog({ token, baseUrl, open, onClose, preview, availab
97
97
  * holds no `gg_` token for the project. Same response shape.
98
98
  */
99
99
  availabilityUrl?: string;
100
+ /** The host's one line above the title — see `BookingDialogOptions.intro`. */
101
+ intro?: string;
102
+ /** Fired once when a booking is confirmed — see `BookingDialogOptions.onBooked`. */
103
+ onBooked?: (booking: BookedDemo) => void;
100
104
  }): react_jsx_runtime.JSX.Element | null;
101
105
 
102
106
  /**
@@ -498,4 +502,4 @@ declare function computeSignature(params: {
498
502
  declare function shouldSkipDuplicate(signature: string, windowMs?: number, now?: number): boolean;
499
503
  declare function clearDedupCache(): void;
500
504
 
501
- export { BookDemoButton, BookingDialog, Breadcrumb, BreadcrumbType, CaptureErrorOptions, CapturedContext, DeviceInfo, FeedbackButton, FeedbackButtonProps, FeedbackPayload, type FeedbackQuery, FeedbackResult, GLITCHGRAB_SHORTCUT, GLITCHGRAB_SHORTCUT_MAC, type GlitchgrabComment, GlitchgrabErrorBoundary, GlitchgrabFeedback, GlitchgrabProvider, GlitchgrabProviderProps, type GlitchgrabReport, type GlitchgrabReportThread, GlitchgrabSession, LeadInput, LeadResult, ReportButton, ReportButtonProps, ReportPayload, ReportResult, UseGlitchgrabReturn, addBreadcrumb, captureContext, captureDeviceInfo, captureError, clearAppContext, clearBreadcrumbs, clearDedupCache, computeSignature, enhanceText, fetchGlitchgrabFeedback, fetchGlitchgrabReportThread, fetchGlitchgrabReports, getAppContext, getBreadcrumbs, getShortcutLabel, initBreadcrumbs, matchesShortcut, postGlitchgrabReportComment, sanitizeUrl, sendFeedback, sendLead, sendReport, setContext, setContexts, shouldSkipDuplicate, useGlitchgrab, useGlitchgrabActions, useGlitchgrabFeedback, useGlitchgrabReportThread, useGlitchgrabReports };
505
+ export { BookDemoButton, BookedDemo, BookingDialog, Breadcrumb, BreadcrumbType, CaptureErrorOptions, CapturedContext, DeviceInfo, FeedbackButton, FeedbackButtonProps, FeedbackPayload, type FeedbackQuery, FeedbackResult, GLITCHGRAB_SHORTCUT, GLITCHGRAB_SHORTCUT_MAC, type GlitchgrabComment, GlitchgrabErrorBoundary, GlitchgrabFeedback, GlitchgrabProvider, GlitchgrabProviderProps, type GlitchgrabReport, type GlitchgrabReportThread, GlitchgrabSession, LeadInput, LeadResult, ReportButton, ReportButtonProps, ReportPayload, ReportResult, UseGlitchgrabReturn, addBreadcrumb, captureContext, captureDeviceInfo, captureError, clearAppContext, clearBreadcrumbs, clearDedupCache, computeSignature, enhanceText, fetchGlitchgrabFeedback, fetchGlitchgrabReportThread, fetchGlitchgrabReports, getAppContext, getBreadcrumbs, getShortcutLabel, initBreadcrumbs, matchesShortcut, postGlitchgrabReportComment, sanitizeUrl, sendFeedback, sendLead, sendReport, setContext, setContexts, shouldSkipDuplicate, useGlitchgrab, useGlitchgrabActions, useGlitchgrabFeedback, useGlitchgrabReportThread, useGlitchgrabReports };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { f as GlitchgrabProviderProps, U as UseGlitchgrabReturn, R as ReportButtonProps, F as FeedbackButtonProps, g as GlitchgrabSession, C as CaptureErrorOptions, e as GlitchgrabFeedback, a as BreadcrumbType, B as Breadcrumb, b as CapturedContext, D as DeviceInfo, c as FeedbackPayload, d as FeedbackResult, L as LeadInput, h as LeadResult, i as ReportPayload, j as ReportResult } from './types-BpTLWJ1y.js';
3
- export { G as GlitchgrabConfig, k as ReportSeverity, l as ReportType, m as RuntimeInfo } from './types-BpTLWJ1y.js';
2
+ import { h as GlitchgrabProviderProps, U as UseGlitchgrabReturn, R as ReportButtonProps, B as BookedDemo, F as FeedbackButtonProps, i as GlitchgrabSession, C as CaptureErrorOptions, g as GlitchgrabFeedback, c as BreadcrumbType, b as Breadcrumb, d as CapturedContext, D as DeviceInfo, e as FeedbackPayload, f as FeedbackResult, L as LeadInput, j as LeadResult, k as ReportPayload, l as ReportResult } from './types-BlMF6wzX.js';
3
+ export { a as BookingDialogOptions, G as GlitchgrabConfig, m as ReportSeverity, n as ReportType, o as RuntimeInfo } from './types-BlMF6wzX.js';
4
4
  import * as React from 'react';
5
5
  import { ReactNode } from 'react';
6
6
 
@@ -81,7 +81,7 @@ declare function BookDemoButton({ label, className, children, }: {
81
81
  }) => ReactNode;
82
82
  }): react_jsx_runtime.JSX.Element;
83
83
 
84
- declare function BookingDialog({ token, baseUrl, open, onClose, preview, availabilityUrl, }: {
84
+ declare function BookingDialog({ token, baseUrl, open, onClose, preview, availabilityUrl, intro, onBooked, }: {
85
85
  token: string;
86
86
  baseUrl: string;
87
87
  open: boolean;
@@ -97,6 +97,10 @@ declare function BookingDialog({ token, baseUrl, open, onClose, preview, availab
97
97
  * holds no `gg_` token for the project. Same response shape.
98
98
  */
99
99
  availabilityUrl?: string;
100
+ /** The host's one line above the title — see `BookingDialogOptions.intro`. */
101
+ intro?: string;
102
+ /** Fired once when a booking is confirmed — see `BookingDialogOptions.onBooked`. */
103
+ onBooked?: (booking: BookedDemo) => void;
100
104
  }): react_jsx_runtime.JSX.Element | null;
101
105
 
102
106
  /**
@@ -498,4 +502,4 @@ declare function computeSignature(params: {
498
502
  declare function shouldSkipDuplicate(signature: string, windowMs?: number, now?: number): boolean;
499
503
  declare function clearDedupCache(): void;
500
504
 
501
- export { BookDemoButton, BookingDialog, Breadcrumb, BreadcrumbType, CaptureErrorOptions, CapturedContext, DeviceInfo, FeedbackButton, FeedbackButtonProps, FeedbackPayload, type FeedbackQuery, FeedbackResult, GLITCHGRAB_SHORTCUT, GLITCHGRAB_SHORTCUT_MAC, type GlitchgrabComment, GlitchgrabErrorBoundary, GlitchgrabFeedback, GlitchgrabProvider, GlitchgrabProviderProps, type GlitchgrabReport, type GlitchgrabReportThread, GlitchgrabSession, LeadInput, LeadResult, ReportButton, ReportButtonProps, ReportPayload, ReportResult, UseGlitchgrabReturn, addBreadcrumb, captureContext, captureDeviceInfo, captureError, clearAppContext, clearBreadcrumbs, clearDedupCache, computeSignature, enhanceText, fetchGlitchgrabFeedback, fetchGlitchgrabReportThread, fetchGlitchgrabReports, getAppContext, getBreadcrumbs, getShortcutLabel, initBreadcrumbs, matchesShortcut, postGlitchgrabReportComment, sanitizeUrl, sendFeedback, sendLead, sendReport, setContext, setContexts, shouldSkipDuplicate, useGlitchgrab, useGlitchgrabActions, useGlitchgrabFeedback, useGlitchgrabReportThread, useGlitchgrabReports };
505
+ export { BookDemoButton, BookedDemo, BookingDialog, Breadcrumb, BreadcrumbType, CaptureErrorOptions, CapturedContext, DeviceInfo, FeedbackButton, FeedbackButtonProps, FeedbackPayload, type FeedbackQuery, FeedbackResult, GLITCHGRAB_SHORTCUT, GLITCHGRAB_SHORTCUT_MAC, type GlitchgrabComment, GlitchgrabErrorBoundary, GlitchgrabFeedback, GlitchgrabProvider, GlitchgrabProviderProps, type GlitchgrabReport, type GlitchgrabReportThread, GlitchgrabSession, LeadInput, LeadResult, ReportButton, ReportButtonProps, ReportPayload, ReportResult, UseGlitchgrabReturn, addBreadcrumb, captureContext, captureDeviceInfo, captureError, clearAppContext, clearBreadcrumbs, clearDedupCache, computeSignature, enhanceText, fetchGlitchgrabFeedback, fetchGlitchgrabReportThread, fetchGlitchgrabReports, getAppContext, getBreadcrumbs, getShortcutLabel, initBreadcrumbs, matchesShortcut, postGlitchgrabReportComment, sanitizeUrl, sendFeedback, sendLead, sendReport, setContext, setContexts, shouldSkipDuplicate, useGlitchgrab, useGlitchgrabActions, useGlitchgrabFeedback, useGlitchgrabReportThread, useGlitchgrabReports };
package/dist/index.js CHANGED
@@ -8617,6 +8617,69 @@ function getTypeIcon(type, color, size = 24) {
8617
8617
 
8618
8618
  // src/booking-dialog.tsx
8619
8619
  var import_react5 = require("react");
8620
+
8621
+ // src/phone.ts
8622
+ var COUNTRIES = [
8623
+ { iso: "IN", name: "India", dial: "91" },
8624
+ { iso: "AE", name: "UAE", dial: "971" },
8625
+ { iso: "US", name: "US / Canada", dial: "1" },
8626
+ { iso: "GB", name: "UK", dial: "44" },
8627
+ { iso: "SG", name: "Singapore", dial: "65" },
8628
+ { iso: "AU", name: "Australia", dial: "61" },
8629
+ { iso: "SA", name: "Saudi Arabia", dial: "966" },
8630
+ { iso: "QA", name: "Qatar", dial: "974" },
8631
+ { iso: "NP", name: "Nepal", dial: "977" },
8632
+ { iso: "BD", name: "Bangladesh", dial: "880" },
8633
+ { iso: "LK", name: "Sri Lanka", dial: "94" },
8634
+ { iso: "DE", name: "Germany", dial: "49" }
8635
+ ];
8636
+ var ZONE_COUNTRY = {
8637
+ "Asia/Kolkata": "91",
8638
+ "Asia/Calcutta": "91",
8639
+ "Asia/Dubai": "971",
8640
+ "Europe/London": "44",
8641
+ "Asia/Singapore": "65",
8642
+ "Asia/Riyadh": "966",
8643
+ "Asia/Qatar": "974",
8644
+ "Asia/Kathmandu": "977",
8645
+ "Asia/Katmandu": "977",
8646
+ "Asia/Dhaka": "880",
8647
+ "Asia/Colombo": "94",
8648
+ "Europe/Berlin": "49"
8649
+ };
8650
+ function defaultDialForZone(zone) {
8651
+ if (ZONE_COUNTRY[zone]) return ZONE_COUNTRY[zone];
8652
+ if (zone.startsWith("America/")) return "1";
8653
+ if (zone.startsWith("Australia/")) return "61";
8654
+ return "91";
8655
+ }
8656
+ function splitTypedPhone(typed, dial) {
8657
+ const trimmed = typed.trim();
8658
+ const digits = trimmed.replace(/\D/g, "");
8659
+ if (trimmed.startsWith("+")) {
8660
+ const match = [...COUNTRIES].sort((a, b) => b.dial.length - a.dial.length).find((c) => digits.startsWith(c.dial));
8661
+ if (match) return { dial: match.dial, national: digits.slice(match.dial.length) };
8662
+ }
8663
+ if (dial === "91" && digits.length === 12 && digits.startsWith("91")) return { dial, national: digits.slice(2) };
8664
+ if (dial === "91" && digits.length === 11 && digits.startsWith("0")) return { dial, national: digits.slice(1) };
8665
+ return { dial, national: digits };
8666
+ }
8667
+ function phoneProblem(dial, national) {
8668
+ const digits = national.replace(/\D/g, "");
8669
+ if (!digits) return "Enter your mobile number";
8670
+ if (dial === "91") {
8671
+ if (digits.length !== 10) return `An Indian mobile has 10 digits \u2014 this has ${digits.length}`;
8672
+ if (!/^[6-9]/.test(digits)) return "An Indian mobile starts with 6, 7, 8 or 9";
8673
+ return null;
8674
+ }
8675
+ if (digits.length < 6 || digits.length > 12) return "Check the number \u2014 it looks too short or too long";
8676
+ return null;
8677
+ }
8678
+ function toE164(dial, national) {
8679
+ return `+${dial}${national.replace(/\D/g, "")}`;
8680
+ }
8681
+
8682
+ // src/booking-dialog.tsx
8620
8683
  var import_jsx_runtime6 = require("react/jsx-runtime");
8621
8684
  function readQuestions(value) {
8622
8685
  if (!Array.isArray(value)) return [];
@@ -8759,7 +8822,9 @@ function BookingDialog({
8759
8822
  open,
8760
8823
  onClose,
8761
8824
  preview = false,
8762
- availabilityUrl
8825
+ availabilityUrl,
8826
+ intro,
8827
+ onBooked
8763
8828
  }) {
8764
8829
  var _a, _b, _c, _d, _e;
8765
8830
  const wide = useMediaQuery(WIDE_QUERY, true);
@@ -8782,6 +8847,8 @@ function BookingDialog({
8782
8847
  const [name, setName] = (0, import_react5.useState)("");
8783
8848
  const [email, setEmail] = (0, import_react5.useState)("");
8784
8849
  const [phone, setPhone] = (0, import_react5.useState)("");
8850
+ const [dial, setDial] = (0, import_react5.useState)(() => defaultDialForZone(localZone()));
8851
+ const [phoneTouched, setPhoneTouched] = (0, import_react5.useState)(false);
8785
8852
  const [note, setNote] = (0, import_react5.useState)("");
8786
8853
  const [questions, setQuestions] = (0, import_react5.useState)([]);
8787
8854
  const [answers, setAnswers] = (0, import_react5.useState)({});
@@ -8892,8 +8959,12 @@ function BookingDialog({
8892
8959
  const view = step !== "slots" ? step : !pageLoaded ? "loading" : questions.length > 0 && !asked ? "questions" : "slots";
8893
8960
  const roomy = step === "slots";
8894
8961
  async function startBooking() {
8895
- var _a2, _b2;
8962
+ var _a2, _b2, _c2;
8896
8963
  if (!selected) return;
8964
+ if (phoneError) {
8965
+ setPhoneTouched(true);
8966
+ return;
8967
+ }
8897
8968
  if (preview) {
8898
8969
  setPreviewEnded(true);
8899
8970
  return;
@@ -8907,7 +8978,7 @@ function BookingDialog({
8907
8978
  body: JSON.stringify({
8908
8979
  name,
8909
8980
  email,
8910
- phone,
8981
+ phone: toE164(dial, phone),
8911
8982
  note,
8912
8983
  answers: Object.fromEntries(given.map((q) => [q.id, q.answer])),
8913
8984
  startsAt: selected.startsAt,
@@ -8926,6 +8997,7 @@ function BookingDialog({
8926
8997
  if (json.data.confirmed) {
8927
8998
  setMeetUrl((_b2 = json.data.meetUrl) != null ? _b2 : null);
8928
8999
  setStep("done");
9000
+ reportBooked(json.data.bookingId, (_c2 = json.data.meetUrl) != null ? _c2 : null);
8929
9001
  return;
8930
9002
  }
8931
9003
  setBookingId(json.data.bookingId);
@@ -8936,8 +9008,16 @@ function BookingDialog({
8936
9008
  setBusy(false);
8937
9009
  }
8938
9010
  }
9011
+ function reportBooked(id, meet) {
9012
+ if (!onBooked || !id || !selected) return;
9013
+ try {
9014
+ onBooked({ bookingId: id, startsAt: selected.startsAt, name, email, phone: toE164(dial, phone), meetUrl: meet });
9015
+ } catch (e) {
9016
+ console.error("[glitchgrab] onBooked threw", e);
9017
+ }
9018
+ }
8939
9019
  async function confirmBooking() {
8940
- var _a2;
9020
+ var _a2, _b2;
8941
9021
  if (!bookingId) return;
8942
9022
  setBusy(true);
8943
9023
  setError(null);
@@ -8954,13 +9034,15 @@ function BookingDialog({
8954
9034
  }
8955
9035
  setMeetUrl(json.data.meetUrl);
8956
9036
  setStep("done");
9037
+ reportBooked(bookingId, (_b2 = json.data.meetUrl) != null ? _b2 : null);
8957
9038
  } catch (e) {
8958
9039
  setError("Couldn't reach the booking service");
8959
9040
  } finally {
8960
9041
  setBusy(false);
8961
9042
  }
8962
9043
  }
8963
- const canSubmitDetails = name.trim() && email.includes("@") && phone.replace(/\D/g, "").length >= 8;
9044
+ const phoneError = phoneProblem(dial, phone);
9045
+ const canSubmitDetails = Boolean(name.trim() && email.includes("@"));
8964
9046
  const selectedEnd = selected ? (_e = selected.endsAt) != null ? _e : new Date(new Date(selected.startsAt).getTime() + page.slotMinutes * 6e4).toISOString() : null;
8965
9047
  const monthDate = new Date(keyToUtc(`${month}-01`));
8966
9048
  const muted = { color: t.muted };
@@ -9107,6 +9189,14 @@ function BookingDialog({
9107
9189
  children: "Preview \u2014 nothing is booked"
9108
9190
  }
9109
9191
  ),
9192
+ intro && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
9193
+ "div",
9194
+ {
9195
+ "data-glitchgrab-booking-intro": true,
9196
+ style: { fontSize: 13, fontWeight: 600, lineHeight: 1.45, paddingRight: 32, color: t.ink, overflowWrap: "anywhere" },
9197
+ children: intro
9198
+ }
9199
+ ),
9110
9200
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { fontSize: 20, fontWeight: 600, lineHeight: 1.25, paddingRight: 32, overflowWrap: "anywhere" }, children: page.title }),
9111
9201
  page.description && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { fontSize: 13, lineHeight: 1.5, overflowWrap: "anywhere", ...muted }, children: page.description }),
9112
9202
  /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 10, marginTop: 4, fontSize: 14 }, children: [
@@ -9549,14 +9639,17 @@ function BookingDialog({
9549
9639
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Field, { t, label: "Your name", value: name, onChange: setName, autoComplete: "name" }),
9550
9640
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Field, { t, label: "Email", value: email, onChange: setEmail, type: "email", autoComplete: "email" }),
9551
9641
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
9552
- Field,
9642
+ PhoneField,
9553
9643
  {
9554
9644
  t,
9555
- label: "Mobile number",
9556
- value: phone,
9557
- onChange: setPhone,
9558
- type: "tel",
9559
- autoComplete: "tel",
9645
+ dial,
9646
+ national: phone,
9647
+ onChange: (nextDial, national) => {
9648
+ setDial(nextDial);
9649
+ setPhone(national);
9650
+ },
9651
+ onBlur: () => setPhoneTouched(true),
9652
+ error: phoneTouched ? phoneError : null,
9560
9653
  hint: requireOtp ? "We send a code here to confirm, then a reminder before the call." : "We send a reminder here before the call."
9561
9654
  }
9562
9655
  ),
@@ -9844,6 +9937,64 @@ function Field({
9844
9937
  hint && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { marginTop: 6, fontSize: 12, fontWeight: 400, color: t.muted }, children: hint })
9845
9938
  ] });
9846
9939
  }
9940
+ function PhoneField({
9941
+ t,
9942
+ dial,
9943
+ national,
9944
+ onChange,
9945
+ onBlur,
9946
+ error,
9947
+ hint
9948
+ }) {
9949
+ const box = {
9950
+ boxSizing: "border-box",
9951
+ padding: "9px 12px",
9952
+ background: t.input,
9953
+ color: t.text,
9954
+ border: `1px solid ${error ? t.danger : t.border}`,
9955
+ borderRadius: 8,
9956
+ fontFamily: "inherit",
9957
+ fontSize: 14,
9958
+ outline: "none"
9959
+ };
9960
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { style: { display: "block", fontSize: 13, fontWeight: 500, color: t.text }, children: [
9961
+ "Mobile number",
9962
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", gap: 8, marginTop: 6 }, children: [
9963
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
9964
+ "select",
9965
+ {
9966
+ "aria-label": "Country code",
9967
+ value: dial,
9968
+ onChange: (e) => onChange(e.target.value, national),
9969
+ style: { ...box, flex: "0 0 auto", paddingRight: 8, cursor: "pointer" },
9970
+ children: COUNTRIES.map((c) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("option", { value: c.dial, children: [
9971
+ c.iso,
9972
+ " +",
9973
+ c.dial
9974
+ ] }, c.iso))
9975
+ }
9976
+ ),
9977
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
9978
+ "input",
9979
+ {
9980
+ type: "tel",
9981
+ autoComplete: "tel",
9982
+ inputMode: "numeric",
9983
+ placeholder: dial === "91" ? "98765 43210" : "Mobile number",
9984
+ value: national,
9985
+ "aria-invalid": Boolean(error),
9986
+ onChange: (e) => {
9987
+ const next = splitTypedPhone(e.target.value, dial);
9988
+ onChange(next.dial, next.national);
9989
+ },
9990
+ onBlur,
9991
+ style: { ...box, flex: "1 1 auto", minWidth: 0, width: "100%" }
9992
+ }
9993
+ )
9994
+ ] }),
9995
+ error ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { role: "alert", style: { marginTop: 6, fontSize: 12, fontWeight: 500, color: t.danger }, children: error }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { marginTop: 6, fontSize: 12, fontWeight: 400, color: t.muted }, children: hint })
9996
+ ] });
9997
+ }
9847
9998
 
9848
9999
  // src/rejection.ts
9849
10000
  var DETAILS_MAX_LENGTH = 1e3;
@@ -10434,8 +10585,18 @@ function GlitchgrabProviderInner({
10434
10585
  const [signedUsers, setSignedUsers] = (0, import_react6.useState)("OFF");
10435
10586
  const aiBlockedUnsigned = signedUsers === "ENFORCE" && !signature;
10436
10587
  const [booking, setBooking] = (0, import_react6.useState)("closed");
10437
- const openBookingDialog = (0, import_react6.useCallback)(() => setBooking("live"), []);
10438
- const openBookingPreview = (0, import_react6.useCallback)(() => setBooking("preview"), []);
10588
+ const [bookingOptions, setBookingOptions] = (0, import_react6.useState)({});
10589
+ const openBookingDialog = (0, import_react6.useCallback)((options) => {
10590
+ setBookingOptions({
10591
+ intro: typeof (options == null ? void 0 : options.intro) === "string" ? options.intro : void 0,
10592
+ onBooked: typeof (options == null ? void 0 : options.onBooked) === "function" ? options.onBooked : void 0
10593
+ });
10594
+ setBooking("live");
10595
+ }, []);
10596
+ const openBookingPreview = (0, import_react6.useCallback)(() => {
10597
+ setBookingOptions({});
10598
+ setBooking("preview");
10599
+ }, []);
10439
10600
  (0, import_react6.useEffect)(() => {
10440
10601
  let cancelled = false;
10441
10602
  fetch(`${baseUrl}/api/v1/sdk/project`, {
@@ -10534,6 +10695,8 @@ function GlitchgrabProviderInner({
10534
10695
  baseUrl: baseUrl != null ? baseUrl : DEFAULT_BASE_URL2,
10535
10696
  open: booking !== "closed",
10536
10697
  preview: booking === "preview",
10698
+ intro: bookingOptions.intro,
10699
+ onBooked: bookingOptions.onBooked,
10537
10700
  onClose: () => setBooking("closed")
10538
10701
  }
10539
10702
  ),
@@ -10675,12 +10838,13 @@ function BookDemoButton({
10675
10838
  children
10676
10839
  }) {
10677
10840
  const { openBookingDialog } = useGlitchgrab();
10678
- if (children) return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_jsx_runtime9.Fragment, { children: children({ onClick: openBookingDialog }) });
10841
+ const open = () => openBookingDialog();
10842
+ if (children) return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_jsx_runtime9.Fragment, { children: children({ onClick: open }) });
10679
10843
  return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
10680
10844
  "button",
10681
10845
  {
10682
10846
  type: "button",
10683
- onClick: openBookingDialog,
10847
+ onClick: open,
10684
10848
  className,
10685
10849
  style: className ? void 0 : {
10686
10850
  padding: "10px 18px",