@swift-food-services/catering-widget 0.2.0-beta.2 → 0.2.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1542 -429
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +1545 -432
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -150,6 +150,7 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
|
|
|
150
150
|
--color-orange-800:oklch(47% .157 37.304);
|
|
151
151
|
--color-amber-50:oklch(98.7% .022 95.277);
|
|
152
152
|
--color-amber-100:oklch(96.2% .059 95.617);
|
|
153
|
+
--color-amber-400:oklch(82.8% .189 84.429);
|
|
153
154
|
--color-amber-500:oklch(76.9% .188 70.08);
|
|
154
155
|
--color-amber-600:oklch(66.6% .179 58.318);
|
|
155
156
|
--color-amber-700:oklch(55.5% .163 48.998);
|
|
@@ -158,6 +159,7 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
|
|
|
158
159
|
--color-green-50:oklch(98.2% .018 155.826);
|
|
159
160
|
--color-green-100:oklch(96.2% .044 156.743);
|
|
160
161
|
--color-green-200:oklch(92.5% .084 155.995);
|
|
162
|
+
--color-green-300:oklch(87.1% .15 154.449);
|
|
161
163
|
--color-green-400:oklch(79.2% .209 151.711);
|
|
162
164
|
--color-green-500:oklch(72.3% .219 149.579);
|
|
163
165
|
--color-green-600:oklch(62.7% .194 149.214);
|
|
@@ -184,6 +186,7 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
|
|
|
184
186
|
--color-white:#fff;
|
|
185
187
|
--spacing:.25rem;
|
|
186
188
|
--container-xs:20rem;
|
|
189
|
+
--container-sm:24rem;
|
|
187
190
|
--container-md:28rem;
|
|
188
191
|
--container-lg:32rem;
|
|
189
192
|
--container-2xl:42rem;
|
|
@@ -2987,6 +2990,49 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
|
|
|
2987
2990
|
z-index: 3;
|
|
2988
2991
|
width: 100%;
|
|
2989
2992
|
}
|
|
2993
|
+
.swift-catering-widget .hero {
|
|
2994
|
+
background-position: 50%;
|
|
2995
|
+
background-size: cover;
|
|
2996
|
+
place-items: center;
|
|
2997
|
+
width: 100%;
|
|
2998
|
+
display: grid;
|
|
2999
|
+
}
|
|
3000
|
+
.swift-catering-widget .hero > * {
|
|
3001
|
+
grid-row-start: 1;
|
|
3002
|
+
grid-column-start: 1;
|
|
3003
|
+
}
|
|
3004
|
+
.swift-catering-widget .divider {
|
|
3005
|
+
white-space: nowrap;
|
|
3006
|
+
height: 1rem;
|
|
3007
|
+
margin: var(--divider-m,1rem 0);
|
|
3008
|
+
--divider-color:var(--color-base-content);
|
|
3009
|
+
flex-direction: row;
|
|
3010
|
+
align-self: stretch;
|
|
3011
|
+
align-items: center;
|
|
3012
|
+
display: flex;
|
|
3013
|
+
}
|
|
3014
|
+
@supports (color:color-mix(in lab, red, red)) {
|
|
3015
|
+
.swift-catering-widget .divider {
|
|
3016
|
+
--divider-color:color-mix(in oklab, var(--color-base-content) 10%, transparent);
|
|
3017
|
+
}
|
|
3018
|
+
}
|
|
3019
|
+
.swift-catering-widget .divider:before,
|
|
3020
|
+
.swift-catering-widget .divider:after {
|
|
3021
|
+
content: "";
|
|
3022
|
+
background-color: var(--divider-color);
|
|
3023
|
+
flex-grow: 1;
|
|
3024
|
+
width: 100%;
|
|
3025
|
+
height: .125rem;
|
|
3026
|
+
}
|
|
3027
|
+
@media print {
|
|
3028
|
+
.swift-catering-widget .divider:before,
|
|
3029
|
+
.swift-catering-widget .divider:after {
|
|
3030
|
+
border: .5px solid;
|
|
3031
|
+
}
|
|
3032
|
+
}
|
|
3033
|
+
.swift-catering-widget .divider:not(:empty) {
|
|
3034
|
+
gap: 1rem;
|
|
3035
|
+
}
|
|
2990
3036
|
.swift-catering-widget .filter {
|
|
2991
3037
|
flex-wrap: wrap;
|
|
2992
3038
|
display: flex;
|
|
@@ -4154,15 +4200,18 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
|
|
|
4154
4200
|
.swift-catering-widget .max-w-7xl {
|
|
4155
4201
|
max-width: var(--container-7xl);
|
|
4156
4202
|
}
|
|
4203
|
+
.swift-catering-widget .max-w-\\[60\\%\\] {
|
|
4204
|
+
max-width: 60%;
|
|
4205
|
+
}
|
|
4157
4206
|
.swift-catering-widget .max-w-\\[100vw\\] {
|
|
4158
4207
|
max-width: 100vw;
|
|
4159
4208
|
}
|
|
4209
|
+
.swift-catering-widget .max-w-\\[260px\\] {
|
|
4210
|
+
max-width: 260px;
|
|
4211
|
+
}
|
|
4160
4212
|
.swift-catering-widget .max-w-\\[280px\\] {
|
|
4161
4213
|
max-width: 280px;
|
|
4162
4214
|
}
|
|
4163
|
-
.swift-catering-widget .max-w-\\[325px\\] {
|
|
4164
|
-
max-width: 325px;
|
|
4165
|
-
}
|
|
4166
4215
|
.swift-catering-widget .max-w-\\[350px\\] {
|
|
4167
4216
|
max-width: 350px;
|
|
4168
4217
|
}
|
|
@@ -4178,12 +4227,18 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
|
|
|
4178
4227
|
.swift-catering-widget .max-w-min {
|
|
4179
4228
|
max-width: min-content;
|
|
4180
4229
|
}
|
|
4230
|
+
.swift-catering-widget .max-w-sm {
|
|
4231
|
+
max-width: var(--container-sm);
|
|
4232
|
+
}
|
|
4181
4233
|
.swift-catering-widget .max-w-xs {
|
|
4182
4234
|
max-width: var(--container-xs);
|
|
4183
4235
|
}
|
|
4184
4236
|
.swift-catering-widget .min-w-0 {
|
|
4185
4237
|
min-width: calc(var(--spacing) * 0);
|
|
4186
4238
|
}
|
|
4239
|
+
.swift-catering-widget .min-w-\\[3\\.5rem\\] {
|
|
4240
|
+
min-width: 3.5rem;
|
|
4241
|
+
}
|
|
4187
4242
|
.swift-catering-widget .min-w-\\[44px\\] {
|
|
4188
4243
|
min-width: 44px;
|
|
4189
4244
|
}
|
|
@@ -4284,9 +4339,15 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
|
|
|
4284
4339
|
.swift-catering-widget .cursor-pointer {
|
|
4285
4340
|
cursor: pointer;
|
|
4286
4341
|
}
|
|
4342
|
+
.swift-catering-widget .touch-auto {
|
|
4343
|
+
touch-action: auto;
|
|
4344
|
+
}
|
|
4287
4345
|
.swift-catering-widget .touch-manipulation {
|
|
4288
4346
|
touch-action: manipulation;
|
|
4289
4347
|
}
|
|
4348
|
+
.swift-catering-widget .touch-none {
|
|
4349
|
+
touch-action: none;
|
|
4350
|
+
}
|
|
4290
4351
|
.swift-catering-widget .resize {
|
|
4291
4352
|
resize: both;
|
|
4292
4353
|
}
|
|
@@ -4763,14 +4824,6 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
|
|
|
4763
4824
|
.swift-catering-widget .bg-base-content {
|
|
4764
4825
|
background-color: var(--color-base-content);
|
|
4765
4826
|
}
|
|
4766
|
-
.swift-catering-widget .bg-black\\/20 {
|
|
4767
|
-
background-color: #0003;
|
|
4768
|
-
}
|
|
4769
|
-
@supports (color:color-mix(in lab, red, red)) {
|
|
4770
|
-
.swift-catering-widget .bg-black\\/20 {
|
|
4771
|
-
background-color: color-mix(in oklab, var(--color-black) 20%, transparent);
|
|
4772
|
-
}
|
|
4773
|
-
}
|
|
4774
4827
|
.swift-catering-widget .bg-black\\/30 {
|
|
4775
4828
|
background-color: #0000004d;
|
|
4776
4829
|
}
|
|
@@ -4795,6 +4848,14 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
|
|
|
4795
4848
|
background-color: color-mix(in oklab, var(--color-black) 50%, transparent);
|
|
4796
4849
|
}
|
|
4797
4850
|
}
|
|
4851
|
+
.swift-catering-widget .bg-black\\/60 {
|
|
4852
|
+
background-color: #0009;
|
|
4853
|
+
}
|
|
4854
|
+
@supports (color:color-mix(in lab, red, red)) {
|
|
4855
|
+
.swift-catering-widget .bg-black\\/60 {
|
|
4856
|
+
background-color: color-mix(in oklab, var(--color-black) 60%, transparent);
|
|
4857
|
+
}
|
|
4858
|
+
}
|
|
4798
4859
|
.swift-catering-widget .bg-black\\/95 {
|
|
4799
4860
|
background-color: #000000f2;
|
|
4800
4861
|
}
|
|
@@ -4844,6 +4905,14 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
|
|
|
4844
4905
|
background-color: color-mix(in oklab, var(--color-gray-900) 30%, transparent);
|
|
4845
4906
|
}
|
|
4846
4907
|
}
|
|
4908
|
+
.swift-catering-widget .bg-gray-900\\/40 {
|
|
4909
|
+
background-color: #10182866;
|
|
4910
|
+
}
|
|
4911
|
+
@supports (color:color-mix(in lab, red, red)) {
|
|
4912
|
+
.swift-catering-widget .bg-gray-900\\/40 {
|
|
4913
|
+
background-color: color-mix(in oklab, var(--color-gray-900) 40%, transparent);
|
|
4914
|
+
}
|
|
4915
|
+
}
|
|
4847
4916
|
.swift-catering-widget .bg-gray-900\\/50 {
|
|
4848
4917
|
background-color: #10182880;
|
|
4849
4918
|
}
|
|
@@ -5097,6 +5166,12 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
|
|
|
5097
5166
|
--tw-gradient-to:var(--color-purple-600);
|
|
5098
5167
|
--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
|
|
5099
5168
|
}
|
|
5169
|
+
.swift-catering-widget .fill-amber-400 {
|
|
5170
|
+
fill: var(--color-amber-400);
|
|
5171
|
+
}
|
|
5172
|
+
.swift-catering-widget .fill-transparent {
|
|
5173
|
+
fill: #0000;
|
|
5174
|
+
}
|
|
5100
5175
|
.swift-catering-widget .object-contain {
|
|
5101
5176
|
object-fit: contain;
|
|
5102
5177
|
}
|
|
@@ -5124,6 +5199,9 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
|
|
|
5124
5199
|
.swift-catering-widget .p-4 {
|
|
5125
5200
|
padding: calc(var(--spacing) * 4);
|
|
5126
5201
|
}
|
|
5202
|
+
.swift-catering-widget .p-5 {
|
|
5203
|
+
padding: calc(var(--spacing) * 5);
|
|
5204
|
+
}
|
|
5127
5205
|
.swift-catering-widget .p-6 {
|
|
5128
5206
|
padding: calc(var(--spacing) * 6);
|
|
5129
5207
|
}
|
|
@@ -5241,6 +5319,9 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
|
|
|
5241
5319
|
.swift-catering-widget .pb-1 {
|
|
5242
5320
|
padding-bottom: calc(var(--spacing) * 1);
|
|
5243
5321
|
}
|
|
5322
|
+
.swift-catering-widget .pb-1\\.5 {
|
|
5323
|
+
padding-bottom: calc(var(--spacing) * 1.5);
|
|
5324
|
+
}
|
|
5244
5325
|
.swift-catering-widget .pb-2 {
|
|
5245
5326
|
padding-bottom: calc(var(--spacing) * 2);
|
|
5246
5327
|
}
|
|
@@ -5413,6 +5494,9 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
|
|
|
5413
5494
|
.swift-catering-widget .whitespace-pre-wrap {
|
|
5414
5495
|
white-space: pre-wrap;
|
|
5415
5496
|
}
|
|
5497
|
+
.swift-catering-widget .text-amber-400 {
|
|
5498
|
+
color: var(--color-amber-400);
|
|
5499
|
+
}
|
|
5416
5500
|
.swift-catering-widget .text-amber-600 {
|
|
5417
5501
|
color: var(--color-amber-600);
|
|
5418
5502
|
}
|
|
@@ -5509,6 +5593,9 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
|
|
|
5509
5593
|
.swift-catering-widget .text-gray-900 {
|
|
5510
5594
|
color: var(--color-gray-900);
|
|
5511
5595
|
}
|
|
5596
|
+
.swift-catering-widget .text-green-300 {
|
|
5597
|
+
color: var(--color-green-300);
|
|
5598
|
+
}
|
|
5512
5599
|
.swift-catering-widget .text-green-500 {
|
|
5513
5600
|
color: var(--color-green-500);
|
|
5514
5601
|
}
|
|
@@ -5561,6 +5648,9 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
|
|
|
5561
5648
|
color: color-mix(in oklab, var(--color-primary) 60%, transparent);
|
|
5562
5649
|
}
|
|
5563
5650
|
}
|
|
5651
|
+
.swift-catering-widget .text-red-300 {
|
|
5652
|
+
color: var(--color-red-300);
|
|
5653
|
+
}
|
|
5564
5654
|
.swift-catering-widget .text-red-400 {
|
|
5565
5655
|
color: var(--color-red-400);
|
|
5566
5656
|
}
|
|
@@ -5588,6 +5678,30 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
|
|
|
5588
5678
|
.swift-catering-widget .text-white {
|
|
5589
5679
|
color: var(--color-white);
|
|
5590
5680
|
}
|
|
5681
|
+
.swift-catering-widget .text-white\\/40 {
|
|
5682
|
+
color: #fff6;
|
|
5683
|
+
}
|
|
5684
|
+
@supports (color:color-mix(in lab, red, red)) {
|
|
5685
|
+
.swift-catering-widget .text-white\\/40 {
|
|
5686
|
+
color: color-mix(in oklab, var(--color-white) 40%, transparent);
|
|
5687
|
+
}
|
|
5688
|
+
}
|
|
5689
|
+
.swift-catering-widget .text-white\\/50 {
|
|
5690
|
+
color: #ffffff80;
|
|
5691
|
+
}
|
|
5692
|
+
@supports (color:color-mix(in lab, red, red)) {
|
|
5693
|
+
.swift-catering-widget .text-white\\/50 {
|
|
5694
|
+
color: color-mix(in oklab, var(--color-white) 50%, transparent);
|
|
5695
|
+
}
|
|
5696
|
+
}
|
|
5697
|
+
.swift-catering-widget .text-white\\/60 {
|
|
5698
|
+
color: #fff9;
|
|
5699
|
+
}
|
|
5700
|
+
@supports (color:color-mix(in lab, red, red)) {
|
|
5701
|
+
.swift-catering-widget .text-white\\/60 {
|
|
5702
|
+
color: color-mix(in oklab, var(--color-white) 60%, transparent);
|
|
5703
|
+
}
|
|
5704
|
+
}
|
|
5591
5705
|
.swift-catering-widget .text-white\\/70 {
|
|
5592
5706
|
color: #ffffffb3;
|
|
5593
5707
|
}
|
|
@@ -5596,6 +5710,14 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
|
|
|
5596
5710
|
color: color-mix(in oklab, var(--color-white) 70%, transparent);
|
|
5597
5711
|
}
|
|
5598
5712
|
}
|
|
5713
|
+
.swift-catering-widget .text-white\\/80 {
|
|
5714
|
+
color: #fffc;
|
|
5715
|
+
}
|
|
5716
|
+
@supports (color:color-mix(in lab, red, red)) {
|
|
5717
|
+
.swift-catering-widget .text-white\\/80 {
|
|
5718
|
+
color: color-mix(in oklab, var(--color-white) 80%, transparent);
|
|
5719
|
+
}
|
|
5720
|
+
}
|
|
5599
5721
|
.swift-catering-widget .text-white\\/90 {
|
|
5600
5722
|
color: #ffffffe6;
|
|
5601
5723
|
}
|
|
@@ -5766,6 +5888,11 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
|
|
|
5766
5888
|
-webkit-backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);
|
|
5767
5889
|
backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);
|
|
5768
5890
|
}
|
|
5891
|
+
.swift-catering-widget .backdrop-blur-\\[1px\\] {
|
|
5892
|
+
--tw-backdrop-blur:blur(1px);
|
|
5893
|
+
-webkit-backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);
|
|
5894
|
+
backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);
|
|
5895
|
+
}
|
|
5769
5896
|
.swift-catering-widget .backdrop-blur-lg {
|
|
5770
5897
|
--tw-backdrop-blur:blur(var(--blur-lg));
|
|
5771
5898
|
-webkit-backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);
|
|
@@ -5853,6 +5980,10 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
|
|
|
5853
5980
|
transition-timing-function: var(--tw-ease,var(--default-transition-timing-function));
|
|
5854
5981
|
transition-duration: var(--tw-duration,var(--default-transition-duration));
|
|
5855
5982
|
}
|
|
5983
|
+
.swift-catering-widget .duration-150 {
|
|
5984
|
+
--tw-duration:.15s;
|
|
5985
|
+
transition-duration: .15s;
|
|
5986
|
+
}
|
|
5856
5987
|
.swift-catering-widget .duration-200 {
|
|
5857
5988
|
--tw-duration:.2s;
|
|
5858
5989
|
transition-duration: .2s;
|
|
@@ -5957,6 +6088,12 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
|
|
|
5957
6088
|
--tw-scale-z:105%;
|
|
5958
6089
|
scale: var(--tw-scale-x) var(--tw-scale-y);
|
|
5959
6090
|
}
|
|
6091
|
+
.swift-catering-widget .hover\\:scale-110:hover {
|
|
6092
|
+
--tw-scale-x:110%;
|
|
6093
|
+
--tw-scale-y:110%;
|
|
6094
|
+
--tw-scale-z:110%;
|
|
6095
|
+
scale: var(--tw-scale-x) var(--tw-scale-y);
|
|
6096
|
+
}
|
|
5960
6097
|
.swift-catering-widget .hover\\:border-base-content\\/20:hover {
|
|
5961
6098
|
border-color: var(--color-base-content);
|
|
5962
6099
|
}
|
|
@@ -6013,6 +6150,14 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
|
|
|
6013
6150
|
background-color: color-mix(in oklab, var(--color-black) 5%, transparent);
|
|
6014
6151
|
}
|
|
6015
6152
|
}
|
|
6153
|
+
.swift-catering-widget .hover\\:bg-black\\/60:hover {
|
|
6154
|
+
background-color: #0009;
|
|
6155
|
+
}
|
|
6156
|
+
@supports (color:color-mix(in lab, red, red)) {
|
|
6157
|
+
.swift-catering-widget .hover\\:bg-black\\/60:hover {
|
|
6158
|
+
background-color: color-mix(in oklab, var(--color-black) 60%, transparent);
|
|
6159
|
+
}
|
|
6160
|
+
}
|
|
6016
6161
|
.swift-catering-widget .hover\\:bg-gray-50:hover {
|
|
6017
6162
|
background-color: var(--color-gray-50);
|
|
6018
6163
|
}
|
|
@@ -6176,6 +6321,9 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
|
|
|
6176
6321
|
.swift-catering-widget .hover\\:text-gray-300:hover {
|
|
6177
6322
|
color: var(--color-gray-300);
|
|
6178
6323
|
}
|
|
6324
|
+
.swift-catering-widget .hover\\:text-gray-500:hover {
|
|
6325
|
+
color: var(--color-gray-500);
|
|
6326
|
+
}
|
|
6179
6327
|
.swift-catering-widget .hover\\:text-gray-600:hover {
|
|
6180
6328
|
color: var(--color-gray-600);
|
|
6181
6329
|
}
|
|
@@ -6308,6 +6456,9 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
|
|
|
6308
6456
|
--tw-tracking:.08em;
|
|
6309
6457
|
letter-spacing: .08em;
|
|
6310
6458
|
}
|
|
6459
|
+
.swift-catering-widget .disabled\\:opacity-40:disabled {
|
|
6460
|
+
opacity: .4;
|
|
6461
|
+
}
|
|
6311
6462
|
.swift-catering-widget .disabled\\:opacity-50:disabled {
|
|
6312
6463
|
opacity: .5;
|
|
6313
6464
|
}
|
|
@@ -6699,10 +6850,16 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
|
|
|
6699
6850
|
.swift-catering-widget .md\\:text-\\[11px\\] {
|
|
6700
6851
|
font-size: 11px;
|
|
6701
6852
|
}
|
|
6853
|
+
.swift-catering-widget .md\\:opacity-0 {
|
|
6854
|
+
opacity: 0;
|
|
6855
|
+
}
|
|
6702
6856
|
@media (hover: hover) {
|
|
6703
6857
|
.swift-catering-widget .md\\:group-hover\\:block:is(:where(.group):hover *) {
|
|
6704
6858
|
display: block;
|
|
6705
6859
|
}
|
|
6860
|
+
.swift-catering-widget .md\\:group-hover\\/msg\\:opacity-100:is(:where(.group\\/msg):hover *) {
|
|
6861
|
+
opacity: 1;
|
|
6862
|
+
}
|
|
6706
6863
|
}
|
|
6707
6864
|
}
|
|
6708
6865
|
@media (min-width: 64rem) {
|
|
@@ -7401,6 +7558,19 @@ function createChatEndpoints(client) {
|
|
|
7401
7558
|
);
|
|
7402
7559
|
if (!res.ok) throw new ChatApiError(`HTTP ${res.status}`, res.status);
|
|
7403
7560
|
return res.json();
|
|
7561
|
+
},
|
|
7562
|
+
submitFeedback: async (sid, body) => {
|
|
7563
|
+
const payload = { rating: body.rating };
|
|
7564
|
+
if (body.note && body.note.trim()) payload.note = body.note.trim();
|
|
7565
|
+
if (typeof body.botReplyEventId === "number") {
|
|
7566
|
+
payload.botReplyEventId = body.botReplyEventId;
|
|
7567
|
+
}
|
|
7568
|
+
const res = await client.request(`/catering-chat/${sid}/feedback`, {
|
|
7569
|
+
method: "POST",
|
|
7570
|
+
body: JSON.stringify(payload)
|
|
7571
|
+
});
|
|
7572
|
+
if (!res.ok) throw new ChatApiError(`HTTP ${res.status}`, res.status);
|
|
7573
|
+
return res.json();
|
|
7404
7574
|
}
|
|
7405
7575
|
};
|
|
7406
7576
|
}
|
|
@@ -12497,7 +12667,8 @@ function useChatSession(options = {}) {
|
|
|
12497
12667
|
{ type: "text", text: entry.text },
|
|
12498
12668
|
...entry.role === "bot" && entry.chips && entry.chips.length > 0 ? [{ type: "chips", chips: entry.chips }] : [],
|
|
12499
12669
|
...restoredParts
|
|
12500
|
-
]
|
|
12670
|
+
],
|
|
12671
|
+
...entry.role === "bot" && entry.eventId ? { eventId: entry.eventId } : {}
|
|
12501
12672
|
};
|
|
12502
12673
|
}
|
|
12503
12674
|
);
|
|
@@ -12518,7 +12689,15 @@ function useChatSession(options = {}) {
|
|
|
12518
12689
|
};
|
|
12519
12690
|
return [...historicMessages, newLive];
|
|
12520
12691
|
}
|
|
12521
|
-
|
|
12692
|
+
if (!existingLive) return historicMessages;
|
|
12693
|
+
const carriedParts = existingLive.parts.filter(
|
|
12694
|
+
(p) => p.type !== "menu_preview" && p.type !== "restaurant_info"
|
|
12695
|
+
);
|
|
12696
|
+
if (carriedParts.length === 0) return historicMessages;
|
|
12697
|
+
return [
|
|
12698
|
+
...historicMessages,
|
|
12699
|
+
{ ...existingLive, parts: carriedParts }
|
|
12700
|
+
];
|
|
12522
12701
|
});
|
|
12523
12702
|
if (markLive && newLiveParts.length > 0) {
|
|
12524
12703
|
const previewIdx = finalLiveParts.findIndex(
|
|
@@ -12563,7 +12742,8 @@ function useChatSession(options = {}) {
|
|
|
12563
12742
|
{ type: "text", text: entry.text },
|
|
12564
12743
|
...entry.role === "bot" && entry.chips && entry.chips.length > 0 ? [{ type: "chips", chips: entry.chips }] : [],
|
|
12565
12744
|
...restoredParts
|
|
12566
|
-
]
|
|
12745
|
+
],
|
|
12746
|
+
...entry.role === "bot" && entry.eventId ? { eventId: entry.eventId } : {}
|
|
12567
12747
|
};
|
|
12568
12748
|
}
|
|
12569
12749
|
);
|
|
@@ -12925,6 +13105,19 @@ function useChatSession(options = {}) {
|
|
|
12925
13105
|
const getTaxonomyValueFor = react.useCallback((field) => {
|
|
12926
13106
|
return taxonomyValueFor(field, lastTaxonomyRef.current);
|
|
12927
13107
|
}, []);
|
|
13108
|
+
const submitFeedback = react.useCallback(
|
|
13109
|
+
async (rating, note, botReplyEventId) => {
|
|
13110
|
+
const sid = sessionIdRef.current;
|
|
13111
|
+
if (!sid) return false;
|
|
13112
|
+
try {
|
|
13113
|
+
await api.chat.submitFeedback(sid, { rating, note, botReplyEventId });
|
|
13114
|
+
return true;
|
|
13115
|
+
} catch {
|
|
13116
|
+
return false;
|
|
13117
|
+
}
|
|
13118
|
+
},
|
|
13119
|
+
[api]
|
|
13120
|
+
);
|
|
12928
13121
|
const latestDraft = react.useMemo(
|
|
12929
13122
|
() => latestMealSessions[latestActiveMealSessionIndex]?.draft ?? null,
|
|
12930
13123
|
[latestMealSessions, latestActiveMealSessionIndex]
|
|
@@ -12970,7 +13163,8 @@ function useChatSession(options = {}) {
|
|
|
12970
13163
|
getTaxonomyValueFor,
|
|
12971
13164
|
setSelectedMealSessionIndex: (idx) => {
|
|
12972
13165
|
selectedMealSessionIndexRef.current = idx;
|
|
12973
|
-
}
|
|
13166
|
+
},
|
|
13167
|
+
submitFeedback
|
|
12974
13168
|
};
|
|
12975
13169
|
}
|
|
12976
13170
|
function legacyToParts(data) {
|
|
@@ -12983,7 +13177,6 @@ function mergeAdaptedMealParts(data) {
|
|
|
12983
13177
|
for (let i = 0; i < meals.length; i++) {
|
|
12984
13178
|
const meal = meals[i];
|
|
12985
13179
|
const blocks = meal.intentBlocks ?? [];
|
|
12986
|
-
if (blocks.length === 0) continue;
|
|
12987
13180
|
synthesized.push({
|
|
12988
13181
|
type: "meal_session",
|
|
12989
13182
|
mealSessionIndex: i,
|
|
@@ -13057,7 +13250,7 @@ function findLatestMealSessionParts(messages) {
|
|
|
13057
13250
|
(a, b) => a.mealSessionIndex - b.mealSessionIndex
|
|
13058
13251
|
);
|
|
13059
13252
|
}
|
|
13060
|
-
var STORAGE_KEY_PREFIX = "swift-food-cart-
|
|
13253
|
+
var STORAGE_KEY_PREFIX = "swift-food-cart-v3-";
|
|
13061
13254
|
var emptyIntent = () => ({
|
|
13062
13255
|
selectedRestaurantId: null,
|
|
13063
13256
|
qtyOverrides: {},
|
|
@@ -13274,6 +13467,8 @@ function ChatSessionProvider({
|
|
|
13274
13467
|
);
|
|
13275
13468
|
const [activeViewedPreview, setActiveViewedPreview] = react.useState(null);
|
|
13276
13469
|
const [suggestionsOverlayDismissed, setSuggestionsOverlayDismissed] = react.useState(false);
|
|
13470
|
+
const [feedbackTarget, setFeedbackTarget] = react.useState(null);
|
|
13471
|
+
const [feedbackRating, setFeedbackRating] = react.useState(0);
|
|
13277
13472
|
react.useEffect(() => {
|
|
13278
13473
|
if (!chat.sessionId) setActiveViewedPreview(null);
|
|
13279
13474
|
}, [chat.sessionId]);
|
|
@@ -13312,6 +13507,17 @@ function ChatSessionProvider({
|
|
|
13312
13507
|
setEditField,
|
|
13313
13508
|
setEditValue,
|
|
13314
13509
|
setSwapTarget,
|
|
13510
|
+
feedbackTarget,
|
|
13511
|
+
feedbackRating,
|
|
13512
|
+
setFeedbackRating,
|
|
13513
|
+
startFeedback: (messageId, up, eventId) => {
|
|
13514
|
+
setFeedbackTarget({ messageId, up, eventId });
|
|
13515
|
+
setFeedbackRating(0);
|
|
13516
|
+
},
|
|
13517
|
+
cancelFeedback: () => {
|
|
13518
|
+
setFeedbackTarget(null);
|
|
13519
|
+
setFeedbackRating(0);
|
|
13520
|
+
},
|
|
13315
13521
|
hasResults,
|
|
13316
13522
|
suggestionsOverlayDismissed,
|
|
13317
13523
|
dismissSuggestionsOverlay: () => setSuggestionsOverlayDismissed(true),
|
|
@@ -13334,21 +13540,23 @@ function useChatSessionContext() {
|
|
|
13334
13540
|
}
|
|
13335
13541
|
return ctx;
|
|
13336
13542
|
}
|
|
13337
|
-
var
|
|
13543
|
+
var BOLD_PATTERN = /\*\*([\s\S]+?)\*\*|<b>([\s\S]*?)<\/b>/g;
|
|
13544
|
+
var BULLET_LINE_PATTERN = /^[ \t]*[*-][ \t]+/gm;
|
|
13338
13545
|
function renderBotText(text) {
|
|
13546
|
+
const normalised = text.replace(BULLET_LINE_PATTERN, "\u2022 ");
|
|
13339
13547
|
const nodes = [];
|
|
13340
13548
|
let cursor = 0;
|
|
13341
13549
|
let key = 0;
|
|
13342
|
-
for (const match of
|
|
13550
|
+
for (const match of normalised.matchAll(BOLD_PATTERN)) {
|
|
13343
13551
|
const start = match.index ?? 0;
|
|
13344
13552
|
if (start > cursor) {
|
|
13345
|
-
nodes.push(
|
|
13553
|
+
nodes.push(normalised.slice(cursor, start));
|
|
13346
13554
|
}
|
|
13347
|
-
nodes.push(/* @__PURE__ */ jsxRuntime.jsx("strong", { children: match[1] }, key++));
|
|
13555
|
+
nodes.push(/* @__PURE__ */ jsxRuntime.jsx("strong", { children: match[1] ?? match[2] ?? "" }, key++));
|
|
13348
13556
|
cursor = start + match[0].length;
|
|
13349
13557
|
}
|
|
13350
|
-
if (cursor <
|
|
13351
|
-
nodes.push(
|
|
13558
|
+
if (cursor < normalised.length) {
|
|
13559
|
+
nodes.push(normalised.slice(cursor));
|
|
13352
13560
|
}
|
|
13353
13561
|
return nodes;
|
|
13354
13562
|
}
|
|
@@ -13595,7 +13803,7 @@ function DraftItemRow({
|
|
|
13595
13803
|
marginTop: 8,
|
|
13596
13804
|
alignItems: "center",
|
|
13597
13805
|
flexWrap: "wrap",
|
|
13598
|
-
paddingLeft: showCheckbox ?
|
|
13806
|
+
paddingLeft: showCheckbox ? 168 : 132
|
|
13599
13807
|
},
|
|
13600
13808
|
children: [
|
|
13601
13809
|
onSwap && /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -13729,9 +13937,9 @@ function ItemPhoto({
|
|
|
13729
13937
|
"div",
|
|
13730
13938
|
{
|
|
13731
13939
|
style: {
|
|
13732
|
-
width:
|
|
13733
|
-
height:
|
|
13734
|
-
borderRadius:
|
|
13940
|
+
width: 120,
|
|
13941
|
+
height: 120,
|
|
13942
|
+
borderRadius: 14,
|
|
13735
13943
|
background: src ? `url(${src}) center/cover` : PLACEHOLDER_BG,
|
|
13736
13944
|
flexShrink: 0,
|
|
13737
13945
|
position: "relative",
|
|
@@ -13749,7 +13957,7 @@ function ItemPhoto({
|
|
|
13749
13957
|
display: "flex",
|
|
13750
13958
|
alignItems: "center",
|
|
13751
13959
|
justifyContent: "center",
|
|
13752
|
-
fontSize: "
|
|
13960
|
+
fontSize: "2.2rem",
|
|
13753
13961
|
color: "var(--ink-faint)"
|
|
13754
13962
|
},
|
|
13755
13963
|
children: initial
|
|
@@ -14239,6 +14447,9 @@ function MenuPreviewCard({
|
|
|
14239
14447
|
}) {
|
|
14240
14448
|
const sections = preview.sections.filter((s) => s.items.length > 0);
|
|
14241
14449
|
const [open, setOpen] = react.useState(defaultOpen);
|
|
14450
|
+
react.useEffect(() => {
|
|
14451
|
+
if (defaultOpen) setOpen(true);
|
|
14452
|
+
}, [preview, defaultOpen]);
|
|
14242
14453
|
const [activeIdx, setActiveIdx] = react.useState(0);
|
|
14243
14454
|
if (sections.length === 0) return null;
|
|
14244
14455
|
const intents = sections.map((s) => s.intent);
|
|
@@ -14652,7 +14863,7 @@ function PreviewItemCard({
|
|
|
14652
14863
|
},
|
|
14653
14864
|
children: [
|
|
14654
14865
|
item.restaurant.name,
|
|
14655
|
-
item.restaurant.cuisine ? ` \xB7 ${item.restaurant.cuisine}` : ""
|
|
14866
|
+
item.restaurant.cuisine ? ` \xB7 ${item.restaurant.cuisine.replace(/_/g, " ")}` : ""
|
|
14656
14867
|
]
|
|
14657
14868
|
}
|
|
14658
14869
|
),
|
|
@@ -15390,6 +15601,22 @@ function formatDay(iso) {
|
|
|
15390
15601
|
if (Number.isNaN(d.getTime())) return iso;
|
|
15391
15602
|
return d.toLocaleDateString(void 0, { weekday: "short" });
|
|
15392
15603
|
}
|
|
15604
|
+
function fallbackCopy(text) {
|
|
15605
|
+
const ta = document.createElement("textarea");
|
|
15606
|
+
ta.value = text;
|
|
15607
|
+
ta.style.position = "fixed";
|
|
15608
|
+
ta.style.opacity = "0";
|
|
15609
|
+
document.body.appendChild(ta);
|
|
15610
|
+
ta.focus();
|
|
15611
|
+
ta.select();
|
|
15612
|
+
let ok = false;
|
|
15613
|
+
try {
|
|
15614
|
+
ok = document.execCommand("copy");
|
|
15615
|
+
} catch {
|
|
15616
|
+
}
|
|
15617
|
+
document.body.removeChild(ta);
|
|
15618
|
+
return ok;
|
|
15619
|
+
}
|
|
15393
15620
|
function MessageThread({
|
|
15394
15621
|
messages,
|
|
15395
15622
|
sessionId,
|
|
@@ -15401,27 +15628,99 @@ function MessageThread({
|
|
|
15401
15628
|
onQtyChange,
|
|
15402
15629
|
liveLatestPreviewKey,
|
|
15403
15630
|
onViewPreviewInPanel,
|
|
15404
|
-
onOpenPreviewItem
|
|
15631
|
+
onOpenPreviewItem,
|
|
15632
|
+
onFeedback,
|
|
15633
|
+
latestBotMessageId,
|
|
15634
|
+
activeFeedbackMessageId
|
|
15405
15635
|
}) {
|
|
15406
|
-
|
|
15407
|
-
|
|
15408
|
-
|
|
15409
|
-
|
|
15410
|
-
|
|
15411
|
-
|
|
15412
|
-
|
|
15413
|
-
|
|
15414
|
-
|
|
15415
|
-
|
|
15416
|
-
|
|
15417
|
-
|
|
15418
|
-
|
|
15419
|
-
|
|
15420
|
-
|
|
15421
|
-
|
|
15422
|
-
|
|
15423
|
-
)
|
|
15424
|
-
|
|
15636
|
+
let latestPreviewMsgId = null;
|
|
15637
|
+
let latestPreviewIdx = -1;
|
|
15638
|
+
for (let mi = messages.length - 1; mi >= 0; mi--) {
|
|
15639
|
+
const m = messages[mi];
|
|
15640
|
+
for (let pi = m.parts.length - 1; pi >= 0; pi--) {
|
|
15641
|
+
if (m.parts[pi].type === "menu_preview") {
|
|
15642
|
+
latestPreviewMsgId = m.id;
|
|
15643
|
+
latestPreviewIdx = pi;
|
|
15644
|
+
break;
|
|
15645
|
+
}
|
|
15646
|
+
}
|
|
15647
|
+
if (latestPreviewMsgId !== null) break;
|
|
15648
|
+
}
|
|
15649
|
+
const [copiedId, setCopiedId] = react.useState(null);
|
|
15650
|
+
const copyMessage = react.useCallback((msg) => {
|
|
15651
|
+
const text = msg.parts.filter((p) => p.type === "text").map((p) => p.text).join("\n");
|
|
15652
|
+
if (!text) return;
|
|
15653
|
+
const onSuccess = () => {
|
|
15654
|
+
setCopiedId(msg.id);
|
|
15655
|
+
window.setTimeout(() => setCopiedId((prev) => prev === msg.id ? null : prev), 1500);
|
|
15656
|
+
};
|
|
15657
|
+
if (navigator.clipboard?.writeText) {
|
|
15658
|
+
navigator.clipboard.writeText(text).then(onSuccess, () => {
|
|
15659
|
+
fallbackCopy(text) && onSuccess();
|
|
15660
|
+
});
|
|
15661
|
+
} else {
|
|
15662
|
+
fallbackCopy(text) && onSuccess();
|
|
15663
|
+
}
|
|
15664
|
+
}, []);
|
|
15665
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexDirection: "column", gap: 12 }, children: messages.map((msg) => {
|
|
15666
|
+
const isBot = msg.sender === "bot";
|
|
15667
|
+
const isUser = msg.sender === "user";
|
|
15668
|
+
const isLatestBot = isBot && msg.id === latestBotMessageId;
|
|
15669
|
+
const isActiveFeedback = msg.id === activeFeedbackMessageId;
|
|
15670
|
+
const hasText = msg.parts.some((p) => p.type === "text");
|
|
15671
|
+
const justCopied = copiedId === msg.id;
|
|
15672
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "group/msg", style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
|
|
15673
|
+
msg.parts.map((part, idx) => ({ part, idx })).sort((a, b) => partSortKey(a.part) - partSortKey(b.part)).map(({ part, idx }) => {
|
|
15674
|
+
const key = `${msg.id}-${idx}`;
|
|
15675
|
+
const isLatestPreview = msg.id === latestPreviewMsgId && idx === latestPreviewIdx;
|
|
15676
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
15677
|
+
PartRenderer,
|
|
15678
|
+
{
|
|
15679
|
+
part,
|
|
15680
|
+
sender: msg.sender,
|
|
15681
|
+
aiMealSessions,
|
|
15682
|
+
onChip,
|
|
15683
|
+
onSwapItem,
|
|
15684
|
+
onRemoveItem,
|
|
15685
|
+
onQtyChange,
|
|
15686
|
+
isLatestPreview,
|
|
15687
|
+
onViewPreviewInPanel,
|
|
15688
|
+
onOpenPreviewItem
|
|
15689
|
+
},
|
|
15690
|
+
key
|
|
15691
|
+
);
|
|
15692
|
+
}),
|
|
15693
|
+
(hasText || isBot && onFeedback) && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
15694
|
+
"div",
|
|
15695
|
+
{
|
|
15696
|
+
className: `flex items-center gap-1 transition-opacity duration-150 ${isUser ? "justify-end" : "justify-start"} ${isLatestBot || isActiveFeedback ? "opacity-100" : "opacity-100 md:opacity-0 md:group-hover/msg:opacity-100"}`,
|
|
15697
|
+
children: [
|
|
15698
|
+
isBot && onFeedback && /* @__PURE__ */ jsxRuntime.jsx(
|
|
15699
|
+
"button",
|
|
15700
|
+
{
|
|
15701
|
+
type: "button",
|
|
15702
|
+
onClick: () => onFeedback(msg.id, false, msg.eventId),
|
|
15703
|
+
className: `p-1 rounded transition-colors ${isActiveFeedback ? "text-primary" : "text-gray-300 hover:text-gray-500"}`,
|
|
15704
|
+
"aria-label": "Send feedback",
|
|
15705
|
+
title: "Send feedback",
|
|
15706
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MessageCircleWarning, { className: "w-3.5 h-3.5" })
|
|
15707
|
+
}
|
|
15708
|
+
),
|
|
15709
|
+
hasText && /* @__PURE__ */ jsxRuntime.jsx(
|
|
15710
|
+
"button",
|
|
15711
|
+
{
|
|
15712
|
+
type: "button",
|
|
15713
|
+
onClick: () => copyMessage(msg),
|
|
15714
|
+
className: "p-1 rounded transition-colors text-gray-300 hover:text-gray-500",
|
|
15715
|
+
"aria-label": justCopied ? "Copied" : "Copy message",
|
|
15716
|
+
children: justCopied ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "w-3.5 h-3.5 text-primary" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { className: "w-3.5 h-3.5" })
|
|
15717
|
+
}
|
|
15718
|
+
)
|
|
15719
|
+
]
|
|
15720
|
+
}
|
|
15721
|
+
)
|
|
15722
|
+
] }, msg.id);
|
|
15723
|
+
}) });
|
|
15425
15724
|
}
|
|
15426
15725
|
function partSortKey(part) {
|
|
15427
15726
|
return part.type === "text" ? 0 : 1;
|
|
@@ -15486,9 +15785,6 @@ function PartRenderer({
|
|
|
15486
15785
|
if (part.type === "missing_fields_clarifier") {
|
|
15487
15786
|
return null;
|
|
15488
15787
|
}
|
|
15489
|
-
if (part.type === "feedback") {
|
|
15490
|
-
return null;
|
|
15491
|
-
}
|
|
15492
15788
|
return null;
|
|
15493
15789
|
}
|
|
15494
15790
|
function StandaloneIntentBlock({
|
|
@@ -15527,10 +15823,11 @@ function ChatMessagesView() {
|
|
|
15527
15823
|
chat,
|
|
15528
15824
|
setEditField,
|
|
15529
15825
|
setEditValue,
|
|
15530
|
-
hasResults,
|
|
15531
15826
|
onViewResults,
|
|
15532
15827
|
setActiveViewedPreview,
|
|
15533
|
-
onOpenPreviewItem
|
|
15828
|
+
onOpenPreviewItem,
|
|
15829
|
+
startFeedback,
|
|
15830
|
+
feedbackTarget
|
|
15534
15831
|
} = useChatSessionContext();
|
|
15535
15832
|
const { messages, sending, awaitingReply, bootstrapping, error, sessionId, handleChip, retryLastSend, latestMealSessions } = chat;
|
|
15536
15833
|
const messagesEndRef = react.useRef(null);
|
|
@@ -15538,6 +15835,12 @@ function ChatMessagesView() {
|
|
|
15538
15835
|
() => messages.map((m) => ({ ...m, parts: chatPartsOnly(m.parts) })).filter((m) => m.parts.length > 0),
|
|
15539
15836
|
[messages]
|
|
15540
15837
|
);
|
|
15838
|
+
const latestBotMessageId = react.useMemo(() => {
|
|
15839
|
+
for (let i = chatMessages.length - 1; i >= 0; i--) {
|
|
15840
|
+
if (chatMessages[i].sender === "bot") return chatMessages[i].id;
|
|
15841
|
+
}
|
|
15842
|
+
return null;
|
|
15843
|
+
}, [chatMessages]);
|
|
15541
15844
|
react.useEffect(() => {
|
|
15542
15845
|
messagesEndRef.current?.scrollIntoView({
|
|
15543
15846
|
behavior: "smooth",
|
|
@@ -15575,7 +15878,10 @@ function ChatMessagesView() {
|
|
|
15575
15878
|
onEditField: handleEditField,
|
|
15576
15879
|
liveLatestPreviewKey: chat.liveLatestPreviewKey,
|
|
15577
15880
|
onViewPreviewInPanel: handleViewPreviewInPanel,
|
|
15578
|
-
onOpenPreviewItem
|
|
15881
|
+
onOpenPreviewItem,
|
|
15882
|
+
onFeedback: startFeedback,
|
|
15883
|
+
latestBotMessageId,
|
|
15884
|
+
activeFeedbackMessageId: feedbackTarget?.messageId ?? null
|
|
15579
15885
|
}
|
|
15580
15886
|
),
|
|
15581
15887
|
awaitingReply && /* @__PURE__ */ jsxRuntime.jsx(TypingIndicator, {}),
|
|
@@ -15604,15 +15910,6 @@ function ChatMessagesView() {
|
|
|
15604
15910
|
]
|
|
15605
15911
|
}
|
|
15606
15912
|
),
|
|
15607
|
-
hasResults && /* @__PURE__ */ jsxRuntime.jsx(
|
|
15608
|
-
"button",
|
|
15609
|
-
{
|
|
15610
|
-
type: "button",
|
|
15611
|
-
onClick: onViewResults,
|
|
15612
|
-
className: "md:hidden flex items-center justify-center gap-1.5 mx-auto mt-2 px-4 py-2 rounded-full bg-primary text-white text-sm font-semibold shadow-sm",
|
|
15613
|
-
children: "\u2728 View menu suggestions"
|
|
15614
|
-
}
|
|
15615
|
-
),
|
|
15616
15913
|
/* @__PURE__ */ jsxRuntime.jsx("div", { ref: messagesEndRef })
|
|
15617
15914
|
] });
|
|
15618
15915
|
}
|
|
@@ -16474,9 +16771,11 @@ function useAddressAutocomplete(onPlaceSelect, options = {}) {
|
|
|
16474
16771
|
function ChatAddressInput({
|
|
16475
16772
|
onPlaceSelect,
|
|
16476
16773
|
onClear,
|
|
16774
|
+
onDismiss,
|
|
16477
16775
|
placeholder = "Enter Location",
|
|
16478
16776
|
initialQuery,
|
|
16479
|
-
autoFocus
|
|
16777
|
+
autoFocus,
|
|
16778
|
+
dropdownDirection = "up"
|
|
16480
16779
|
}) {
|
|
16481
16780
|
const {
|
|
16482
16781
|
inputRef,
|
|
@@ -16496,6 +16795,33 @@ function ChatAddressInput({
|
|
|
16496
16795
|
react.useEffect(() => {
|
|
16497
16796
|
if (autoFocus) inputRef.current?.focus();
|
|
16498
16797
|
}, []);
|
|
16798
|
+
const [dropdownRect, setDropdownRect] = react.useState(null);
|
|
16799
|
+
react.useLayoutEffect(() => {
|
|
16800
|
+
if (!open || predictions.length === 0) {
|
|
16801
|
+
setDropdownRect(null);
|
|
16802
|
+
return;
|
|
16803
|
+
}
|
|
16804
|
+
const update = () => {
|
|
16805
|
+
const el = containerRef.current;
|
|
16806
|
+
if (!el) return;
|
|
16807
|
+
const rect = el.getBoundingClientRect();
|
|
16808
|
+
setDropdownRect(
|
|
16809
|
+
dropdownDirection === "down" ? { left: rect.left, top: rect.bottom + 4, width: rect.width } : { left: rect.left, bottom: window.innerHeight - rect.top + 4, width: rect.width }
|
|
16810
|
+
);
|
|
16811
|
+
};
|
|
16812
|
+
update();
|
|
16813
|
+
window.addEventListener("resize", update);
|
|
16814
|
+
window.addEventListener("scroll", update, true);
|
|
16815
|
+
const vv = window.visualViewport;
|
|
16816
|
+
vv?.addEventListener("resize", update);
|
|
16817
|
+
vv?.addEventListener("scroll", update);
|
|
16818
|
+
return () => {
|
|
16819
|
+
window.removeEventListener("resize", update);
|
|
16820
|
+
window.removeEventListener("scroll", update, true);
|
|
16821
|
+
vv?.removeEventListener("resize", update);
|
|
16822
|
+
vv?.removeEventListener("scroll", update);
|
|
16823
|
+
};
|
|
16824
|
+
}, [open, predictions.length]);
|
|
16499
16825
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef, className: "relative", children: [
|
|
16500
16826
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
16501
16827
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -16514,62 +16840,87 @@ function ChatAddressInput({
|
|
|
16514
16840
|
onChange: (e) => setQuery(e.target.value),
|
|
16515
16841
|
onKeyDown: handleKeyDown,
|
|
16516
16842
|
placeholder,
|
|
16517
|
-
autoComplete: "
|
|
16518
|
-
|
|
16843
|
+
autoComplete: "off",
|
|
16844
|
+
autoCorrect: "off",
|
|
16845
|
+
autoCapitalize: "off",
|
|
16846
|
+
spellCheck: false,
|
|
16847
|
+
className: "flex-1 bg-transparent text-base text-gray-800 placeholder:text-gray-400 outline-none py-1 touch-auto"
|
|
16519
16848
|
}
|
|
16520
16849
|
),
|
|
16521
|
-
query.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
16850
|
+
(query.length > 0 || onDismiss) && /* @__PURE__ */ jsxRuntime.jsx(
|
|
16522
16851
|
"button",
|
|
16523
16852
|
{
|
|
16524
16853
|
type: "button",
|
|
16525
16854
|
onClick: () => {
|
|
16526
|
-
|
|
16527
|
-
|
|
16528
|
-
|
|
16855
|
+
if (onDismiss) {
|
|
16856
|
+
onDismiss();
|
|
16857
|
+
} else {
|
|
16858
|
+
setQuery("");
|
|
16859
|
+
onClear?.();
|
|
16860
|
+
inputRef.current?.focus();
|
|
16861
|
+
}
|
|
16529
16862
|
},
|
|
16530
16863
|
className: "flex-shrink-0 rounded-full p-0.5 text-gray-400 hover:bg-base-100 hover:text-gray-600 transition-colors",
|
|
16531
|
-
"aria-label": "Clear address",
|
|
16864
|
+
"aria-label": onDismiss ? "Close" : "Clear address",
|
|
16532
16865
|
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "w-3.5 h-3.5" })
|
|
16533
16866
|
}
|
|
16534
16867
|
)
|
|
16535
16868
|
] }),
|
|
16536
|
-
open && predictions.length > 0 &&
|
|
16537
|
-
|
|
16538
|
-
|
|
16539
|
-
|
|
16540
|
-
|
|
16541
|
-
|
|
16542
|
-
|
|
16543
|
-
|
|
16544
|
-
|
|
16545
|
-
|
|
16546
|
-
|
|
16547
|
-
|
|
16548
|
-
|
|
16869
|
+
open && predictions.length > 0 && dropdownRect && typeof document !== "undefined" && reactDom.createPortal(
|
|
16870
|
+
/* Portal to the widget's shared overlay root so the
|
|
16871
|
+
dropdown escapes the bar pill's overflow-hidden +
|
|
16872
|
+
rounded-3xl clip (where it was otherwise invisible). */
|
|
16873
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
16874
|
+
"div",
|
|
16875
|
+
{
|
|
16876
|
+
style: {
|
|
16877
|
+
position: "fixed",
|
|
16878
|
+
left: dropdownRect.left,
|
|
16879
|
+
...dropdownRect.top != null ? { top: dropdownRect.top } : { bottom: dropdownRect.bottom },
|
|
16880
|
+
width: dropdownRect.width
|
|
16881
|
+
},
|
|
16882
|
+
className: "z-[60] rounded-lg border border-base-200 bg-white shadow-lg overflow-hidden",
|
|
16883
|
+
children: predictions.map((p, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
16884
|
+
"button",
|
|
16549
16885
|
{
|
|
16550
|
-
|
|
16551
|
-
|
|
16552
|
-
|
|
16553
|
-
|
|
16554
|
-
|
|
16555
|
-
|
|
16556
|
-
|
|
16557
|
-
|
|
16558
|
-
|
|
16559
|
-
|
|
16560
|
-
|
|
16561
|
-
|
|
16562
|
-
|
|
16563
|
-
|
|
16564
|
-
|
|
16565
|
-
|
|
16566
|
-
|
|
16567
|
-
|
|
16568
|
-
|
|
16569
|
-
|
|
16570
|
-
|
|
16571
|
-
|
|
16572
|
-
|
|
16886
|
+
type: "button",
|
|
16887
|
+
onMouseDown: (e) => {
|
|
16888
|
+
e.preventDefault();
|
|
16889
|
+
handleSelect(p);
|
|
16890
|
+
},
|
|
16891
|
+
onMouseEnter: () => setActiveIndex(idx),
|
|
16892
|
+
className: `flex w-full items-start gap-2 px-3 py-2 text-left transition-colors ${idx === activeIndex ? "bg-base-100" : "hover:bg-base-100"}`,
|
|
16893
|
+
children: [
|
|
16894
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
16895
|
+
"svg",
|
|
16896
|
+
{
|
|
16897
|
+
className: "h-3.5 w-3.5 flex-shrink-0 text-base-content/40 mt-0.5",
|
|
16898
|
+
fill: "none",
|
|
16899
|
+
stroke: "currentColor",
|
|
16900
|
+
viewBox: "0 0 24 24",
|
|
16901
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
16902
|
+
"path",
|
|
16903
|
+
{
|
|
16904
|
+
strokeLinecap: "round",
|
|
16905
|
+
strokeLinejoin: "round",
|
|
16906
|
+
strokeWidth: 2,
|
|
16907
|
+
d: "M17.657 16.657L13.414 20.9a2 2 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0zM15 11a3 3 0 11-6 0 3 3 0 016 0z"
|
|
16908
|
+
}
|
|
16909
|
+
)
|
|
16910
|
+
}
|
|
16911
|
+
),
|
|
16912
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
|
|
16913
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-base-content truncate", children: p.structured_formatting.main_text }),
|
|
16914
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-base-content/50 truncate", children: p.structured_formatting.secondary_text })
|
|
16915
|
+
] })
|
|
16916
|
+
]
|
|
16917
|
+
},
|
|
16918
|
+
p.place_id
|
|
16919
|
+
))
|
|
16920
|
+
}
|
|
16921
|
+
),
|
|
16922
|
+
getOverlayRoot()
|
|
16923
|
+
)
|
|
16573
16924
|
] });
|
|
16574
16925
|
}
|
|
16575
16926
|
var GATE_PROMPT = "What is the code to use the AI chat and test our beta version?";
|
|
@@ -16663,8 +17014,25 @@ function readUnlocked() {
|
|
|
16663
17014
|
return false;
|
|
16664
17015
|
}
|
|
16665
17016
|
}
|
|
17017
|
+
var unlockedValue = readUnlocked();
|
|
17018
|
+
var subscribers = /* @__PURE__ */ new Set();
|
|
17019
|
+
function setUnlocked(next) {
|
|
17020
|
+
if (unlockedValue === next) return;
|
|
17021
|
+
unlockedValue = next;
|
|
17022
|
+
subscribers.forEach((cb) => cb());
|
|
17023
|
+
}
|
|
17024
|
+
function subscribe(cb) {
|
|
17025
|
+
subscribers.add(cb);
|
|
17026
|
+
return () => {
|
|
17027
|
+
subscribers.delete(cb);
|
|
17028
|
+
};
|
|
17029
|
+
}
|
|
16666
17030
|
function useBetaUnlock() {
|
|
16667
|
-
const
|
|
17031
|
+
const unlocked = react.useSyncExternalStore(
|
|
17032
|
+
subscribe,
|
|
17033
|
+
() => unlockedValue,
|
|
17034
|
+
() => false
|
|
17035
|
+
);
|
|
16668
17036
|
const tryUnlock = react.useCallback((code) => {
|
|
16669
17037
|
if (code.trim() !== BETA_CODE) return false;
|
|
16670
17038
|
setUnlocked(true);
|
|
@@ -16698,7 +17066,8 @@ function AIChatBody() {
|
|
|
16698
17066
|
applyEditField,
|
|
16699
17067
|
handleChip,
|
|
16700
17068
|
editingMealSessionIndex,
|
|
16701
|
-
setEditingMealSessionIndex
|
|
17069
|
+
setEditingMealSessionIndex,
|
|
17070
|
+
submitFeedback
|
|
16702
17071
|
},
|
|
16703
17072
|
resetEverything,
|
|
16704
17073
|
editField,
|
|
@@ -16708,7 +17077,11 @@ function AIChatBody() {
|
|
|
16708
17077
|
setEditValue,
|
|
16709
17078
|
setSwapTarget,
|
|
16710
17079
|
cart,
|
|
16711
|
-
dismissSuggestionsOverlay
|
|
17080
|
+
dismissSuggestionsOverlay,
|
|
17081
|
+
feedbackTarget,
|
|
17082
|
+
feedbackRating,
|
|
17083
|
+
setFeedbackRating,
|
|
17084
|
+
cancelFeedback
|
|
16712
17085
|
} = useChatSessionContext();
|
|
16713
17086
|
const buildChatAddress = useChatAddressFromContext();
|
|
16714
17087
|
const { contactInfo, setContactInfo } = useCateringState();
|
|
@@ -16717,6 +17090,9 @@ function AIChatBody() {
|
|
|
16717
17090
|
const [pillEditing, setPillEditing] = react.useState(false);
|
|
16718
17091
|
const textareaRef = react.useRef(null);
|
|
16719
17092
|
const [input, setInput] = react.useState("");
|
|
17093
|
+
const [feedbackHover, setFeedbackHover] = react.useState(0);
|
|
17094
|
+
const [feedbackState, setFeedbackState] = react.useState("idle");
|
|
17095
|
+
const [feedbackNote, setFeedbackNote] = react.useState("");
|
|
16720
17096
|
const [pendingInputFocus, setPendingInputFocus] = react.useState(false);
|
|
16721
17097
|
const messagesScrollRef = react.useRef(null);
|
|
16722
17098
|
const [showScrollDown, setShowScrollDown] = react.useState(false);
|
|
@@ -16751,6 +17127,31 @@ function AIChatBody() {
|
|
|
16751
17127
|
el.focus();
|
|
16752
17128
|
setPendingInputFocus(false);
|
|
16753
17129
|
}, [pendingInputFocus, gateActive, pillEditing, bootstrapping, sessionId]);
|
|
17130
|
+
const inFeedbackMode = feedbackTarget !== null;
|
|
17131
|
+
const RATING_LABELS = ["Terrible", "Poor", "Okay", "Good", "Great"];
|
|
17132
|
+
react.useEffect(() => {
|
|
17133
|
+
if (!feedbackTarget) return;
|
|
17134
|
+
setFeedbackHover(0);
|
|
17135
|
+
setFeedbackNote("");
|
|
17136
|
+
setFeedbackState("idle");
|
|
17137
|
+
}, [feedbackTarget]);
|
|
17138
|
+
function closeFeedback() {
|
|
17139
|
+
cancelFeedback();
|
|
17140
|
+
setFeedbackHover(0);
|
|
17141
|
+
setFeedbackNote("");
|
|
17142
|
+
setFeedbackState("idle");
|
|
17143
|
+
}
|
|
17144
|
+
async function handleFeedbackSubmit() {
|
|
17145
|
+
if (feedbackRating < 1 || !feedbackTarget) return;
|
|
17146
|
+
setFeedbackState("sending");
|
|
17147
|
+
const ok = await submitFeedback(feedbackRating, feedbackNote || void 0, feedbackTarget.eventId);
|
|
17148
|
+
if (ok) {
|
|
17149
|
+
setFeedbackState("done");
|
|
17150
|
+
window.setTimeout(closeFeedback, 900);
|
|
17151
|
+
} else {
|
|
17152
|
+
setFeedbackState("error");
|
|
17153
|
+
}
|
|
17154
|
+
}
|
|
16754
17155
|
function handlePlaceSelect(place) {
|
|
16755
17156
|
const parsed = parsePlaceResult(place);
|
|
16756
17157
|
if (!parsed) return;
|
|
@@ -16798,6 +17199,10 @@ function AIChatBody() {
|
|
|
16798
17199
|
void handleChip(chip);
|
|
16799
17200
|
}
|
|
16800
17201
|
function submitText() {
|
|
17202
|
+
if (inFeedbackMode) {
|
|
17203
|
+
void handleFeedbackSubmit();
|
|
17204
|
+
return;
|
|
17205
|
+
}
|
|
16801
17206
|
if (sending || bootstrapping || !sessionId || !input.trim()) return;
|
|
16802
17207
|
if (gateActive && !hasAddress) return;
|
|
16803
17208
|
void sendText(input, buildChatAddress());
|
|
@@ -16808,6 +17213,10 @@ function AIChatBody() {
|
|
|
16808
17213
|
submitText();
|
|
16809
17214
|
}
|
|
16810
17215
|
function handleKeyDown(e) {
|
|
17216
|
+
if (e.key === "Escape" && inFeedbackMode) {
|
|
17217
|
+
closeFeedback();
|
|
17218
|
+
return;
|
|
17219
|
+
}
|
|
16811
17220
|
if (e.key === "Enter" && !e.shiftKey) {
|
|
16812
17221
|
e.preventDefault();
|
|
16813
17222
|
submitText();
|
|
@@ -16855,6 +17264,46 @@ function AIChatBody() {
|
|
|
16855
17264
|
)
|
|
16856
17265
|
] }),
|
|
16857
17266
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex-1 min-h-0", children: [
|
|
17267
|
+
!gateActive && !inFeedbackMode && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute left-0 right-0 z-10 px-3 pt-1.5 flex justify-center pointer-events-none", children: [
|
|
17268
|
+
hasAddress && !pillEditing && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
17269
|
+
"button",
|
|
17270
|
+
{
|
|
17271
|
+
type: "button",
|
|
17272
|
+
onClick: () => setPillEditing(true),
|
|
17273
|
+
className: "pointer-events-auto inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full bg-black/50 backdrop-blur-sm text-white/90 hover:bg-black/60 transition-colors text-xs max-w-full shadow-sm",
|
|
17274
|
+
children: [
|
|
17275
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17276
|
+
lucideReact.MapPin,
|
|
17277
|
+
{
|
|
17278
|
+
className: "w-3 h-3 flex-shrink-0 text-white/70",
|
|
17279
|
+
"aria-hidden": true
|
|
17280
|
+
}
|
|
17281
|
+
),
|
|
17282
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: contactInfo?.addressLine1 }),
|
|
17283
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-white/50", children: "\xB7" }),
|
|
17284
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold text-white", children: "change" })
|
|
17285
|
+
]
|
|
17286
|
+
}
|
|
17287
|
+
),
|
|
17288
|
+
pillEditing && /* @__PURE__ */ jsxRuntime.jsx(
|
|
17289
|
+
"div",
|
|
17290
|
+
{
|
|
17291
|
+
ref: pillEditRef,
|
|
17292
|
+
className: "pointer-events-auto w-full rounded-xl border border-base-300 bg-white px-3 py-2 shadow-sm",
|
|
17293
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
17294
|
+
ChatAddressInput,
|
|
17295
|
+
{
|
|
17296
|
+
onPlaceSelect: handlePlaceSelect,
|
|
17297
|
+
onClear: handleClearAddress,
|
|
17298
|
+
onDismiss: () => setPillEditing(false),
|
|
17299
|
+
initialQuery: contactInfo?.addressLine1 ?? "",
|
|
17300
|
+
autoFocus: true,
|
|
17301
|
+
dropdownDirection: "down"
|
|
17302
|
+
}
|
|
17303
|
+
)
|
|
17304
|
+
}
|
|
17305
|
+
)
|
|
17306
|
+
] }),
|
|
16858
17307
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
16859
17308
|
"div",
|
|
16860
17309
|
{
|
|
@@ -16895,113 +17344,124 @@ function AIChatBody() {
|
|
|
16895
17344
|
}
|
|
16896
17345
|
}
|
|
16897
17346
|
) }),
|
|
16898
|
-
/* @__PURE__ */ jsxRuntime.
|
|
16899
|
-
react$1.
|
|
16900
|
-
|
|
16901
|
-
|
|
16902
|
-
|
|
16903
|
-
|
|
16904
|
-
|
|
16905
|
-
|
|
16906
|
-
|
|
16907
|
-
{
|
|
16908
|
-
|
|
16909
|
-
|
|
16910
|
-
|
|
16911
|
-
|
|
16912
|
-
|
|
16913
|
-
|
|
16914
|
-
|
|
16915
|
-
|
|
16916
|
-
|
|
16917
|
-
|
|
16918
|
-
|
|
16919
|
-
|
|
16920
|
-
|
|
16921
|
-
|
|
16922
|
-
|
|
16923
|
-
animate: { opacity: 1, y: 0 },
|
|
16924
|
-
exit: { opacity: 0, y: -8 },
|
|
16925
|
-
transition: { duration: 0.18, ease: "easeOut" },
|
|
16926
|
-
children: gateActive ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
16927
|
-
"form",
|
|
16928
|
-
{
|
|
16929
|
-
onSubmit: handleSubmit,
|
|
16930
|
-
className: "flex flex-col rounded-xl border border-base-300 bg-white px-3 py-2 focus-within:border-primary transition-colors",
|
|
16931
|
-
children: [
|
|
16932
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pb-2 border-b border-base-200", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
16933
|
-
ChatAddressInput,
|
|
17347
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex-shrink-0 border-t border-base-200 p-2.5", children: [
|
|
17348
|
+
/* @__PURE__ */ jsxRuntime.jsx(react$1.AnimatePresence, { children: inFeedbackMode && /* @__PURE__ */ jsxRuntime.jsx(
|
|
17349
|
+
react$1.motion.div,
|
|
17350
|
+
{
|
|
17351
|
+
initial: { opacity: 0, y: 4 },
|
|
17352
|
+
animate: { opacity: 1, y: 0 },
|
|
17353
|
+
exit: { opacity: 0, y: 4 },
|
|
17354
|
+
transition: { duration: 0.15, ease: "easeOut" },
|
|
17355
|
+
className: "absolute left-0 right-0 bottom-full z-10 flex justify-center pb-1.5 pointer-events-none",
|
|
17356
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pointer-events-auto inline-flex items-center gap-2 px-3.5 py-2.5 rounded-full bg-black/50 backdrop-blur-sm shadow-sm", children: [
|
|
17357
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17358
|
+
"button",
|
|
17359
|
+
{
|
|
17360
|
+
type: "button",
|
|
17361
|
+
onClick: closeFeedback,
|
|
17362
|
+
className: "p-0.5 rounded text-white/60 hover:text-white transition-colors",
|
|
17363
|
+
"aria-label": "Cancel feedback",
|
|
17364
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "w-3.5 h-3.5" })
|
|
17365
|
+
}
|
|
17366
|
+
),
|
|
17367
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-white/70", children: "Rate:" }),
|
|
17368
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-0.5", children: [1, 2, 3, 4, 5].map((n) => {
|
|
17369
|
+
const active = feedbackHover || feedbackRating;
|
|
17370
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
17371
|
+
"button",
|
|
16934
17372
|
{
|
|
16935
|
-
|
|
16936
|
-
|
|
16937
|
-
|
|
16938
|
-
|
|
16939
|
-
|
|
16940
|
-
|
|
16941
|
-
|
|
16942
|
-
|
|
16943
|
-
|
|
16944
|
-
|
|
16945
|
-
|
|
16946
|
-
|
|
16947
|
-
|
|
16948
|
-
|
|
16949
|
-
|
|
16950
|
-
|
|
16951
|
-
|
|
16952
|
-
|
|
16953
|
-
|
|
16954
|
-
|
|
16955
|
-
|
|
16956
|
-
|
|
16957
|
-
|
|
16958
|
-
|
|
16959
|
-
|
|
16960
|
-
|
|
16961
|
-
|
|
16962
|
-
|
|
16963
|
-
|
|
16964
|
-
|
|
16965
|
-
|
|
16966
|
-
}
|
|
16967
|
-
) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
16968
|
-
hasAddress && !pillEditing && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
16969
|
-
"button",
|
|
17373
|
+
type: "button",
|
|
17374
|
+
"aria-label": `${n} star${n > 1 ? "s" : ""}`,
|
|
17375
|
+
onMouseEnter: () => setFeedbackHover(n),
|
|
17376
|
+
onMouseLeave: () => setFeedbackHover(0),
|
|
17377
|
+
onClick: () => setFeedbackRating(n),
|
|
17378
|
+
className: "p-0.5 transition-transform hover:scale-110",
|
|
17379
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
17380
|
+
lucideReact.Star,
|
|
17381
|
+
{
|
|
17382
|
+
className: `h-5 w-5 transition-colors ${n <= active ? "fill-amber-400 text-amber-400" : "fill-transparent text-white/40"}`
|
|
17383
|
+
}
|
|
17384
|
+
)
|
|
17385
|
+
},
|
|
17386
|
+
n
|
|
17387
|
+
);
|
|
17388
|
+
}) }),
|
|
17389
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-white/80 min-w-[3.5rem]", children: (feedbackHover || feedbackRating) > 0 ? RATING_LABELS[(feedbackHover || feedbackRating) - 1] : "" }),
|
|
17390
|
+
feedbackState === "error" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-red-300", children: "Failed" }),
|
|
17391
|
+
feedbackState === "done" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-green-300 font-medium", children: "Thanks!" })
|
|
17392
|
+
] })
|
|
17393
|
+
}
|
|
17394
|
+
) }),
|
|
17395
|
+
/* @__PURE__ */ jsxRuntime.jsx(react$1.AnimatePresence, { mode: "wait", initial: false, children: editField !== null ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
17396
|
+
react$1.motion.div,
|
|
17397
|
+
{
|
|
17398
|
+
initial: { opacity: 0, y: 8 },
|
|
17399
|
+
animate: { opacity: 1, y: 0 },
|
|
17400
|
+
exit: { opacity: 0, y: 8 },
|
|
17401
|
+
transition: { duration: 0.18, ease: "easeOut" },
|
|
17402
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
17403
|
+
InlineFieldEditor,
|
|
16970
17404
|
{
|
|
16971
|
-
|
|
16972
|
-
|
|
16973
|
-
|
|
17405
|
+
field: editField,
|
|
17406
|
+
initialValue: editValue,
|
|
17407
|
+
onSave: handleEditSave,
|
|
17408
|
+
onCancel: () => {
|
|
17409
|
+
setEditField(null);
|
|
17410
|
+
setEditingMealSessionIndex(void 0);
|
|
17411
|
+
}
|
|
17412
|
+
}
|
|
17413
|
+
)
|
|
17414
|
+
},
|
|
17415
|
+
"editor"
|
|
17416
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
17417
|
+
react$1.motion.div,
|
|
17418
|
+
{
|
|
17419
|
+
initial: { opacity: 0, y: -8 },
|
|
17420
|
+
animate: { opacity: 1, y: 0 },
|
|
17421
|
+
exit: { opacity: 0, y: -8 },
|
|
17422
|
+
transition: { duration: 0.18, ease: "easeOut" },
|
|
17423
|
+
children: gateActive ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
17424
|
+
"form",
|
|
17425
|
+
{
|
|
17426
|
+
onSubmit: handleSubmit,
|
|
17427
|
+
className: "flex flex-col rounded-xl border border-base-300 bg-white px-3 py-2 focus-within:border-primary transition-colors",
|
|
16974
17428
|
children: [
|
|
16975
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
16976
|
-
|
|
17429
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pb-2 border-b border-base-200", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
17430
|
+
ChatAddressInput,
|
|
16977
17431
|
{
|
|
16978
|
-
|
|
16979
|
-
|
|
17432
|
+
onPlaceSelect: handlePlaceSelect,
|
|
17433
|
+
onClear: handleClearAddress,
|
|
17434
|
+
autoFocus: true
|
|
16980
17435
|
}
|
|
16981
|
-
),
|
|
16982
|
-
/* @__PURE__ */ jsxRuntime.
|
|
16983
|
-
|
|
16984
|
-
|
|
17436
|
+
) }),
|
|
17437
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-end gap-2 pt-2", children: [
|
|
17438
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17439
|
+
"textarea",
|
|
17440
|
+
{
|
|
17441
|
+
ref: textareaRef,
|
|
17442
|
+
rows: 3,
|
|
17443
|
+
value: inFeedbackMode ? feedbackNote : input,
|
|
17444
|
+
onChange: (e) => inFeedbackMode ? setFeedbackNote(e.target.value) : setInput(e.target.value),
|
|
17445
|
+
onKeyDown: handleKeyDown,
|
|
17446
|
+
placeholder: inFeedbackMode ? feedbackRating <= 2 ? "What went wrong? (optional)" : "Add a note (optional)" : "Ask for menu suggestions...",
|
|
17447
|
+
disabled: bootstrapping || !sessionId,
|
|
17448
|
+
className: "flex-1 bg-transparent text-sm text-gray-800 placeholder:text-gray-400 outline-none resize-none leading-snug py-1 overflow-hidden"
|
|
17449
|
+
}
|
|
17450
|
+
),
|
|
17451
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17452
|
+
"button",
|
|
17453
|
+
{
|
|
17454
|
+
type: "submit",
|
|
17455
|
+
disabled: inFeedbackMode ? feedbackRating < 1 || feedbackState === "sending" : sending || bootstrapping || !input.trim() || !sessionId || !hasAddress,
|
|
17456
|
+
className: "flex h-7 w-7 flex-shrink-0 items-center justify-center rounded-full bg-primary text-white transition-colors hover:bg-primary/90 disabled:opacity-50",
|
|
17457
|
+
title: inFeedbackMode ? "Submit feedback" : hasAddress ? "Send" : "Enter a delivery address first",
|
|
17458
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Send, { className: "w-3.5 h-3.5" })
|
|
17459
|
+
}
|
|
17460
|
+
)
|
|
17461
|
+
] })
|
|
16985
17462
|
]
|
|
16986
17463
|
}
|
|
16987
|
-
),
|
|
16988
|
-
pillEditing && /* @__PURE__ */ jsxRuntime.jsx(
|
|
16989
|
-
"div",
|
|
16990
|
-
{
|
|
16991
|
-
ref: pillEditRef,
|
|
16992
|
-
className: "mb-2 rounded-xl border border-base-300 bg-white px-3 py-2",
|
|
16993
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
16994
|
-
ChatAddressInput,
|
|
16995
|
-
{
|
|
16996
|
-
onPlaceSelect: handlePlaceSelect,
|
|
16997
|
-
onClear: handleClearAddress,
|
|
16998
|
-
initialQuery: contactInfo?.addressLine1 ?? "",
|
|
16999
|
-
autoFocus: true
|
|
17000
|
-
}
|
|
17001
|
-
)
|
|
17002
|
-
}
|
|
17003
|
-
),
|
|
17004
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
17464
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
17005
17465
|
"form",
|
|
17006
17466
|
{
|
|
17007
17467
|
onSubmit: handleSubmit,
|
|
@@ -17012,11 +17472,11 @@ function AIChatBody() {
|
|
|
17012
17472
|
{
|
|
17013
17473
|
ref: textareaRef,
|
|
17014
17474
|
rows: 1,
|
|
17015
|
-
value: input,
|
|
17016
|
-
onChange: (e) => setInput(e.target.value),
|
|
17475
|
+
value: inFeedbackMode ? feedbackNote : input,
|
|
17476
|
+
onChange: (e) => inFeedbackMode ? setFeedbackNote(e.target.value) : setInput(e.target.value),
|
|
17017
17477
|
onKeyDown: handleKeyDown,
|
|
17018
|
-
placeholder: "Ask for menu suggestions...",
|
|
17019
|
-
disabled: bootstrapping || !sessionId,
|
|
17478
|
+
placeholder: inFeedbackMode ? feedbackRating <= 2 ? "What went wrong? (optional)" : "Add a note (optional)" : "Ask for menu suggestions...",
|
|
17479
|
+
disabled: inFeedbackMode ? feedbackState === "sending" : bootstrapping || !sessionId,
|
|
17020
17480
|
className: "flex-1 bg-transparent text-sm text-gray-800 placeholder:text-gray-400 outline-none resize-none leading-snug py-1 overflow-hidden"
|
|
17021
17481
|
}
|
|
17022
17482
|
),
|
|
@@ -17024,19 +17484,19 @@ function AIChatBody() {
|
|
|
17024
17484
|
"button",
|
|
17025
17485
|
{
|
|
17026
17486
|
type: "submit",
|
|
17027
|
-
disabled: sending || bootstrapping || !input.trim() || !sessionId,
|
|
17487
|
+
disabled: inFeedbackMode ? feedbackRating < 1 || feedbackState === "sending" : sending || bootstrapping || !input.trim() || !sessionId,
|
|
17028
17488
|
className: "flex h-7 w-7 flex-shrink-0 items-center justify-center rounded-full bg-primary text-white transition-colors hover:bg-primary/90 disabled:opacity-50",
|
|
17029
|
-
title: "Send",
|
|
17489
|
+
title: inFeedbackMode ? "Submit feedback" : "Send",
|
|
17030
17490
|
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Send, { className: "w-3.5 h-3.5" })
|
|
17031
17491
|
}
|
|
17032
17492
|
)
|
|
17033
17493
|
]
|
|
17034
17494
|
}
|
|
17035
|
-
)
|
|
17036
|
-
|
|
17037
|
-
|
|
17038
|
-
|
|
17039
|
-
|
|
17495
|
+
) })
|
|
17496
|
+
},
|
|
17497
|
+
"input"
|
|
17498
|
+
) })
|
|
17499
|
+
] }),
|
|
17040
17500
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17041
17501
|
SwapModal,
|
|
17042
17502
|
{
|
|
@@ -17075,6 +17535,213 @@ function AIChatBody() {
|
|
|
17075
17535
|
)
|
|
17076
17536
|
] });
|
|
17077
17537
|
}
|
|
17538
|
+
function MobileAddressPickerSurface({
|
|
17539
|
+
onPlaceSelect,
|
|
17540
|
+
onBack,
|
|
17541
|
+
onRemove,
|
|
17542
|
+
onClose,
|
|
17543
|
+
hasAddress,
|
|
17544
|
+
initialQuery
|
|
17545
|
+
}) {
|
|
17546
|
+
const {
|
|
17547
|
+
inputRef,
|
|
17548
|
+
containerRef,
|
|
17549
|
+
query,
|
|
17550
|
+
setQuery,
|
|
17551
|
+
predictions,
|
|
17552
|
+
activeIndex,
|
|
17553
|
+
setActiveIndex,
|
|
17554
|
+
handleSelect,
|
|
17555
|
+
handleKeyDown
|
|
17556
|
+
} = useAddressAutocomplete(onPlaceSelect);
|
|
17557
|
+
react.useEffect(() => {
|
|
17558
|
+
if (initialQuery) setQuery(initialQuery);
|
|
17559
|
+
}, []);
|
|
17560
|
+
react.useEffect(() => {
|
|
17561
|
+
inputRef.current?.focus();
|
|
17562
|
+
}, []);
|
|
17563
|
+
const handleSearchKeyDown = (e) => {
|
|
17564
|
+
if (e.key === "Enter" && activeIndex < 0) {
|
|
17565
|
+
e.preventDefault();
|
|
17566
|
+
inputRef.current?.blur();
|
|
17567
|
+
return;
|
|
17568
|
+
}
|
|
17569
|
+
handleKeyDown(e);
|
|
17570
|
+
};
|
|
17571
|
+
const handleSurfacePointerDown = (e) => {
|
|
17572
|
+
const target = e.target;
|
|
17573
|
+
if (!target) return;
|
|
17574
|
+
if (target.closest("[data-keep-keyboard]")) return;
|
|
17575
|
+
if (target.closest("button")) return;
|
|
17576
|
+
inputRef.current?.blur();
|
|
17577
|
+
};
|
|
17578
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
17579
|
+
react$1.motion.div,
|
|
17580
|
+
{
|
|
17581
|
+
initial: { opacity: 0 },
|
|
17582
|
+
animate: { opacity: 1 },
|
|
17583
|
+
exit: { opacity: 0 },
|
|
17584
|
+
transition: { duration: 0.18, ease: "easeOut" },
|
|
17585
|
+
onPointerDown: handleSurfacePointerDown,
|
|
17586
|
+
className: "absolute inset-0 flex flex-col bg-white",
|
|
17587
|
+
children: [
|
|
17588
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-shrink-0 flex items-center justify-between px-3 pt-3", children: [
|
|
17589
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17590
|
+
"button",
|
|
17591
|
+
{
|
|
17592
|
+
type: "button",
|
|
17593
|
+
onClick: onBack,
|
|
17594
|
+
"aria-label": "Back to chat",
|
|
17595
|
+
"aria-hidden": !hasAddress,
|
|
17596
|
+
tabIndex: hasAddress ? 0 : -1,
|
|
17597
|
+
className: `flex h-9 w-9 items-center justify-center rounded-full text-gray-700 hover:bg-base-100 transition-opacity ${hasAddress ? "opacity-100" : "pointer-events-none opacity-0"}`,
|
|
17598
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeft, { className: "h-4 w-4" })
|
|
17599
|
+
}
|
|
17600
|
+
),
|
|
17601
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17602
|
+
"button",
|
|
17603
|
+
{
|
|
17604
|
+
type: "button",
|
|
17605
|
+
onClick: onClose,
|
|
17606
|
+
"aria-label": "Close AI chat",
|
|
17607
|
+
className: "flex h-9 w-9 items-center justify-center rounded-full text-gray-700 hover:bg-base-100",
|
|
17608
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-4 w-4" })
|
|
17609
|
+
}
|
|
17610
|
+
)
|
|
17611
|
+
] }),
|
|
17612
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
17613
|
+
"div",
|
|
17614
|
+
{
|
|
17615
|
+
ref: containerRef,
|
|
17616
|
+
className: "flex min-h-0 flex-1 flex-col px-6 pb-6",
|
|
17617
|
+
children: [
|
|
17618
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
17619
|
+
react$1.motion.div,
|
|
17620
|
+
{
|
|
17621
|
+
initial: { opacity: 0, y: 6 },
|
|
17622
|
+
animate: { opacity: 1, y: 0 },
|
|
17623
|
+
exit: { opacity: 0, y: 6 },
|
|
17624
|
+
transition: { duration: 0.2, delay: 0.08, ease: "easeOut" },
|
|
17625
|
+
className: "flex flex-shrink-0 flex-col items-center text-center pt-6 pb-6",
|
|
17626
|
+
children: [
|
|
17627
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-16 w-16 items-center justify-center rounded-full bg-primary/10", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MapPin, { className: "h-7 w-7 text-primary" }) }),
|
|
17628
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "mt-4 text-xl font-semibold text-gray-900", children: "Delivery address" }),
|
|
17629
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 max-w-[260px] text-sm text-gray-500", children: "Required to find caterers near you." })
|
|
17630
|
+
]
|
|
17631
|
+
}
|
|
17632
|
+
),
|
|
17633
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17634
|
+
react$1.motion.div,
|
|
17635
|
+
{
|
|
17636
|
+
layoutId: "catering-address-pill",
|
|
17637
|
+
transition: { duration: 0.28, ease: "easeOut" },
|
|
17638
|
+
"data-keep-keyboard": true,
|
|
17639
|
+
className: "flex-shrink-0 rounded-xl bg-base-100",
|
|
17640
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 px-3 py-2.5", children: [
|
|
17641
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17642
|
+
lucideReact.Search,
|
|
17643
|
+
{
|
|
17644
|
+
className: "h-4 w-4 flex-shrink-0 text-gray-400",
|
|
17645
|
+
"aria-hidden": true
|
|
17646
|
+
}
|
|
17647
|
+
),
|
|
17648
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17649
|
+
"input",
|
|
17650
|
+
{
|
|
17651
|
+
ref: inputRef,
|
|
17652
|
+
type: "search",
|
|
17653
|
+
value: query,
|
|
17654
|
+
onChange: (e) => setQuery(e.target.value),
|
|
17655
|
+
onKeyDown: handleSearchKeyDown,
|
|
17656
|
+
placeholder: "Search address\u2026",
|
|
17657
|
+
autoComplete: "off",
|
|
17658
|
+
autoCorrect: "off",
|
|
17659
|
+
autoCapitalize: "off",
|
|
17660
|
+
spellCheck: false,
|
|
17661
|
+
enterKeyHint: "search",
|
|
17662
|
+
className: "flex-1 bg-transparent text-base text-gray-800 placeholder:text-gray-400 outline-none py-1 touch-auto"
|
|
17663
|
+
}
|
|
17664
|
+
),
|
|
17665
|
+
query.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
17666
|
+
"button",
|
|
17667
|
+
{
|
|
17668
|
+
type: "button",
|
|
17669
|
+
onClick: () => {
|
|
17670
|
+
setQuery("");
|
|
17671
|
+
inputRef.current?.focus();
|
|
17672
|
+
},
|
|
17673
|
+
"aria-label": "Clear search",
|
|
17674
|
+
className: "flex-shrink-0 rounded-full p-0.5 text-gray-400 hover:bg-base-200 hover:text-gray-600 transition-colors",
|
|
17675
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "w-3.5 h-3.5" })
|
|
17676
|
+
}
|
|
17677
|
+
)
|
|
17678
|
+
] })
|
|
17679
|
+
}
|
|
17680
|
+
),
|
|
17681
|
+
predictions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
17682
|
+
react$1.motion.div,
|
|
17683
|
+
{
|
|
17684
|
+
initial: { opacity: 0 },
|
|
17685
|
+
animate: { opacity: 1 },
|
|
17686
|
+
exit: { opacity: 0 },
|
|
17687
|
+
transition: { duration: 0.18, ease: "easeOut" },
|
|
17688
|
+
"data-allow-touch": true,
|
|
17689
|
+
className: "mt-4 min-h-0 flex-1 overflow-y-auto overscroll-contain flex flex-col gap-2",
|
|
17690
|
+
children: predictions.map((p, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
17691
|
+
"button",
|
|
17692
|
+
{
|
|
17693
|
+
type: "button",
|
|
17694
|
+
onMouseDown: (e) => {
|
|
17695
|
+
e.preventDefault();
|
|
17696
|
+
handleSelect(p);
|
|
17697
|
+
inputRef.current?.blur();
|
|
17698
|
+
},
|
|
17699
|
+
onMouseEnter: () => setActiveIndex(idx),
|
|
17700
|
+
className: `flex w-full flex-shrink-0 items-start gap-3 rounded-xl border border-base-200 bg-white px-3 py-3 text-left transition-colors ${idx === activeIndex ? "bg-base-100" : "hover:bg-base-100"}`,
|
|
17701
|
+
children: [
|
|
17702
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17703
|
+
lucideReact.MapPin,
|
|
17704
|
+
{
|
|
17705
|
+
className: "h-4 w-4 flex-shrink-0 text-gray-500 mt-0.5",
|
|
17706
|
+
"aria-hidden": true
|
|
17707
|
+
}
|
|
17708
|
+
),
|
|
17709
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
17710
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "truncate text-sm font-semibold text-gray-900", children: p.structured_formatting.main_text }),
|
|
17711
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "truncate text-xs text-gray-500", children: p.structured_formatting.secondary_text })
|
|
17712
|
+
] })
|
|
17713
|
+
]
|
|
17714
|
+
},
|
|
17715
|
+
p.place_id
|
|
17716
|
+
))
|
|
17717
|
+
}
|
|
17718
|
+
),
|
|
17719
|
+
hasAddress && /* @__PURE__ */ jsxRuntime.jsx(
|
|
17720
|
+
react$1.motion.div,
|
|
17721
|
+
{
|
|
17722
|
+
initial: { opacity: 0 },
|
|
17723
|
+
animate: { opacity: 1 },
|
|
17724
|
+
exit: { opacity: 0 },
|
|
17725
|
+
transition: { duration: 0.18, delay: 0.16, ease: "easeOut" },
|
|
17726
|
+
className: "mt-6 flex flex-shrink-0 justify-center",
|
|
17727
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
17728
|
+
"button",
|
|
17729
|
+
{
|
|
17730
|
+
type: "button",
|
|
17731
|
+
onClick: onRemove,
|
|
17732
|
+
className: "text-sm font-medium text-red-600 hover:text-red-700 transition-colors",
|
|
17733
|
+
children: "Remove address"
|
|
17734
|
+
}
|
|
17735
|
+
)
|
|
17736
|
+
}
|
|
17737
|
+
)
|
|
17738
|
+
]
|
|
17739
|
+
}
|
|
17740
|
+
)
|
|
17741
|
+
]
|
|
17742
|
+
}
|
|
17743
|
+
);
|
|
17744
|
+
}
|
|
17078
17745
|
function AISuggestionsBottomButton() {
|
|
17079
17746
|
const {
|
|
17080
17747
|
hasResults,
|
|
@@ -17592,8 +18259,8 @@ function aiPlanToPricingInput(mealSessionParts, aiMealSessions, cart) {
|
|
|
17592
18259
|
if (orderItems.length === 0) continue;
|
|
17593
18260
|
out.push({
|
|
17594
18261
|
sessionName: meta?.sessionName ?? `Meal ${ms.mealSessionIndex + 1}`,
|
|
17595
|
-
sessionDate: meta?.
|
|
17596
|
-
eventTime: meta?.
|
|
18262
|
+
sessionDate: meta?.isoSessionDate ?? "",
|
|
18263
|
+
eventTime: meta?.isoEventTime ?? "",
|
|
17597
18264
|
guestCount: meta?.guestCount ?? void 0,
|
|
17598
18265
|
orderItems
|
|
17599
18266
|
});
|
|
@@ -18065,6 +18732,11 @@ function IntentStepper({
|
|
|
18065
18732
|
() => checkMinOrders(orderedMeals, aiMealSessions, cart),
|
|
18066
18733
|
[orderedMeals, aiMealSessions, cart]
|
|
18067
18734
|
);
|
|
18735
|
+
const myPos = orderedMeals.findIndex(
|
|
18736
|
+
(m) => m.mealSessionIndex === activeMealSessionIndex
|
|
18737
|
+
);
|
|
18738
|
+
const isFirstMeal = myPos <= 0;
|
|
18739
|
+
const isLastMeal = myPos >= 0 && myPos === orderedMeals.length - 1;
|
|
18068
18740
|
if (!activeMeal) {
|
|
18069
18741
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
18070
18742
|
"div",
|
|
@@ -18085,6 +18757,23 @@ function IntentStepper({
|
|
|
18085
18757
|
);
|
|
18086
18758
|
}
|
|
18087
18759
|
if (blocks.length === 0) {
|
|
18760
|
+
const emptyPrevLabel = !isFirstMeal ? aiMealSessions[orderedMeals[myPos - 1].mealSessionIndex]?.sessionName ?? null : null;
|
|
18761
|
+
const emptyNextLabel = !isLastMeal ? aiMealSessions[orderedMeals[myPos + 1].mealSessionIndex]?.sessionName ?? null : null;
|
|
18762
|
+
const handleEmptyPrev = () => {
|
|
18763
|
+
if (sending || isFirstMeal) return;
|
|
18764
|
+
pendingReviewRef.current = true;
|
|
18765
|
+
onPickMealSession(orderedMeals[myPos - 1].mealSessionIndex);
|
|
18766
|
+
};
|
|
18767
|
+
const handleEmptyNext = () => {
|
|
18768
|
+
if (sending || isLastMeal) return;
|
|
18769
|
+
onPickMealSession(orderedMeals[myPos + 1].mealSessionIndex);
|
|
18770
|
+
};
|
|
18771
|
+
const handleEmptyJumpTo = (targetMealSessionIndex, targetIntentIdx) => {
|
|
18772
|
+
if (sending) return;
|
|
18773
|
+
if (targetMealSessionIndex === activeMealSessionIndex) return;
|
|
18774
|
+
pendingIntentIdxRef.current = targetIntentIdx;
|
|
18775
|
+
onPickMealSession(targetMealSessionIndex);
|
|
18776
|
+
};
|
|
18088
18777
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
18089
18778
|
"div",
|
|
18090
18779
|
{
|
|
@@ -18094,11 +18783,34 @@ function IntentStepper({
|
|
|
18094
18783
|
flex: 1,
|
|
18095
18784
|
minHeight: 0,
|
|
18096
18785
|
marginBottom: 16,
|
|
18786
|
+
// Cluster topSlot + empty card + NavBar as one block centred
|
|
18787
|
+
// vertically — same trick the populated branch uses so the
|
|
18788
|
+
// tabs / nav don't get pinned to the panel's top/bottom
|
|
18789
|
+
// edges when the content above is short.
|
|
18097
18790
|
justifyContent: "center"
|
|
18098
18791
|
},
|
|
18099
18792
|
children: [
|
|
18100
18793
|
topSlot && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginBottom: 12, flexShrink: 0 }, children: topSlot }),
|
|
18101
|
-
/* @__PURE__ */ jsxRuntime.jsx(EmptyStepperState, {})
|
|
18794
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { flexShrink: 0, marginBottom: 8 }, children: /* @__PURE__ */ jsxRuntime.jsx(EmptyStepperState, { missingFields: activeMealMeta?.missingFields }) }),
|
|
18795
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
18796
|
+
NavBar,
|
|
18797
|
+
{
|
|
18798
|
+
onPrev: handleEmptyPrev,
|
|
18799
|
+
onNext: handleEmptyNext,
|
|
18800
|
+
onJumpTo: handleEmptyJumpTo,
|
|
18801
|
+
prevLabel: emptyPrevLabel,
|
|
18802
|
+
nextLabel: emptyNextLabel,
|
|
18803
|
+
atFinal: false,
|
|
18804
|
+
sending,
|
|
18805
|
+
showPrev: !isFirstMeal,
|
|
18806
|
+
showNext: !isLastMeal,
|
|
18807
|
+
mealSessions: orderedMeals,
|
|
18808
|
+
aiMealSessions,
|
|
18809
|
+
activeMealSessionIndex,
|
|
18810
|
+
currentIntentIndex: 0,
|
|
18811
|
+
cart
|
|
18812
|
+
}
|
|
18813
|
+
)
|
|
18102
18814
|
]
|
|
18103
18815
|
}
|
|
18104
18816
|
);
|
|
@@ -18106,13 +18818,8 @@ function IntentStepper({
|
|
|
18106
18818
|
const pickedName = selected?.restaurant.name ?? "\u2014";
|
|
18107
18819
|
const pickedId = selected?.restaurant.id ?? "";
|
|
18108
18820
|
const alts = block ? block.restaurantPicks.filter((rp) => rp.restaurant.id !== pickedId) : [];
|
|
18109
|
-
const myPos = orderedMeals.findIndex(
|
|
18110
|
-
(m) => m.mealSessionIndex === activeMealSessionIndex
|
|
18111
|
-
);
|
|
18112
18821
|
const isFirstIntent = !isReview && safeIntentIdx === 0;
|
|
18113
18822
|
const isLastIntent = !isReview && safeIntentIdx === blocks.length - 1;
|
|
18114
|
-
const isFirstMeal = myPos <= 0;
|
|
18115
|
-
const isLastMeal = myPos >= 0 && myPos === orderedMeals.length - 1;
|
|
18116
18823
|
const atFinal = isReview && isLastMeal;
|
|
18117
18824
|
const prevLabel = isReview ? capitalize(blocks[blocks.length - 1].intent.phrase) : !isFirstIntent ? capitalize(blocks[safeIntentIdx - 1].intent.phrase) : !isFirstMeal ? aiMealSessions[orderedMeals[myPos - 1].mealSessionIndex]?.sessionName ?? null : null;
|
|
18118
18825
|
const nextLabel = isReview ? !isLastMeal ? aiMealSessions[orderedMeals[myPos + 1].mealSessionIndex]?.sessionName ?? null : null : !isLastIntent ? capitalize(blocks[safeIntentIdx + 1].intent.phrase) : "Review";
|
|
@@ -18218,8 +18925,11 @@ function IntentStepper({
|
|
|
18218
18925
|
{
|
|
18219
18926
|
total: blocks.length + 1,
|
|
18220
18927
|
currentIdx: safeIntentIdx,
|
|
18221
|
-
|
|
18222
|
-
|
|
18928
|
+
labels: [
|
|
18929
|
+
...blocks.map((b) => capitalize(b.intent.phrase)),
|
|
18930
|
+
"Review"
|
|
18931
|
+
],
|
|
18932
|
+
onStepClick: setIntentIndex
|
|
18223
18933
|
}
|
|
18224
18934
|
),
|
|
18225
18935
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { padding: "8px 18px 14px" }, children: [
|
|
@@ -18496,11 +19206,114 @@ function capitalize(s) {
|
|
|
18496
19206
|
if (!s) return s;
|
|
18497
19207
|
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
18498
19208
|
}
|
|
19209
|
+
var CHEVRON_DEPTH = 10;
|
|
19210
|
+
var CHEVRON_HEIGHT = 34;
|
|
19211
|
+
var CHEVRON_RADIUS = 8;
|
|
19212
|
+
function chevronPath(w, h, pos) {
|
|
19213
|
+
const d = CHEVRON_DEPTH;
|
|
19214
|
+
const r = CHEVRON_RADIUS;
|
|
19215
|
+
if (pos === "only") {
|
|
19216
|
+
return `M${r},0 H${w - r} Q${w},0 ${w},${r} V${h - r} Q${w},${h} ${w - r},${h} H${r} Q0,${h} 0,${h - r} V${r} Q0,0 ${r},0Z`;
|
|
19217
|
+
}
|
|
19218
|
+
if (pos === "first") {
|
|
19219
|
+
return `M${r},0 H${w - d} L${w},${h / 2} L${w - d},${h} H${r} Q0,${h} 0,${h - r} V${r} Q0,0 ${r},0Z`;
|
|
19220
|
+
}
|
|
19221
|
+
if (pos === "last") {
|
|
19222
|
+
return `M0,0 H${w - r} Q${w},0 ${w},${r} V${h - r} Q${w},${h} ${w - r},${h} H0 L${d},${h / 2}Z`;
|
|
19223
|
+
}
|
|
19224
|
+
return `M0,0 H${w - d} L${w},${h / 2} L${w - d},${h} H0 L${d},${h / 2}Z`;
|
|
19225
|
+
}
|
|
19226
|
+
function ChevronStep({
|
|
19227
|
+
label,
|
|
19228
|
+
status,
|
|
19229
|
+
pos,
|
|
19230
|
+
onClick
|
|
19231
|
+
}) {
|
|
19232
|
+
const ref = react.useRef(null);
|
|
19233
|
+
const [width, setWidth] = react.useState(0);
|
|
19234
|
+
react.useEffect(() => {
|
|
19235
|
+
if (!ref.current) return;
|
|
19236
|
+
const ro = new ResizeObserver(([entry]) => {
|
|
19237
|
+
setWidth(Math.round(entry.contentRect.width));
|
|
19238
|
+
});
|
|
19239
|
+
ro.observe(ref.current);
|
|
19240
|
+
return () => ro.disconnect();
|
|
19241
|
+
}, []);
|
|
19242
|
+
const fill = status === "done" ? "color-mix(in srgb, var(--brand) 80%, var(--paper))" : status === "active" ? "var(--brand)" : "var(--rule)";
|
|
19243
|
+
const textColor = status === "done" || status === "active" ? "var(--paper)" : "var(--ink-faint)";
|
|
19244
|
+
const isNotched = pos === "middle" || pos === "last";
|
|
19245
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
19246
|
+
"div",
|
|
19247
|
+
{
|
|
19248
|
+
ref,
|
|
19249
|
+
role: onClick ? "button" : void 0,
|
|
19250
|
+
tabIndex: onClick ? 0 : void 0,
|
|
19251
|
+
onClick,
|
|
19252
|
+
onKeyDown: onClick ? (e) => {
|
|
19253
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
19254
|
+
e.preventDefault();
|
|
19255
|
+
onClick();
|
|
19256
|
+
}
|
|
19257
|
+
} : void 0,
|
|
19258
|
+
style: {
|
|
19259
|
+
flex: 1,
|
|
19260
|
+
minWidth: 0,
|
|
19261
|
+
height: CHEVRON_HEIGHT,
|
|
19262
|
+
position: "relative",
|
|
19263
|
+
marginLeft: isNotched ? -1 : 0,
|
|
19264
|
+
cursor: onClick ? "pointer" : void 0
|
|
19265
|
+
},
|
|
19266
|
+
children: [
|
|
19267
|
+
width > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
19268
|
+
"svg",
|
|
19269
|
+
{
|
|
19270
|
+
width,
|
|
19271
|
+
height: CHEVRON_HEIGHT,
|
|
19272
|
+
viewBox: `0 0 ${width} ${CHEVRON_HEIGHT}`,
|
|
19273
|
+
style: { position: "absolute", inset: 0 },
|
|
19274
|
+
"aria-hidden": "true",
|
|
19275
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: chevronPath(width, CHEVRON_HEIGHT, pos), fill })
|
|
19276
|
+
}
|
|
19277
|
+
),
|
|
19278
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
19279
|
+
"div",
|
|
19280
|
+
{
|
|
19281
|
+
style: {
|
|
19282
|
+
position: "relative",
|
|
19283
|
+
height: "100%",
|
|
19284
|
+
display: "flex",
|
|
19285
|
+
alignItems: "center",
|
|
19286
|
+
justifyContent: "center",
|
|
19287
|
+
paddingLeft: isNotched ? CHEVRON_DEPTH + 4 : 12,
|
|
19288
|
+
paddingRight: pos === "last" || pos === "only" ? 12 : CHEVRON_DEPTH + 4
|
|
19289
|
+
},
|
|
19290
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
19291
|
+
"span",
|
|
19292
|
+
{
|
|
19293
|
+
style: {
|
|
19294
|
+
fontSize: "0.72rem",
|
|
19295
|
+
fontWeight: status === "active" ? 600 : 400,
|
|
19296
|
+
color: textColor,
|
|
19297
|
+
whiteSpace: "nowrap",
|
|
19298
|
+
overflow: "hidden",
|
|
19299
|
+
textOverflow: "ellipsis",
|
|
19300
|
+
textTransform: "capitalize",
|
|
19301
|
+
letterSpacing: "0.01em"
|
|
19302
|
+
},
|
|
19303
|
+
children: label
|
|
19304
|
+
}
|
|
19305
|
+
)
|
|
19306
|
+
}
|
|
19307
|
+
)
|
|
19308
|
+
]
|
|
19309
|
+
}
|
|
19310
|
+
);
|
|
19311
|
+
}
|
|
18499
19312
|
function ProgressStrip({
|
|
18500
19313
|
total,
|
|
18501
19314
|
currentIdx,
|
|
18502
|
-
|
|
18503
|
-
|
|
19315
|
+
labels,
|
|
19316
|
+
onStepClick
|
|
18504
19317
|
}) {
|
|
18505
19318
|
const { dismissSuggestionsOverlay } = useChatSessionContext();
|
|
18506
19319
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -18508,40 +19321,25 @@ function ProgressStrip({
|
|
|
18508
19321
|
{
|
|
18509
19322
|
style: {
|
|
18510
19323
|
display: "flex",
|
|
18511
|
-
gap: 6,
|
|
18512
19324
|
alignItems: "center",
|
|
19325
|
+
gap: 10,
|
|
18513
19326
|
padding: "16px 18px 8px"
|
|
18514
19327
|
},
|
|
18515
19328
|
children: [
|
|
18516
|
-
Array.from({ length: total }, (_, i) =>
|
|
18517
|
-
"
|
|
18518
|
-
|
|
18519
|
-
|
|
18520
|
-
|
|
18521
|
-
|
|
18522
|
-
|
|
18523
|
-
|
|
18524
|
-
|
|
18525
|
-
|
|
18526
|
-
},
|
|
18527
|
-
i
|
|
18528
|
-
)),
|
|
18529
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
18530
|
-
"span",
|
|
18531
|
-
{
|
|
18532
|
-
style: {
|
|
18533
|
-
color: "var(--ink-faint)",
|
|
18534
|
-
fontSize: "0.78rem",
|
|
18535
|
-
marginLeft: 8,
|
|
18536
|
-
whiteSpace: "nowrap"
|
|
19329
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flex: 1, minWidth: 0 }, children: Array.from({ length: total }, (_, i) => {
|
|
19330
|
+
const status = i < currentIdx ? "done" : i === currentIdx ? "active" : "pending";
|
|
19331
|
+
const pos = total === 1 ? "only" : i === 0 ? "first" : i === total - 1 ? "last" : "middle";
|
|
19332
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
19333
|
+
ChevronStep,
|
|
19334
|
+
{
|
|
19335
|
+
label: labels[i] ?? `Step ${i + 1}`,
|
|
19336
|
+
status,
|
|
19337
|
+
pos,
|
|
19338
|
+
onClick: onStepClick && i !== currentIdx ? () => onStepClick(i) : void 0
|
|
18537
19339
|
},
|
|
18538
|
-
|
|
18539
|
-
|
|
18540
|
-
|
|
18541
|
-
mealName
|
|
18542
|
-
]
|
|
18543
|
-
}
|
|
18544
|
-
),
|
|
19340
|
+
i
|
|
19341
|
+
);
|
|
19342
|
+
}) }),
|
|
18545
19343
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
18546
19344
|
"button",
|
|
18547
19345
|
{
|
|
@@ -18553,7 +19351,6 @@ function ProgressStrip({
|
|
|
18553
19351
|
style: {
|
|
18554
19352
|
width: 36,
|
|
18555
19353
|
height: 36,
|
|
18556
|
-
marginLeft: 10,
|
|
18557
19354
|
borderRadius: 999,
|
|
18558
19355
|
border: "none",
|
|
18559
19356
|
background: "var(--ink)",
|
|
@@ -18579,6 +19376,7 @@ function NavBar({
|
|
|
18579
19376
|
atFinal,
|
|
18580
19377
|
sending,
|
|
18581
19378
|
showPrev,
|
|
19379
|
+
showNext = true,
|
|
18582
19380
|
mealSessions,
|
|
18583
19381
|
aiMealSessions,
|
|
18584
19382
|
activeMealSessionIndex,
|
|
@@ -18665,7 +19463,7 @@ function NavBar({
|
|
|
18665
19463
|
{
|
|
18666
19464
|
type: "button",
|
|
18667
19465
|
onClick: onNext,
|
|
18668
|
-
disabled: sending,
|
|
19466
|
+
disabled: !showNext || sending,
|
|
18669
19467
|
className: "chip chip-brand",
|
|
18670
19468
|
style: {
|
|
18671
19469
|
height: 40,
|
|
@@ -18673,6 +19471,7 @@ function NavBar({
|
|
|
18673
19471
|
fontSize: atFinal ? "0.95rem" : "0.85rem",
|
|
18674
19472
|
fontWeight: 500,
|
|
18675
19473
|
justifyContent: "center",
|
|
19474
|
+
visibility: showNext ? "visible" : "hidden",
|
|
18676
19475
|
cursor: sending ? "default" : "pointer",
|
|
18677
19476
|
opacity: sending ? 0.7 : 1
|
|
18678
19477
|
},
|
|
@@ -18700,10 +19499,11 @@ function TimelinePill({
|
|
|
18700
19499
|
const activeMeal = mealSessions[activeMealPos];
|
|
18701
19500
|
if (!activeMeal) return null;
|
|
18702
19501
|
const activeMealMeta = aiMealSessions[activeMeal.mealSessionIndex];
|
|
18703
|
-
const
|
|
19502
|
+
const isEmptyMeal = activeMeal.intentBlocks.length === 0;
|
|
19503
|
+
const isReviewStep = !isEmptyMeal && currentIntentIndex === activeMeal.intentBlocks.length;
|
|
18704
19504
|
const currentIntent = activeMeal.intentBlocks[currentIntentIndex];
|
|
18705
|
-
if (!isReviewStep && !currentIntent) return null;
|
|
18706
|
-
const labelText = isReviewStep ? "Review" : currentIntent.intent.phrase;
|
|
19505
|
+
if (!isEmptyMeal && !isReviewStep && !currentIntent) return null;
|
|
19506
|
+
const labelText = isEmptyMeal ? null : isReviewStep ? "Review" : currentIntent.intent.phrase;
|
|
18707
19507
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
18708
19508
|
"div",
|
|
18709
19509
|
{
|
|
@@ -18735,14 +19535,23 @@ function TimelinePill({
|
|
|
18735
19535
|
opacity: hovered ? 1 : 0.85,
|
|
18736
19536
|
transition: "opacity 150ms ease"
|
|
18737
19537
|
},
|
|
18738
|
-
"aria-label": `Step ${currentIntentIndex + 1} of ${activeMeal.intentBlocks.length + 1}: ${labelText}. Click to see the full itinerary.`,
|
|
19538
|
+
"aria-label": isEmptyMeal ? `${activeMealMeta?.sessionName ?? "Meal"}. Click to see the full itinerary.` : `Step ${currentIntentIndex + 1} of ${activeMeal.intentBlocks.length + 1}: ${labelText}. Click to see the full itinerary.`,
|
|
18739
19539
|
"aria-expanded": hovered,
|
|
18740
19540
|
children: [
|
|
18741
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
18742
|
-
|
|
18743
|
-
|
|
18744
|
-
|
|
18745
|
-
|
|
19541
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
19542
|
+
"span",
|
|
19543
|
+
{
|
|
19544
|
+
style: {
|
|
19545
|
+
color: isEmptyMeal ? "var(--ink)" : "var(--ink-faint)",
|
|
19546
|
+
fontWeight: isEmptyMeal ? 500 : 400
|
|
19547
|
+
},
|
|
19548
|
+
children: [
|
|
19549
|
+
activeMealMeta?.sessionName ?? `Meal ${activeMeal.mealSessionIndex + 1}`,
|
|
19550
|
+
!isEmptyMeal && " \xB7 "
|
|
19551
|
+
]
|
|
19552
|
+
}
|
|
19553
|
+
),
|
|
19554
|
+
!isEmptyMeal && /* @__PURE__ */ jsxRuntime.jsx(
|
|
18746
19555
|
"span",
|
|
18747
19556
|
{
|
|
18748
19557
|
style: {
|
|
@@ -19222,7 +20031,23 @@ function EmptyIntentState({ message }) {
|
|
|
19222
20031
|
}
|
|
19223
20032
|
);
|
|
19224
20033
|
}
|
|
19225
|
-
|
|
20034
|
+
var MISSING_FIELD_LABELS = {
|
|
20035
|
+
guestCount: "guest count",
|
|
20036
|
+
sessionDate: "date",
|
|
20037
|
+
eventTime: "time"
|
|
20038
|
+
};
|
|
20039
|
+
function formatMissingFieldList(fields) {
|
|
20040
|
+
const labels = fields.map((f) => MISSING_FIELD_LABELS[f] ?? f);
|
|
20041
|
+
if (labels.length === 0) return "";
|
|
20042
|
+
if (labels.length === 1) return labels[0];
|
|
20043
|
+
if (labels.length === 2) return `${labels[0]} and ${labels[1]}`;
|
|
20044
|
+
return `${labels.slice(0, -1).join(", ")}, and ${labels[labels.length - 1]}`;
|
|
20045
|
+
}
|
|
20046
|
+
function EmptyStepperState({
|
|
20047
|
+
missingFields
|
|
20048
|
+
}) {
|
|
20049
|
+
const hasMissing = !!missingFields && missingFields.length > 0;
|
|
20050
|
+
const label = hasMissing ? formatMissingFieldList(missingFields) : null;
|
|
19226
20051
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
19227
20052
|
"div",
|
|
19228
20053
|
{
|
|
@@ -19234,7 +20059,11 @@ function EmptyStepperState() {
|
|
|
19234
20059
|
textAlign: "center",
|
|
19235
20060
|
color: "var(--ink-faint)"
|
|
19236
20061
|
},
|
|
19237
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "display-italic", style: { fontSize: "0.95rem" }, children:
|
|
20062
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "display-italic", style: { fontSize: "0.95rem" }, children: hasMissing ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
20063
|
+
"Tell me the ",
|
|
20064
|
+
label,
|
|
20065
|
+
" for this meal and I'll suggest a menu."
|
|
20066
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: "No items yet for this meal \u2014 keep chatting on the right." }) })
|
|
19238
20067
|
}
|
|
19239
20068
|
);
|
|
19240
20069
|
}
|
|
@@ -26049,17 +26878,8 @@ function useCateringTutorial({
|
|
|
26049
26878
|
const [tutorialStep, setTutorialStep] = react.useState(null);
|
|
26050
26879
|
const [tutorialPhase, setTutorialPhase] = react.useState("navigation");
|
|
26051
26880
|
react.useEffect(() => {
|
|
26052
|
-
|
|
26053
|
-
|
|
26054
|
-
setTutorialPhase("completed");
|
|
26055
|
-
setTutorialStep(null);
|
|
26056
|
-
} else if (mealSessions.length === 1 && mealSessions[0].orderItems.length === 0) {
|
|
26057
|
-
setTutorialPhase("navigation");
|
|
26058
|
-
setTutorialStep(0);
|
|
26059
|
-
} else {
|
|
26060
|
-
setTutorialPhase("completed");
|
|
26061
|
-
setTutorialStep(null);
|
|
26062
|
-
}
|
|
26881
|
+
setTutorialPhase("completed");
|
|
26882
|
+
setTutorialStep(null);
|
|
26063
26883
|
}, []);
|
|
26064
26884
|
const getTutorialSteps = react.useCallback(() => {
|
|
26065
26885
|
switch (tutorialPhase) {
|
|
@@ -26481,6 +27301,7 @@ function CateringOrderBuilder() {
|
|
|
26481
27301
|
const [removeItemIndex, setRemoveItemIndex] = react.useState(null);
|
|
26482
27302
|
const [isClearAllConfirmOpen, setIsClearAllConfirmOpen] = react.useState(false);
|
|
26483
27303
|
const [isMobileCartMenuOpen, setIsMobileCartMenuOpen] = react.useState(false);
|
|
27304
|
+
const [isMobileChatMenuOpen, setIsMobileChatMenuOpen] = react.useState(false);
|
|
26484
27305
|
const [isDesktopCartMenuOpen, setIsDesktopCartMenuOpen] = react.useState(false);
|
|
26485
27306
|
const [isAIMobileUnavailableOpen, setIsAIMobileUnavailableOpen] = react.useState(false);
|
|
26486
27307
|
const storage = useStorage();
|
|
@@ -26500,11 +27321,20 @@ function CateringOrderBuilder() {
|
|
|
26500
27321
|
"chat"
|
|
26501
27322
|
);
|
|
26502
27323
|
react.useEffect(() => {
|
|
26503
|
-
if (!isMobileAIChatOpen)
|
|
27324
|
+
if (!isMobileAIChatOpen) {
|
|
27325
|
+
setMobileChatView("chat");
|
|
27326
|
+
setMobileAddressPillEditing(false);
|
|
27327
|
+
setIsMobileChatMenuOpen(false);
|
|
27328
|
+
}
|
|
26504
27329
|
}, [isMobileAIChatOpen]);
|
|
26505
27330
|
const [mobileAIInput, setMobileAIInput] = react.useState("");
|
|
26506
27331
|
const [mobileAIInputHeight, setMobileAIInputHeight] = react.useState(44);
|
|
26507
27332
|
const mobileAIInputRef = react.useRef(null);
|
|
27333
|
+
const [mobileGateError, setMobileGateError] = react.useState(null);
|
|
27334
|
+
const mobileChatScrollRef = react.useRef(null);
|
|
27335
|
+
const [mobileAddressPillEditing, setMobileAddressPillEditing] = react.useState(false);
|
|
27336
|
+
const buildChatAddress = useChatAddressFromContext();
|
|
27337
|
+
const hasChatAddress = !!(contactInfo?.addressLine1 && contactInfo.latitude !== void 0 && contactInfo.longitude !== void 0);
|
|
26508
27338
|
const handleMobileAIInput = () => {
|
|
26509
27339
|
const el = mobileAIInputRef.current;
|
|
26510
27340
|
if (!el) return;
|
|
@@ -26523,6 +27353,7 @@ function CateringOrderBuilder() {
|
|
|
26523
27353
|
}
|
|
26524
27354
|
};
|
|
26525
27355
|
const [isMobileSearchOpen, setIsMobileSearchOpen] = react.useState(false);
|
|
27356
|
+
const [isMobileSearchActive, setIsMobileSearchActive] = react.useState(false);
|
|
26526
27357
|
const [mobileSearchState, setMobileSearchState] = react.useState({ mode: "list", query: "" });
|
|
26527
27358
|
const mobileSearchSetterRef = react.useRef(null);
|
|
26528
27359
|
const mobileSearchInputRef = react.useRef(null);
|
|
@@ -26530,12 +27361,17 @@ function CateringOrderBuilder() {
|
|
|
26530
27361
|
const suppressMobileSearchScrollCloseRef = react.useRef(false);
|
|
26531
27362
|
const [mobileSearchCaretVisible, setMobileSearchCaretVisible] = react.useState(false);
|
|
26532
27363
|
const [keyboardOffset, setKeyboardOffset] = react.useState(0);
|
|
27364
|
+
const [vvOffsetTop, setVvOffsetTop] = react.useState(0);
|
|
27365
|
+
const [vvHeight, setVvHeight] = react.useState(null);
|
|
26533
27366
|
react.useEffect(() => {
|
|
26534
27367
|
if (typeof window === "undefined" || !window.visualViewport) return;
|
|
26535
27368
|
const vv = window.visualViewport;
|
|
26536
27369
|
const update = () => {
|
|
26537
|
-
|
|
26538
|
-
|
|
27370
|
+
setKeyboardOffset(
|
|
27371
|
+
Math.max(0, window.innerHeight - vv.height - vv.offsetTop)
|
|
27372
|
+
);
|
|
27373
|
+
setVvOffsetTop(vv.offsetTop);
|
|
27374
|
+
setVvHeight(vv.height);
|
|
26539
27375
|
};
|
|
26540
27376
|
update();
|
|
26541
27377
|
vv.addEventListener("resize", update);
|
|
@@ -26545,6 +27381,48 @@ function CateringOrderBuilder() {
|
|
|
26545
27381
|
vv.removeEventListener("scroll", update);
|
|
26546
27382
|
};
|
|
26547
27383
|
}, []);
|
|
27384
|
+
react.useEffect(() => {
|
|
27385
|
+
if (typeof document === "undefined") return;
|
|
27386
|
+
if (!isMobileAIChatOpen) return;
|
|
27387
|
+
const html = document.documentElement;
|
|
27388
|
+
const body = document.body;
|
|
27389
|
+
const prev = {
|
|
27390
|
+
htmlOverflow: html.style.overflow,
|
|
27391
|
+
bodyOverflow: body.style.overflow,
|
|
27392
|
+
bodyOverscroll: body.style.overscrollBehavior
|
|
27393
|
+
};
|
|
27394
|
+
html.style.overflow = "hidden";
|
|
27395
|
+
body.style.overflow = "hidden";
|
|
27396
|
+
body.style.overscrollBehavior = "none";
|
|
27397
|
+
const preventTouch = (e) => {
|
|
27398
|
+
const target = e.target;
|
|
27399
|
+
if (target?.closest?.("[data-allow-touch]")) return;
|
|
27400
|
+
if (target instanceof HTMLTextAreaElement && target.scrollHeight > target.clientHeight + 1) {
|
|
27401
|
+
return;
|
|
27402
|
+
}
|
|
27403
|
+
e.preventDefault();
|
|
27404
|
+
};
|
|
27405
|
+
document.addEventListener("touchmove", preventTouch, { passive: false });
|
|
27406
|
+
return () => {
|
|
27407
|
+
html.style.overflow = prev.htmlOverflow;
|
|
27408
|
+
body.style.overflow = prev.bodyOverflow;
|
|
27409
|
+
body.style.overscrollBehavior = prev.bodyOverscroll;
|
|
27410
|
+
document.removeEventListener("touchmove", preventTouch);
|
|
27411
|
+
};
|
|
27412
|
+
}, [isMobileAIChatOpen]);
|
|
27413
|
+
const [chatInputFocused, setChatInputFocused] = react.useState(false);
|
|
27414
|
+
react.useEffect(() => {
|
|
27415
|
+
if (!isMobileAIChatOpen) return;
|
|
27416
|
+
if (!chatInputFocused) return;
|
|
27417
|
+
const el = mobileChatScrollRef.current;
|
|
27418
|
+
if (!el) return;
|
|
27419
|
+
el.scrollTop = el.scrollHeight;
|
|
27420
|
+
const id = setTimeout(() => {
|
|
27421
|
+
const node = mobileChatScrollRef.current;
|
|
27422
|
+
if (node) node.scrollTop = node.scrollHeight;
|
|
27423
|
+
}, 350);
|
|
27424
|
+
return () => clearTimeout(id);
|
|
27425
|
+
}, [isMobileAIChatOpen, chatInputFocused]);
|
|
26548
27426
|
react.useEffect(() => {
|
|
26549
27427
|
if (!isMobileSearchOpen) {
|
|
26550
27428
|
setMobileSearchCaretVisible(false);
|
|
@@ -26609,6 +27487,7 @@ function CateringOrderBuilder() {
|
|
|
26609
27487
|
mobileSearchSetterRef.current?.(value);
|
|
26610
27488
|
};
|
|
26611
27489
|
const openMobileSearch = () => {
|
|
27490
|
+
setIsMobileSearchActive(true);
|
|
26612
27491
|
mobileSearchInputRef.current?.focus({ preventScroll: true });
|
|
26613
27492
|
setTimeout(() => {
|
|
26614
27493
|
setIsMobileSearchOpen(true);
|
|
@@ -26620,8 +27499,46 @@ function CateringOrderBuilder() {
|
|
|
26620
27499
|
mobileSearchInputRef.current?.blur();
|
|
26621
27500
|
setTimeout(() => {
|
|
26622
27501
|
setIsMobileSearchOpen(false);
|
|
27502
|
+
setIsMobileSearchActive(false);
|
|
26623
27503
|
}, 250);
|
|
26624
27504
|
};
|
|
27505
|
+
const handleMobileAddressPick = (place) => {
|
|
27506
|
+
const parsed = parsePlaceResult(place);
|
|
27507
|
+
if (!parsed) return;
|
|
27508
|
+
setContactInfo({
|
|
27509
|
+
...contactInfo ?? {},
|
|
27510
|
+
...parsed.contactInfo
|
|
27511
|
+
});
|
|
27512
|
+
setMobileAddressPillEditing(false);
|
|
27513
|
+
requestAnimationFrame(() => {
|
|
27514
|
+
mobileAIInputRef.current?.focus();
|
|
27515
|
+
});
|
|
27516
|
+
};
|
|
27517
|
+
const handleMobileAddressClear = () => {
|
|
27518
|
+
setContactInfo({
|
|
27519
|
+
...contactInfo ?? {},
|
|
27520
|
+
addressLine1: "",
|
|
27521
|
+
city: "",
|
|
27522
|
+
zipcode: "",
|
|
27523
|
+
latitude: void 0,
|
|
27524
|
+
longitude: void 0
|
|
27525
|
+
});
|
|
27526
|
+
setMobileAddressPillEditing(false);
|
|
27527
|
+
};
|
|
27528
|
+
const handleMobileGateSubmit = () => {
|
|
27529
|
+
const code = mobileAIInput.trim();
|
|
27530
|
+
if (!code) return;
|
|
27531
|
+
if (tryUnlockAiBeta(code)) {
|
|
27532
|
+
setMobileAIInput("");
|
|
27533
|
+
resetMobileAIInputHeight();
|
|
27534
|
+
setMobileGateError(null);
|
|
27535
|
+
return;
|
|
27536
|
+
}
|
|
27537
|
+
setMobileGateError("Incorrect code. Try again.");
|
|
27538
|
+
setMobileAIInput("");
|
|
27539
|
+
resetMobileAIInputHeight();
|
|
27540
|
+
mobileAIInputRef.current?.focus();
|
|
27541
|
+
};
|
|
26625
27542
|
const closeMobileAIChat = () => {
|
|
26626
27543
|
mobileAIInputRef.current?.blur();
|
|
26627
27544
|
setTimeout(() => {
|
|
@@ -26657,7 +27574,6 @@ function CateringOrderBuilder() {
|
|
|
26657
27574
|
handleTutorialNext,
|
|
26658
27575
|
handleSkipTutorial,
|
|
26659
27576
|
triggerSessionCreated,
|
|
26660
|
-
resetTutorial,
|
|
26661
27577
|
getTutorialSteps
|
|
26662
27578
|
} = useCateringTutorial({
|
|
26663
27579
|
mealSessions,
|
|
@@ -26719,6 +27635,9 @@ function CateringOrderBuilder() {
|
|
|
26719
27635
|
setExpandedItemId(item.id);
|
|
26720
27636
|
};
|
|
26721
27637
|
const { stickyTopOffset = 0, publishableKey, aiEnabled = false } = useCateringConfig();
|
|
27638
|
+
const { unlocked: aiBetaUnlocked, tryUnlock: tryUnlockAiBeta } = useBetaUnlock();
|
|
27639
|
+
const mobileAddressGateActive = isMobileAIChatOpen && aiBetaUnlocked && !hasChatAddress;
|
|
27640
|
+
const mobileAddressEditorOpen = mobileAddressGateActive || aiBetaUnlocked && mobileAddressPillEditing;
|
|
26722
27641
|
const effectiveRightPanelTab = aiEnabled ? rightPanelTab : "cart";
|
|
26723
27642
|
const [overlayVisible, setOverlayVisible] = react.useState(false);
|
|
26724
27643
|
const basketColumnRef = react.useRef(null);
|
|
@@ -27500,7 +28419,7 @@ function CateringOrderBuilder() {
|
|
|
27500
28419
|
}))
|
|
27501
28420
|
}
|
|
27502
28421
|
),
|
|
27503
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className:
|
|
28422
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex flex-col md:flex-row px-2${isMobileAIChatOpen ? " hidden md:flex" : ""}`, children: [
|
|
27504
28423
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0 flex flex-col", children: [
|
|
27505
28424
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
27506
28425
|
SessionPickerDropdown,
|
|
@@ -27702,40 +28621,6 @@ function CateringOrderBuilder() {
|
|
|
27702
28621
|
]
|
|
27703
28622
|
}
|
|
27704
28623
|
),
|
|
27705
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
27706
|
-
"button",
|
|
27707
|
-
{
|
|
27708
|
-
onClick: () => {
|
|
27709
|
-
setIsDesktopCartMenuOpen(false);
|
|
27710
|
-
resetTutorial();
|
|
27711
|
-
setNavMode("dates");
|
|
27712
|
-
setSelectedDayDate(null);
|
|
27713
|
-
},
|
|
27714
|
-
className: "flex w-full items-center gap-2 px-3 py-2.5 text-left text-sm text-gray-700 transition-colors hover:bg-base-100",
|
|
27715
|
-
children: [
|
|
27716
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
27717
|
-
"svg",
|
|
27718
|
-
{
|
|
27719
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
27720
|
-
className: "h-4 w-4",
|
|
27721
|
-
fill: "none",
|
|
27722
|
-
viewBox: "0 0 24 24",
|
|
27723
|
-
stroke: "currentColor",
|
|
27724
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
27725
|
-
"path",
|
|
27726
|
-
{
|
|
27727
|
-
strokeLinecap: "round",
|
|
27728
|
-
strokeLinejoin: "round",
|
|
27729
|
-
strokeWidth: 2,
|
|
27730
|
-
d: "M8.228 9c.549-1.165 2.03-2 3.772-2 2.21 0 4 1.343 4 3 0 1.4-1.278 2.575-3.006 2.907-.542.104-.994.54-.994 1.093m0 3h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
|
27731
|
-
}
|
|
27732
|
-
)
|
|
27733
|
-
}
|
|
27734
|
-
),
|
|
27735
|
-
"Tutorial"
|
|
27736
|
-
]
|
|
27737
|
-
}
|
|
27738
|
-
),
|
|
27739
28624
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
27740
28625
|
"button",
|
|
27741
28626
|
{
|
|
@@ -27770,45 +28655,143 @@ function CateringOrderBuilder() {
|
|
|
27770
28655
|
}
|
|
27771
28656
|
)
|
|
27772
28657
|
] }),
|
|
27773
|
-
isMobileAIChatOpen && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
27774
|
-
|
|
27775
|
-
|
|
27776
|
-
|
|
27777
|
-
|
|
27778
|
-
|
|
27779
|
-
|
|
27780
|
-
}
|
|
27781
|
-
|
|
27782
|
-
|
|
27783
|
-
|
|
27784
|
-
|
|
27785
|
-
|
|
27786
|
-
|
|
27787
|
-
|
|
27788
|
-
|
|
27789
|
-
|
|
27790
|
-
|
|
27791
|
-
|
|
28658
|
+
isMobileAIChatOpen && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
28659
|
+
"div",
|
|
28660
|
+
{
|
|
28661
|
+
className: "fixed left-0 right-0 z-40 md:hidden swift-chat-design",
|
|
28662
|
+
style: {
|
|
28663
|
+
top: vvOffsetTop,
|
|
28664
|
+
height: vvHeight ?? "100vh"
|
|
28665
|
+
},
|
|
28666
|
+
children: [
|
|
28667
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
28668
|
+
"div",
|
|
28669
|
+
{
|
|
28670
|
+
className: "absolute inset-0 bg-white",
|
|
28671
|
+
"aria-hidden": "true"
|
|
28672
|
+
}
|
|
28673
|
+
),
|
|
28674
|
+
/* @__PURE__ */ jsxRuntime.jsx(react$1.LayoutGroup, { children: /* @__PURE__ */ jsxRuntime.jsx(react$1.AnimatePresence, { initial: false, mode: "popLayout", children: mobileAddressEditorOpen ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
28675
|
+
MobileAddressPickerSurface,
|
|
28676
|
+
{
|
|
28677
|
+
hasAddress: hasChatAddress,
|
|
28678
|
+
initialQuery: mobileAddressPillEditing ? contactInfo?.addressLine1 ?? "" : "",
|
|
28679
|
+
onPlaceSelect: handleMobileAddressPick,
|
|
28680
|
+
onBack: () => setMobileAddressPillEditing(false),
|
|
28681
|
+
onRemove: handleMobileAddressClear,
|
|
28682
|
+
onClose: closeMobileAIChat
|
|
28683
|
+
},
|
|
28684
|
+
"address-picker"
|
|
28685
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
28686
|
+
react$1.motion.div,
|
|
28687
|
+
{
|
|
28688
|
+
initial: { opacity: 0 },
|
|
28689
|
+
animate: { opacity: 1 },
|
|
28690
|
+
exit: { opacity: 0 },
|
|
28691
|
+
transition: { duration: 0.18, ease: "easeOut" },
|
|
28692
|
+
className: "absolute inset-0",
|
|
28693
|
+
children: [
|
|
28694
|
+
aiBetaUnlocked && hasChatAddress && mobileChatView === "chat" && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
28695
|
+
react$1.motion.button,
|
|
28696
|
+
{
|
|
28697
|
+
type: "button",
|
|
28698
|
+
layoutId: "catering-address-pill",
|
|
28699
|
+
transition: { duration: 0.28, ease: "easeOut" },
|
|
28700
|
+
onClick: () => setMobileAddressPillEditing(true),
|
|
28701
|
+
className: "absolute top-3 left-3 z-10 inline-flex max-w-[60%] items-center gap-1.5 rounded-xl bg-black/60 backdrop-blur-sm px-3 py-2 text-xs text-white",
|
|
28702
|
+
children: [
|
|
28703
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
28704
|
+
lucideReact.MapPin,
|
|
28705
|
+
{
|
|
28706
|
+
className: "h-3.5 w-3.5 flex-shrink-0 text-white/80",
|
|
28707
|
+
"aria-hidden": true
|
|
28708
|
+
}
|
|
28709
|
+
),
|
|
28710
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-medium", children: contactInfo?.addressLine1 }),
|
|
28711
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-white/50", children: "\xB7" }),
|
|
28712
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold text-white", children: "change" })
|
|
28713
|
+
]
|
|
28714
|
+
}
|
|
28715
|
+
),
|
|
28716
|
+
mobileChatView === "chat" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
28717
|
+
"button",
|
|
28718
|
+
{
|
|
28719
|
+
type: "button",
|
|
28720
|
+
onClick: closeMobileAIChat,
|
|
28721
|
+
className: "absolute top-3 right-3 z-10 flex h-9 w-9 items-center justify-center rounded-full bg-black/60 backdrop-blur-sm text-white",
|
|
28722
|
+
title: "Close AI chat",
|
|
28723
|
+
"aria-label": "Close AI chat",
|
|
28724
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-4 w-4" })
|
|
28725
|
+
}
|
|
28726
|
+
),
|
|
28727
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
28728
|
+
"div",
|
|
28729
|
+
{
|
|
28730
|
+
ref: mobileChatScrollRef,
|
|
28731
|
+
"data-allow-touch": true,
|
|
28732
|
+
className: "absolute inset-x-0 top-0 overflow-y-auto overscroll-contain",
|
|
28733
|
+
style: { bottom: 64 },
|
|
28734
|
+
children: !aiBetaUnlocked ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-4 pt-14 pb-4 flex flex-col gap-3", children: [
|
|
28735
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
28736
|
+
TextBubble,
|
|
28737
|
+
{
|
|
28738
|
+
sender: "bot",
|
|
28739
|
+
text: "What is the code to use the AI chat and test our beta version?"
|
|
28740
|
+
}
|
|
28741
|
+
),
|
|
28742
|
+
mobileGateError && /* @__PURE__ */ jsxRuntime.jsx("p", { role: "alert", className: "text-xs text-red-600", children: mobileGateError })
|
|
28743
|
+
] }) : mobileChatView === "results" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
28744
|
+
MobileResultsView,
|
|
28745
|
+
{
|
|
28746
|
+
onBack: () => setMobileChatView("chat")
|
|
28747
|
+
}
|
|
28748
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
28749
|
+
MobileChatThread,
|
|
28750
|
+
{
|
|
28751
|
+
hasAddressTopPill: hasChatAddress && aiBetaUnlocked
|
|
28752
|
+
}
|
|
28753
|
+
)
|
|
28754
|
+
}
|
|
28755
|
+
),
|
|
28756
|
+
aiBetaUnlocked && mobileChatView === "chat" && /* @__PURE__ */ jsxRuntime.jsx(MobileChatFloatingChips, { bottomOffset: 64 + 8 })
|
|
28757
|
+
]
|
|
28758
|
+
},
|
|
28759
|
+
"chat-surface"
|
|
28760
|
+
) }) })
|
|
28761
|
+
]
|
|
28762
|
+
}
|
|
28763
|
+
),
|
|
27792
28764
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
27793
28765
|
"div",
|
|
27794
28766
|
{
|
|
27795
|
-
className: `fixed left-0 right-0 md:hidden z-50 ${keyboardOffset > 100 && !isMobileAIChatOpen ? "hidden" : ""}`,
|
|
28767
|
+
className: `fixed left-0 right-0 md:hidden z-50 ${mobileAddressEditorOpen || keyboardOffset > 100 && !isMobileAIChatOpen && !isMobileSearchActive ? "hidden" : ""}`,
|
|
27796
28768
|
style: { bottom: keyboardOffset },
|
|
28769
|
+
"aria-hidden": mobileAddressEditorOpen,
|
|
27797
28770
|
children: [
|
|
27798
28771
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
27799
28772
|
"div",
|
|
27800
28773
|
{
|
|
27801
28774
|
ref: mobileBarRowRef,
|
|
27802
|
-
className: "relative
|
|
28775
|
+
className: "relative px-3 pt-1 pb-2",
|
|
27803
28776
|
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full items-end gap-2", children: [
|
|
27804
28777
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
27805
28778
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
27806
28779
|
"button",
|
|
27807
28780
|
{
|
|
27808
|
-
|
|
28781
|
+
onMouseDown: (e) => {
|
|
28782
|
+
if (chatInputFocused) e.preventDefault();
|
|
28783
|
+
},
|
|
28784
|
+
onClick: isMobileAIChatOpen ? chatInputFocused ? () => mobileAIInputRef.current?.blur() : () => setIsMobileChatMenuOpen((v) => !v) : () => setIsMobileCartMenuOpen((v) => !v),
|
|
27809
28785
|
className: "flex h-11 w-11 items-center justify-center rounded-full border border-base-200 bg-white/70 text-gray-700 shadow-sm backdrop-blur-sm transition-colors hover:bg-white",
|
|
27810
|
-
title: isMobileAIChatOpen ? "
|
|
27811
|
-
|
|
28786
|
+
title: isMobileAIChatOpen ? chatInputFocused ? "Hide keyboard" : "Chat actions" : "More actions",
|
|
28787
|
+
"aria-label": isMobileAIChatOpen ? chatInputFocused ? "Hide keyboard" : "Chat actions" : "More actions",
|
|
28788
|
+
children: isMobileAIChatOpen && chatInputFocused ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "h-4 w-4" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MoreHorizontal, { className: "h-4 w-4" })
|
|
28789
|
+
}
|
|
28790
|
+
),
|
|
28791
|
+
isMobileAIChatOpen && isMobileChatMenuOpen && /* @__PURE__ */ jsxRuntime.jsx(
|
|
28792
|
+
MobileChatActionsMenu,
|
|
28793
|
+
{
|
|
28794
|
+
onClose: () => setIsMobileChatMenuOpen(false)
|
|
27812
28795
|
}
|
|
27813
28796
|
),
|
|
27814
28797
|
isMobileCartMenuOpen && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
@@ -27853,40 +28836,6 @@ function CateringOrderBuilder() {
|
|
|
27853
28836
|
]
|
|
27854
28837
|
}
|
|
27855
28838
|
),
|
|
27856
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
27857
|
-
"button",
|
|
27858
|
-
{
|
|
27859
|
-
onClick: () => {
|
|
27860
|
-
setIsMobileCartMenuOpen(false);
|
|
27861
|
-
resetTutorial();
|
|
27862
|
-
setNavMode("dates");
|
|
27863
|
-
setSelectedDayDate(null);
|
|
27864
|
-
},
|
|
27865
|
-
className: "flex w-full items-center gap-2 px-3 py-2.5 text-left text-sm text-gray-700 transition-colors hover:bg-base-100",
|
|
27866
|
-
children: [
|
|
27867
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
27868
|
-
"svg",
|
|
27869
|
-
{
|
|
27870
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
27871
|
-
className: "h-4 w-4",
|
|
27872
|
-
fill: "none",
|
|
27873
|
-
viewBox: "0 0 24 24",
|
|
27874
|
-
stroke: "currentColor",
|
|
27875
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
27876
|
-
"path",
|
|
27877
|
-
{
|
|
27878
|
-
strokeLinecap: "round",
|
|
27879
|
-
strokeLinejoin: "round",
|
|
27880
|
-
strokeWidth: 2,
|
|
27881
|
-
d: "M8.228 9c.549-1.165 2.03-2 3.772-2 2.21 0 4 1.343 4 3 0 1.4-1.278 2.575-3.006 2.907-.542.104-.994.54-.994 1.093m0 3h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
|
27882
|
-
}
|
|
27883
|
-
)
|
|
27884
|
-
}
|
|
27885
|
-
),
|
|
27886
|
-
"Tutorial"
|
|
27887
|
-
]
|
|
27888
|
-
}
|
|
27889
|
-
),
|
|
27890
28839
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-3 border-t border-base-200" }),
|
|
27891
28840
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
27892
28841
|
"button",
|
|
@@ -27910,15 +28859,21 @@ function CateringOrderBuilder() {
|
|
|
27910
28859
|
"button",
|
|
27911
28860
|
{
|
|
27912
28861
|
type: "button",
|
|
27913
|
-
onClick: () =>
|
|
27914
|
-
|
|
28862
|
+
onClick: () => {
|
|
28863
|
+
if (aiEnabled) {
|
|
28864
|
+
setIsMobileAIChatOpen(true);
|
|
28865
|
+
} else {
|
|
28866
|
+
setIsAIMobileUnavailableOpen(true);
|
|
28867
|
+
}
|
|
28868
|
+
},
|
|
28869
|
+
title: aiEnabled ? void 0 : "Coming Soon",
|
|
27915
28870
|
className: `absolute inset-0 flex items-center justify-center gap-1.5 px-4 py-1 transition duration-[250ms] ease-out ${isMobileSearchOpen || isMobileAIChatOpen ? "pointer-events-none -translate-y-full opacity-0" : "translate-y-0 opacity-100"}`,
|
|
27916
28871
|
"aria-hidden": isMobileSearchOpen || isMobileAIChatOpen,
|
|
27917
28872
|
tabIndex: isMobileSearchOpen || isMobileAIChatOpen ? -1 : 0,
|
|
27918
28873
|
children: [
|
|
27919
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className:
|
|
27920
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className:
|
|
27921
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-1 rounded-full bg-primary px-1.5 py-0.5 text-[8px] font-bold uppercase tracking-wider text-white shadow-sm whitespace-nowrap", children: "
|
|
28874
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: `h-4 w-4 ${aiEnabled ? "text-primary" : "text-gray-400"}` }),
|
|
28875
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: `text-sm font-semibold ${aiEnabled ? "text-gray-800" : "text-gray-400"}`, children: "Ask AI" }),
|
|
28876
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-1 rounded-full bg-primary px-1.5 py-0.5 text-[8px] font-bold uppercase tracking-wider text-white shadow-sm whitespace-nowrap", children: aiEnabled ? "Beta" : "Soon" })
|
|
27922
28877
|
]
|
|
27923
28878
|
}
|
|
27924
28879
|
),
|
|
@@ -27933,12 +28888,16 @@ function CateringOrderBuilder() {
|
|
|
27933
28888
|
"input",
|
|
27934
28889
|
{
|
|
27935
28890
|
ref: mobileSearchInputRef,
|
|
27936
|
-
type: "
|
|
28891
|
+
type: "search",
|
|
27937
28892
|
value: mobileSearchState.query,
|
|
27938
28893
|
onChange: (e) => handleMobileSearchInputChange(e.target.value),
|
|
27939
28894
|
placeholder: "Search Swift Food",
|
|
27940
28895
|
tabIndex: isMobileSearchOpen ? 0 : -1,
|
|
27941
|
-
|
|
28896
|
+
autoComplete: "off",
|
|
28897
|
+
autoCorrect: "off",
|
|
28898
|
+
autoCapitalize: "off",
|
|
28899
|
+
spellCheck: false,
|
|
28900
|
+
className: `h-full w-full rounded-full bg-transparent pl-9 pr-3 text-base placeholder:text-xs focus:outline-none touch-auto ${mobileSearchCaretVisible ? "" : "caret-transparent"}`
|
|
27942
28901
|
}
|
|
27943
28902
|
)
|
|
27944
28903
|
]
|
|
@@ -27957,12 +28916,22 @@ function CateringOrderBuilder() {
|
|
|
27957
28916
|
{
|
|
27958
28917
|
inputRef: mobileAIInputRef,
|
|
27959
28918
|
value: mobileAIInput,
|
|
27960
|
-
onChange:
|
|
28919
|
+
onChange: (v) => {
|
|
28920
|
+
setMobileAIInput(v);
|
|
28921
|
+
if (mobileGateError) setMobileGateError(null);
|
|
28922
|
+
},
|
|
27961
28923
|
onInputResize: handleMobileAIInput,
|
|
27962
28924
|
onResetHeight: resetMobileAIInputHeight,
|
|
27963
28925
|
tabbable: isMobileAIChatOpen,
|
|
27964
28926
|
isOpen: isMobileAIChatOpen,
|
|
27965
|
-
onFocus: () =>
|
|
28927
|
+
onFocus: () => {
|
|
28928
|
+
setMobileChatView("chat");
|
|
28929
|
+
setChatInputFocused(true);
|
|
28930
|
+
},
|
|
28931
|
+
onBlur: () => setChatInputFocused(false),
|
|
28932
|
+
gateMode: !aiBetaUnlocked,
|
|
28933
|
+
onGateSubmit: handleMobileGateSubmit,
|
|
28934
|
+
buildAddress: buildChatAddress
|
|
27966
28935
|
}
|
|
27967
28936
|
)
|
|
27968
28937
|
}
|
|
@@ -27972,7 +28941,7 @@ function CateringOrderBuilder() {
|
|
|
27972
28941
|
"button",
|
|
27973
28942
|
{
|
|
27974
28943
|
onClick: isMobileSearchOpen ? closeMobileSearch : openMobileSearch,
|
|
27975
|
-
className: `flex h-11 flex-shrink-0 items-center justify-center rounded-full border bg-white/70 text-gray-700 backdrop-blur-sm transition-all duration-[250ms] ease-out hover:bg-white ${isMobileAIChatOpen ? "pointer-events-none w-0 -ml-2 border-transparent opacity-0 shadow-none" : "w-11 border-base-200 opacity-100 shadow-sm"}`,
|
|
28944
|
+
className: `flex h-11 flex-shrink-0 items-center justify-center rounded-full border bg-white/70 text-gray-700 backdrop-blur-sm transition-all duration-[250ms] ease-out hover:bg-white ${isMobileAIChatOpen ? "pointer-events-none w-0 -ml-2 border-transparent bg-transparent opacity-0 shadow-none" : "w-11 border-base-200 opacity-100 shadow-sm"}`,
|
|
27976
28945
|
title: isMobileSearchOpen ? "Close search" : "Search",
|
|
27977
28946
|
"aria-label": isMobileSearchOpen ? "Close search" : "Open search",
|
|
27978
28947
|
"aria-hidden": isMobileAIChatOpen,
|
|
@@ -27984,7 +28953,7 @@ function CateringOrderBuilder() {
|
|
|
27984
28953
|
] })
|
|
27985
28954
|
}
|
|
27986
28955
|
),
|
|
27987
|
-
mealSessions.some((s) => s.orderItems.length > 0) && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4 bg-primary", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
28956
|
+
mealSessions.some((s) => s.orderItems.length > 0) && !isMobileAIChatOpen && !isMobileSearchOpen && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4 bg-primary", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
27988
28957
|
"button",
|
|
27989
28958
|
{
|
|
27990
28959
|
onClick: () => setIsViewOrderOpen(true),
|
|
@@ -28146,13 +29115,12 @@ function CateringOrderBuilder() {
|
|
|
28146
29115
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-10 w-10 items-center justify-center rounded-full bg-primary/10", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "h-5 w-5 text-primary" }) }),
|
|
28147
29116
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
28148
29117
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-base font-bold text-gray-900", children: "Plan your menu with AI" }),
|
|
28149
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-500", children: "
|
|
29118
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-500", children: "Coming soon" })
|
|
28150
29119
|
] })
|
|
28151
29120
|
] }),
|
|
28152
29121
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-6 space-y-2 text-sm text-gray-600", children: [
|
|
28153
29122
|
/* @__PURE__ */ jsxRuntime.jsx("p", { children: "Chat with our AI to plan the perfect menu \u2014 tell it your guest count, dietary needs, and budget." }),
|
|
28154
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", {
|
|
28155
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-500", children: "Mobile support is coming soon." })
|
|
29123
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-500", children: "We're putting the finishing touches on it. Check back soon." })
|
|
28156
29124
|
] }),
|
|
28157
29125
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
28158
29126
|
"button",
|
|
@@ -28283,35 +29251,136 @@ function CateringOrderBuilder() {
|
|
|
28283
29251
|
}
|
|
28284
29252
|
);
|
|
28285
29253
|
}
|
|
28286
|
-
function
|
|
29254
|
+
function MobileChatActionsMenu({
|
|
29255
|
+
onClose
|
|
29256
|
+
}) {
|
|
28287
29257
|
const {
|
|
28288
29258
|
chat: { bootstrapping },
|
|
28289
29259
|
dismissSuggestionsOverlay,
|
|
28290
29260
|
resetEverything
|
|
28291
29261
|
} = useChatSessionContext();
|
|
28292
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
28293
|
-
|
|
29262
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
29263
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
29264
|
+
"div",
|
|
29265
|
+
{
|
|
29266
|
+
className: "fixed inset-0 z-40",
|
|
29267
|
+
onClick: onClose,
|
|
29268
|
+
"aria-hidden": "true"
|
|
29269
|
+
}
|
|
29270
|
+
),
|
|
29271
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute bottom-full left-0 z-50 mb-2 w-44 overflow-hidden rounded-xl border border-base-200 bg-white shadow-lg", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
29272
|
+
"button",
|
|
29273
|
+
{
|
|
29274
|
+
type: "button",
|
|
29275
|
+
onClick: () => {
|
|
29276
|
+
if (typeof window !== "undefined" && !window.confirm(
|
|
29277
|
+
"Start a new chat? Your conversation history will be cleared."
|
|
29278
|
+
)) {
|
|
29279
|
+
return;
|
|
29280
|
+
}
|
|
29281
|
+
onClose();
|
|
29282
|
+
dismissSuggestionsOverlay();
|
|
29283
|
+
window.setTimeout(() => {
|
|
29284
|
+
void resetEverything();
|
|
29285
|
+
}, 220);
|
|
29286
|
+
},
|
|
29287
|
+
disabled: bootstrapping,
|
|
29288
|
+
className: "flex w-full items-center gap-2 px-3 py-2.5 text-left text-sm text-gray-700 transition-colors hover:bg-base-100 disabled:cursor-not-allowed disabled:opacity-50",
|
|
29289
|
+
children: [
|
|
29290
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.RotateCcw, { className: "h-4 w-4" }),
|
|
29291
|
+
"Reset chat"
|
|
29292
|
+
]
|
|
29293
|
+
}
|
|
29294
|
+
) })
|
|
29295
|
+
] });
|
|
29296
|
+
}
|
|
29297
|
+
function MobileChatThread({
|
|
29298
|
+
hasAddressTopPill
|
|
29299
|
+
}) {
|
|
29300
|
+
const { hasResults } = useChatSessionContext();
|
|
29301
|
+
const suggestionsH = hasResults ? 36 + 6 : 0;
|
|
29302
|
+
const paddingBottom = suggestionsH > 0 ? suggestionsH + 24 : 16;
|
|
29303
|
+
const paddingTop = hasAddressTopPill ? 68 : 56;
|
|
29304
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4", style: { paddingTop, paddingBottom }, children: /* @__PURE__ */ jsxRuntime.jsx(ChatMessagesView, {}) });
|
|
29305
|
+
}
|
|
29306
|
+
function MobileChatFloatingChips({ bottomOffset }) {
|
|
29307
|
+
const {
|
|
29308
|
+
hasResults,
|
|
29309
|
+
onViewResults,
|
|
29310
|
+
feedbackTarget,
|
|
29311
|
+
feedbackRating,
|
|
29312
|
+
setFeedbackRating,
|
|
29313
|
+
cancelFeedback
|
|
29314
|
+
} = useChatSessionContext();
|
|
29315
|
+
const [feedbackHover, setFeedbackHover] = react.useState(0);
|
|
29316
|
+
const inFeedbackMode = feedbackTarget !== null;
|
|
29317
|
+
react.useEffect(() => {
|
|
29318
|
+
if (!feedbackTarget) setFeedbackHover(0);
|
|
29319
|
+
}, [feedbackTarget]);
|
|
29320
|
+
if (!hasResults && !inFeedbackMode) return null;
|
|
29321
|
+
const RATING_LABELS = ["Terrible", "Poor", "Okay", "Good", "Great"];
|
|
29322
|
+
const activeStar = feedbackHover || feedbackRating;
|
|
29323
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
29324
|
+
"div",
|
|
28294
29325
|
{
|
|
28295
|
-
|
|
28296
|
-
|
|
28297
|
-
|
|
28298
|
-
|
|
28299
|
-
|
|
28300
|
-
|
|
28301
|
-
|
|
28302
|
-
|
|
28303
|
-
|
|
28304
|
-
|
|
28305
|
-
|
|
28306
|
-
|
|
28307
|
-
|
|
28308
|
-
|
|
28309
|
-
|
|
28310
|
-
|
|
28311
|
-
|
|
28312
|
-
|
|
28313
|
-
|
|
28314
|
-
|
|
29326
|
+
style: { bottom: bottomOffset },
|
|
29327
|
+
className: "pointer-events-none absolute inset-x-0 z-10 flex flex-col items-center gap-1.5 px-4 touch-none",
|
|
29328
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(react$1.AnimatePresence, { mode: "wait", children: inFeedbackMode ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
29329
|
+
react$1.motion.div,
|
|
29330
|
+
{
|
|
29331
|
+
initial: { opacity: 0, scale: 0.95 },
|
|
29332
|
+
animate: { opacity: 1, scale: 1 },
|
|
29333
|
+
exit: { opacity: 0, scale: 0.95 },
|
|
29334
|
+
transition: { duration: 0.15, ease: "easeOut" },
|
|
29335
|
+
className: "pointer-events-auto inline-flex items-center gap-2 px-3.5 py-2.5 rounded-full bg-black/50 backdrop-blur-sm shadow-sm",
|
|
29336
|
+
children: [
|
|
29337
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
29338
|
+
"button",
|
|
29339
|
+
{
|
|
29340
|
+
type: "button",
|
|
29341
|
+
onClick: cancelFeedback,
|
|
29342
|
+
className: "p-0.5 rounded text-white/60 hover:text-white transition-colors",
|
|
29343
|
+
"aria-label": "Cancel feedback",
|
|
29344
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "w-3.5 h-3.5" })
|
|
29345
|
+
}
|
|
29346
|
+
),
|
|
29347
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-white/70", children: "Rate:" }),
|
|
29348
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1", children: [1, 2, 3, 4, 5].map((n) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
29349
|
+
"button",
|
|
29350
|
+
{
|
|
29351
|
+
type: "button",
|
|
29352
|
+
"aria-label": `${n} star${n > 1 ? "s" : ""}`,
|
|
29353
|
+
onMouseEnter: () => setFeedbackHover(n),
|
|
29354
|
+
onMouseLeave: () => setFeedbackHover(0),
|
|
29355
|
+
onClick: () => setFeedbackRating(n),
|
|
29356
|
+
className: "p-1 transition-transform hover:scale-110",
|
|
29357
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
29358
|
+
lucideReact.Star,
|
|
29359
|
+
{
|
|
29360
|
+
className: `h-7 w-7 transition-colors ${n <= activeStar ? "fill-amber-400 text-amber-400" : "fill-transparent text-white/40"}`
|
|
29361
|
+
}
|
|
29362
|
+
)
|
|
29363
|
+
},
|
|
29364
|
+
n
|
|
29365
|
+
)) }),
|
|
29366
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-white/80 min-w-[3.5rem]", children: activeStar > 0 ? RATING_LABELS[activeStar - 1] : "" })
|
|
29367
|
+
]
|
|
29368
|
+
},
|
|
29369
|
+
"feedback-pill"
|
|
29370
|
+
) : hasResults ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
29371
|
+
react$1.motion.button,
|
|
29372
|
+
{
|
|
29373
|
+
type: "button",
|
|
29374
|
+
onClick: onViewResults,
|
|
29375
|
+
initial: { opacity: 0, scale: 0.95 },
|
|
29376
|
+
animate: { opacity: 1, scale: 1 },
|
|
29377
|
+
exit: { opacity: 0, scale: 0.95 },
|
|
29378
|
+
transition: { duration: 0.15, ease: "easeOut" },
|
|
29379
|
+
className: "pointer-events-auto flex items-center justify-center gap-1.5 px-4 py-2 rounded-full bg-primary text-white text-sm font-semibold shadow-md whitespace-nowrap",
|
|
29380
|
+
children: "\u2728 View menu suggestions"
|
|
29381
|
+
},
|
|
29382
|
+
"view-suggestions"
|
|
29383
|
+
) : null })
|
|
28315
29384
|
}
|
|
28316
29385
|
);
|
|
28317
29386
|
}
|
|
@@ -28323,17 +29392,56 @@ function MobileAIInput({
|
|
|
28323
29392
|
onResetHeight,
|
|
28324
29393
|
tabbable,
|
|
28325
29394
|
isOpen,
|
|
28326
|
-
onFocus
|
|
29395
|
+
onFocus,
|
|
29396
|
+
onBlur,
|
|
29397
|
+
gateMode = false,
|
|
29398
|
+
onGateSubmit,
|
|
29399
|
+
buildAddress,
|
|
29400
|
+
submitBlocked = false
|
|
28327
29401
|
}) {
|
|
28328
29402
|
const {
|
|
28329
|
-
chat: { sending, bootstrapping, sessionId, sendText }
|
|
29403
|
+
chat: { sending, bootstrapping, sessionId, sendText, submitFeedback },
|
|
29404
|
+
feedbackTarget,
|
|
29405
|
+
feedbackRating,
|
|
29406
|
+
cancelFeedback
|
|
28330
29407
|
} = useChatSessionContext();
|
|
29408
|
+
const inFeedbackMode = feedbackTarget !== null;
|
|
29409
|
+
const [feedbackState, setFeedbackState] = react.useState("idle");
|
|
29410
|
+
react.useEffect(() => {
|
|
29411
|
+
if (!feedbackTarget) setFeedbackState("idle");
|
|
29412
|
+
}, [feedbackTarget]);
|
|
29413
|
+
const chatDisabled = sending || bootstrapping || !sessionId;
|
|
29414
|
+
const inputDisabled = inFeedbackMode ? feedbackState === "sending" : bootstrapping || !sessionId;
|
|
29415
|
+
const sendDisabled = inFeedbackMode ? feedbackState === "sending" : submitBlocked || (gateMode ? !value.trim() : chatDisabled || !value.trim());
|
|
28331
29416
|
function submit() {
|
|
28332
|
-
if (
|
|
28333
|
-
|
|
29417
|
+
if (inFeedbackMode) {
|
|
29418
|
+
void handleFeedbackSubmit();
|
|
29419
|
+
return;
|
|
29420
|
+
}
|
|
29421
|
+
if (!value.trim()) return;
|
|
29422
|
+
if (submitBlocked) return;
|
|
29423
|
+
if (gateMode) {
|
|
29424
|
+
onGateSubmit?.();
|
|
29425
|
+
return;
|
|
29426
|
+
}
|
|
29427
|
+
if (chatDisabled) return;
|
|
29428
|
+
void sendText(value, buildAddress?.() ?? void 0);
|
|
28334
29429
|
onChange("");
|
|
28335
29430
|
onResetHeight();
|
|
28336
29431
|
}
|
|
29432
|
+
async function handleFeedbackSubmit() {
|
|
29433
|
+
if (!feedbackTarget) return;
|
|
29434
|
+
setFeedbackState("sending");
|
|
29435
|
+
const ok = await submitFeedback(feedbackRating || 1, value || void 0, feedbackTarget.eventId);
|
|
29436
|
+
if (ok) {
|
|
29437
|
+
setFeedbackState("done");
|
|
29438
|
+
onChange("");
|
|
29439
|
+
onResetHeight();
|
|
29440
|
+
window.setTimeout(() => cancelFeedback(), 900);
|
|
29441
|
+
} else {
|
|
29442
|
+
setFeedbackState("error");
|
|
29443
|
+
}
|
|
29444
|
+
}
|
|
28337
29445
|
function handleKeyDown(e) {
|
|
28338
29446
|
if (e.key === "Enter" && !e.shiftKey) {
|
|
28339
29447
|
e.preventDefault();
|
|
@@ -28351,10 +29459,15 @@ function MobileAIInput({
|
|
|
28351
29459
|
onInput: onInputResize,
|
|
28352
29460
|
onKeyDown: handleKeyDown,
|
|
28353
29461
|
onFocus,
|
|
28354
|
-
|
|
29462
|
+
onBlur,
|
|
29463
|
+
placeholder: inFeedbackMode ? "Add a note (optional)" : gateMode ? "Enter access code\u2026" : "How can I help?",
|
|
28355
29464
|
tabIndex: tabbable ? 0 : -1,
|
|
28356
|
-
disabled:
|
|
28357
|
-
|
|
29465
|
+
disabled: gateMode ? false : inputDisabled,
|
|
29466
|
+
autoComplete: "off",
|
|
29467
|
+
autoCorrect: "off",
|
|
29468
|
+
autoCapitalize: "off",
|
|
29469
|
+
spellCheck: false,
|
|
29470
|
+
className: "block w-full resize-none bg-transparent pl-4 pr-12 py-3 text-base leading-5 focus:outline-none overflow-hidden disabled:opacity-50 touch-auto"
|
|
28358
29471
|
}
|
|
28359
29472
|
),
|
|
28360
29473
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -28363,7 +29476,7 @@ function MobileAIInput({
|
|
|
28363
29476
|
type: "button",
|
|
28364
29477
|
onClick: submit,
|
|
28365
29478
|
tabIndex: tabbable ? 0 : -1,
|
|
28366
|
-
disabled:
|
|
29479
|
+
disabled: sendDisabled,
|
|
28367
29480
|
"aria-hidden": !isOpen,
|
|
28368
29481
|
className: `absolute right-1.5 bottom-1.5 z-10 flex h-8 w-8 items-center justify-center rounded-full bg-primary text-white transition-all duration-[250ms] ease-out hover:bg-primary/90 disabled:opacity-50 ${isOpen ? "scale-100 opacity-100" : "pointer-events-none scale-0 opacity-0"}`,
|
|
28369
29482
|
title: "Send",
|