astro-tractstack 2.2.10 → 2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/README.md +1 -1
  2. package/bin/create-tractstack.js +2 -2
  3. package/dist/index.js +177 -18
  4. package/package.json +4 -2
  5. package/templates/custom/minimal/CodeHook.astro +22 -5
  6. package/templates/custom/shopify/Cart.tsx +372 -0
  7. package/templates/custom/shopify/CartIcon.tsx +47 -0
  8. package/templates/custom/shopify/CartModal.tsx +63 -0
  9. package/templates/custom/shopify/CheckoutModal.tsx +576 -0
  10. package/templates/custom/shopify/NativeBookingCalendar.tsx +375 -0
  11. package/templates/custom/shopify/ShopifyCartManager.tsx +200 -0
  12. package/templates/custom/shopify/ShopifyCheckout.tsx +167 -0
  13. package/templates/custom/shopify/ShopifyProductGrid.tsx +247 -0
  14. package/templates/custom/shopify/ShopifyServiceList.tsx +135 -0
  15. package/templates/custom/shopify/cart.astro +23 -0
  16. package/templates/custom/with-examples/CodeHook.astro +17 -1
  17. package/templates/custom/with-examples/ProductGrid.astro +1 -1
  18. package/templates/src/client/app.js +4 -2
  19. package/templates/src/components/Footer.astro +4 -4
  20. package/templates/src/components/Header.astro +44 -12
  21. package/templates/src/components/edit/pane/AddPanePanel_new.tsx +3 -3
  22. package/templates/src/components/edit/pane/AiRestylePaneModal.tsx +2 -2
  23. package/templates/src/components/edit/pane/steps/AiCreativeDesignStep.tsx +2 -2
  24. package/templates/src/components/edit/pane/steps/AiLibraryCopyStep.tsx +3 -3
  25. package/templates/src/components/edit/pane/steps/AiRefineDesignStep.tsx +2 -2
  26. package/templates/src/components/edit/pane/steps/AiStandardDesignStep.tsx +7 -7
  27. package/templates/src/components/form/advanced/APIConfigSection.tsx +407 -38
  28. package/templates/src/components/form/shopify/SchedulingSection.tsx +354 -0
  29. package/templates/src/components/storykeep/Dashboard.tsx +18 -4
  30. package/templates/src/components/storykeep/Dashboard_Advanced.tsx +1 -0
  31. package/templates/src/components/storykeep/Dashboard_Content.tsx +5 -96
  32. package/templates/src/components/storykeep/Dashboard_Shopify.tsx +668 -0
  33. package/templates/src/components/storykeep/StoryKeepBackdrop.astro +43 -23
  34. package/templates/src/components/storykeep/controls/content/BeliefTable.tsx +14 -5
  35. package/templates/src/components/storykeep/controls/content/ContentBrowser.tsx +0 -14
  36. package/templates/src/components/storykeep/controls/content/KnownResourceForm.tsx +36 -13
  37. package/templates/src/components/storykeep/controls/content/KnownResourceTable.tsx +5 -2
  38. package/templates/src/components/storykeep/controls/content/ManageContent.tsx +4 -11
  39. package/templates/src/components/storykeep/controls/content/MenuTable.tsx +14 -5
  40. package/templates/src/components/storykeep/controls/content/ProductTable.tsx +333 -0
  41. package/templates/src/components/storykeep/controls/content/ResourceBulkIngest.tsx +9 -5
  42. package/templates/src/components/storykeep/controls/content/ResourceForm.tsx +108 -8
  43. package/templates/src/components/storykeep/controls/content/ResourceTable.tsx +13 -4
  44. package/templates/src/components/storykeep/controls/content/StoryFragmentTable.tsx +14 -5
  45. package/templates/src/components/storykeep/shopify/ShopifyDashboard.tsx +111 -0
  46. package/templates/src/components/storykeep/shopify/ShopifyDashboard_Bookings.tsx +393 -0
  47. package/templates/src/components/storykeep/shopify/ShopifyDashboard_Products.tsx +46 -0
  48. package/templates/src/components/storykeep/shopify/ShopifyDashboard_Schedule.tsx +78 -0
  49. package/templates/src/components/storykeep/shopify/ShopifyDashboard_Search.tsx +55 -0
  50. package/templates/src/components/storykeep/shopify/ShopifyDashboard_Services.tsx +47 -0
  51. package/templates/src/lib/resources.ts +11 -21
  52. package/templates/src/pages/api/auth/lookup-lead.ts +72 -0
  53. package/templates/src/pages/api/booking/availability.ts +72 -0
  54. package/templates/src/pages/api/booking/cancel.ts +73 -0
  55. package/templates/src/pages/api/booking/confirm.ts +82 -0
  56. package/templates/src/pages/api/booking/hold.ts +75 -0
  57. package/templates/src/pages/api/booking/list.ts +66 -0
  58. package/templates/src/pages/api/booking/metrics.ts +60 -0
  59. package/templates/src/pages/api/booking/release.ts +76 -0
  60. package/templates/src/pages/api/sandbox.ts +2 -2
  61. package/templates/src/pages/api/shopify/createCart.ts +69 -0
  62. package/templates/src/pages/api/shopify/getProducts.ts +64 -0
  63. package/templates/src/pages/storykeep/login.astro +26 -24
  64. package/templates/src/pages/storykeep/logout.astro +1 -10
  65. package/templates/src/pages/storykeep/manage.astro +69 -0
  66. package/templates/src/pages/storykeep/{content.astro → pages.astro} +4 -8
  67. package/templates/src/pages/storykeep/shopify.astro +101 -0
  68. package/templates/src/stores/navigation.ts +3 -42
  69. package/templates/src/stores/nodes.ts +3 -1
  70. package/templates/src/stores/resources.ts +7 -10
  71. package/templates/src/stores/shopify.ts +266 -0
  72. package/templates/src/types/tractstack.ts +75 -0
  73. package/templates/src/utils/api/advancedConfig.ts +7 -1
  74. package/templates/src/utils/api/advancedHelpers.ts +87 -7
  75. package/templates/src/utils/api/bookingHelpers.ts +125 -0
  76. package/templates/src/utils/api/brandHelpers.ts +14 -0
  77. package/templates/src/utils/api/resourceConfig.ts +13 -5
  78. package/templates/src/utils/auth.ts +29 -9
  79. package/templates/src/utils/compositor/aiGeneration.ts +3 -3
  80. package/templates/src/utils/compositor/aiPaneParser.ts +2 -2
  81. package/templates/src/utils/customHelpers.ts +49 -0
  82. package/templates/src/utils/helpers.ts +59 -0
  83. package/templates/src/utils/profileStorage.ts +5 -0
  84. package/templates/src/utils/tenantResolver.ts +2 -1
  85. package/utils/inject-files.ts +161 -2
@@ -1,4 +1,7 @@
1
+ import { useState } from 'react';
2
+ import { Dialog, Portal } from '@ark-ui/react';
1
3
  import StringInput from '../StringInput';
4
+ import BooleanToggle from '../BooleanToggle';
2
5
  import type { FormStateReturn } from '@/hooks/useFormState';
3
6
  import type {
4
7
  AdvancedConfigState,
@@ -16,54 +19,420 @@ export default function APIConfigSection({
16
19
  }: APIConfigSectionProps) {
17
20
  const { state, updateField, errors } = formState;
18
21
 
22
+ const [isModalOpen, setIsModalOpen] = useState(false);
23
+ const goBackend =
24
+ import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
25
+
26
+ // Status flags
19
27
  const aaiConfigured = status?.aaiAPIKeySet;
28
+ const shopifyStorefrontConfigured = status?.shopifyStorefrontTokenSet;
29
+ const shopifySecretConfigured = status?.shopifyApiSecretSet;
30
+ const shopifyDomainConfigured = status?.shopifyStoreDomainSet;
31
+ const shopifyVersionConfigured = Boolean(status?.shopifyApiVersion);
32
+ const shopifyAdminSlugConfigured = status?.shopifyAdminSlugSet;
33
+ const shopifyWebhooksConfigured = status?.userSetupWebhooks;
34
+ const resendConfigured = status?.resendApiKeySet;
35
+
36
+ const renderStatusBadge = (isConfigured: boolean | undefined) => {
37
+ if (status === null) {
38
+ return (
39
+ <span className="ml-2 inline-flex items-center rounded-full bg-gray-100 px-2 py-0.5 text-xs font-bold text-gray-800">
40
+ Loading...
41
+ </span>
42
+ );
43
+ }
44
+ return isConfigured ? (
45
+ <span className="ml-2 inline-flex items-center rounded-full bg-green-100 px-2 py-0.5 text-xs font-bold text-green-800">
46
+ ✓ Set
47
+ </span>
48
+ ) : (
49
+ <span className="ml-2 inline-flex items-center rounded-full bg-yellow-100 px-2 py-0.5 text-xs font-bold text-yellow-800">
50
+ Not Set
51
+ </span>
52
+ );
53
+ };
20
54
 
21
55
  return (
22
56
  <div className="bg-white shadow md:rounded-lg">
23
57
  <div className="px-4 py-5 md:p-6">
24
- <div className="flex items-center justify-between">
25
- <h3 className="text-base font-bold leading-6 text-gray-900">
26
- API Configuration
27
- </h3>
28
- <div className="flex items-center">
29
- {aaiConfigured ? (
30
- <span className="inline-flex items-center rounded-full bg-green-100 px-2.5 py-0.5 text-xs font-bold text-green-800">
31
- ✓ Configured
32
- </span>
33
- ) : status !== null ? (
34
- <span className="inline-flex items-center rounded-full bg-yellow-100 px-2.5 py-0.5 text-xs font-bold text-yellow-800">
35
- Optional
36
- </span>
37
- ) : (
38
- <span className="inline-flex items-center rounded-full bg-gray-100 px-2.5 py-0.5 text-xs font-bold text-gray-800">
39
- Loading...
40
- </span>
41
- )}
42
- </div>
43
- </div>
58
+ <h3 className="text-base font-bold leading-6 text-gray-900">
59
+ API Integrations
60
+ </h3>
44
61
  <div className="mt-2 max-w-xl text-sm text-gray-500">
45
- <p>Configure external API keys for enhanced functionality.</p>
46
- </div>
47
- <div className="mt-5">
48
- <StringInput
49
- label="AssemblyAI API Key"
50
- value={state.aaiApiKey}
51
- onChange={(value) => updateField('aaiApiKey', value)}
52
- type="password"
53
- placeholder={
54
- aaiConfigured ? '••••••••••••••••' : 'Enter AssemblyAI API key'
55
- }
56
- error={errors.aaiApiKey}
57
- />
58
- </div>
59
- <div className="mt-3 text-xs text-gray-500">
60
62
  <p>
61
- Used for audio transcription and analysis features. Optional but
62
- required for audio processing.
63
- {aaiConfigured && ' Leave blank to keep existing key.'}
63
+ Configure external services to enable advanced features like AI,
64
+ Commerce, and Email.
64
65
  </p>
65
66
  </div>
67
+
68
+ <div className="mt-6 space-y-8">
69
+ {/* AssemblyAI Section */}
70
+ <div className="border-t border-gray-100 pt-6">
71
+ <div className="mb-4 flex items-center justify-between">
72
+ <h4 className="text-sm font-bold text-gray-900">
73
+ AssemblyAI (Audio Intelligence)
74
+ </h4>
75
+ {renderStatusBadge(aaiConfigured)}
76
+ </div>
77
+ <StringInput
78
+ label="API Key"
79
+ value={state.aaiApiKey}
80
+ onChange={(value) => updateField('aaiApiKey', value)}
81
+ type="password"
82
+ placeholder={
83
+ aaiConfigured ? '••••••••••••••••' : 'Enter AssemblyAI API key'
84
+ }
85
+ error={errors.aaiApiKey}
86
+ />
87
+ <p className="mt-2 text-xs text-gray-500">
88
+ Required for audio transcription and analysis.
89
+ {aaiConfigured && ' Leave blank to keep existing key.'}
90
+ </p>
91
+ </div>
92
+
93
+ {/* Shopify Section */}
94
+ <div className="border-t border-gray-100 pt-6">
95
+ <div className="mb-4 flex items-center justify-between">
96
+ <h4 className="text-sm font-bold text-gray-900">
97
+ Shopify (Commerce)
98
+ </h4>
99
+ {renderStatusBadge(
100
+ shopifyStorefrontConfigured &&
101
+ shopifySecretConfigured &&
102
+ shopifyDomainConfigured &&
103
+ shopifyVersionConfigured &&
104
+ shopifyAdminSlugConfigured &&
105
+ shopifyWebhooksConfigured
106
+ )}
107
+ </div>
108
+ <div className="space-y-4">
109
+ <div>
110
+ <StringInput
111
+ label="Shopify Store Domain"
112
+ value={state.shopifyStoreDomain}
113
+ onChange={(value) => updateField('shopifyStoreDomain', value)}
114
+ placeholder={
115
+ shopifyDomainConfigured
116
+ ? 'your-shop.myshopify.com'
117
+ : 'your-shop.myshopify.com'
118
+ }
119
+ error={errors.shopifyStoreDomain}
120
+ />
121
+ <p className="mt-1 text-xs text-gray-500">
122
+ The primary .myshopify.com domain for your store.
123
+ </p>
124
+ </div>
125
+
126
+ <div>
127
+ <StringInput
128
+ label="Shopify Admin Slug"
129
+ value={state.shopifyAdminSlug}
130
+ onChange={(value) => updateField('shopifyAdminSlug', value)}
131
+ placeholder="your-store-slug"
132
+ error={errors.shopifyAdminSlug}
133
+ />
134
+ <p className="mt-1 text-xs text-gray-500">
135
+ The internal Shopify slug (found in
136
+ admin.shopify.com/store/SLUG).
137
+ </p>
138
+ </div>
139
+
140
+ <div>
141
+ <StringInput
142
+ label="API Version"
143
+ value={state.shopifyApiVersion}
144
+ onChange={(value) => updateField('shopifyApiVersion', value)}
145
+ type="text"
146
+ placeholder="2026-01"
147
+ error={errors.shopifyApiVersion}
148
+ />
149
+ <p className="mt-1 text-xs text-gray-500">
150
+ Target specific Shopify API version (YYYY-MM).
151
+ </p>
152
+ </div>
153
+
154
+ <div>
155
+ <StringInput
156
+ label="Headless channel, Private Access Token"
157
+ value={state.shopifyStorefrontToken}
158
+ onChange={(value) =>
159
+ updateField('shopifyStorefrontToken', value)
160
+ }
161
+ type="password"
162
+ placeholder={
163
+ shopifyStorefrontConfigured
164
+ ? '••••••••••••••••'
165
+ : 'shpat_...'
166
+ }
167
+ error={errors.shopifyStorefrontToken}
168
+ />
169
+ <p className="mt-1 text-xs text-gray-500">
170
+ Private access token for fetching products.
171
+ {shopifyStorefrontConfigured &&
172
+ ' Leave blank to keep existing.'}
173
+ </p>
174
+ </div>
175
+
176
+ <div>
177
+ <StringInput
178
+ label="API Secret Key"
179
+ value={state.shopifyApiSecret}
180
+ onChange={(value) => updateField('shopifyApiSecret', value)}
181
+ type="password"
182
+ placeholder={
183
+ shopifySecretConfigured ? '••••••••••••••••' : 'shpss_...'
184
+ }
185
+ error={errors.shopifyApiSecret}
186
+ />
187
+ <p className="mt-1 text-xs text-gray-500">
188
+ Required for Webhook signature verification.
189
+ {shopifySecretConfigured && ' Leave blank to keep existing.'}
190
+ </p>
191
+ </div>
192
+
193
+ {!shopifyWebhooksConfigured && (
194
+ <div className="mt-6 border-t border-gray-100 pt-6">
195
+ <div className="mb-4 rounded-md border border-amber-200 bg-amber-50 p-4">
196
+ <h5 className="text-sm font-bold text-amber-800">
197
+ Webhook Configuration Required
198
+ </h5>
199
+ <p className="mb-3 mt-1 text-xs text-amber-700">
200
+ To ensure synchronization between Shopify and the
201
+ TractStack native booking system, you must configure
202
+ webhook subscriptions within your Shopify Admin panel.
203
+ </p>
204
+ <button
205
+ onClick={() => setIsModalOpen(true)}
206
+ className="text-xs font-bold text-amber-900 underline hover:text-amber-700"
207
+ type="button"
208
+ >
209
+ [ Detailed Instructions ]
210
+ </button>
211
+ </div>
212
+
213
+ <BooleanToggle
214
+ label="Webhooks Manually Configured"
215
+ description="I have manually created the required webhooks (orders/paid, products/*) in my Shopify Admin."
216
+ value={state.userSetupWebhooks}
217
+ onChange={(value) =>
218
+ updateField('userSetupWebhooks', value)
219
+ }
220
+ />
221
+ </div>
222
+ )}
223
+ </div>
224
+ </div>
225
+
226
+ {/* Resend Section */}
227
+ <div className="border-t border-gray-100 pt-6">
228
+ <div className="mb-4 flex items-center justify-between">
229
+ <h4 className="text-sm font-bold text-gray-900">
230
+ Resend (Transactional Email)
231
+ </h4>
232
+ {renderStatusBadge(resendConfigured)}
233
+ </div>
234
+ <StringInput
235
+ label="API Key"
236
+ value={state.resendApiKey}
237
+ onChange={(value) => updateField('resendApiKey', value)}
238
+ type="password"
239
+ placeholder={resendConfigured ? '••••••••••••••••' : 're_...'}
240
+ error={errors.resendApiKey}
241
+ />
242
+ <p className="mt-2 text-xs text-gray-500">
243
+ Required for sending system emails.
244
+ {resendConfigured && ' Leave blank to keep existing key.'}
245
+ </p>
246
+ </div>
247
+ </div>
66
248
  </div>
249
+
250
+ <Dialog.Root
251
+ open={isModalOpen}
252
+ onOpenChange={(details) => setIsModalOpen(details.open)}
253
+ preventScroll={true}
254
+ lazyMount
255
+ unmountOnExit
256
+ >
257
+ <Portal>
258
+ <Dialog.Backdrop className="fixed inset-0 z-50 bg-black bg-opacity-75" />
259
+ <Dialog.Positioner className="fixed inset-0 z-50 flex items-center justify-center p-4">
260
+ <Dialog.Content
261
+ className="relative flex w-full max-w-2xl flex-col overflow-hidden rounded-lg bg-white shadow-xl"
262
+ style={{ maxHeight: '90vh' }}
263
+ >
264
+ {/* Header - Fixed height */}
265
+ <div className="flex items-center justify-between border-b border-gray-200 px-6 py-4">
266
+ <Dialog.Title className="text-xl font-bold text-gray-900">
267
+ How to Configure Webhooks in Shopify
268
+ </Dialog.Title>
269
+ <Dialog.CloseTrigger asChild>
270
+ <button
271
+ className="text-gray-400 hover:text-gray-600"
272
+ type="button"
273
+ >
274
+ <span className="text-2xl">&times;</span>
275
+ </button>
276
+ </Dialog.CloseTrigger>
277
+ </div>
278
+
279
+ {/* Body - Scrollable via flex-1 */}
280
+ <div className="flex-1 overflow-y-auto p-6 text-sm text-gray-700">
281
+ <ol className="mb-6 list-decimal space-y-2 pl-5">
282
+ <li>Log in to your Shopify Admin dashboard.</li>
283
+ <li>
284
+ Click on <strong>Settings</strong> (the gear icon) in the
285
+ bottom left corner.
286
+ </li>
287
+ <li>
288
+ In the left sidebar, select <strong>Notifications</strong>.
289
+ </li>
290
+ <li>
291
+ Scroll all the way to the bottom to the{' '}
292
+ <strong>Webhooks</strong> section.
293
+ </li>
294
+ <li>
295
+ Click the <strong>Create webhook</strong> button.
296
+ </li>
297
+ <li>
298
+ For each required webhook (listed below), configure the
299
+ following settings:
300
+ <ul className="mt-2 list-disc space-y-1 pl-5">
301
+ <li>
302
+ <strong>Event:</strong> Select the specific event (e.g.,
303
+ Order payment, Product creation).
304
+ </li>
305
+ <li>
306
+ <strong>Format:</strong> Select JSON (TractStack relies
307
+ on JSON unmarshaling).
308
+ </li>
309
+ <li>
310
+ <strong>URL:</strong> Enter your backend webhook URL:{' '}
311
+ <code className="rounded bg-gray-100 px-1 py-0.5 text-xs">
312
+ {goBackend}/api/v1/hooks/shopify
313
+ </code>
314
+ </li>
315
+ <li>
316
+ <strong>Webhook API version:</strong> Select the version
317
+ that matches your ShopifyAPIVersion configured in
318
+ TractStack.
319
+ </li>
320
+ </ul>
321
+ </li>
322
+ <li>
323
+ Click <strong>Save</strong>.
324
+ </li>
325
+ </ol>
326
+
327
+ <div className="mb-6 border-l-4 border-red-500 bg-red-50 p-4">
328
+ <p className="font-bold text-red-800">CRITICAL:</p>
329
+ <p className="mt-1 text-red-700">
330
+ After saving your first webhook, Shopify will display a{' '}
331
+ <strong>Webhook signing secret</strong> at the bottom of the
332
+ Webhooks section. You must copy this secret and add it to
333
+ your TractStack API Config as the Shopify API Secret. The
334
+ backend uses this to verify the HMAC signature of all
335
+ incoming payloads.
336
+ </p>
337
+ </div>
338
+
339
+ <h4 className="mb-3 text-lg font-bold">
340
+ Required Webhooks Breakdown
341
+ </h4>
342
+ <p className="mb-4">
343
+ You must create a separate webhook subscription for each of
344
+ the following four topics. All of them should point to the
345
+ exact same URL:{' '}
346
+ <code className="rounded bg-gray-100 px-1 py-0.5 text-xs">
347
+ {goBackend}/api/v1/hooks/shopify
348
+ </code>
349
+ </p>
350
+
351
+ <div className="space-y-4">
352
+ <div className="rounded border border-gray-200 bg-gray-50 p-4">
353
+ <h5 className="font-bold">1. Order Paid</h5>
354
+ <ul className="mt-2 space-y-1 text-xs">
355
+ <li>
356
+ <span className="font-bold text-gray-900">
357
+ Shopify Event Name:
358
+ </span>{' '}
359
+ Order payment
360
+ </li>
361
+ <li>
362
+ <span className="font-bold text-gray-900">
363
+ Topic Header:
364
+ </span>{' '}
365
+ orders/paid
366
+ </li>
367
+ <li>
368
+ <span className="font-bold text-gray-900">
369
+ Purpose:
370
+ </span>{' '}
371
+ Transitions the corresponding hold in the bookings
372
+ database table from PENDING to CONFIRMED.
373
+ </li>
374
+ </ul>
375
+ </div>
376
+
377
+ <div className="rounded border border-gray-200 bg-gray-50 p-4">
378
+ <h5 className="font-bold">2. Product Creation</h5>
379
+ <ul className="mt-2 space-y-1 text-xs">
380
+ <li>
381
+ <span className="font-bold text-gray-900">
382
+ Shopify Event Name:
383
+ </span>{' '}
384
+ Product creation
385
+ </li>
386
+ <li>
387
+ <span className="font-bold text-gray-900">
388
+ Topic Header:
389
+ </span>{' '}
390
+ products/create
391
+ </li>
392
+ </ul>
393
+ </div>
394
+
395
+ <div className="rounded border border-gray-200 bg-gray-50 p-4">
396
+ <h5 className="font-bold">3. Product Update</h5>
397
+ <ul className="mt-2 space-y-1 text-xs">
398
+ <li>
399
+ <span className="font-bold text-gray-900">
400
+ Shopify Event Name:
401
+ </span>{' '}
402
+ Product update
403
+ </li>
404
+ <li>
405
+ <span className="font-bold text-gray-900">
406
+ Topic Header:
407
+ </span>{' '}
408
+ products/update
409
+ </li>
410
+ </ul>
411
+ </div>
412
+
413
+ <div className="rounded border border-gray-200 bg-gray-50 p-4">
414
+ <h5 className="font-bold">4. Product Deletion</h5>
415
+ <ul className="mt-2 space-y-1 text-xs">
416
+ <li>
417
+ <span className="font-bold text-gray-900">
418
+ Shopify Event Name:
419
+ </span>{' '}
420
+ Product deletion
421
+ </li>
422
+ <li>
423
+ <span className="font-bold text-gray-900">
424
+ Topic Header:
425
+ </span>{' '}
426
+ products/delete
427
+ </li>
428
+ </ul>
429
+ </div>
430
+ </div>
431
+ </div>
432
+ </Dialog.Content>
433
+ </Dialog.Positioner>
434
+ </Portal>
435
+ </Dialog.Root>
67
436
  </div>
68
437
  );
69
438
  }