@sonordev/site-kit 3.2.0 → 3.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.
Files changed (142) hide show
  1. package/agent-manifest.json +1 -1
  2. package/dist/AnalyticsProvider-26VS3CQR.js +29 -0
  3. package/dist/{AnalyticsProvider-WK2Z6AIN.js.map → AnalyticsProvider-26VS3CQR.js.map} +1 -1
  4. package/dist/AnalyticsProvider-AMHG4DIE.mjs +8 -0
  5. package/dist/{AnalyticsProvider-CD635CHQ.mjs.map → AnalyticsProvider-AMHG4DIE.mjs.map} +1 -1
  6. package/dist/ChatWidget-NIYNSMLU.js +17 -0
  7. package/dist/{ChatWidget-AIOOZY6H.js.map → ChatWidget-NIYNSMLU.js.map} +1 -1
  8. package/dist/ChatWidget-UKPEQEHB.mjs +8 -0
  9. package/dist/{ChatWidget-UAAWDBNS.mjs.map → ChatWidget-UKPEQEHB.mjs.map} +1 -1
  10. package/dist/EngageWidget-33QCFWQW.js +16 -0
  11. package/dist/{EngageWidget-RWVWW56C.js.map → EngageWidget-33QCFWQW.js.map} +1 -1
  12. package/dist/EngageWidget-S76ZMDEF.mjs +7 -0
  13. package/dist/{EngageWidget-EZ5T6H3K.mjs.map → EngageWidget-S76ZMDEF.mjs.map} +1 -1
  14. package/dist/{SignalCore-4B4RNYLV.mjs → SignalCore-2AUGAOQT.mjs} +4 -4
  15. package/dist/{SignalCore-4B4RNYLV.mjs.map → SignalCore-2AUGAOQT.mjs.map} +1 -1
  16. package/dist/{SignalCore-AECW2JFP.js → SignalCore-2UXXM4FF.js} +8 -8
  17. package/dist/{SignalCore-AECW2JFP.js.map → SignalCore-2UXXM4FF.js.map} +1 -1
  18. package/dist/SitemapSync-RBHXPQAQ.mjs +6 -0
  19. package/dist/{SitemapSync-CIZCAZXK.mjs.map → SitemapSync-RBHXPQAQ.mjs.map} +1 -1
  20. package/dist/SitemapSync-WQJMHJNY.js +15 -0
  21. package/dist/{SitemapSync-AICU4SSV.js.map → SitemapSync-WQJMHJNY.js.map} +1 -1
  22. package/dist/analytics/index.js +11 -11
  23. package/dist/analytics/index.mjs +4 -4
  24. package/dist/brand.css +13 -3
  25. package/dist/{chunk-OTY7EWET.mjs → chunk-2RLG4KBJ.mjs} +4 -4
  26. package/dist/{chunk-OTY7EWET.mjs.map → chunk-2RLG4KBJ.mjs.map} +1 -1
  27. package/dist/{chunk-6HPNFWSC.mjs → chunk-5KVT66R6.mjs} +3 -3
  28. package/dist/{chunk-6HPNFWSC.mjs.map → chunk-5KVT66R6.mjs.map} +1 -1
  29. package/dist/{chunk-RFIWVH3D.mjs → chunk-6BDXN4X3.mjs} +3 -3
  30. package/dist/{chunk-RFIWVH3D.mjs.map → chunk-6BDXN4X3.mjs.map} +1 -1
  31. package/dist/{chunk-GCDVKOSM.js → chunk-6UK5JIKE.js} +3 -3
  32. package/dist/{chunk-GCDVKOSM.js.map → chunk-6UK5JIKE.js.map} +1 -1
  33. package/dist/{chunk-GN62H6EG.mjs → chunk-AXFM4MFK.mjs} +8 -8
  34. package/dist/{chunk-GN62H6EG.mjs.map → chunk-AXFM4MFK.mjs.map} +1 -1
  35. package/dist/{chunk-S3YQGTBF.js → chunk-BOTWTNHW.js} +12 -12
  36. package/dist/{chunk-S3YQGTBF.js.map → chunk-BOTWTNHW.js.map} +1 -1
  37. package/dist/{chunk-I2GTT2DG.js → chunk-BPKDRTEA.js} +107 -34
  38. package/dist/chunk-BPKDRTEA.js.map +1 -0
  39. package/dist/{chunk-4NTMIU6V.js → chunk-EL6ZMYD2.js} +6 -6
  40. package/dist/{chunk-4NTMIU6V.js.map → chunk-EL6ZMYD2.js.map} +1 -1
  41. package/dist/{chunk-UT2CF4FC.js → chunk-EM4DFSC5.js} +4 -4
  42. package/dist/{chunk-UT2CF4FC.js.map → chunk-EM4DFSC5.js.map} +1 -1
  43. package/dist/chunk-EOENN46G.js +8 -0
  44. package/dist/{chunk-WRZQS7O4.js.map → chunk-EOENN46G.js.map} +1 -1
  45. package/dist/{chunk-LZSCCJ4O.mjs → chunk-FO6Y27AH.mjs} +11 -5
  46. package/dist/chunk-FO6Y27AH.mjs.map +1 -0
  47. package/dist/{chunk-5OWZUNNE.js → chunk-FX3VR4BF.js} +7 -7
  48. package/dist/{chunk-5OWZUNNE.js.map → chunk-FX3VR4BF.js.map} +1 -1
  49. package/dist/{chunk-TE3W5REY.js → chunk-G4FJJK6J.js} +14 -14
  50. package/dist/{chunk-TE3W5REY.js.map → chunk-G4FJJK6J.js.map} +1 -1
  51. package/dist/{chunk-R5A64DCX.js → chunk-I2M533CW.js} +8 -8
  52. package/dist/{chunk-R5A64DCX.js.map → chunk-I2M533CW.js.map} +1 -1
  53. package/dist/{chunk-FMZOZQBV.mjs → chunk-ILLOVVVP.mjs} +107 -34
  54. package/dist/chunk-ILLOVVVP.mjs.map +1 -0
  55. package/dist/{chunk-HAZN43I6.js → chunk-K2P7KPEQ.js} +30 -28
  56. package/dist/chunk-K2P7KPEQ.js.map +1 -0
  57. package/dist/{chunk-EAASMIWX.js → chunk-M2EGCGIT.js} +15 -9
  58. package/dist/chunk-M2EGCGIT.js.map +1 -0
  59. package/dist/{chunk-2WYEJOGA.mjs → chunk-M4HLDK62.mjs} +3 -3
  60. package/dist/{chunk-2WYEJOGA.mjs.map → chunk-M4HLDK62.mjs.map} +1 -1
  61. package/dist/{chunk-T2DEEKVQ.mjs → chunk-NNPF4KRZ.mjs} +3 -3
  62. package/dist/{chunk-T2DEEKVQ.mjs.map → chunk-NNPF4KRZ.mjs.map} +1 -1
  63. package/dist/{chunk-NAVDN4AE.js → chunk-P3QZRG2Z.js} +29 -40
  64. package/dist/chunk-P3QZRG2Z.js.map +1 -0
  65. package/dist/{chunk-EIWRPGOK.mjs → chunk-PLQ4CUNI.mjs} +4 -4
  66. package/dist/{chunk-EIWRPGOK.mjs.map → chunk-PLQ4CUNI.mjs.map} +1 -1
  67. package/dist/{chunk-45QHDA7Q.mjs → chunk-PUGRSMAV.mjs} +3 -3
  68. package/dist/{chunk-45QHDA7Q.mjs.map → chunk-PUGRSMAV.mjs.map} +1 -1
  69. package/dist/{chunk-4FBV5BJW.js → chunk-QOFC3BYG.js} +5 -5
  70. package/dist/{chunk-4FBV5BJW.js.map → chunk-QOFC3BYG.js.map} +1 -1
  71. package/dist/chunk-S4FJIG6Y.mjs +6 -0
  72. package/dist/{chunk-SN2O72UF.mjs.map → chunk-S4FJIG6Y.mjs.map} +1 -1
  73. package/dist/{chunk-DSRPKUQI.mjs → chunk-SLOZWRWU.mjs} +28 -39
  74. package/dist/chunk-SLOZWRWU.mjs.map +1 -0
  75. package/dist/{chunk-TVCCZ7NR.js → chunk-WAYG3LS2.js} +14 -14
  76. package/dist/{chunk-TVCCZ7NR.js.map → chunk-WAYG3LS2.js.map} +1 -1
  77. package/dist/{chunk-N2HR2E4Z.mjs → chunk-WEHJRE3H.mjs} +25 -23
  78. package/dist/chunk-WEHJRE3H.mjs.map +1 -0
  79. package/dist/{chunk-NDHFU4HV.mjs → chunk-X72PFC4X.mjs} +4 -4
  80. package/dist/{chunk-NDHFU4HV.mjs.map → chunk-X72PFC4X.mjs.map} +1 -1
  81. package/dist/{chunk-SLWTG2LJ.js → chunk-XOCQANYF.js} +13 -13
  82. package/dist/{chunk-SLWTG2LJ.js.map → chunk-XOCQANYF.js.map} +1 -1
  83. package/dist/{chunk-57QV6NIY.mjs → chunk-ZCZEKWFW.mjs} +3 -3
  84. package/dist/{chunk-57QV6NIY.mjs.map → chunk-ZCZEKWFW.mjs.map} +1 -1
  85. package/dist/cli/index.js +2 -2
  86. package/dist/cli/index.mjs +1 -1
  87. package/dist/commerce/index.js +50 -50
  88. package/dist/commerce/index.mjs +5 -5
  89. package/dist/engage/index.js +8 -8
  90. package/dist/engage/index.mjs +5 -5
  91. package/dist/fleet/index.js +7 -7
  92. package/dist/fleet/index.mjs +3 -3
  93. package/dist/forms/index.js +18 -18
  94. package/dist/forms/index.js.map +1 -1
  95. package/dist/forms/index.mjs +10 -10
  96. package/dist/forms/index.mjs.map +1 -1
  97. package/dist/forms/styles.css +4 -2
  98. package/dist/images/index.js +10 -10
  99. package/dist/images/index.mjs +3 -3
  100. package/dist/index.js +67 -68
  101. package/dist/index.js.map +1 -1
  102. package/dist/index.mjs +14 -15
  103. package/dist/index.mjs.map +1 -1
  104. package/dist/layout/client.js +6 -6
  105. package/dist/layout/client.mjs +5 -5
  106. package/dist/layout/index.js +7 -7
  107. package/dist/layout/index.mjs +5 -5
  108. package/dist/maps/index.d.mts +4 -2
  109. package/dist/maps/index.d.ts +4 -2
  110. package/dist/maps/index.js +4 -4
  111. package/dist/maps/index.js.map +1 -1
  112. package/dist/maps/index.mjs +2 -2
  113. package/dist/maps/index.mjs.map +1 -1
  114. package/dist/seo/client.js +4 -4
  115. package/dist/seo/client.mjs +3 -3
  116. package/dist/seo/index.js +4 -4
  117. package/dist/seo/index.mjs +3 -3
  118. package/dist/signal/index.js +11 -11
  119. package/dist/signal/index.mjs +2 -2
  120. package/dist/sync/index.d.mts +10 -1
  121. package/dist/sync/index.d.ts +10 -1
  122. package/dist/sync/index.js +15 -13
  123. package/dist/sync/index.mjs +3 -1
  124. package/package.json +1 -1
  125. package/dist/AnalyticsProvider-CD635CHQ.mjs +0 -8
  126. package/dist/AnalyticsProvider-WK2Z6AIN.js +0 -29
  127. package/dist/ChatWidget-AIOOZY6H.js +0 -17
  128. package/dist/ChatWidget-UAAWDBNS.mjs +0 -8
  129. package/dist/EngageWidget-EZ5T6H3K.mjs +0 -7
  130. package/dist/EngageWidget-RWVWW56C.js +0 -16
  131. package/dist/SitemapSync-AICU4SSV.js +0 -15
  132. package/dist/SitemapSync-CIZCAZXK.mjs +0 -6
  133. package/dist/chunk-DSRPKUQI.mjs.map +0 -1
  134. package/dist/chunk-EAASMIWX.js.map +0 -1
  135. package/dist/chunk-FMZOZQBV.mjs.map +0 -1
  136. package/dist/chunk-HAZN43I6.js.map +0 -1
  137. package/dist/chunk-I2GTT2DG.js.map +0 -1
  138. package/dist/chunk-LZSCCJ4O.mjs.map +0 -1
  139. package/dist/chunk-N2HR2E4Z.mjs.map +0 -1
  140. package/dist/chunk-NAVDN4AE.js.map +0 -1
  141. package/dist/chunk-SN2O72UF.mjs +0 -6
  142. package/dist/chunk-WRZQS7O4.js +0 -8
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
  'use strict';
3
3
 
4
- var chunkGCDVKOSM_js = require('./chunk-GCDVKOSM.js');
4
+ var chunk6UK5JIKE_js = require('./chunk-6UK5JIKE.js');
5
5
  var React = require('react');
6
6
  var jsxRuntime = require('react/jsx-runtime');
7
7
 
@@ -16,8 +16,8 @@ function SignalExperiment({
16
16
  trackImpression = true,
17
17
  children
18
18
  }) {
19
- const { assignment, variant, isControl } = chunkGCDVKOSM_js.useSignalExperiment(experimentId);
20
- const trackEvent = chunkGCDVKOSM_js.useSignalEvent();
19
+ const { assignment, variant, isControl } = chunk6UK5JIKE_js.useSignalExperiment(experimentId);
20
+ const trackEvent = chunk6UK5JIKE_js.useSignalEvent();
21
21
  React.useEffect(() => {
22
22
  if (trackImpression && variant) {
23
23
  trackEvent({
@@ -44,7 +44,7 @@ function SignalExperiment({
44
44
  return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: variants.control || null });
45
45
  }
46
46
  function useExperimentVariant(experimentId) {
47
- return chunkGCDVKOSM_js.useSignalExperiment(experimentId);
47
+ return chunk6UK5JIKE_js.useSignalExperiment(experimentId);
48
48
  }
49
49
  function ExperimentConversion({
50
50
  experimentId,
@@ -52,8 +52,8 @@ function ExperimentConversion({
52
52
  value,
53
53
  children
54
54
  }) {
55
- const trackEvent = chunkGCDVKOSM_js.useSignalEvent();
56
- const { variant } = chunkGCDVKOSM_js.useSignalExperiment(experimentId);
55
+ const trackEvent = chunk6UK5JIKE_js.useSignalEvent();
56
+ const { variant } = chunk6UK5JIKE_js.useSignalExperiment(experimentId);
57
57
  const handleInteraction = () => {
58
58
  trackEvent({
59
59
  event_type: "experiment",
@@ -79,5 +79,5 @@ function ExperimentConversion({
79
79
  exports.ExperimentConversion = ExperimentConversion;
80
80
  exports.SignalExperiment = SignalExperiment;
81
81
  exports.useExperimentVariant = useExperimentVariant;
82
- //# sourceMappingURL=chunk-R5A64DCX.js.map
83
- //# sourceMappingURL=chunk-R5A64DCX.js.map
82
+ //# sourceMappingURL=chunk-I2M533CW.js.map
83
+ //# sourceMappingURL=chunk-I2M533CW.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/signal/SignalExperiment.tsx"],"names":["useSignalExperiment","useSignalEvent","useEffect","jsx","Fragment","React"],"mappings":";;;;;;;;;;AAgDO,SAAS,gBAAA,CAAiB;AAAA,EAC/B,YAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,eAAA,GAAkB,IAAA;AAAA,EAClB;AACF,CAAA,EAA0B;AACxB,EAAA,MAAM,EAAE,UAAA,EAAY,OAAA,EAAS,SAAA,EAAU,GAAIA,qCAAoB,YAAY,CAAA;AAC3E,EAAA,MAAM,aAAaC,+BAAA,EAAe;AAGlC,EAAAC,eAAA,CAAU,MAAM;AACd,IAAA,IAAI,mBAAmB,OAAA,EAAS;AAC9B,MAAA,UAAA,CAAW;AAAA,QACT,UAAA,EAAY,YAAA;AAAA,QACZ,UAAA,EAAY,YAAA;AAAA,QACZ,UAAA,EAAY;AAAA,UACV,aAAA,EAAe,YAAA;AAAA,UACf,WAAA,EAAa;AAAA;AACf,OACD,CAAA;AAAA,IACH;AAAA,EACF,GAAG,CAAC,YAAA,EAAc,OAAA,EAAS,eAAA,EAAiB,UAAU,CAAC,CAAA;AAGvD,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,uBAAOC,cAAA,CAAAC,mBAAA,EAAA,EAAG,mBAAS,EAAE,OAAA,EAAS,WAAW,SAAA,EAAW,SAAA,EAAW,CAAA,EAAE,CAAA;AAAA,EACnE;AAGA,EAAA,MAAM,kBAAkB,OAAA,IAAW,SAAA;AACnC,EAAA,MAAM,OAAA,GAAU,SAAS,eAAe,CAAA;AAExC,EAAA,IAAI,YAAY,MAAA,EAAW;AACzB,IAAA,6DAAU,QAAA,EAAA,OAAA,EAAQ,CAAA;AAAA,EACpB;AAGA,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,6DAAU,QAAA,EAAA,QAAA,EAAS,CAAA;AAAA,EACrB;AAEA,EAAA,uBAAOD,cAAA,CAAAC,mBAAA,EAAA,EAAG,QAAA,EAAA,QAAA,CAAS,OAAA,IAAW,IAAA,EAAK,CAAA;AACrC;AAYO,SAAS,qBAAqB,YAAA,EAAsB;AACzD,EAAA,OAAOJ,qCAAoB,YAAY,CAAA;AACzC;AAoBO,SAAS,oBAAA,CAAqB;AAAA,EACnC,YAAA;AAAA,EACA,WAAA,GAAc,OAAA;AAAA,EACd,KAAA;AAAA,EACA;AACF,CAAA,EAKG;AACD,EAAA,MAAM,aAAaC,+BAAA,EAAe;AAClC,EAAA,MAAM,EAAE,OAAA,EAAQ,GAAID,oCAAA,CAAoB,YAAY,CAAA;AAEpD,EAAA,MAAM,oBAAoB,MAAM;AAC9B,IAAA,UAAA,CAAW;AAAA,MACT,UAAA,EAAY,YAAA;AAAA,MACZ,UAAA,EAAY,YAAA;AAAA,MACZ,UAAA,EAAY;AAAA,QACV,aAAA,EAAe,YAAA;AAAA,QACf,WAAA,EAAa,OAAA;AAAA,QACb,YAAA,EAAc,WAAA;AAAA,QACd;AAAA;AACF,KACD,CAAA;AAAA,EACH,CAAA;AAEA,EAAA,OAAOK,sBAAA,CAAM,aAAa,QAAA,EAAU;AAAA,IAClC,OAAA,EAAS,CAAC,CAAA,KAAwB;AAChC,MAAA,iBAAA,EAAkB;AAElB,MAAA,IAAK,QAAA,CAAS,MAAsD,OAAA,EAAS;AAC3E,QAAC,QAAA,CAAS,KAAA,CAAsD,OAAA,CAAS,CAAC,CAAA;AAAA,MAC5E;AAAA,IACF;AAAA,GACD,CAAA;AACH","file":"chunk-R5A64DCX.js","sourcesContent":["/**\n * @sonordev/site-kit/signal - SignalExperiment\n * \n * A/B test component that renders different variants based on Signal assignment.\n * Uses Thompson Sampling (Bayesian bandit) for optimization.\n */\n\n'use client'\n\nimport React, { useMemo, useEffect } from 'react'\nimport { useSignalExperiment, useSignalEvent } from './SignalBridge'\n\ninterface SignalExperimentProps {\n /** Unique experiment ID */\n experimentId: string\n \n /** Variants to test - keys are variant names, values are React nodes */\n variants: Record<string, React.ReactNode>\n \n /** Fallback content if no assignment (defaults to 'control' variant) */\n fallback?: React.ReactNode\n \n /** Track impression automatically */\n trackImpression?: boolean\n \n /** Children function for more control */\n children?: (props: { variant: string; isControl: boolean }) => React.ReactNode\n}\n\n/**\n * Renders different content variants based on Signal's A/B assignment.\n * \n * @example\n * // Simple variant switching\n * <SignalExperiment experimentId=\"hero-cta\" variants={{\n * control: <Button>Get Started</Button>,\n * variant_a: <Button variant=\"primary\">Start Free Trial</Button>,\n * variant_b: <Button variant=\"secondary\">Book a Demo</Button>,\n * }} />\n * \n * @example\n * // With render prop for more control\n * <SignalExperiment experimentId=\"pricing-layout\">\n * {({ variant, isControl }) => (\n * <PricingSection layout={isControl ? 'cards' : 'table'} />\n * )}\n * </SignalExperiment>\n */\nexport function SignalExperiment({\n experimentId,\n variants,\n fallback,\n trackImpression = true,\n children,\n}: SignalExperimentProps) {\n const { assignment, variant, isControl } = useSignalExperiment(experimentId)\n const trackEvent = useSignalEvent()\n \n // Track impression when variant is rendered\n useEffect(() => {\n if (trackImpression && variant) {\n trackEvent({\n event_type: 'experiment',\n event_name: 'impression',\n event_data: {\n experiment_id: experimentId,\n variant_key: variant,\n },\n })\n }\n }, [experimentId, variant, trackImpression, trackEvent])\n \n // If using render prop\n if (children) {\n return <>{children({ variant: variant || 'control', isControl })}</>\n }\n \n // Determine what to render\n const selectedVariant = variant || 'control'\n const content = variants[selectedVariant]\n \n if (content !== undefined) {\n return <>{content}</>\n }\n \n // Fallback to provided fallback or control\n if (fallback) {\n return <>{fallback}</>\n }\n \n return <>{variants.control || null}</>\n}\n\n/**\n * Hook for conditional experiment logic\n * \n * @example\n * const { variant, isControl } = useExperimentVariant('pricing-test')\n * \n * return isControl \n * ? <OldPricing />\n * : <NewPricing showAnnual={variant === 'annual_first'} />\n */\nexport function useExperimentVariant(experimentId: string) {\n return useSignalExperiment(experimentId)\n}\n\n/**\n * Component for tracking experiment conversions\n * Wraps interactive elements to track when they convert\n * \n * @example\n * <SignalExperiment experimentId=\"signup-button\" variants={{\n * control: (\n * <ExperimentConversion experimentId=\"signup-button\" outcomeType=\"click\">\n * <Button>Sign Up</Button>\n * </ExperimentConversion>\n * ),\n * variant_a: (\n * <ExperimentConversion experimentId=\"signup-button\" outcomeType=\"click\">\n * <Button variant=\"large\">Join Now - It's Free!</Button>\n * </ExperimentConversion>\n * ),\n * }} />\n */\nexport function ExperimentConversion({\n experimentId,\n outcomeType = 'click',\n value,\n children,\n}: {\n experimentId: string\n outcomeType?: string\n value?: number\n children: React.ReactElement<{ onClick?: (e: React.MouseEvent) => void }>\n}) {\n const trackEvent = useSignalEvent()\n const { variant } = useSignalExperiment(experimentId)\n\n const handleInteraction = () => {\n trackEvent({\n event_type: 'experiment',\n event_name: 'conversion',\n event_data: {\n experiment_id: experimentId,\n variant_key: variant,\n outcome_type: outcomeType,\n value,\n },\n })\n }\n\n return React.cloneElement(children, {\n onClick: (e: React.MouseEvent) => {\n handleInteraction()\n // Call original onClick if exists\n if ((children.props as { onClick?: (e: React.MouseEvent) => void }).onClick) {\n (children.props as { onClick?: (e: React.MouseEvent) => void }).onClick!(e)\n }\n },\n })\n}\n"]}
1
+ {"version":3,"sources":["../src/signal/SignalExperiment.tsx"],"names":["useSignalExperiment","useSignalEvent","useEffect","jsx","Fragment","React"],"mappings":";;;;;;;;;;AAgDO,SAAS,gBAAA,CAAiB;AAAA,EAC/B,YAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,eAAA,GAAkB,IAAA;AAAA,EAClB;AACF,CAAA,EAA0B;AACxB,EAAA,MAAM,EAAE,UAAA,EAAY,OAAA,EAAS,SAAA,EAAU,GAAIA,qCAAoB,YAAY,CAAA;AAC3E,EAAA,MAAM,aAAaC,+BAAA,EAAe;AAGlC,EAAAC,eAAA,CAAU,MAAM;AACd,IAAA,IAAI,mBAAmB,OAAA,EAAS;AAC9B,MAAA,UAAA,CAAW;AAAA,QACT,UAAA,EAAY,YAAA;AAAA,QACZ,UAAA,EAAY,YAAA;AAAA,QACZ,UAAA,EAAY;AAAA,UACV,aAAA,EAAe,YAAA;AAAA,UACf,WAAA,EAAa;AAAA;AACf,OACD,CAAA;AAAA,IACH;AAAA,EACF,GAAG,CAAC,YAAA,EAAc,OAAA,EAAS,eAAA,EAAiB,UAAU,CAAC,CAAA;AAGvD,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,uBAAOC,cAAA,CAAAC,mBAAA,EAAA,EAAG,mBAAS,EAAE,OAAA,EAAS,WAAW,SAAA,EAAW,SAAA,EAAW,CAAA,EAAE,CAAA;AAAA,EACnE;AAGA,EAAA,MAAM,kBAAkB,OAAA,IAAW,SAAA;AACnC,EAAA,MAAM,OAAA,GAAU,SAAS,eAAe,CAAA;AAExC,EAAA,IAAI,YAAY,MAAA,EAAW;AACzB,IAAA,6DAAU,QAAA,EAAA,OAAA,EAAQ,CAAA;AAAA,EACpB;AAGA,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,6DAAU,QAAA,EAAA,QAAA,EAAS,CAAA;AAAA,EACrB;AAEA,EAAA,uBAAOD,cAAA,CAAAC,mBAAA,EAAA,EAAG,QAAA,EAAA,QAAA,CAAS,OAAA,IAAW,IAAA,EAAK,CAAA;AACrC;AAYO,SAAS,qBAAqB,YAAA,EAAsB;AACzD,EAAA,OAAOJ,qCAAoB,YAAY,CAAA;AACzC;AAoBO,SAAS,oBAAA,CAAqB;AAAA,EACnC,YAAA;AAAA,EACA,WAAA,GAAc,OAAA;AAAA,EACd,KAAA;AAAA,EACA;AACF,CAAA,EAKG;AACD,EAAA,MAAM,aAAaC,+BAAA,EAAe;AAClC,EAAA,MAAM,EAAE,OAAA,EAAQ,GAAID,oCAAA,CAAoB,YAAY,CAAA;AAEpD,EAAA,MAAM,oBAAoB,MAAM;AAC9B,IAAA,UAAA,CAAW;AAAA,MACT,UAAA,EAAY,YAAA;AAAA,MACZ,UAAA,EAAY,YAAA;AAAA,MACZ,UAAA,EAAY;AAAA,QACV,aAAA,EAAe,YAAA;AAAA,QACf,WAAA,EAAa,OAAA;AAAA,QACb,YAAA,EAAc,WAAA;AAAA,QACd;AAAA;AACF,KACD,CAAA;AAAA,EACH,CAAA;AAEA,EAAA,OAAOK,sBAAA,CAAM,aAAa,QAAA,EAAU;AAAA,IAClC,OAAA,EAAS,CAAC,CAAA,KAAwB;AAChC,MAAA,iBAAA,EAAkB;AAElB,MAAA,IAAK,QAAA,CAAS,MAAsD,OAAA,EAAS;AAC3E,QAAC,QAAA,CAAS,KAAA,CAAsD,OAAA,CAAS,CAAC,CAAA;AAAA,MAC5E;AAAA,IACF;AAAA,GACD,CAAA;AACH","file":"chunk-I2M533CW.js","sourcesContent":["/**\n * @sonordev/site-kit/signal - SignalExperiment\n * \n * A/B test component that renders different variants based on Signal assignment.\n * Uses Thompson Sampling (Bayesian bandit) for optimization.\n */\n\n'use client'\n\nimport React, { useMemo, useEffect } from 'react'\nimport { useSignalExperiment, useSignalEvent } from './SignalBridge'\n\ninterface SignalExperimentProps {\n /** Unique experiment ID */\n experimentId: string\n \n /** Variants to test - keys are variant names, values are React nodes */\n variants: Record<string, React.ReactNode>\n \n /** Fallback content if no assignment (defaults to 'control' variant) */\n fallback?: React.ReactNode\n \n /** Track impression automatically */\n trackImpression?: boolean\n \n /** Children function for more control */\n children?: (props: { variant: string; isControl: boolean }) => React.ReactNode\n}\n\n/**\n * Renders different content variants based on Signal's A/B assignment.\n * \n * @example\n * // Simple variant switching\n * <SignalExperiment experimentId=\"hero-cta\" variants={{\n * control: <Button>Get Started</Button>,\n * variant_a: <Button variant=\"primary\">Start Free Trial</Button>,\n * variant_b: <Button variant=\"secondary\">Book a Demo</Button>,\n * }} />\n * \n * @example\n * // With render prop for more control\n * <SignalExperiment experimentId=\"pricing-layout\">\n * {({ variant, isControl }) => (\n * <PricingSection layout={isControl ? 'cards' : 'table'} />\n * )}\n * </SignalExperiment>\n */\nexport function SignalExperiment({\n experimentId,\n variants,\n fallback,\n trackImpression = true,\n children,\n}: SignalExperimentProps) {\n const { assignment, variant, isControl } = useSignalExperiment(experimentId)\n const trackEvent = useSignalEvent()\n \n // Track impression when variant is rendered\n useEffect(() => {\n if (trackImpression && variant) {\n trackEvent({\n event_type: 'experiment',\n event_name: 'impression',\n event_data: {\n experiment_id: experimentId,\n variant_key: variant,\n },\n })\n }\n }, [experimentId, variant, trackImpression, trackEvent])\n \n // If using render prop\n if (children) {\n return <>{children({ variant: variant || 'control', isControl })}</>\n }\n \n // Determine what to render\n const selectedVariant = variant || 'control'\n const content = variants[selectedVariant]\n \n if (content !== undefined) {\n return <>{content}</>\n }\n \n // Fallback to provided fallback or control\n if (fallback) {\n return <>{fallback}</>\n }\n \n return <>{variants.control || null}</>\n}\n\n/**\n * Hook for conditional experiment logic\n * \n * @example\n * const { variant, isControl } = useExperimentVariant('pricing-test')\n * \n * return isControl \n * ? <OldPricing />\n * : <NewPricing showAnnual={variant === 'annual_first'} />\n */\nexport function useExperimentVariant(experimentId: string) {\n return useSignalExperiment(experimentId)\n}\n\n/**\n * Component for tracking experiment conversions\n * Wraps interactive elements to track when they convert\n * \n * @example\n * <SignalExperiment experimentId=\"signup-button\" variants={{\n * control: (\n * <ExperimentConversion experimentId=\"signup-button\" outcomeType=\"click\">\n * <Button>Sign Up</Button>\n * </ExperimentConversion>\n * ),\n * variant_a: (\n * <ExperimentConversion experimentId=\"signup-button\" outcomeType=\"click\">\n * <Button variant=\"large\">Join Now - It's Free!</Button>\n * </ExperimentConversion>\n * ),\n * }} />\n */\nexport function ExperimentConversion({\n experimentId,\n outcomeType = 'click',\n value,\n children,\n}: {\n experimentId: string\n outcomeType?: string\n value?: number\n children: React.ReactElement<{ onClick?: (e: React.MouseEvent) => void }>\n}) {\n const trackEvent = useSignalEvent()\n const { variant } = useSignalExperiment(experimentId)\n\n const handleInteraction = () => {\n trackEvent({\n event_type: 'experiment',\n event_name: 'conversion',\n event_data: {\n experiment_id: experimentId,\n variant_key: variant,\n outcome_type: outcomeType,\n value,\n },\n })\n }\n\n return React.cloneElement(children, {\n onClick: (e: React.MouseEvent) => {\n handleInteraction()\n // Call original onClick if exists\n if ((children.props as { onClick?: (e: React.MouseEvent) => void }).onClick) {\n (children.props as { onClick?: (e: React.MouseEvent) => void }).onClick!(e)\n }\n },\n })\n}\n"]}
@@ -1,9 +1,8 @@
1
1
  'use client';
2
+ import { sonorFetch } from './chunk-FO6Y27AH.mjs';
2
3
  import { useState, useRef, useMemo, useEffect, useCallback } from 'react';
3
4
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
4
5
 
5
- // src/sync/BookingWidget.tsx
6
-
7
6
  // src/sync/api.ts
8
7
  var DEFAULT_API_URL = "https://api.sonor.io";
9
8
  function getApiConfig() {
@@ -11,10 +10,9 @@ function getApiConfig() {
11
10
  const apiKey = typeof window !== "undefined" ? window.__SITE_KIT_API_KEY__ : void 0;
12
11
  return { apiUrl, apiKey };
13
12
  }
14
- function buildHeaders(apiKey, isPost = false) {
13
+ function buildHeaders(isPost = false) {
15
14
  const headers = {};
16
15
  if (isPost) headers["Content-Type"] = "application/json";
17
- if (apiKey) headers["x-api-key"] = apiKey;
18
16
  return headers;
19
17
  }
20
18
  async function fetchBookingTypes(orgSlug, apiUrl, apiKey) {
@@ -22,7 +20,7 @@ async function fetchBookingTypes(orgSlug, apiUrl, apiKey) {
22
20
  const url = apiUrl || cfg.apiUrl;
23
21
  const key = apiKey || cfg.apiKey;
24
22
  const endpoint = key ? `${url}/sync/widget/types` : `${url}/sync/public/${orgSlug}/types`;
25
- const response = await fetch(endpoint, { headers: buildHeaders(key) });
23
+ const response = await sonorFetch(endpoint, { headers: buildHeaders() }, { apiKey: key, retries: 0 });
26
24
  if (!response.ok) {
27
25
  const msg = await response.json().catch(() => ({ message: response.statusText }));
28
26
  const detail = msg && typeof msg.message === "string" ? msg.message : response.statusText;
@@ -36,7 +34,7 @@ async function fetchBookingTypeDetails(typeSlug, orgSlug, apiUrl, apiKey) {
36
34
  const url = apiUrl || cfg.apiUrl;
37
35
  const key = apiKey || cfg.apiKey;
38
36
  const endpoint = key ? `${url}/sync/widget/types/${typeSlug}` : `${url}/sync/public/${orgSlug}/types/${typeSlug}`;
39
- const response = await fetch(endpoint, { headers: buildHeaders(key) });
37
+ const response = await sonorFetch(endpoint, { headers: buildHeaders() }, { apiKey: key, retries: 0 });
40
38
  if (!response.ok) {
41
39
  const msg = await response.json().catch(() => ({ message: response.statusText }));
42
40
  const detail = msg && typeof msg.message === "string" ? msg.message : response.statusText;
@@ -52,7 +50,7 @@ async function fetchAvailability(typeSlug, date, orgSlug, apiUrl, apiKey, timezo
52
50
  if (timezone) params.append("timezone", timezone);
53
51
  if (hostId) params.append("hostId", hostId);
54
52
  const endpoint = key ? `${url}/sync/widget/availability/${typeSlug}?${params}` : `${url}/sync/public/${orgSlug}/availability/${typeSlug}?${params}`;
55
- const response = await fetch(endpoint, { headers: buildHeaders(key) });
53
+ const response = await sonorFetch(endpoint, { headers: buildHeaders() }, { apiKey: key, retries: 0 });
56
54
  if (!response.ok) {
57
55
  const msg = await response.json().catch(() => ({ message: response.statusText }));
58
56
  let detail = msg && typeof msg.message === "string" ? String(msg.message).trim() : (response.statusText || "").trim();
@@ -75,11 +73,11 @@ async function createSlotHold(holdData, apiUrl, apiKey) {
75
73
  const url = apiUrl || cfg.apiUrl;
76
74
  const key = apiKey || cfg.apiKey;
77
75
  const endpoint = key ? `${url}/sync/widget/hold` : `${url}/sync/public/hold`;
78
- const response = await fetch(endpoint, {
76
+ const response = await sonorFetch(endpoint, {
79
77
  method: "POST",
80
- headers: buildHeaders(key, true),
78
+ headers: buildHeaders(true),
81
79
  body: JSON.stringify(holdData)
82
- });
80
+ }, { apiKey: key, retries: 0 });
83
81
  if (!response.ok) {
84
82
  throw new Error(`Failed to hold slot: ${response.statusText}`);
85
83
  }
@@ -90,21 +88,21 @@ async function releaseSlotHold(holdId, apiUrl, apiKey) {
90
88
  const url = apiUrl || cfg.apiUrl;
91
89
  const key = apiKey || cfg.apiKey;
92
90
  const endpoint = key ? `${url}/sync/widget/hold/${holdId}` : `${url}/sync/public/hold/${holdId}`;
93
- await fetch(endpoint, {
91
+ await sonorFetch(endpoint, {
94
92
  method: "DELETE",
95
- headers: buildHeaders(key)
96
- });
93
+ headers: buildHeaders()
94
+ }, { apiKey: key, retries: 0 });
97
95
  }
98
96
  async function createBooking(bookingData, apiUrl, apiKey) {
99
97
  const cfg = getApiConfig();
100
98
  const url = apiUrl || cfg.apiUrl;
101
99
  const key = apiKey || cfg.apiKey;
102
100
  const endpoint = key ? `${url}/sync/widget/booking` : `${url}/sync/public/booking`;
103
- const response = await fetch(endpoint, {
101
+ const response = await sonorFetch(endpoint, {
104
102
  method: "POST",
105
- headers: buildHeaders(key, true),
103
+ headers: buildHeaders(true),
106
104
  body: JSON.stringify(bookingData)
107
- });
105
+ }, { apiKey: key, retries: 0 });
108
106
  if (!response.ok) {
109
107
  const errorData = await response.json().catch(() => ({}));
110
108
  throw new Error(errorData.message || `Failed to create booking: ${response.statusText}`);
@@ -125,7 +123,7 @@ async function fetchAvailableDates(typeSlug, startDate, endDate, orgSlug, apiUrl
125
123
  }
126
124
  } catch {
127
125
  }
128
- current.setDate(current.getDate() + 1);
126
+ current.setUTCDate(current.getUTCDate() + 1);
129
127
  }
130
128
  return availableDates;
131
129
  }
@@ -198,6 +196,12 @@ function calendarDays(year, month) {
198
196
  for (let d = 1; d <= last.getDate(); d++) cells.push(new Date(year, month, d));
199
197
  return cells;
200
198
  }
199
+ function toLocalDateStr(d) {
200
+ const y = d.getFullYear();
201
+ const m = String(d.getMonth() + 1).padStart(2, "0");
202
+ const day = String(d.getDate()).padStart(2, "0");
203
+ return `${y}-${m}-${day}`;
204
+ }
201
205
  function ChevronLeft() {
202
206
  return /* @__PURE__ */ jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx("path", { d: "M12.5 15L7.5 10L12.5 5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) });
203
207
  }
@@ -251,6 +255,7 @@ function BookingWidget({
251
255
  onBookingComplete,
252
256
  onError,
253
257
  hideTypeSelector = false,
258
+ autoSelectFirstDay = true,
254
259
  styles = {}
255
260
  }) {
256
261
  const apiKey = propApiKey || (typeof window !== "undefined" ? window.__SITE_KIT_API_KEY__ : void 0);
@@ -270,6 +275,9 @@ function BookingWidget({
270
275
  const [guestInfo, setGuestInfo] = useState({ name: "", email: "" });
271
276
  const [bookingResult, setBookingResult] = useState(null);
272
277
  const [submitting, setSubmitting] = useState(false);
278
+ const [autoProbing, setAutoProbing] = useState(false);
279
+ const probeRef = useRef(0);
280
+ const prefetchedRef = useRef(null);
273
281
  const slotsRef = useRef(null);
274
282
  const today = useMemo(() => {
275
283
  const d = /* @__PURE__ */ new Date();
@@ -311,16 +319,57 @@ function BookingWidget({
311
319
  }, [orgSlug, apiKey, bookingTypeSlug, apiUrl, onError]);
312
320
  useEffect(() => {
313
321
  if (!selectedDate || !selectedType) return;
314
- const dateStr = selectedDate.toISOString().split("T")[0];
315
- setSlotsLoading(true);
316
- setSlots([]);
322
+ const dateStr = toLocalDateStr(selectedDate);
317
323
  setSelectedSlot(null);
318
324
  setConfirmedSlot(false);
325
+ const prefetched = prefetchedRef.current;
326
+ if (prefetched && prefetched.dateStr === dateStr) {
327
+ prefetchedRef.current = null;
328
+ setSlots(prefetched.slots);
329
+ setSlotsLoading(false);
330
+ return;
331
+ }
332
+ setSlotsLoading(true);
333
+ setSlots([]);
319
334
  fetchAvailability(selectedType.slug, dateStr, orgSlug, apiUrl, apiKey, timezone).then((s) => setSlots(s.filter((slot) => slot.available))).catch((err) => {
320
335
  setError(err.message);
321
336
  onError?.(err);
322
337
  }).finally(() => setSlotsLoading(false));
323
338
  }, [selectedDate, selectedType, orgSlug, apiKey, apiUrl, timezone, onError]);
339
+ useEffect(() => {
340
+ if (!autoSelectFirstDay || !selectedType || selectedDate) return;
341
+ const probeId = ++probeRef.current;
342
+ let cancelled = false;
343
+ const PROBE_DAYS = 14;
344
+ const startOffset = Math.floor((selectedType.min_notice_hours || 0) / 24);
345
+ (async () => {
346
+ setAutoProbing(true);
347
+ try {
348
+ for (let i = startOffset; i < startOffset + PROBE_DAYS; i++) {
349
+ const d = new Date(today);
350
+ d.setDate(d.getDate() + i);
351
+ if (d > maxDate) break;
352
+ const dateStr = toLocalDateStr(d);
353
+ const s = await fetchAvailability(selectedType.slug, dateStr, orgSlug, apiUrl, apiKey, timezone);
354
+ if (cancelled || probeRef.current !== probeId) return;
355
+ const open = s.filter((slot) => slot.available);
356
+ if (open.length > 0) {
357
+ prefetchedRef.current = { dateStr, slots: open };
358
+ setViewMonth(new Date(d.getFullYear(), d.getMonth(), 1));
359
+ setSelectedDate(d);
360
+ return;
361
+ }
362
+ }
363
+ } catch {
364
+ } finally {
365
+ if (!cancelled && probeRef.current === probeId) setAutoProbing(false);
366
+ }
367
+ })();
368
+ return () => {
369
+ cancelled = true;
370
+ setAutoProbing(false);
371
+ };
372
+ }, [autoSelectFirstDay, selectedType, selectedDate, orgSlug, apiKey, apiUrl, timezone, today, maxDate]);
324
373
  const handleSlotSelect = useCallback((slot) => {
325
374
  setSelectedSlot(slot);
326
375
  setConfirmedSlot(false);
@@ -412,7 +461,7 @@ function BookingWidget({
412
461
  const cssVars = {
413
462
  "--sk-primary": styles.primaryColor || "#0069ff",
414
463
  "--sk-primary-hover": styles.primaryColor ? `color-mix(in srgb, ${styles.primaryColor} 90%, black)` : "#0055d4",
415
- "--sk-primary-light": styles.primaryColor ? `color-mix(in srgb, ${styles.primaryColor} 12%, white)` : "#e8f1ff",
464
+ "--sk-primary-light": styles.primaryColor ? `color-mix(in srgb, ${styles.primaryColor} 12%, ${styles.backgroundColor || "white"})` : "#e8f1ff",
416
465
  "--sk-bg": styles.backgroundColor || "#ffffff",
417
466
  "--sk-bg-elevated": styles.elevatedColor || "#f9fafb",
418
467
  "--sk-surface": styles.surfaceColor || "#f3f4f6",
@@ -420,9 +469,9 @@ function BookingWidget({
420
469
  "--sk-text-secondary": styles.textSecondary || "#6b7280",
421
470
  "--sk-text-tertiary": styles.textTertiary || "#9ca3af",
422
471
  "--sk-border": styles.borderColor || "#e5e7eb",
423
- "--sk-error": "#ef4444",
424
- "--sk-success": "#10b981",
425
- "--sk-warning": "#f59e0b",
472
+ "--sk-error": "#dc2626",
473
+ "--sk-success": "#047857",
474
+ "--sk-warning": "#b45309",
426
475
  "--sk-radius": styles.borderRadius || "8px",
427
476
  "--sk-font": styles.fontFamily || "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",
428
477
  "--sk-input-border": styles.inputBorderColor || styles.borderColor || "#e5e7eb",
@@ -517,12 +566,15 @@ function BookingWidget({
517
566
  );
518
567
  }) })
519
568
  ] }),
520
- /* @__PURE__ */ jsx("div", { className: `bw-times${selectedDate ? " visible" : ""}`, ref: slotsRef, children: !selectedDate ? /* @__PURE__ */ jsxs("div", { className: "bw-times-placeholder", children: [
569
+ /* @__PURE__ */ jsx("div", { className: `bw-times${selectedDate ? " visible" : ""}`, ref: slotsRef, children: !selectedDate ? autoProbing ? /* @__PURE__ */ jsxs("div", { className: "bw-times-skeleton", "aria-hidden": "true", children: [
570
+ /* @__PURE__ */ jsx("div", { className: "bw-skel-line" }),
571
+ [0, 1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx("div", { className: "bw-skel-slot" }, i))
572
+ ] }) : /* @__PURE__ */ jsxs("div", { className: "bw-times-placeholder", children: [
521
573
  /* @__PURE__ */ jsx(CalendarPlusIcon, {}),
522
574
  /* @__PURE__ */ jsx("span", { children: "Select a date to view available times" })
523
- ] }) : slotsLoading ? /* @__PURE__ */ jsxs("div", { className: "bw-loading", children: [
524
- /* @__PURE__ */ jsx(SpinnerIcon, {}),
525
- " Loading times..."
575
+ ] }) : slotsLoading ? /* @__PURE__ */ jsxs("div", { className: "bw-times-skeleton", "aria-hidden": "true", children: [
576
+ /* @__PURE__ */ jsx("div", { className: "bw-skel-line" }),
577
+ [0, 1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx("div", { className: "bw-skel-slot" }, i))
526
578
  ] }) : slots.length === 0 ? /* @__PURE__ */ jsx("div", { className: "bw-times-empty", children: "No available times on this date. Try another day." }) : /* @__PURE__ */ jsxs("div", { className: "bw-times-scroll", children: [
527
579
  /* @__PURE__ */ jsx("p", { className: "bw-times-date", children: selectedDate.toLocaleDateString("en-US", { weekday: "long", month: "short", day: "numeric" }) }),
528
580
  groupedSlots.morning.length > 0 && /* @__PURE__ */ jsxs("div", { className: "bw-time-group", children: [
@@ -788,13 +840,34 @@ var WIDGET_CSS = `
788
840
  /* \u2500\u2500 Animation \u2500\u2500 */
789
841
  @keyframes bw-fade-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
790
842
  @keyframes bw-spin { to { transform: rotate(360deg); } }
843
+ @keyframes bw-shimmer { to { background-position: -200% 0; } }
791
844
  .bw-fade-in { animation: bw-fade-in 0.25s ease-out; }
792
845
  .bw-spinner { animation: bw-spin 0.8s linear infinite; }
793
846
 
847
+ /* \u2500\u2500 Accessibility \u2500\u2500 */
848
+ .bw-root :is(button, a):focus-visible { outline: 2px solid var(--sk-primary); outline-offset: 2px; }
849
+ @media (prefers-reduced-motion: reduce) {
850
+ .bw-fade-in, .bw-skel-slot, .bw-skel-line { animation: none; }
851
+ }
852
+
853
+ /* \u2500\u2500 Loading skeleton (time slots) \u2500\u2500 */
854
+ .bw-skel-line {
855
+ height: 14px; width: 70%; margin-bottom: 14px; border-radius: 4px;
856
+ background: linear-gradient(90deg, var(--sk-surface) 25%, var(--sk-bg-elevated) 50%, var(--sk-surface) 75%);
857
+ background-size: 200% 100%; animation: bw-shimmer 1.1s linear infinite;
858
+ }
859
+ .bw-skel-slot {
860
+ height: 44px; margin-bottom: 6px; border-radius: var(--sk-radius);
861
+ background: linear-gradient(90deg, var(--sk-surface) 25%, var(--sk-bg-elevated) 50%, var(--sk-surface) 75%);
862
+ background-size: 200% 100%; animation: bw-shimmer 1.1s linear infinite;
863
+ }
864
+
794
865
  /* \u2500\u2500 Error \u2500\u2500 */
795
866
  .bw-error {
796
867
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
797
- background: #fef2f2; border: 1px solid #fecaca; color: #b91c1c;
868
+ background: color-mix(in srgb, var(--sk-error) 10%, var(--sk-bg));
869
+ border: 1px solid color-mix(in srgb, var(--sk-error) 35%, var(--sk-bg));
870
+ color: var(--sk-error);
798
871
  padding: 10px 14px; border-radius: var(--sk-radius); margin-bottom: 16px; font-size: 0.875rem;
799
872
  }
800
873
  .bw-error button { background: none; border: none; color: inherit; cursor: pointer; font-size: 1.25rem; line-height: 1; padding: 0; }
@@ -910,7 +983,7 @@ var WIDGET_CSS = `
910
983
  .bw-time-label { display: block; font-size: 0.6875rem; font-weight: 600; color: var(--sk-text-tertiary); text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: 6px; }
911
984
 
912
985
  .bw-time-btn {
913
- display: block; width: 100%;
986
+ display: block; width: 100%; min-height: 44px;
914
987
  padding: 10px 12px; margin-bottom: 6px;
915
988
  border: 1.5px solid var(--sk-border); border-radius: var(--sk-radius);
916
989
  background: var(--sk-bg); cursor: pointer;
@@ -936,7 +1009,7 @@ var WIDGET_CSS = `
936
1009
  }
937
1010
  .bw-time-confirm {
938
1011
  display: inline-flex; align-items: center; justify-content: center; gap: 4px;
939
- padding: 10px 16px; border: none;
1012
+ min-height: 44px; padding: 10px 16px; border: none;
940
1013
  background: var(--sk-primary); color: #fff;
941
1014
  font-size: 0.8125rem; font-weight: 600; cursor: pointer;
942
1015
  transition: background 0.15s;
@@ -969,7 +1042,7 @@ var WIDGET_CSS = `
969
1042
  }
970
1043
  .bw-submit {
971
1044
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
972
- width: 100%; padding: 14px; margin-top: 4px;
1045
+ width: 100%; min-height: 48px; padding: 14px; margin-top: 4px;
973
1046
  background: var(--sk-primary); color: #fff; border: none;
974
1047
  border-radius: var(--sk-radius); font-size: 0.9375rem; font-weight: 600;
975
1048
  cursor: pointer; transition: background 0.15s;
@@ -1014,5 +1087,5 @@ var WIDGET_CSS = `
1014
1087
  `;
1015
1088
 
1016
1089
  export { BookingWidget, createBooking, createSlotHold, detectTimezone, fetchAvailability, fetchAvailableDates, fetchBookingTypeDetails, fetchBookingTypes, formatDate, formatDuration, formatTime, releaseSlotHold };
1017
- //# sourceMappingURL=chunk-FMZOZQBV.mjs.map
1018
- //# sourceMappingURL=chunk-FMZOZQBV.mjs.map
1090
+ //# sourceMappingURL=chunk-ILLOVVVP.mjs.map
1091
+ //# sourceMappingURL=chunk-ILLOVVVP.mjs.map