@burdenoff/microfe-store 2026.801.1 → 2026.819.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 (69) hide show
  1. package/dist/StoreAdminRoutes.js +27 -27
  2. package/dist/StoreRoot.js +78 -45
  3. package/dist/StoreRoot.js.map +1 -1
  4. package/dist/StoreRoutes.js +163 -85
  5. package/dist/StoreRoutes.js.map +1 -1
  6. package/dist/components/InstallAppModal.js +211 -137
  7. package/dist/components/InstallAppModal.js.map +1 -1
  8. package/dist/components/sourcing/SourcingConfirmationDialog.d.ts +15 -0
  9. package/dist/components/sourcing/SourcingConfirmationDialog.js +61 -0
  10. package/dist/components/sourcing/SourcingConfirmationDialog.js.map +1 -0
  11. package/dist/components/sourcing/SourcingUi.d.ts +51 -0
  12. package/dist/components/sourcing/SourcingUi.js +176 -0
  13. package/dist/components/sourcing/SourcingUi.js.map +1 -0
  14. package/dist/generated/global-operations.d.ts +713 -0
  15. package/dist/generated/global-operations.js +557 -175
  16. package/dist/generated/global-operations.js.map +1 -1
  17. package/dist/generated/global-types.d.ts +2158 -2159
  18. package/dist/generated/global-types.js +8 -2
  19. package/dist/generated/global-types.js.map +1 -1
  20. package/dist/hooks/useBackendCart.js +17 -17
  21. package/dist/hooks/useInstallations.js +32 -32
  22. package/dist/hooks/useOrders.js +7 -7
  23. package/dist/hooks/useSourcing.d.ts +319 -0
  24. package/dist/hooks/useSourcing.js +87 -0
  25. package/dist/hooks/useSourcing.js.map +1 -0
  26. package/dist/hooks/useStoreGraphQL.js +163 -163
  27. package/dist/index.js +12 -12
  28. package/dist/pages/AdminDashboardPage.js +132 -132
  29. package/dist/pages/AdminReviewModerationPage.js +55 -55
  30. package/dist/pages/AdminStoresPage.js +95 -95
  31. package/dist/pages/AdminSubmissionsQueuePage.js +297 -297
  32. package/dist/pages/AdminSubmissionsQueuePage.js.map +1 -1
  33. package/dist/pages/AppDetailPage.js +65 -65
  34. package/dist/pages/AppSettingsPage.js +32 -32
  35. package/dist/pages/CartPage.js +66 -66
  36. package/dist/pages/CreateSourcingRequestPage.d.ts +3 -0
  37. package/dist/pages/CreateSourcingRequestPage.js +439 -0
  38. package/dist/pages/CreateSourcingRequestPage.js.map +1 -0
  39. package/dist/pages/InstalledAppsPage.js +15 -15
  40. package/dist/pages/InstalledAppsPage.js.map +1 -1
  41. package/dist/pages/MarketplaceHomePage.js +384 -384
  42. package/dist/pages/MarketplaceHomePage.js.map +1 -1
  43. package/dist/pages/MyLicensesPage.js +39 -39
  44. package/dist/pages/OrderConfirmationPage.js +57 -57
  45. package/dist/pages/OrdersPage.js +3 -3
  46. package/dist/pages/OrdersPage.js.map +1 -1
  47. package/dist/pages/ProductDetailPage.js +6 -6
  48. package/dist/pages/SellerSourcingOffersPage.d.ts +3 -0
  49. package/dist/pages/SellerSourcingOffersPage.js +284 -0
  50. package/dist/pages/SellerSourcingOffersPage.js.map +1 -0
  51. package/dist/pages/SellerSourcingOpportunitiesPage.d.ts +3 -0
  52. package/dist/pages/SellerSourcingOpportunitiesPage.js +272 -0
  53. package/dist/pages/SellerSourcingOpportunitiesPage.js.map +1 -0
  54. package/dist/pages/SellerSourcingOpportunityDetailPage.d.ts +3 -0
  55. package/dist/pages/SellerSourcingOpportunityDetailPage.js +465 -0
  56. package/dist/pages/SellerSourcingOpportunityDetailPage.js.map +1 -0
  57. package/dist/pages/SourcingRequestDetailPage.d.ts +3 -0
  58. package/dist/pages/SourcingRequestDetailPage.js +447 -0
  59. package/dist/pages/SourcingRequestDetailPage.js.map +1 -0
  60. package/dist/pages/SourcingRequestsPage.d.ts +3 -0
  61. package/dist/pages/SourcingRequestsPage.js +272 -0
  62. package/dist/pages/SourcingRequestsPage.js.map +1 -0
  63. package/dist/providers/SourcingAccessProvider.d.ts +21 -0
  64. package/dist/providers/SourcingAccessProvider.js +95 -0
  65. package/dist/providers/SourcingAccessProvider.js.map +1 -0
  66. package/dist/translations/en.d.ts +3 -0
  67. package/dist/translations/en.js +3 -0
  68. package/dist/translations/en.js.map +1 -1
  69. package/package.json +2 -2
@@ -0,0 +1,439 @@
1
+ import { useStore as e } from "../providers/StoreProvider.js";
2
+ import { useSourcingApi as t } from "../hooks/useSourcing.js";
3
+ import { SourcingUnit as n } from "../generated/global-types.js";
4
+ import { ContextRequiredPanel as r, SOURCING_UNITS as i, SourcingPageHeader as a, formatSourcingUnit as o, helpClassName as s, inputClassName as c, joinStorePath as l, labelClassName as u, primaryButtonClassName as d, secondaryButtonClassName as f, toErrorMessage as p } from "../components/sourcing/SourcingUi.js";
5
+ import { useState as m } from "react";
6
+ import { useNavigate as h } from "react-router";
7
+ import { FilePlus2 as g, Loader2 as _, PackageSearch as v } from "lucide-react";
8
+ import { jsx as y, jsxs as b } from "react/jsx-runtime";
9
+ import { GlassCard as x, PagePurpose as S } from "@burdenoff/fe-libs/ui";
10
+ //#region src/pages/CreateSourcingRequestPage.tsx
11
+ var C = {
12
+ productName: "",
13
+ category: "",
14
+ summary: "",
15
+ quantity: "",
16
+ unit: n.Unit,
17
+ deliveryWindowStart: "",
18
+ deliveryWindowEnd: "",
19
+ deliveryCountry: "",
20
+ deliveryRegion: "",
21
+ deliveryCity: "",
22
+ targetUnitPrice: ""
23
+ }, w = /^(?:0|[1-9]\d{0,15})(?:\.\d{1,2})?$/, T = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
24
+ function E(e) {
25
+ return e.trim().toLowerCase().replaceAll(/[_\s]+/g, "-").replaceAll(/-+/g, "-");
26
+ }
27
+ function D(e) {
28
+ let t = {}, n = e.productName.trim(), r = E(e.category), i = Number(e.quantity), a = new Date(e.deliveryWindowStart), o = new Date(e.deliveryWindowEnd);
29
+ return (n.length < 2 || n.length > 160) && (t.productName = "Enter a product name between 2 and 160 characters."), (r.length < 2 || r.length > 64 || !T.test(r)) && (t.category = "Use 2–64 lowercase letters, numbers, and single hyphens."), e.summary.trim().length > 1e3 && (t.summary = "Summary cannot exceed 1,000 characters."), (!Number.isSafeInteger(i) || i < 1 || i > 1e6) && (t.quantity = "Quantity must be a whole number from 1 to 1,000,000."), (!e.deliveryWindowStart || Number.isNaN(a.getTime())) && (t.deliveryWindowStart = "Choose a valid delivery window start."), (!e.deliveryWindowEnd || Number.isNaN(o.getTime()) || o <= a) && (t.deliveryWindowEnd = "Delivery window end must be after its start."), /^[A-Za-z]{2}$/.test(e.deliveryCountry.trim()) || (t.deliveryCountry = "Use a two-letter country code, such as IN or US."), e.deliveryRegion.trim().length > 120 && (t.deliveryRegion = "Region cannot exceed 120 characters."), e.deliveryCity.trim().length > 120 && (t.deliveryCity = "City cannot exceed 120 characters."), e.targetUnitPrice && (!w.test(e.targetUnitPrice.trim()) || Number(e.targetUnitPrice) <= 0) && (t.targetUnitPrice = "Enter a positive amount with no more than two decimal places."), t;
30
+ }
31
+ var O = () => {
32
+ let n = h(), { basePath: w } = e(), { createBuyerRequest: T, hasOrganizationContext: O } = t(), [k, A] = m(C), [j, M] = m({}), [N, P] = m(null), [F, I] = m(!1), L = l(w, "sourcing/requests"), R = (e) => (t) => {
33
+ let n = t.target.value;
34
+ A((t) => ({
35
+ ...t,
36
+ [e]: n
37
+ })), M((t) => ({
38
+ ...t,
39
+ [e]: void 0
40
+ }));
41
+ }, z = async (e) => {
42
+ if (e.preventDefault(), !O || F) return;
43
+ let t = D(k);
44
+ if (M(t), P(null), Object.keys(t).length > 0) return;
45
+ let r = (e) => e.trim() || void 0, i = {
46
+ productName: k.productName.trim(),
47
+ category: E(k.category),
48
+ summary: r(k.summary),
49
+ quantity: Number(k.quantity),
50
+ unit: k.unit,
51
+ deliveryWindowStart: new Date(k.deliveryWindowStart).toISOString(),
52
+ deliveryWindowEnd: new Date(k.deliveryWindowEnd).toISOString(),
53
+ deliveryCountry: k.deliveryCountry.trim().toUpperCase(),
54
+ deliveryRegion: r(k.deliveryRegion),
55
+ deliveryCity: r(k.deliveryCity),
56
+ targetUnitPrice: r(k.targetUnitPrice),
57
+ targetCurrency: k.targetUnitPrice.trim() ? "USD" : void 0
58
+ };
59
+ I(!0);
60
+ try {
61
+ n(l(w, `sourcing/requests/${(await T(i)).id}`), { replace: !0 });
62
+ } catch (e) {
63
+ P(p(e, "The sourcing request could not be created."));
64
+ } finally {
65
+ I(!1);
66
+ }
67
+ }, B = (e) => {
68
+ let t = j[e];
69
+ return t ? /* @__PURE__ */ y("p", {
70
+ id: `${e}-error`,
71
+ className: "mt-1 text-xs text-text-danger",
72
+ children: t
73
+ }) : null;
74
+ };
75
+ return /* @__PURE__ */ b("div", {
76
+ className: "min-h-full bg-surface-default",
77
+ children: [/* @__PURE__ */ y(a, {
78
+ title: "Create sourcing request",
79
+ description: "Share only the purchase details verified publishers need to prepare an offer.",
80
+ icon: /* @__PURE__ */ y(g, {
81
+ className: "size-5",
82
+ "aria-hidden": "true"
83
+ }),
84
+ onBack: () => n(L)
85
+ }), /* @__PURE__ */ b("main", {
86
+ className: "mx-auto max-w-4xl px-4 py-6 sm:px-6",
87
+ children: [/* @__PURE__ */ y(S, {
88
+ className: "mb-6",
89
+ children: "Your user and active organization own this request. Billing identity is resolved securely by Store; it is never entered in this form. Publishers see the product, quantity, destination, delivery window, and optional target price only."
90
+ }), O ? /* @__PURE__ */ y("form", {
91
+ onSubmit: (e) => void z(e),
92
+ noValidate: !0,
93
+ children: /* @__PURE__ */ b(x, {
94
+ className: "p-5 sm:p-6",
95
+ children: [
96
+ /* @__PURE__ */ b("section", {
97
+ "aria-labelledby": "request-product-heading",
98
+ children: [/* @__PURE__ */ b("div", {
99
+ className: "flex items-center gap-2",
100
+ children: [/* @__PURE__ */ y(v, {
101
+ className: "size-5 text-text-accent",
102
+ "aria-hidden": "true"
103
+ }), /* @__PURE__ */ y("h2", {
104
+ id: "request-product-heading",
105
+ className: "text-lg font-semibold text-text-primary",
106
+ children: "Product needed"
107
+ })]
108
+ }), /* @__PURE__ */ b("div", {
109
+ className: "mt-5 grid gap-5 sm:grid-cols-2",
110
+ children: [
111
+ /* @__PURE__ */ b("label", {
112
+ className: `${u} sm:col-span-2`,
113
+ children: [
114
+ "Product name",
115
+ /* @__PURE__ */ y("input", {
116
+ type: "text",
117
+ value: k.productName,
118
+ onChange: R("productName"),
119
+ required: !0,
120
+ maxLength: 160,
121
+ autoComplete: "off",
122
+ "aria-invalid": !!j.productName,
123
+ "aria-describedby": j.productName ? "productName-error" : void 0,
124
+ placeholder: "Example: Organic basmati rice",
125
+ className: c
126
+ }),
127
+ B("productName")
128
+ ]
129
+ }),
130
+ /* @__PURE__ */ b("label", {
131
+ className: u,
132
+ children: [
133
+ "Category",
134
+ /* @__PURE__ */ y("input", {
135
+ type: "text",
136
+ value: k.category,
137
+ onChange: R("category"),
138
+ onBlur: () => A((e) => ({
139
+ ...e,
140
+ category: E(e.category)
141
+ })),
142
+ required: !0,
143
+ maxLength: 64,
144
+ autoComplete: "off",
145
+ "aria-invalid": !!j.category,
146
+ "aria-describedby": j.category ? "category-error" : "category-help",
147
+ placeholder: "food-grains",
148
+ className: c
149
+ }),
150
+ B("category"),
151
+ j.category ? null : /* @__PURE__ */ y("p", {
152
+ id: "category-help",
153
+ className: s,
154
+ children: "A short category slug; spaces are converted to hyphens."
155
+ })
156
+ ]
157
+ }),
158
+ /* @__PURE__ */ b("label", {
159
+ className: u,
160
+ children: [
161
+ "Quantity",
162
+ /* @__PURE__ */ y("input", {
163
+ type: "number",
164
+ value: k.quantity,
165
+ onChange: R("quantity"),
166
+ required: !0,
167
+ min: 1,
168
+ max: 1e6,
169
+ step: 1,
170
+ inputMode: "numeric",
171
+ "aria-invalid": !!j.quantity,
172
+ "aria-describedby": j.quantity ? "quantity-error" : void 0,
173
+ className: c
174
+ }),
175
+ B("quantity")
176
+ ]
177
+ }),
178
+ /* @__PURE__ */ b("label", {
179
+ className: u,
180
+ children: ["Unit", /* @__PURE__ */ y("select", {
181
+ value: k.unit,
182
+ onChange: R("unit"),
183
+ className: c,
184
+ children: i.map((e) => /* @__PURE__ */ y("option", {
185
+ value: e,
186
+ children: o(e)
187
+ }, e))
188
+ })]
189
+ }),
190
+ /* @__PURE__ */ b("label", {
191
+ className: `${u} sm:col-span-2`,
192
+ children: [
193
+ "Summary ",
194
+ /* @__PURE__ */ y("span", {
195
+ className: "font-normal text-text-tertiary",
196
+ children: "(optional)"
197
+ }),
198
+ /* @__PURE__ */ y("textarea", {
199
+ value: k.summary,
200
+ onChange: R("summary"),
201
+ maxLength: 1e3,
202
+ rows: 4,
203
+ "aria-invalid": !!j.summary,
204
+ "aria-describedby": j.summary ? "summary-error" : "summary-help",
205
+ placeholder: "Add grade, packaging, certification, or other offer requirements.",
206
+ className: `${c} resize-y`
207
+ }),
208
+ B("summary"),
209
+ j.summary ? null : /* @__PURE__ */ b("p", {
210
+ id: "summary-help",
211
+ className: s,
212
+ children: [k.summary.length, "/1,000 characters"]
213
+ })
214
+ ]
215
+ }),
216
+ /* @__PURE__ */ b("div", {
217
+ role: "note",
218
+ className: "rounded-lg border border-status-warning-border bg-status-warning-bg-subtle p-4 text-sm text-status-warning-text sm:col-span-2",
219
+ children: [/* @__PURE__ */ y("p", {
220
+ className: "font-semibold",
221
+ children: "This summary is visible to eligible publishers."
222
+ }), /* @__PURE__ */ y("p", {
223
+ className: "mt-1 leading-6",
224
+ children: "Do not include personal or contact details, trust or compliance records, payment or billing information, credentials, private addresses, or other confidential data. Share only product and delivery requirements needed to prepare an offer."
225
+ })]
226
+ })
227
+ ]
228
+ })]
229
+ }),
230
+ /* @__PURE__ */ b("section", {
231
+ "aria-labelledby": "request-delivery-heading",
232
+ className: "mt-8 border-t border-border-seam pt-6",
233
+ children: [/* @__PURE__ */ y("h2", {
234
+ id: "request-delivery-heading",
235
+ className: "text-lg font-semibold text-text-primary",
236
+ children: "Delivery"
237
+ }), /* @__PURE__ */ b("div", {
238
+ className: "mt-5 grid gap-5 sm:grid-cols-2",
239
+ children: [
240
+ /* @__PURE__ */ b("label", {
241
+ className: u,
242
+ children: [
243
+ "Window starts",
244
+ /* @__PURE__ */ y("input", {
245
+ type: "datetime-local",
246
+ value: k.deliveryWindowStart,
247
+ onChange: R("deliveryWindowStart"),
248
+ required: !0,
249
+ "aria-invalid": !!j.deliveryWindowStart,
250
+ "aria-describedby": j.deliveryWindowStart ? "deliveryWindowStart-error" : void 0,
251
+ className: c
252
+ }),
253
+ B("deliveryWindowStart")
254
+ ]
255
+ }),
256
+ /* @__PURE__ */ b("label", {
257
+ className: u,
258
+ children: [
259
+ "Window ends",
260
+ /* @__PURE__ */ y("input", {
261
+ type: "datetime-local",
262
+ value: k.deliveryWindowEnd,
263
+ onChange: R("deliveryWindowEnd"),
264
+ required: !0,
265
+ min: k.deliveryWindowStart || void 0,
266
+ "aria-invalid": !!j.deliveryWindowEnd,
267
+ "aria-describedby": j.deliveryWindowEnd ? "deliveryWindowEnd-error" : void 0,
268
+ className: c
269
+ }),
270
+ B("deliveryWindowEnd")
271
+ ]
272
+ }),
273
+ /* @__PURE__ */ b("label", {
274
+ className: u,
275
+ children: [
276
+ "Country code",
277
+ /* @__PURE__ */ y("input", {
278
+ type: "text",
279
+ value: k.deliveryCountry,
280
+ onChange: R("deliveryCountry"),
281
+ required: !0,
282
+ minLength: 2,
283
+ maxLength: 2,
284
+ autoComplete: "country",
285
+ "aria-invalid": !!j.deliveryCountry,
286
+ "aria-describedby": j.deliveryCountry ? "deliveryCountry-error" : "deliveryCountry-help",
287
+ placeholder: "IN",
288
+ className: `${c} uppercase`
289
+ }),
290
+ B("deliveryCountry"),
291
+ j.deliveryCountry ? null : /* @__PURE__ */ y("p", {
292
+ id: "deliveryCountry-help",
293
+ className: s,
294
+ children: "ISO two-letter country code."
295
+ })
296
+ ]
297
+ }),
298
+ /* @__PURE__ */ b("label", {
299
+ className: u,
300
+ children: [
301
+ "Region or state",
302
+ " ",
303
+ /* @__PURE__ */ y("span", {
304
+ className: "font-normal text-text-tertiary",
305
+ children: "(optional)"
306
+ }),
307
+ /* @__PURE__ */ y("input", {
308
+ type: "text",
309
+ value: k.deliveryRegion,
310
+ onChange: R("deliveryRegion"),
311
+ maxLength: 120,
312
+ autoComplete: "address-level1",
313
+ "aria-invalid": !!j.deliveryRegion,
314
+ "aria-describedby": j.deliveryRegion ? "deliveryRegion-error" : void 0,
315
+ className: c
316
+ }),
317
+ B("deliveryRegion")
318
+ ]
319
+ }),
320
+ /* @__PURE__ */ b("label", {
321
+ className: u,
322
+ children: [
323
+ "City ",
324
+ /* @__PURE__ */ y("span", {
325
+ className: "font-normal text-text-tertiary",
326
+ children: "(optional)"
327
+ }),
328
+ /* @__PURE__ */ y("input", {
329
+ type: "text",
330
+ value: k.deliveryCity,
331
+ onChange: R("deliveryCity"),
332
+ maxLength: 120,
333
+ autoComplete: "address-level2",
334
+ "aria-invalid": !!j.deliveryCity,
335
+ "aria-describedby": j.deliveryCity ? "deliveryCity-error" : void 0,
336
+ className: c
337
+ }),
338
+ B("deliveryCity")
339
+ ]
340
+ })
341
+ ]
342
+ })]
343
+ }),
344
+ /* @__PURE__ */ b("section", {
345
+ "aria-labelledby": "request-budget-heading",
346
+ className: "mt-8 border-t border-border-seam pt-6",
347
+ children: [
348
+ /* @__PURE__ */ b("h2", {
349
+ id: "request-budget-heading",
350
+ className: "text-lg font-semibold text-text-primary",
351
+ children: ["Target price ", /* @__PURE__ */ y("span", {
352
+ className: "font-normal text-text-tertiary",
353
+ children: "(optional)"
354
+ })]
355
+ }),
356
+ /* @__PURE__ */ y("p", {
357
+ className: "mt-1 text-sm text-text-secondary",
358
+ children: "This is a target unit price, not an order total. Store calculates the accepted order total from the seller's persisted offer."
359
+ }),
360
+ /* @__PURE__ */ b("div", {
361
+ className: "mt-5 grid gap-5 sm:grid-cols-2",
362
+ children: [/* @__PURE__ */ b("label", {
363
+ className: u,
364
+ children: [
365
+ "Target unit price",
366
+ /* @__PURE__ */ y("input", {
367
+ type: "text",
368
+ value: k.targetUnitPrice,
369
+ onChange: R("targetUnitPrice"),
370
+ inputMode: "decimal",
371
+ maxLength: 19,
372
+ "aria-invalid": !!j.targetUnitPrice,
373
+ "aria-describedby": j.targetUnitPrice ? "targetUnitPrice-error" : "targetUnitPrice-help",
374
+ placeholder: "125.50",
375
+ className: c
376
+ }),
377
+ B("targetUnitPrice"),
378
+ j.targetUnitPrice ? null : /* @__PURE__ */ y("p", {
379
+ id: "targetUnitPrice-help",
380
+ className: s,
381
+ children: "Positive amount with up to two decimal places."
382
+ })
383
+ ]
384
+ }), /* @__PURE__ */ b("div", { children: [
385
+ /* @__PURE__ */ y("span", {
386
+ className: u,
387
+ children: "Settlement currency"
388
+ }),
389
+ /* @__PURE__ */ y("div", {
390
+ className: `${c} flex items-center bg-surface-muted font-semibold`,
391
+ children: "USD"
392
+ }),
393
+ /* @__PURE__ */ y("p", {
394
+ className: s,
395
+ children: "Store sourcing offers, orders, earnings, and payouts currently settle in USD."
396
+ })
397
+ ] })]
398
+ })
399
+ ]
400
+ }),
401
+ N ? /* @__PURE__ */ y("div", {
402
+ role: "alert",
403
+ className: "mt-6 rounded-lg border border-border-danger bg-surface-danger-muted px-4 py-3 text-sm text-text-danger",
404
+ children: N
405
+ }) : null,
406
+ /* @__PURE__ */ b("div", {
407
+ className: "mt-7 flex flex-col-reverse gap-3 border-t border-border-seam pt-5 sm:flex-row sm:justify-end",
408
+ children: [/* @__PURE__ */ y("button", {
409
+ type: "button",
410
+ onClick: () => n(L),
411
+ disabled: F,
412
+ className: f,
413
+ children: "Cancel"
414
+ }), /* @__PURE__ */ b("button", {
415
+ type: "submit",
416
+ disabled: F,
417
+ className: d,
418
+ children: [F ? /* @__PURE__ */ y(_, {
419
+ className: "size-4 animate-spin",
420
+ "aria-hidden": "true"
421
+ }) : /* @__PURE__ */ y(g, {
422
+ className: "size-4",
423
+ "aria-hidden": "true"
424
+ }), F ? "Creating request…" : "Create request"]
425
+ })]
426
+ })
427
+ ]
428
+ })
429
+ }) : /* @__PURE__ */ y(r, {
430
+ title: "Choose an organization before creating a request",
431
+ description: "Use the app context switcher to select a global organization with a billing account. You do not need to select or create a farm workspace."
432
+ })]
433
+ })]
434
+ });
435
+ };
436
+ //#endregion
437
+ export { O as CreateSourcingRequestPage };
438
+
439
+ //# sourceMappingURL=CreateSourcingRequestPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CreateSourcingRequestPage.js","names":[],"sources":["../../src/pages/CreateSourcingRequestPage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport type { ChangeEvent, FC, FormEvent } from 'react';\nimport { useNavigate } from 'react-router';\nimport { FilePlus2, Loader2, PackageSearch } from 'lucide-react';\nimport { GlassCard, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { SourcingUnit } from '../generated/global-types';\nimport type { CreateSourcingRequestInput } from '../generated/global-types';\nimport { useStore } from '../providers/StoreProvider';\nimport { useSourcingApi } from '../hooks/useSourcing';\nimport {\n ContextRequiredPanel,\n helpClassName,\n inputClassName,\n joinStorePath,\n labelClassName,\n primaryButtonClassName,\n secondaryButtonClassName,\n SOURCING_UNITS,\n SourcingPageHeader,\n formatSourcingUnit,\n toErrorMessage,\n} from '../components/sourcing/SourcingUi';\n\ninterface RequestFormState {\n productName: string;\n category: string;\n summary: string;\n quantity: string;\n unit: SourcingUnit;\n deliveryWindowStart: string;\n deliveryWindowEnd: string;\n deliveryCountry: string;\n deliveryRegion: string;\n deliveryCity: string;\n targetUnitPrice: string;\n}\n\ntype FieldName = keyof RequestFormState;\ntype FieldErrors = Partial<Record<FieldName, string>>;\n\nconst INITIAL_FORM: RequestFormState = {\n productName: '',\n category: '',\n summary: '',\n quantity: '',\n unit: SourcingUnit.Unit,\n deliveryWindowStart: '',\n deliveryWindowEnd: '',\n deliveryCountry: '',\n deliveryRegion: '',\n deliveryCity: '',\n targetUnitPrice: '',\n};\n\nconst MONEY_PATTERN = /^(?:0|[1-9]\\d{0,15})(?:\\.\\d{1,2})?$/;\nconst CATEGORY_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\n\nfunction normalizeCategory(value: string): string {\n return value\n .trim()\n .toLowerCase()\n .replaceAll(/[_\\s]+/g, '-')\n .replaceAll(/-+/g, '-');\n}\n\nfunction validate(form: RequestFormState): FieldErrors {\n const errors: FieldErrors = {};\n const productName = form.productName.trim();\n const category = normalizeCategory(form.category);\n const quantity = Number(form.quantity);\n const start = new Date(form.deliveryWindowStart);\n const end = new Date(form.deliveryWindowEnd);\n\n if (productName.length < 2 || productName.length > 160) {\n errors.productName = 'Enter a product name between 2 and 160 characters.';\n }\n if (category.length < 2 || category.length > 64 || !CATEGORY_PATTERN.test(category)) {\n errors.category = 'Use 2–64 lowercase letters, numbers, and single hyphens.';\n }\n if (form.summary.trim().length > 1000) {\n errors.summary = 'Summary cannot exceed 1,000 characters.';\n }\n if (!Number.isSafeInteger(quantity) || quantity < 1 || quantity > 1_000_000) {\n errors.quantity = 'Quantity must be a whole number from 1 to 1,000,000.';\n }\n if (!form.deliveryWindowStart || Number.isNaN(start.getTime())) {\n errors.deliveryWindowStart = 'Choose a valid delivery window start.';\n }\n if (!form.deliveryWindowEnd || Number.isNaN(end.getTime()) || end <= start) {\n errors.deliveryWindowEnd = 'Delivery window end must be after its start.';\n }\n if (!/^[A-Za-z]{2}$/.test(form.deliveryCountry.trim())) {\n errors.deliveryCountry = 'Use a two-letter country code, such as IN or US.';\n }\n if (form.deliveryRegion.trim().length > 120) {\n errors.deliveryRegion = 'Region cannot exceed 120 characters.';\n }\n if (form.deliveryCity.trim().length > 120) {\n errors.deliveryCity = 'City cannot exceed 120 characters.';\n }\n if (\n form.targetUnitPrice &&\n (!MONEY_PATTERN.test(form.targetUnitPrice.trim()) || Number(form.targetUnitPrice) <= 0)\n ) {\n errors.targetUnitPrice = 'Enter a positive amount with no more than two decimal places.';\n }\n\n return errors;\n}\n\nexport const CreateSourcingRequestPage: FC = () => {\n const navigate = useNavigate();\n const { basePath } = useStore();\n const { createBuyerRequest, hasOrganizationContext } = useSourcingApi();\n const [form, setForm] = useState<RequestFormState>(INITIAL_FORM);\n const [errors, setErrors] = useState<FieldErrors>({});\n const [submitError, setSubmitError] = useState<string | null>(null);\n const [submitting, setSubmitting] = useState(false);\n\n const listPath = joinStorePath(basePath, 'sourcing/requests');\n\n const updateField =\n <TField extends FieldName>(field: TField) =>\n (event: ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => {\n const value = event.target.value;\n setForm((current) => ({ ...current, [field]: value }));\n setErrors((current) => ({ ...current, [field]: undefined }));\n };\n\n const handleSubmit = async (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n if (!hasOrganizationContext || submitting) return;\n\n const validationErrors = validate(form);\n setErrors(validationErrors);\n setSubmitError(null);\n if (Object.keys(validationErrors).length > 0) return;\n\n const optional = (value: string) => value.trim() || undefined;\n const input: CreateSourcingRequestInput = {\n productName: form.productName.trim(),\n category: normalizeCategory(form.category),\n summary: optional(form.summary),\n quantity: Number(form.quantity),\n unit: form.unit,\n deliveryWindowStart: new Date(form.deliveryWindowStart).toISOString(),\n deliveryWindowEnd: new Date(form.deliveryWindowEnd).toISOString(),\n deliveryCountry: form.deliveryCountry.trim().toUpperCase(),\n deliveryRegion: optional(form.deliveryRegion),\n deliveryCity: optional(form.deliveryCity),\n targetUnitPrice: optional(form.targetUnitPrice),\n targetCurrency: form.targetUnitPrice.trim() ? 'USD' : undefined,\n };\n\n setSubmitting(true);\n try {\n const request = await createBuyerRequest(input);\n navigate(joinStorePath(basePath, `sourcing/requests/${request.id}`), { replace: true });\n } catch (error) {\n setSubmitError(toErrorMessage(error, 'The sourcing request could not be created.'));\n } finally {\n setSubmitting(false);\n }\n };\n\n const fieldError = (field: FieldName) => {\n const message = errors[field];\n return message ? (\n <p id={`${field}-error`} className=\"mt-1 text-xs text-text-danger\">\n {message}\n </p>\n ) : null;\n };\n\n return (\n <div className=\"min-h-full bg-surface-default\">\n <SourcingPageHeader\n title=\"Create sourcing request\"\n description=\"Share only the purchase details verified publishers need to prepare an offer.\"\n icon={<FilePlus2 className=\"size-5\" aria-hidden=\"true\" />}\n onBack={() => navigate(listPath)}\n />\n\n <main className=\"mx-auto max-w-4xl px-4 py-6 sm:px-6\">\n <PagePurpose className=\"mb-6\">\n Your user and active organization own this request. Billing identity is resolved securely\n by Store; it is never entered in this form. Publishers see the product, quantity,\n destination, delivery window, and optional target price only.\n </PagePurpose>\n\n {!hasOrganizationContext ? (\n <ContextRequiredPanel\n title=\"Choose an organization before creating a request\"\n description=\"Use the app context switcher to select a global organization with a billing account. You do not need to select or create a farm workspace.\"\n />\n ) : (\n <form onSubmit={(event) => void handleSubmit(event)} noValidate>\n <GlassCard className=\"p-5 sm:p-6\">\n <section aria-labelledby=\"request-product-heading\">\n <div className=\"flex items-center gap-2\">\n <PackageSearch className=\"size-5 text-text-accent\" aria-hidden=\"true\" />\n <h2\n id=\"request-product-heading\"\n className=\"text-lg font-semibold text-text-primary\"\n >\n Product needed\n </h2>\n </div>\n <div className=\"mt-5 grid gap-5 sm:grid-cols-2\">\n <label className={`${labelClassName} sm:col-span-2`}>\n Product name\n <input\n type=\"text\"\n value={form.productName}\n onChange={updateField('productName')}\n required\n maxLength={160}\n autoComplete=\"off\"\n aria-invalid={Boolean(errors.productName)}\n aria-describedby={errors.productName ? 'productName-error' : undefined}\n placeholder=\"Example: Organic basmati rice\"\n className={inputClassName}\n />\n {fieldError('productName')}\n </label>\n\n <label className={labelClassName}>\n Category\n <input\n type=\"text\"\n value={form.category}\n onChange={updateField('category')}\n onBlur={() =>\n setForm((current) => ({\n ...current,\n category: normalizeCategory(current.category),\n }))\n }\n required\n maxLength={64}\n autoComplete=\"off\"\n aria-invalid={Boolean(errors.category)}\n aria-describedby={errors.category ? 'category-error' : 'category-help'}\n placeholder=\"food-grains\"\n className={inputClassName}\n />\n {fieldError('category')}\n {!errors.category ? (\n <p id=\"category-help\" className={helpClassName}>\n A short category slug; spaces are converted to hyphens.\n </p>\n ) : null}\n </label>\n\n <label className={labelClassName}>\n Quantity\n <input\n type=\"number\"\n value={form.quantity}\n onChange={updateField('quantity')}\n required\n min={1}\n max={1_000_000}\n step={1}\n inputMode=\"numeric\"\n aria-invalid={Boolean(errors.quantity)}\n aria-describedby={errors.quantity ? 'quantity-error' : undefined}\n className={inputClassName}\n />\n {fieldError('quantity')}\n </label>\n\n <label className={labelClassName}>\n Unit\n <select\n value={form.unit}\n onChange={updateField('unit')}\n className={inputClassName}\n >\n {SOURCING_UNITS.map((unit) => (\n <option key={unit} value={unit}>\n {formatSourcingUnit(unit)}\n </option>\n ))}\n </select>\n </label>\n\n <label className={`${labelClassName} sm:col-span-2`}>\n Summary <span className=\"font-normal text-text-tertiary\">(optional)</span>\n <textarea\n value={form.summary}\n onChange={updateField('summary')}\n maxLength={1000}\n rows={4}\n aria-invalid={Boolean(errors.summary)}\n aria-describedby={errors.summary ? 'summary-error' : 'summary-help'}\n placeholder=\"Add grade, packaging, certification, or other offer requirements.\"\n className={`${inputClassName} resize-y`}\n />\n {fieldError('summary')}\n {!errors.summary ? (\n <p id=\"summary-help\" className={helpClassName}>\n {form.summary.length}/1,000 characters\n </p>\n ) : null}\n </label>\n <div\n role=\"note\"\n className=\"rounded-lg border border-status-warning-border bg-status-warning-bg-subtle p-4 text-sm text-status-warning-text sm:col-span-2\"\n >\n <p className=\"font-semibold\">This summary is visible to eligible publishers.</p>\n <p className=\"mt-1 leading-6\">\n Do not include personal or contact details, trust or compliance records,\n payment or billing information, credentials, private addresses, or other\n confidential data. Share only product and delivery requirements needed to\n prepare an offer.\n </p>\n </div>\n </div>\n </section>\n\n <section\n aria-labelledby=\"request-delivery-heading\"\n className=\"mt-8 border-t border-border-seam pt-6\"\n >\n <h2\n id=\"request-delivery-heading\"\n className=\"text-lg font-semibold text-text-primary\"\n >\n Delivery\n </h2>\n <div className=\"mt-5 grid gap-5 sm:grid-cols-2\">\n <label className={labelClassName}>\n Window starts\n <input\n type=\"datetime-local\"\n value={form.deliveryWindowStart}\n onChange={updateField('deliveryWindowStart')}\n required\n aria-invalid={Boolean(errors.deliveryWindowStart)}\n aria-describedby={\n errors.deliveryWindowStart ? 'deliveryWindowStart-error' : undefined\n }\n className={inputClassName}\n />\n {fieldError('deliveryWindowStart')}\n </label>\n <label className={labelClassName}>\n Window ends\n <input\n type=\"datetime-local\"\n value={form.deliveryWindowEnd}\n onChange={updateField('deliveryWindowEnd')}\n required\n min={form.deliveryWindowStart || undefined}\n aria-invalid={Boolean(errors.deliveryWindowEnd)}\n aria-describedby={\n errors.deliveryWindowEnd ? 'deliveryWindowEnd-error' : undefined\n }\n className={inputClassName}\n />\n {fieldError('deliveryWindowEnd')}\n </label>\n <label className={labelClassName}>\n Country code\n <input\n type=\"text\"\n value={form.deliveryCountry}\n onChange={updateField('deliveryCountry')}\n required\n minLength={2}\n maxLength={2}\n autoComplete=\"country\"\n aria-invalid={Boolean(errors.deliveryCountry)}\n aria-describedby={\n errors.deliveryCountry ? 'deliveryCountry-error' : 'deliveryCountry-help'\n }\n placeholder=\"IN\"\n className={`${inputClassName} uppercase`}\n />\n {fieldError('deliveryCountry')}\n {!errors.deliveryCountry ? (\n <p id=\"deliveryCountry-help\" className={helpClassName}>\n ISO two-letter country code.\n </p>\n ) : null}\n </label>\n <label className={labelClassName}>\n Region or state{' '}\n <span className=\"font-normal text-text-tertiary\">(optional)</span>\n <input\n type=\"text\"\n value={form.deliveryRegion}\n onChange={updateField('deliveryRegion')}\n maxLength={120}\n autoComplete=\"address-level1\"\n aria-invalid={Boolean(errors.deliveryRegion)}\n aria-describedby={errors.deliveryRegion ? 'deliveryRegion-error' : undefined}\n className={inputClassName}\n />\n {fieldError('deliveryRegion')}\n </label>\n <label className={labelClassName}>\n City <span className=\"font-normal text-text-tertiary\">(optional)</span>\n <input\n type=\"text\"\n value={form.deliveryCity}\n onChange={updateField('deliveryCity')}\n maxLength={120}\n autoComplete=\"address-level2\"\n aria-invalid={Boolean(errors.deliveryCity)}\n aria-describedby={errors.deliveryCity ? 'deliveryCity-error' : undefined}\n className={inputClassName}\n />\n {fieldError('deliveryCity')}\n </label>\n </div>\n </section>\n\n <section\n aria-labelledby=\"request-budget-heading\"\n className=\"mt-8 border-t border-border-seam pt-6\"\n >\n <h2 id=\"request-budget-heading\" className=\"text-lg font-semibold text-text-primary\">\n Target price <span className=\"font-normal text-text-tertiary\">(optional)</span>\n </h2>\n <p className=\"mt-1 text-sm text-text-secondary\">\n This is a target unit price, not an order total. Store calculates the accepted\n order total from the seller's persisted offer.\n </p>\n <div className=\"mt-5 grid gap-5 sm:grid-cols-2\">\n <label className={labelClassName}>\n Target unit price\n <input\n type=\"text\"\n value={form.targetUnitPrice}\n onChange={updateField('targetUnitPrice')}\n inputMode=\"decimal\"\n maxLength={19}\n aria-invalid={Boolean(errors.targetUnitPrice)}\n aria-describedby={\n errors.targetUnitPrice ? 'targetUnitPrice-error' : 'targetUnitPrice-help'\n }\n placeholder=\"125.50\"\n className={inputClassName}\n />\n {fieldError('targetUnitPrice')}\n {!errors.targetUnitPrice ? (\n <p id=\"targetUnitPrice-help\" className={helpClassName}>\n Positive amount with up to two decimal places.\n </p>\n ) : null}\n </label>\n <div>\n <span className={labelClassName}>Settlement currency</span>\n <div\n className={`${inputClassName} flex items-center bg-surface-muted font-semibold`}\n >\n USD\n </div>\n <p className={helpClassName}>\n Store sourcing offers, orders, earnings, and payouts currently settle in USD.\n </p>\n </div>\n </div>\n </section>\n\n {submitError ? (\n <div\n role=\"alert\"\n className=\"mt-6 rounded-lg border border-border-danger bg-surface-danger-muted px-4 py-3 text-sm text-text-danger\"\n >\n {submitError}\n </div>\n ) : null}\n\n <div className=\"mt-7 flex flex-col-reverse gap-3 border-t border-border-seam pt-5 sm:flex-row sm:justify-end\">\n <button\n type=\"button\"\n onClick={() => navigate(listPath)}\n disabled={submitting}\n className={secondaryButtonClassName}\n >\n Cancel\n </button>\n <button type=\"submit\" disabled={submitting} className={primaryButtonClassName}>\n {submitting ? (\n <Loader2 className=\"size-4 animate-spin\" aria-hidden=\"true\" />\n ) : (\n <FilePlus2 className=\"size-4\" aria-hidden=\"true\" />\n )}\n {submitting ? 'Creating request…' : 'Create request'}\n </button>\n </div>\n </GlassCard>\n </form>\n )}\n </main>\n </div>\n );\n};\n"],"mappings":"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"}
@@ -3,11 +3,11 @@ import { useInstallationStatusUpdatedSubscription as t } from "../generated/glob
3
3
  import { useInstallations as n } from "../hooks/useInstallations.js";
4
4
  import { StoreInstallationStatus as r } from "../generated/global-types.js";
5
5
  import { useCallback as i, useMemo as a, useState as o } from "react";
6
- import { useI18n as ee } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
7
- import { AlertCircle as te, ChevronLeft as ne, ChevronRight as s, ExternalLink as c, Loader2 as l, Plus as u, RefreshCw as d, Search as f, Settings as re, Trash2 as p } from "lucide-react";
8
- import { useApolloClient as ie } from "@apollo/client/react";
6
+ import { useNavigate as ee } from "react-router";
7
+ import { useI18n as te } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
8
+ import { AlertCircle as ne, ChevronLeft as s, ChevronRight as c, ExternalLink as l, Loader2 as u, Plus as d, RefreshCw as f, Search as re, Settings as p, Trash2 as ie } from "lucide-react";
9
+ import { useApolloClient as ae } from "@apollo/client/react";
9
10
  import { Fragment as m, jsx as h, jsxs as g } from "react/jsx-runtime";
10
- import { useNavigate as ae } from "react-router";
11
11
  import { gql as _ } from "@apollo/client";
12
12
  import { AlertDialog as v, AlertDialogAction as oe, AlertDialogCancel as y, AlertDialogContent as b, AlertDialogDescription as x, AlertDialogFooter as S, AlertDialogHeader as C, AlertDialogTitle as se, IllustratedEmptyState as ce, PagePurpose as le } from "@burdenoff/fe-libs/ui";
13
13
  //#region src/pages/InstalledAppsPage.tsx
@@ -84,7 +84,7 @@ var j = _`
84
84
  )
85
85
  }
86
86
  `, M = () => {
87
- let _ = ae(), { basePath: D, workspaceId: M } = e(), { t: N } = ee(), P = ie(), [F, I] = o("all"), [L, R] = o(""), [z, B] = o(1), [V, H] = o(null), [U, W] = o(null), { installations: G, totalCount: K, hasMore: q, loading: J, error: Y, uninstall: de, uninstallingIds: fe, refetch: X } = n({
87
+ let _ = ee(), { basePath: D, workspaceId: M } = e(), { t: N } = te(), P = ae(), [F, I] = o("all"), [L, R] = o(""), [z, B] = o(1), [V, H] = o(null), [U, W] = o(null), { installations: G, totalCount: K, hasMore: q, loading: J, error: Y, uninstall: de, uninstallingIds: fe, refetch: X } = n({
88
88
  filter: a(() => F === "all" ? void 0 : { status: F }, [F]),
89
89
  limit: w,
90
90
  offset: (z - 1) * w
@@ -135,7 +135,7 @@ var j = _`
135
135
  type: "button",
136
136
  onClick: () => _(`${D}/marketplace`),
137
137
  className: "flex cursor-pointer items-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 font-semibold text-action-primary-text transition-colors hover:opacity-90",
138
- children: [/* @__PURE__ */ h(u, { className: "size-5" }), /* @__PURE__ */ h("span", { children: N("pages.installed.installNew", { defaultValue: "Install New App" }) })]
138
+ children: [/* @__PURE__ */ h(d, { className: "size-5" }), /* @__PURE__ */ h("span", { children: N("pages.installed.installNew", { defaultValue: "Install New App" }) })]
139
139
  })]
140
140
  })
141
141
  }),
@@ -159,7 +159,7 @@ var j = _`
159
159
  }, e.label)),
160
160
  /* @__PURE__ */ g("div", {
161
161
  className: "relative ml-auto",
162
- children: [/* @__PURE__ */ h(f, { className: "pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-text-muted" }), /* @__PURE__ */ h("input", {
162
+ children: [/* @__PURE__ */ h(re, { className: "pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-text-muted" }), /* @__PURE__ */ h("input", {
163
163
  type: "search",
164
164
  value: L,
165
165
  onChange: (e) => R(e.target.value),
@@ -171,7 +171,7 @@ var j = _`
171
171
  type: "button",
172
172
  onClick: () => X(),
173
173
  className: "inline-flex cursor-pointer items-center gap-2 rounded-lg border border-border-default bg-bg-surface px-3 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken",
174
- children: [/* @__PURE__ */ h(d, { className: "size-4" }), "Refresh"]
174
+ children: [/* @__PURE__ */ h(f, { className: "size-4" }), "Refresh"]
175
175
  })
176
176
  ]
177
177
  }),
@@ -183,7 +183,7 @@ var j = _`
183
183
  J ? /* @__PURE__ */ h("output", {
184
184
  "aria-label": "Loading installed apps",
185
185
  className: "flex items-center justify-center py-16",
186
- children: /* @__PURE__ */ h(l, {
186
+ children: /* @__PURE__ */ h(u, {
187
187
  className: "size-8 animate-spin text-text-muted",
188
188
  "aria-hidden": "true"
189
189
  })
@@ -191,7 +191,7 @@ var j = _`
191
191
  role: "alert",
192
192
  className: "flex flex-col items-center justify-center rounded-xl border border-status-error-border bg-status-error-bg-subtle py-16 text-center",
193
193
  children: [
194
- /* @__PURE__ */ h(te, { className: "mb-3 size-10 text-status-error-text" }),
194
+ /* @__PURE__ */ h(ne, { className: "mb-3 size-10 text-status-error-text" }),
195
195
  /* @__PURE__ */ h("h3", {
196
196
  className: "text-lg font-semibold text-status-error-text",
197
197
  children: "Failed to load installations"
@@ -346,7 +346,7 @@ var j = _`
346
346
  onClick: () => _(`${D}/installed/${e.id}`),
347
347
  className: "inline-flex cursor-pointer items-center gap-1.5 rounded-lg border border-border-default px-3 py-1.5 text-xs font-medium text-text-primary hover:bg-bg-sunken",
348
348
  title: "View installation details",
349
- children: [/* @__PURE__ */ h(c, { className: "size-3.5" }), "Details"]
349
+ children: [/* @__PURE__ */ h(l, { className: "size-3.5" }), "Details"]
350
350
  }) : /* @__PURE__ */ g(m, { children: [/* @__PURE__ */ h("button", {
351
351
  type: "button",
352
352
  onClick: () => _(`${D}/installed/${e.id}`),
@@ -356,7 +356,7 @@ var j = _`
356
356
  type: "button",
357
357
  onClick: () => _(`${D}/installed/${e.id}/settings`),
358
358
  className: "inline-flex cursor-pointer items-center gap-1.5 rounded-lg border border-border-default px-3 py-1.5 text-xs font-medium text-text-primary hover:bg-bg-sunken",
359
- children: [/* @__PURE__ */ h(re, { className: "size-3.5" }), "Configure"]
359
+ children: [/* @__PURE__ */ h(p, { className: "size-3.5" }), "Configure"]
360
360
  })] }),
361
361
  /* @__PURE__ */ h("button", {
362
362
  type: "button",
@@ -369,7 +369,7 @@ var j = _`
369
369
  onClick: () => W(e),
370
370
  disabled: a,
371
371
  className: "inline-flex cursor-pointer items-center gap-1.5 rounded-lg border border-status-error-border px-3 py-1.5 text-xs font-medium text-status-error-text hover:bg-status-error-bg-subtle disabled:opacity-60",
372
- children: [a ? /* @__PURE__ */ h(l, { className: "size-3.5 animate-spin" }) : /* @__PURE__ */ h(p, { className: "size-3.5" }), "Uninstall"]
372
+ children: [a ? /* @__PURE__ */ h(u, { className: "size-3.5 animate-spin" }) : /* @__PURE__ */ h(ie, { className: "size-3.5" }), "Uninstall"]
373
373
  })
374
374
  ]
375
375
  })
@@ -388,7 +388,7 @@ var j = _`
388
388
  onClick: () => B((e) => Math.max(1, e - 1)),
389
389
  disabled: z === 1 || J,
390
390
  className: "inline-flex cursor-pointer items-center gap-1.5 rounded-lg border border-border-default px-3 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken disabled:cursor-not-allowed disabled:opacity-40",
391
- children: [/* @__PURE__ */ h(ne, { className: "size-4" }), "Previous"]
391
+ children: [/* @__PURE__ */ h(s, { className: "size-4" }), "Previous"]
392
392
  }),
393
393
  /* @__PURE__ */ h("div", {
394
394
  className: "flex items-center gap-1",
@@ -407,7 +407,7 @@ var j = _`
407
407
  onClick: () => B((e) => q ? e + 1 : Math.min(Z, e + 1)),
408
408
  disabled: z >= Z || J,
409
409
  className: "inline-flex cursor-pointer items-center gap-1.5 rounded-lg border border-border-default px-3 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken disabled:cursor-not-allowed disabled:opacity-40",
410
- children: ["Next", /* @__PURE__ */ h(s, { className: "size-4" })]
410
+ children: ["Next", /* @__PURE__ */ h(c, { className: "size-4" })]
411
411
  })
412
412
  ]
413
413
  })