@mohasinac/appkit 4.21.0 → 4.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_internal/server/features/checkout/locked-lines.js +12 -2
- package/dist/_internal/server/features/stores/adapters.d.ts +1 -1
- package/dist/_internal/server/features/stores/adapters.js +5 -0
- package/dist/_internal/server/jobs/core/auctionSettlement.js +10 -4
- package/dist/_internal/server/jobs/core/offerExpiry.js +10 -2
- package/dist/_internal/server/jobs/core/payoutBatch.js +15 -3
- package/dist/_internal/shared/features/products/schema.d.ts +8 -8
- package/dist/_internal/shared/features/promotions/schema.d.ts +4 -4
- package/dist/_internal/shared/history/index.d.ts +1 -1
- package/dist/_internal/shared/history/types.d.ts +16 -0
- package/dist/client.d.ts +7 -0
- package/dist/client.js +4 -0
- package/dist/constants/field-names.d.ts +12 -0
- package/dist/constants/field-names.js +12 -0
- package/dist/features/account/components/AddressForm.js +45 -29
- package/dist/features/admin/actions/admin-actions.js +13 -3
- package/dist/features/admin/components/AdminBidsView.js +7 -1
- package/dist/features/admin/components/AdminBundleEditorView.js +3 -0
- package/dist/features/admin/components/AdminScammerEditorView.d.ts +5 -1
- package/dist/features/admin/components/AdminScammerEditorView.js +3 -2
- package/dist/features/admin/components/AdminSupportTicketDetailView.d.ts +5 -1
- package/dist/features/admin/components/AdminSupportTicketDetailView.js +3 -2
- package/dist/features/auctions/components/PlaceBidFormClient.js +3 -1
- package/dist/features/auctions/repository/bid.repository.d.ts +21 -8
- package/dist/features/auctions/repository/bid.repository.js +57 -33
- package/dist/features/auctions/schemas/firestore.d.ts +27 -0
- package/dist/features/auctions/schemas/firestore.js +21 -0
- package/dist/features/auth/schemas/index.d.ts +2 -2
- package/dist/features/catalogue/actions/approve-catalogue-listing.js +7 -6
- package/dist/features/catalogue/actions/list-from-catalogue.js +2 -2
- package/dist/features/catalogue/actions/submit-for-approval.js +1 -4
- package/dist/features/catalogue/components/AdminCatalogueApprovalsView.js +5 -1
- package/dist/features/catalogue/components/CatalogueItemEditorView.js +3 -1
- package/dist/features/catalogue/repository/catalogue.repository.d.ts +23 -0
- package/dist/features/catalogue/repository/catalogue.repository.js +28 -1
- package/dist/features/catalogue/schemas/firestore.d.ts +19 -0
- package/dist/features/catalogue/schemas/firestore.js +12 -0
- package/dist/features/categories/schemas/index.d.ts +2 -2
- package/dist/features/layout/BottomActions.js +18 -1
- package/dist/features/layout/BottomActionsContext.d.ts +19 -0
- package/dist/features/layout/BottomActionsContext.js +37 -0
- package/dist/features/layout/hooks/useBottomActions.d.ts +10 -0
- package/dist/features/layout/hooks/useBottomActions.js +48 -11
- package/dist/features/layout/hooks/useFormBottomActions.d.ts +57 -0
- package/dist/features/layout/hooks/useFormBottomActions.js +89 -0
- package/dist/features/layout/index.d.ts +2 -0
- package/dist/features/layout/index.js +1 -0
- package/dist/features/messages/schemas/index.d.ts +6 -6
- package/dist/features/orders/schemas/index.d.ts +12 -12
- package/dist/features/payments/repository/payout.repository.d.ts +18 -5
- package/dist/features/payments/repository/payout.repository.js +45 -19
- package/dist/features/payments/schemas/firestore.d.ts +33 -1
- package/dist/features/payments/schemas/firestore.js +39 -0
- package/dist/features/payments/schemas/index.d.ts +12 -12
- package/dist/features/products/components/MakeOfferButton.js +5 -3
- package/dist/features/products/schemas/index.d.ts +2 -2
- package/dist/features/promotions/schemas/index.d.ts +12 -12
- package/dist/features/scams/repository/scammer.repository.d.ts +18 -1
- package/dist/features/scams/repository/scammer.repository.js +24 -2
- package/dist/features/scams/schemas/firestore.d.ts +24 -0
- package/dist/features/scams/schemas/firestore.js +30 -0
- package/dist/features/shell/QuickFormDrawer.js +15 -1
- package/dist/features/shell/SectionForm.d.ts +16 -2
- package/dist/features/shell/SectionForm.js +28 -2
- package/dist/features/shipments/components/AdminShipmentEditorView.js +5 -2
- package/dist/features/shipments/repository/shipments.repository.d.ts +18 -0
- package/dist/features/shipments/repository/shipments.repository.js +23 -1
- package/dist/features/shipments/schemas/firestore.d.ts +14 -0
- package/dist/features/shipments/schemas/firestore.js +19 -0
- package/dist/features/status-history/components/RecordStatusTimeline.d.ts +12 -0
- package/dist/features/status-history/components/RecordStatusTimeline.js +90 -0
- package/dist/features/status-history/index.d.ts +2 -0
- package/dist/features/status-history/index.js +1 -0
- package/dist/features/stores/repository/store.repository.d.ts +30 -2
- package/dist/features/stores/repository/store.repository.js +43 -4
- package/dist/features/stores/schemas/firestore.d.ts +29 -0
- package/dist/features/stores/schemas/firestore.js +31 -0
- package/dist/features/support/repository/support.repository.d.ts +47 -3
- package/dist/features/support/repository/support.repository.js +72 -12
- package/dist/features/support/schemas/firestore.d.ts +38 -1
- package/dist/features/support/schemas/firestore.js +34 -0
- package/dist/features/support/schemas/index.d.ts +2 -2
- package/dist/features/tester/seed-data/tester-checklist-seed-data.js +90 -0
- package/dist/index.d.ts +7 -1
- package/dist/index.js +16 -1
- package/dist/schemas/registry.d.ts +32 -32
- package/dist/seed/bids-seed-data.js +8 -0
- package/dist/ui/components/Form.d.ts +22 -1
- package/dist/ui/components/Form.js +30 -2
- package/dist/ui/components/Modal.js +4 -3
- package/dist/ui/components/SideDrawer.js +5 -4
- package/dist/ui/components/overlay-context.d.ts +21 -0
- package/dist/ui/components/overlay-context.js +25 -0
- package/dist/ui/forms/FormErrorList.d.ts +29 -0
- package/dist/ui/forms/FormErrorList.js +36 -0
- package/dist/ui/forms/FormErrorSummary.d.ts +8 -0
- package/dist/ui/forms/FormErrorSummary.js +15 -8
- package/dist/ui/forms/FormShell.d.ts +25 -1
- package/dist/ui/forms/FormShell.js +39 -4
- package/dist/ui/forms/index.d.ts +2 -0
- package/dist/ui/forms/index.js +1 -0
- package/package.json +1 -1
|
@@ -1234,7 +1234,7 @@ export declare const SCHEMAS: {
|
|
|
1234
1234
|
}, import("zod").ZodTypeAny, "passthrough"> | undefined;
|
|
1235
1235
|
featuredPriority?: number | undefined;
|
|
1236
1236
|
isBrand?: boolean | undefined;
|
|
1237
|
-
createdByType?: "
|
|
1237
|
+
createdByType?: "admin" | "store" | undefined;
|
|
1238
1238
|
createdByStoreId?: string | undefined;
|
|
1239
1239
|
itemCode?: string | undefined;
|
|
1240
1240
|
brandWebsite?: string | undefined;
|
|
@@ -1333,7 +1333,7 @@ export declare const SCHEMAS: {
|
|
|
1333
1333
|
}, import("zod").ZodTypeAny, "passthrough"> | undefined;
|
|
1334
1334
|
featuredPriority?: number | undefined;
|
|
1335
1335
|
isBrand?: boolean | undefined;
|
|
1336
|
-
createdByType?: "
|
|
1336
|
+
createdByType?: "admin" | "store" | undefined;
|
|
1337
1337
|
createdByStoreId?: string | undefined;
|
|
1338
1338
|
itemCode?: string | undefined;
|
|
1339
1339
|
brandWebsite?: string | undefined;
|
|
@@ -1406,7 +1406,7 @@ export declare const SCHEMAS: {
|
|
|
1406
1406
|
}>;
|
|
1407
1407
|
}, "strip", import("zod").ZodTypeAny, {
|
|
1408
1408
|
type: "fixed" | "percentage" | "free_shipping" | "buy_x_get_y";
|
|
1409
|
-
scope: "
|
|
1409
|
+
scope: "seller" | "admin";
|
|
1410
1410
|
name: string;
|
|
1411
1411
|
discount: {
|
|
1412
1412
|
value: number;
|
|
@@ -1425,7 +1425,7 @@ export declare const SCHEMAS: {
|
|
|
1425
1425
|
description?: string | undefined;
|
|
1426
1426
|
}, {
|
|
1427
1427
|
type: "fixed" | "percentage" | "free_shipping" | "buy_x_get_y";
|
|
1428
|
-
scope: "
|
|
1428
|
+
scope: "seller" | "admin";
|
|
1429
1429
|
name: string;
|
|
1430
1430
|
discount: {
|
|
1431
1431
|
value: number;
|
|
@@ -1485,7 +1485,7 @@ export declare const SCHEMAS: {
|
|
|
1485
1485
|
couponId: string;
|
|
1486
1486
|
couponSnapshot: {
|
|
1487
1487
|
type: "fixed" | "percentage" | "free_shipping" | "buy_x_get_y";
|
|
1488
|
-
scope: "
|
|
1488
|
+
scope: "seller" | "admin";
|
|
1489
1489
|
name: string;
|
|
1490
1490
|
discount: {
|
|
1491
1491
|
value: number;
|
|
@@ -1525,7 +1525,7 @@ export declare const SCHEMAS: {
|
|
|
1525
1525
|
couponId: string;
|
|
1526
1526
|
couponSnapshot: {
|
|
1527
1527
|
type: "fixed" | "percentage" | "free_shipping" | "buy_x_get_y";
|
|
1528
|
-
scope: "
|
|
1528
|
+
scope: "seller" | "admin";
|
|
1529
1529
|
name: string;
|
|
1530
1530
|
discount: {
|
|
1531
1531
|
value: number;
|
|
@@ -1596,7 +1596,7 @@ export declare const SCHEMAS: {
|
|
|
1596
1596
|
body: string;
|
|
1597
1597
|
isRead: boolean;
|
|
1598
1598
|
senderId: string;
|
|
1599
|
-
senderRole: "
|
|
1599
|
+
senderRole: "buyer" | "seller";
|
|
1600
1600
|
sentAt: string | Date | import("zod").objectOutputType<{
|
|
1601
1601
|
toDate: import("zod").ZodFunction<import("zod").ZodTuple<[], import("zod").ZodUnknown>, import("zod").ZodDate>;
|
|
1602
1602
|
}, import("zod").ZodTypeAny, "passthrough">;
|
|
@@ -1606,7 +1606,7 @@ export declare const SCHEMAS: {
|
|
|
1606
1606
|
body: string;
|
|
1607
1607
|
isRead: boolean;
|
|
1608
1608
|
senderId: string;
|
|
1609
|
-
senderRole: "
|
|
1609
|
+
senderRole: "buyer" | "seller";
|
|
1610
1610
|
sentAt: string | Date | import("zod").objectInputType<{
|
|
1611
1611
|
toDate: import("zod").ZodFunction<import("zod").ZodTuple<[], import("zod").ZodUnknown>, import("zod").ZodDate>;
|
|
1612
1612
|
}, import("zod").ZodTypeAny, "passthrough">;
|
|
@@ -1644,7 +1644,7 @@ export declare const SCHEMAS: {
|
|
|
1644
1644
|
body: string;
|
|
1645
1645
|
isRead: boolean;
|
|
1646
1646
|
senderId: string;
|
|
1647
|
-
senderRole: "
|
|
1647
|
+
senderRole: "buyer" | "seller";
|
|
1648
1648
|
sentAt: string | Date | import("zod").objectOutputType<{
|
|
1649
1649
|
toDate: import("zod").ZodFunction<import("zod").ZodTuple<[], import("zod").ZodUnknown>, import("zod").ZodDate>;
|
|
1650
1650
|
}, import("zod").ZodTypeAny, "passthrough">;
|
|
@@ -1677,7 +1677,7 @@ export declare const SCHEMAS: {
|
|
|
1677
1677
|
body: string;
|
|
1678
1678
|
isRead: boolean;
|
|
1679
1679
|
senderId: string;
|
|
1680
|
-
senderRole: "
|
|
1680
|
+
senderRole: "buyer" | "seller";
|
|
1681
1681
|
sentAt: string | Date | import("zod").objectInputType<{
|
|
1682
1682
|
toDate: import("zod").ZodFunction<import("zod").ZodTuple<[], import("zod").ZodUnknown>, import("zod").ZodDate>;
|
|
1683
1683
|
}, import("zod").ZodTypeAny, "passthrough">;
|
|
@@ -1838,7 +1838,7 @@ export declare const SCHEMAS: {
|
|
|
1838
1838
|
code: string;
|
|
1839
1839
|
type: "fixed" | "percentage" | "free_shipping" | "buy_x_get_y";
|
|
1840
1840
|
id: string;
|
|
1841
|
-
scope: "
|
|
1841
|
+
scope: "seller" | "admin";
|
|
1842
1842
|
name: string;
|
|
1843
1843
|
createdAt: string | Date | import("zod").objectOutputType<{
|
|
1844
1844
|
toDate: import("zod").ZodFunction<import("zod").ZodTuple<[], import("zod").ZodUnknown>, import("zod").ZodDate>;
|
|
@@ -1896,7 +1896,7 @@ export declare const SCHEMAS: {
|
|
|
1896
1896
|
code: string;
|
|
1897
1897
|
type: "fixed" | "percentage" | "free_shipping" | "buy_x_get_y";
|
|
1898
1898
|
id: string;
|
|
1899
|
-
scope: "
|
|
1899
|
+
scope: "seller" | "admin";
|
|
1900
1900
|
name: string;
|
|
1901
1901
|
createdAt: string | Date | import("zod").objectInputType<{
|
|
1902
1902
|
toDate: import("zod").ZodFunction<import("zod").ZodTuple<[], import("zod").ZodUnknown>, import("zod").ZodDate>;
|
|
@@ -2372,14 +2372,14 @@ export declare const SCHEMAS: {
|
|
|
2372
2372
|
code: string;
|
|
2373
2373
|
type: "auto" | "coupon" | "deal";
|
|
2374
2374
|
discountAmount: number;
|
|
2375
|
-
scope?: "
|
|
2375
|
+
scope?: "seller" | "admin" | undefined;
|
|
2376
2376
|
storeId?: string | undefined;
|
|
2377
2377
|
couponId?: string | undefined;
|
|
2378
2378
|
}, {
|
|
2379
2379
|
code: string;
|
|
2380
2380
|
type: "auto" | "coupon" | "deal";
|
|
2381
2381
|
discountAmount: number;
|
|
2382
|
-
scope?: "
|
|
2382
|
+
scope?: "seller" | "admin" | undefined;
|
|
2383
2383
|
storeId?: string | undefined;
|
|
2384
2384
|
couponId?: string | undefined;
|
|
2385
2385
|
}>, "many">>;
|
|
@@ -2510,9 +2510,9 @@ export declare const SCHEMAS: {
|
|
|
2510
2510
|
overrideReason: import("zod").ZodOptional<import("zod").ZodString>;
|
|
2511
2511
|
}, "strip", import("zod").ZodTypeAny, {
|
|
2512
2512
|
type: "full" | "partial";
|
|
2513
|
+
reason: string;
|
|
2513
2514
|
amount: number;
|
|
2514
2515
|
refundId: string;
|
|
2515
|
-
reason: string;
|
|
2516
2516
|
refundedAt: string | Date | import("zod").objectOutputType<{
|
|
2517
2517
|
toDate: import("zod").ZodFunction<import("zod").ZodTuple<[], import("zod").ZodUnknown>, import("zod").ZodDate>;
|
|
2518
2518
|
}, import("zod").ZodTypeAny, "passthrough">;
|
|
@@ -2525,9 +2525,9 @@ export declare const SCHEMAS: {
|
|
|
2525
2525
|
overrideReason?: string | undefined;
|
|
2526
2526
|
}, {
|
|
2527
2527
|
type: "full" | "partial";
|
|
2528
|
+
reason: string;
|
|
2528
2529
|
amount: number;
|
|
2529
2530
|
refundId: string;
|
|
2530
|
-
reason: string;
|
|
2531
2531
|
refundedAt: string | Date | import("zod").objectInputType<{
|
|
2532
2532
|
toDate: import("zod").ZodFunction<import("zod").ZodTuple<[], import("zod").ZodUnknown>, import("zod").ZodDate>;
|
|
2533
2533
|
}, import("zod").ZodTypeAny, "passthrough">;
|
|
@@ -2668,7 +2668,7 @@ export declare const SCHEMAS: {
|
|
|
2668
2668
|
code: string;
|
|
2669
2669
|
type: "auto" | "coupon" | "deal";
|
|
2670
2670
|
discountAmount: number;
|
|
2671
|
-
scope?: "
|
|
2671
|
+
scope?: "seller" | "admin" | undefined;
|
|
2672
2672
|
storeId?: string | undefined;
|
|
2673
2673
|
couponId?: string | undefined;
|
|
2674
2674
|
}[] | undefined;
|
|
@@ -2700,9 +2700,9 @@ export declare const SCHEMAS: {
|
|
|
2700
2700
|
paymentBatchId?: string | undefined;
|
|
2701
2701
|
refunds?: {
|
|
2702
2702
|
type: "full" | "partial";
|
|
2703
|
+
reason: string;
|
|
2703
2704
|
amount: number;
|
|
2704
2705
|
refundId: string;
|
|
2705
|
-
reason: string;
|
|
2706
2706
|
refundedAt: string | Date | import("zod").objectOutputType<{
|
|
2707
2707
|
toDate: import("zod").ZodFunction<import("zod").ZodTuple<[], import("zod").ZodUnknown>, import("zod").ZodDate>;
|
|
2708
2708
|
}, import("zod").ZodTypeAny, "passthrough">;
|
|
@@ -2816,7 +2816,7 @@ export declare const SCHEMAS: {
|
|
|
2816
2816
|
code: string;
|
|
2817
2817
|
type: "auto" | "coupon" | "deal";
|
|
2818
2818
|
discountAmount: number;
|
|
2819
|
-
scope?: "
|
|
2819
|
+
scope?: "seller" | "admin" | undefined;
|
|
2820
2820
|
storeId?: string | undefined;
|
|
2821
2821
|
couponId?: string | undefined;
|
|
2822
2822
|
}[] | undefined;
|
|
@@ -2848,9 +2848,9 @@ export declare const SCHEMAS: {
|
|
|
2848
2848
|
paymentBatchId?: string | undefined;
|
|
2849
2849
|
refunds?: {
|
|
2850
2850
|
type: "full" | "partial";
|
|
2851
|
+
reason: string;
|
|
2851
2852
|
amount: number;
|
|
2852
2853
|
refundId: string;
|
|
2853
|
-
reason: string;
|
|
2854
2854
|
refundedAt: string | Date | import("zod").objectInputType<{
|
|
2855
2855
|
toDate: import("zod").ZodFunction<import("zod").ZodTuple<[], import("zod").ZodUnknown>, import("zod").ZodDate>;
|
|
2856
2856
|
}, import("zod").ZodTypeAny, "passthrough">;
|
|
@@ -2944,20 +2944,20 @@ export declare const SCHEMAS: {
|
|
|
2944
2944
|
toDate: import("zod").ZodFunction<import("zod").ZodTuple<[], import("zod").ZodUnknown>, import("zod").ZodDate>;
|
|
2945
2945
|
}, import("zod").ZodTypeAny, "passthrough">>]>;
|
|
2946
2946
|
}, "strip", import("zod").ZodTypeAny, {
|
|
2947
|
+
reason: string;
|
|
2947
2948
|
orderId: string;
|
|
2948
2949
|
refundId: string;
|
|
2949
2950
|
refundedAmount: number;
|
|
2950
2951
|
deductedAmount: number;
|
|
2951
|
-
reason: string;
|
|
2952
2952
|
appliedAt: string | Date | import("zod").objectOutputType<{
|
|
2953
2953
|
toDate: import("zod").ZodFunction<import("zod").ZodTuple<[], import("zod").ZodUnknown>, import("zod").ZodDate>;
|
|
2954
2954
|
}, import("zod").ZodTypeAny, "passthrough">;
|
|
2955
2955
|
}, {
|
|
2956
|
+
reason: string;
|
|
2956
2957
|
orderId: string;
|
|
2957
2958
|
refundId: string;
|
|
2958
2959
|
refundedAmount: number;
|
|
2959
2960
|
deductedAmount: number;
|
|
2960
|
-
reason: string;
|
|
2961
2961
|
appliedAt: string | Date | import("zod").objectInputType<{
|
|
2962
2962
|
toDate: import("zod").ZodFunction<import("zod").ZodTuple<[], import("zod").ZodUnknown>, import("zod").ZodDate>;
|
|
2963
2963
|
}, import("zod").ZodTypeAny, "passthrough">;
|
|
@@ -2999,6 +2999,9 @@ export declare const SCHEMAS: {
|
|
|
2999
2999
|
platformFeeRate: number;
|
|
3000
3000
|
paymentMethod: "bank_transfer" | "upi";
|
|
3001
3001
|
orderIds: string[];
|
|
3002
|
+
processedAt?: string | Date | import("zod").objectOutputType<{
|
|
3003
|
+
toDate: import("zod").ZodFunction<import("zod").ZodTuple<[], import("zod").ZodUnknown>, import("zod").ZodDate>;
|
|
3004
|
+
}, import("zod").ZodTypeAny, "passthrough"> | undefined;
|
|
3002
3005
|
bankAccount?: {
|
|
3003
3006
|
accountHolderName: string;
|
|
3004
3007
|
accountNumberMasked: string;
|
|
@@ -3014,19 +3017,16 @@ export declare const SCHEMAS: {
|
|
|
3014
3017
|
gstRate?: number | undefined;
|
|
3015
3018
|
isAutomatic?: boolean | undefined;
|
|
3016
3019
|
refundDeductions?: {
|
|
3020
|
+
reason: string;
|
|
3017
3021
|
orderId: string;
|
|
3018
3022
|
refundId: string;
|
|
3019
3023
|
refundedAmount: number;
|
|
3020
3024
|
deductedAmount: number;
|
|
3021
|
-
reason: string;
|
|
3022
3025
|
appliedAt: string | Date | import("zod").objectOutputType<{
|
|
3023
3026
|
toDate: import("zod").ZodFunction<import("zod").ZodTuple<[], import("zod").ZodUnknown>, import("zod").ZodDate>;
|
|
3024
3027
|
}, import("zod").ZodTypeAny, "passthrough">;
|
|
3025
3028
|
}[] | undefined;
|
|
3026
3029
|
netAmount?: number | undefined;
|
|
3027
|
-
processedAt?: string | Date | import("zod").objectOutputType<{
|
|
3028
|
-
toDate: import("zod").ZodFunction<import("zod").ZodTuple<[], import("zod").ZodUnknown>, import("zod").ZodDate>;
|
|
3029
|
-
}, import("zod").ZodTypeAny, "passthrough"> | undefined;
|
|
3030
3030
|
}, {
|
|
3031
3031
|
currency: string;
|
|
3032
3032
|
status: "paid" | "failed" | "pending" | "processing";
|
|
@@ -3049,6 +3049,9 @@ export declare const SCHEMAS: {
|
|
|
3049
3049
|
platformFeeRate: number;
|
|
3050
3050
|
paymentMethod: "bank_transfer" | "upi";
|
|
3051
3051
|
orderIds: string[];
|
|
3052
|
+
processedAt?: string | Date | import("zod").objectInputType<{
|
|
3053
|
+
toDate: import("zod").ZodFunction<import("zod").ZodTuple<[], import("zod").ZodUnknown>, import("zod").ZodDate>;
|
|
3054
|
+
}, import("zod").ZodTypeAny, "passthrough"> | undefined;
|
|
3052
3055
|
bankAccount?: {
|
|
3053
3056
|
accountHolderName: string;
|
|
3054
3057
|
accountNumberMasked: string;
|
|
@@ -3064,19 +3067,16 @@ export declare const SCHEMAS: {
|
|
|
3064
3067
|
gstRate?: number | undefined;
|
|
3065
3068
|
isAutomatic?: boolean | undefined;
|
|
3066
3069
|
refundDeductions?: {
|
|
3070
|
+
reason: string;
|
|
3067
3071
|
orderId: string;
|
|
3068
3072
|
refundId: string;
|
|
3069
3073
|
refundedAmount: number;
|
|
3070
3074
|
deductedAmount: number;
|
|
3071
|
-
reason: string;
|
|
3072
3075
|
appliedAt: string | Date | import("zod").objectInputType<{
|
|
3073
3076
|
toDate: import("zod").ZodFunction<import("zod").ZodTuple<[], import("zod").ZodUnknown>, import("zod").ZodDate>;
|
|
3074
3077
|
}, import("zod").ZodTypeAny, "passthrough">;
|
|
3075
3078
|
}[] | undefined;
|
|
3076
3079
|
netAmount?: number | undefined;
|
|
3077
|
-
processedAt?: string | Date | import("zod").objectInputType<{
|
|
3078
|
-
toDate: import("zod").ZodFunction<import("zod").ZodTuple<[], import("zod").ZodUnknown>, import("zod").ZodDate>;
|
|
3079
|
-
}, import("zod").ZodTypeAny, "passthrough"> | undefined;
|
|
3080
3080
|
}>;
|
|
3081
3081
|
readonly reviews: import("zod").ZodObject<{
|
|
3082
3082
|
createdAt: import("zod").ZodUnion<[import("zod").ZodDate, import("zod").ZodString, import("zod").ZodObject<{
|
|
@@ -4192,6 +4192,7 @@ export declare const SCHEMAS: {
|
|
|
4192
4192
|
closedAt?: string | Date | import("zod").objectOutputType<{
|
|
4193
4193
|
toDate: import("zod").ZodFunction<import("zod").ZodTuple<[], import("zod").ZodUnknown>, import("zod").ZodDate>;
|
|
4194
4194
|
}, import("zod").ZodTypeAny, "passthrough"> | undefined;
|
|
4195
|
+
assignedToName?: string | undefined;
|
|
4195
4196
|
relatedParties?: {
|
|
4196
4197
|
storeId?: string | undefined;
|
|
4197
4198
|
userId?: string | undefined;
|
|
@@ -4199,7 +4200,6 @@ export declare const SCHEMAS: {
|
|
|
4199
4200
|
productId?: string | undefined;
|
|
4200
4201
|
bidId?: string | undefined;
|
|
4201
4202
|
} | undefined;
|
|
4202
|
-
assignedToName?: string | undefined;
|
|
4203
4203
|
internalNotes?: string | undefined;
|
|
4204
4204
|
}, {
|
|
4205
4205
|
status: "closed" | "open" | "resolved" | "in_progress" | "waiting_on_user";
|
|
@@ -4235,6 +4235,7 @@ export declare const SCHEMAS: {
|
|
|
4235
4235
|
closedAt?: string | Date | import("zod").objectInputType<{
|
|
4236
4236
|
toDate: import("zod").ZodFunction<import("zod").ZodTuple<[], import("zod").ZodUnknown>, import("zod").ZodDate>;
|
|
4237
4237
|
}, import("zod").ZodTypeAny, "passthrough"> | undefined;
|
|
4238
|
+
assignedToName?: string | undefined;
|
|
4238
4239
|
relatedParties?: {
|
|
4239
4240
|
storeId?: string | undefined;
|
|
4240
4241
|
userId?: string | undefined;
|
|
@@ -4242,7 +4243,6 @@ export declare const SCHEMAS: {
|
|
|
4242
4243
|
productId?: string | undefined;
|
|
4243
4244
|
bidId?: string | undefined;
|
|
4244
4245
|
} | undefined;
|
|
4245
|
-
assignedToName?: string | undefined;
|
|
4246
4246
|
internalNotes?: string | undefined;
|
|
4247
4247
|
}>;
|
|
4248
4248
|
};
|
|
@@ -35,6 +35,14 @@ const BIDDER_NAMES = {
|
|
|
35
35
|
"user-rohit-collector": "Mock User 14",
|
|
36
36
|
"user-ananya-collector": "Mock User 9",
|
|
37
37
|
};
|
|
38
|
+
/*
|
|
39
|
+
* Typed on the document, not `FirestoreDocument`. Once `BidDocument` gained
|
|
40
|
+
* `statusHistory?: StatusChangeEntry[]`, `Partial<BidDocument>` stopped being
|
|
41
|
+
* assignable to `FirestoreDocument` — an array of objects does not satisfy
|
|
42
|
+
* that index signature. The right fix is to narrow the parameter to what the
|
|
43
|
+
* caller actually passes rather than widen the document to keep a helper
|
|
44
|
+
* happy.
|
|
45
|
+
*/
|
|
38
46
|
function withBidDefaults(b) {
|
|
39
47
|
return {
|
|
40
48
|
...b,
|
|
@@ -28,13 +28,34 @@ export interface FormProps extends Omit<React.FormHTMLAttributes<HTMLFormElement
|
|
|
28
28
|
* provider would shadow the parent's for everything rendered as `children`.
|
|
29
29
|
*/
|
|
30
30
|
shellCtx?: FormShellContextValue;
|
|
31
|
+
/**
|
|
32
|
+
* Publish Save/Cancel and the mobile error sheet into the bottom-chrome
|
|
33
|
+
* tier — the same bar the cart uses.
|
|
34
|
+
*
|
|
35
|
+
* Opt-IN, unlike `<SectionForm>` where it is on by default. `<Form>` is the
|
|
36
|
+
* generic wrapper and is used inside `<Modal>` and `<SideDrawer>` footers,
|
|
37
|
+
* inside listing toolbars, and several times over on one page
|
|
38
|
+
* (`AdminSiteSettingsView` mounts twenty). Publishing route-level chrome
|
|
39
|
+
* from all of those by default would be wrong far more often than right.
|
|
40
|
+
* The hook additionally suppresses itself inside an overlay, so passing
|
|
41
|
+
* this in a modal is a no-op rather than a bug.
|
|
42
|
+
*/
|
|
43
|
+
bottomBar?: FormBottomBarConfig;
|
|
31
44
|
/** Cross-axis alignment of flex/grid children. Replaces raw `items-*` className. */
|
|
32
45
|
align?: "start" | "center" | "end" | "stretch";
|
|
33
46
|
/** Gap between children — use instead of raw `gap-*` className. */
|
|
34
47
|
gap?: GapToken;
|
|
35
48
|
}
|
|
36
49
|
export type GapToken = "none" | "xs" | "sm" | "md" | "lg" | "xl";
|
|
37
|
-
export
|
|
50
|
+
export interface FormBottomBarConfig {
|
|
51
|
+
onSubmit: () => void | Promise<void>;
|
|
52
|
+
onCancel?: () => void;
|
|
53
|
+
submitLabel?: string;
|
|
54
|
+
cancelLabel?: string;
|
|
55
|
+
isLoading?: boolean;
|
|
56
|
+
disabled?: boolean;
|
|
57
|
+
}
|
|
58
|
+
export declare function Form({ children, spacing, schema, shellCtx: shellCtxProp, bottomBar, align, gap, surface, padding, paddingX, paddingY, rounded, roundedTop, roundedBottom, border, shadow, overflow, className, ...props }: FormProps): React.JSX.Element;
|
|
38
59
|
export interface FormGroupProps {
|
|
39
60
|
children: React.ReactNode;
|
|
40
61
|
columns?: 1 | 2 | 3 | 4;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import React from "react";
|
|
3
4
|
import { Row } from "./Layout";
|
|
4
5
|
import { buildSurfaceClasses } from "./surface-tokens";
|
|
5
6
|
import { FormShellContext, useFormShellState, } from "../forms/FormShell";
|
|
7
|
+
import { useFormBottomActions } from "../../features/layout/hooks/useFormBottomActions";
|
|
6
8
|
const FORM_SPACING_MAP = {
|
|
7
9
|
none: "",
|
|
8
10
|
xs: "space-y-1",
|
|
@@ -43,9 +45,35 @@ const FORM_ALIGN_MAP = {
|
|
|
43
45
|
end: "items-end",
|
|
44
46
|
stretch: "items-stretch",
|
|
45
47
|
};
|
|
46
|
-
export function Form({ children, spacing, schema, shellCtx: shellCtxProp, align, gap, surface, padding, paddingX, paddingY, rounded, roundedTop, roundedBottom, border, shadow, overflow, className = "", ...props }) {
|
|
48
|
+
export function Form({ children, spacing, schema, shellCtx: shellCtxProp, bottomBar, align, gap, surface, padding, paddingX, paddingY, rounded, roundedTop, roundedBottom, border, shadow, overflow, className = "", ...props }) {
|
|
47
49
|
const helpers = useFormShellState(schema);
|
|
48
50
|
const effectiveCtx = shellCtxProp ?? helpers.shellCtx;
|
|
51
|
+
/*
|
|
52
|
+
* Marking the attempt on the NATIVE submit event covers both shapes this
|
|
53
|
+
* component is used in: the caller that calls `validate()` (which marks
|
|
54
|
+
* anyway) and the caller that hand-rolls its checks in the submit button's
|
|
55
|
+
* `onClick`. React fires `onClick` before `onSubmit`, so by the time the
|
|
56
|
+
* re-render happens the errors are already in the context.
|
|
57
|
+
*
|
|
58
|
+
* `effectiveCtx` may come from a parent's `useFormShellState`, so mark on
|
|
59
|
+
* whichever context is actually mounted — not on `helpers`, which is a
|
|
60
|
+
* second, ignored state instance in that case.
|
|
61
|
+
*/
|
|
62
|
+
const { onSubmit: onSubmitProp } = props;
|
|
63
|
+
const handleSubmit = React.useCallback((e) => {
|
|
64
|
+
effectiveCtx.markSubmitAttempted();
|
|
65
|
+
onSubmitProp?.(e);
|
|
66
|
+
}, [effectiveCtx, onSubmitProp]);
|
|
67
|
+
useFormBottomActions({
|
|
68
|
+
onSubmit: bottomBar?.onSubmit ?? (() => { }),
|
|
69
|
+
onCancel: bottomBar?.onCancel,
|
|
70
|
+
submitLabel: bottomBar?.submitLabel,
|
|
71
|
+
cancelLabel: bottomBar?.cancelLabel,
|
|
72
|
+
isLoading: bottomBar?.isLoading,
|
|
73
|
+
disabled: bottomBar?.disabled,
|
|
74
|
+
enabled: bottomBar != null,
|
|
75
|
+
ctx: effectiveCtx,
|
|
76
|
+
});
|
|
49
77
|
const content = typeof children === "function"
|
|
50
78
|
? children({ ...helpers, shellCtx: effectiveCtx })
|
|
51
79
|
: children;
|
|
@@ -56,7 +84,7 @@ export function Form({ children, spacing, schema, shellCtx: shellCtxProp, align,
|
|
|
56
84
|
gap ? GAP_MAP[gap] : "",
|
|
57
85
|
buildSurfaceClasses({ surface, padding, paddingX, paddingY, rounded, roundedTop, roundedBottom, border, shadow, overflow }),
|
|
58
86
|
className,
|
|
59
|
-
].filter(Boolean).join(" "), ...props, children: content }) }));
|
|
87
|
+
].filter(Boolean).join(" "), ...props, onSubmit: handleSubmit, children: content }) }));
|
|
60
88
|
}
|
|
61
89
|
export function FormGroup({ children, columns = 1, gap = "md", className = "", }) {
|
|
62
90
|
const gridClasses = {
|
|
@@ -7,6 +7,7 @@ import { Heading } from "./Typography";
|
|
|
7
7
|
import { Button } from "./Button";
|
|
8
8
|
import { SPRING_GENTLE } from "../../tokens/motion";
|
|
9
9
|
import { useHandMode } from "../../_internal/client/hand-mode";
|
|
10
|
+
import { OverlayContext } from "./overlay-context";
|
|
10
11
|
const SIZE_CLASSES = {
|
|
11
12
|
sm: "appkit-modal__panel--sm",
|
|
12
13
|
md: "appkit-modal__panel--md",
|
|
@@ -69,9 +70,9 @@ export function Modal({ isOpen, open, onClose, title, children, size = "md", sho
|
|
|
69
70
|
if (typeof document === "undefined") {
|
|
70
71
|
return null;
|
|
71
72
|
}
|
|
72
|
-
return createPortal(_jsx(AnimatePresence, { children: visible && (_jsxs(motion.div, { className: "appkit-modal", role: "dialog", "aria-modal": "true", "aria-labelledby": title ? titleId : undefined, onKeyDown: handleKeyDown, initial: reduced ? false : { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.15 }, "data-section": "modal-div-561", children: [_jsx("div", { className: "appkit-modal__backdrop", "aria-hidden": "true", onClick: onClose }), _jsxs(motion.div, { ref: panelRef, tabIndex: -1, className: ["appkit-modal__panel", SIZE_CLASSES[size], className]
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
return createPortal(_jsx(OverlayContext.Provider, { value: true, children: _jsx(AnimatePresence, { children: visible && (_jsxs(motion.div, { className: "appkit-modal", role: "dialog", "aria-modal": "true", "aria-labelledby": title ? titleId : undefined, onKeyDown: handleKeyDown, initial: reduced ? false : { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.15 }, "data-section": "modal-div-561", children: [_jsx("div", { className: "appkit-modal__backdrop", "aria-hidden": "true", onClick: onClose }), _jsxs(motion.div, { ref: panelRef, tabIndex: -1, className: ["appkit-modal__panel", SIZE_CLASSES[size], className]
|
|
74
|
+
.filter(Boolean)
|
|
75
|
+
.join(" "), initial: reduced ? false : { opacity: 0, scale: 0.95, y: 8 }, animate: { opacity: 1, scale: 1, y: 0 }, exit: { opacity: 0, scale: 0.95, y: 8 }, transition: SPRING_GENTLE, "data-section": "modal-div-562", children: [(title || showCloseButton) && (_jsxs("div", { className: hand === "left" ? "appkit-modal__header flex-row-reverse" : "appkit-modal__header", "data-section": "modal-div-563", children: [title ? (_jsx(Heading, { level: 2, id: titleId, className: "appkit-modal__title", children: title })) : (_jsx("span", {})), showCloseButton ? (_jsx(Button, { variant: "ghost", size: "sm", type: "button", onClick: onClose, className: "appkit-modal__close", "aria-label": "Close", children: _jsx("span", { className: "appkit-modal__close-icon", "aria-hidden": "true", children: "\u00D7" }) })) : null] })), _jsx("div", { className: "appkit-modal__body", "data-section": "modal-div-564", children: children }), actions ? _jsx(ModalFooter, { children: actions }) : null] })] })) }) }), document.body);
|
|
75
76
|
}
|
|
76
77
|
export function ModalFooter({ children, className = "", }) {
|
|
77
78
|
return (_jsx("div", { className: [
|
|
@@ -10,6 +10,7 @@ import { useSwipe } from "../../react";
|
|
|
10
10
|
import { Text } from "./Typography";
|
|
11
11
|
import { SPRING_SNAPPY } from "../../tokens/motion";
|
|
12
12
|
import { useHandMode } from "../../_internal/client/hand-mode";
|
|
13
|
+
import { OverlayContext } from "./overlay-context";
|
|
13
14
|
const UI_SIDE_DRAWER = {
|
|
14
15
|
backdrop: "appkit-side-drawer__backdrop",
|
|
15
16
|
root: "appkit-side-drawer",
|
|
@@ -152,8 +153,8 @@ export function SideDrawer({ isOpen, onClose, title, children, footer, mode = "v
|
|
|
152
153
|
const reduced = useReducedMotion();
|
|
153
154
|
const positionClass = resolvedSide === "left" ? UI_SIDE_DRAWER.left : UI_SIDE_DRAWER.right;
|
|
154
155
|
const slideX = resolvedSide === "left" ? "-100%" : "100%";
|
|
155
|
-
return (_jsx(AnimatePresence, { children: isOpen && (_jsxs(_Fragment, { children: [_jsx(motion.div, { className: UI_SIDE_DRAWER.backdrop, onClick: attemptClose, "aria-hidden": "true", initial: reduced ? false : { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.2 } }), _jsxs(motion.div, { ref: drawerRef, className: [UI_SIDE_DRAWER.root, positionClass].join(" "), role: "dialog", "aria-modal": "true", "aria-labelledby": "drawer-title", initial: reduced ? false : { x: slideX }, animate: { x: 0 }, exit: { x: slideX }, transition: SPRING_SNAPPY, "data-section": "sidedrawer-div-598", children: [_jsxs(Row, { justify: "between", gap: "none", className: [
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
156
|
+
return (_jsx(OverlayContext.Provider, { value: true, children: _jsx(AnimatePresence, { children: isOpen && (_jsxs(_Fragment, { children: [_jsx(motion.div, { className: UI_SIDE_DRAWER.backdrop, onClick: attemptClose, "aria-hidden": "true", initial: reduced ? false : { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.2 } }), _jsxs(motion.div, { ref: drawerRef, className: [UI_SIDE_DRAWER.root, positionClass].join(" "), role: "dialog", "aria-modal": "true", "aria-labelledby": "drawer-title", initial: reduced ? false : { x: slideX }, animate: { x: 0 }, exit: { x: slideX }, transition: SPRING_SNAPPY, "data-section": "sidedrawer-div-598", children: [_jsxs(Row, { justify: "between", gap: "none", className: [
|
|
157
|
+
UI_SIDE_DRAWER.header,
|
|
158
|
+
UI_SIDE_DRAWER.headerMode[mode],
|
|
159
|
+
].join(" "), children: [_jsxs(Row, { gap: "3", className: "min-w-0", reverse: hand === "left", children: [_jsx(Button, { variant: "ghost", onClick: attemptClose, className: UI_SIDE_DRAWER.closeBtn, "aria-label": tActions("close"), children: _jsx("svg", { className: UI_SIDE_DRAWER.closeIcon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) }), _jsx(Heading, { level: 3, id: "drawer-title", className: "truncate", children: title })] }), mode === "delete" && (_jsx(Span, { className: UI_SIDE_DRAWER.deleteBadge, children: tActions("delete") }))] }), _jsx("div", { className: UI_SIDE_DRAWER.content, "data-section": "sidedrawer-div-599", children: children }), footer && _jsx("div", { className: UI_SIDE_DRAWER.footer, "data-section": "sidedrawer-div-600", children: footer })] }), showUnsavedWarning && (_jsxs(_Fragment, { children: [_jsx("div", { className: UI_SIDE_DRAWER.warnBackdrop, onClick: cancelClose }), _jsxs("div", { className: UI_SIDE_DRAWER.warnDialog, "data-section": "sidedrawer-div-601", children: [_jsxs("div", { className: UI_SIDE_DRAWER.warnHeader, "data-section": "sidedrawer-div-602", children: [_jsx("div", { className: UI_SIDE_DRAWER.warnIcon, "data-section": "sidedrawer-div-603", children: _jsx("svg", { fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" }) }) }), _jsxs("div", { "data-section": "sidedrawer-div-604", children: [_jsx(Heading, { level: 4, className: "mb-1", children: tConfirm("unsavedChangesTitle") }), _jsx(Text, { className: UI_SIDE_DRAWER.warnText, children: tConfirm("unsavedChangesDescription") })] })] }), _jsxs("div", { className: UI_SIDE_DRAWER.warnActions, "data-section": "sidedrawer-div-605", children: [_jsx(Button, { variant: "outline", onClick: cancelClose, size: "sm", children: tActions("keepEditing") }), _jsx(Button, { variant: "danger", onClick: confirmClose, size: "sm", children: tActions("discardChanges") })] })] })] }))] })) }) }));
|
|
159
160
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* "Am I rendering inside a Modal or a SideDrawer?"
|
|
3
|
+
*
|
|
4
|
+
* WHY: route-level chrome must not attach itself to content that is floating
|
|
5
|
+
* above the route. The concrete case is `useFormBottomActions` — a form on a
|
|
6
|
+
* page publishes its Save/Cancel row and its error sheet into the fixed
|
|
7
|
+
* `BottomChrome` tier, which is correct there and wrong inside an overlay:
|
|
8
|
+
* the overlay already owns a footer, and a bar pinned to the viewport bottom
|
|
9
|
+
* would sit *behind* the backdrop, below the very dialog it belongs to.
|
|
10
|
+
*
|
|
11
|
+
* Detection has to come from the overlay itself. There is no way to infer it
|
|
12
|
+
* from the DOM at render time (both portal elsewhere), and asking every form
|
|
13
|
+
* to declare where it is being rendered is the kind of convention that is one
|
|
14
|
+
* forgetful call site away from a bar appearing under a backdrop.
|
|
15
|
+
*
|
|
16
|
+
* Mounted by `Modal` and `SideDrawer`. Default `false`, so a component outside
|
|
17
|
+
* any overlay — the overwhelmingly common case — needs no provider at all.
|
|
18
|
+
*/
|
|
19
|
+
export declare const OverlayContext: import("react").Context<boolean>;
|
|
20
|
+
/** True when the calling component is rendered inside a Modal or SideDrawer. */
|
|
21
|
+
export declare function useIsInsideOverlay(): boolean;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { createContext, useContext } from "react";
|
|
3
|
+
/**
|
|
4
|
+
* "Am I rendering inside a Modal or a SideDrawer?"
|
|
5
|
+
*
|
|
6
|
+
* WHY: route-level chrome must not attach itself to content that is floating
|
|
7
|
+
* above the route. The concrete case is `useFormBottomActions` — a form on a
|
|
8
|
+
* page publishes its Save/Cancel row and its error sheet into the fixed
|
|
9
|
+
* `BottomChrome` tier, which is correct there and wrong inside an overlay:
|
|
10
|
+
* the overlay already owns a footer, and a bar pinned to the viewport bottom
|
|
11
|
+
* would sit *behind* the backdrop, below the very dialog it belongs to.
|
|
12
|
+
*
|
|
13
|
+
* Detection has to come from the overlay itself. There is no way to infer it
|
|
14
|
+
* from the DOM at render time (both portal elsewhere), and asking every form
|
|
15
|
+
* to declare where it is being rendered is the kind of convention that is one
|
|
16
|
+
* forgetful call site away from a bar appearing under a backdrop.
|
|
17
|
+
*
|
|
18
|
+
* Mounted by `Modal` and `SideDrawer`. Default `false`, so a component outside
|
|
19
|
+
* any overlay — the overwhelmingly common case — needs no provider at all.
|
|
20
|
+
*/
|
|
21
|
+
export const OverlayContext = createContext(false);
|
|
22
|
+
/** True when the calling component is rendered inside a Modal or SideDrawer. */
|
|
23
|
+
export function useIsInsideOverlay() {
|
|
24
|
+
return useContext(OverlayContext);
|
|
25
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type FormShellContextValue } from "./FormShell";
|
|
2
|
+
export interface FormErrorListProps {
|
|
3
|
+
/**
|
|
4
|
+
* Read errors from this context value instead of the ambient one. The
|
|
5
|
+
* mobile bottom sheet needs it: `useFormBottomActions` builds the panel as
|
|
6
|
+
* a detached ReactNode that is rendered by `BottomActions`, high up in the
|
|
7
|
+
* layout tree and therefore OUTSIDE the form's own provider.
|
|
8
|
+
*/
|
|
9
|
+
ctx?: FormShellContextValue;
|
|
10
|
+
className?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* The `<ul>` of current validation errors, with a jump link per entry when
|
|
14
|
+
* the form declares sections.
|
|
15
|
+
*
|
|
16
|
+
* WHY it is its own file: two surfaces render this exact list — the inline
|
|
17
|
+
* `<FormErrorSummary>` beside the submit button on desktop, and the mobile
|
|
18
|
+
* "Fix N issues" sheet in the bottom-chrome tier. Writing it twice would mean
|
|
19
|
+
* a jump-link fix, an empty-state fix or a wording fix landing in one and not
|
|
20
|
+
* the other, which is the bug-fix multiplier the Duplication Framework calls
|
|
21
|
+
* out. There are exactly two consumers and they are the same list, so this is
|
|
22
|
+
* a consolidation, not speculative abstraction.
|
|
23
|
+
*
|
|
24
|
+
* Renders nothing when there are no errors. It does NOT gate on
|
|
25
|
+
* `submitAttempted` — that is the *summary's* decision, not the list's, and
|
|
26
|
+
* the sheet needs to keep rendering while open.
|
|
27
|
+
*/
|
|
28
|
+
export declare function FormErrorList({ ctx: ctxProp, className }: FormErrorListProps): import("react").JSX.Element | null;
|
|
29
|
+
export default FormErrorList;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useContext } from "react";
|
|
4
|
+
import { FormShellContext } from "./FormShell";
|
|
5
|
+
import { Span } from "../components/Typography";
|
|
6
|
+
/**
|
|
7
|
+
* The `<ul>` of current validation errors, with a jump link per entry when
|
|
8
|
+
* the form declares sections.
|
|
9
|
+
*
|
|
10
|
+
* WHY it is its own file: two surfaces render this exact list — the inline
|
|
11
|
+
* `<FormErrorSummary>` beside the submit button on desktop, and the mobile
|
|
12
|
+
* "Fix N issues" sheet in the bottom-chrome tier. Writing it twice would mean
|
|
13
|
+
* a jump-link fix, an empty-state fix or a wording fix landing in one and not
|
|
14
|
+
* the other, which is the bug-fix multiplier the Duplication Framework calls
|
|
15
|
+
* out. There are exactly two consumers and they are the same list, so this is
|
|
16
|
+
* a consolidation, not speculative abstraction.
|
|
17
|
+
*
|
|
18
|
+
* Renders nothing when there are no errors. It does NOT gate on
|
|
19
|
+
* `submitAttempted` — that is the *summary's* decision, not the list's, and
|
|
20
|
+
* the sheet needs to keep rendering while open.
|
|
21
|
+
*/
|
|
22
|
+
export function FormErrorList({ ctx: ctxProp, className }) {
|
|
23
|
+
const ambient = useContext(FormShellContext);
|
|
24
|
+
const ctx = ctxProp ?? ambient;
|
|
25
|
+
if (!ctx)
|
|
26
|
+
return null;
|
|
27
|
+
const entries = Object.entries(ctx.errors);
|
|
28
|
+
if (entries.length === 0)
|
|
29
|
+
return null;
|
|
30
|
+
return (_jsx("ul", { className: ["appkit-formshell__error-summary__list", className].filter(Boolean).join(" "), children: entries.map(([key, message]) => {
|
|
31
|
+
const stepIndex = ctx.fieldToStepIndex?.[key];
|
|
32
|
+
const stepLabel = stepIndex != null ? ctx.steps[stepIndex]?.label : undefined;
|
|
33
|
+
return (_jsx("li", { children: stepLabel ? (_jsxs("button", { type: "button", className: "appkit-formshell__error-summary__step-link", onClick: () => ctx.goToStep(stepIndex), children: [_jsxs(Span, { weight: "semibold", children: [stepLabel, ":"] }), " ", message] })) : (_jsx(Span, { children: message })) }, key));
|
|
34
|
+
}) }));
|
|
35
|
+
}
|
|
36
|
+
export default FormErrorList;
|
|
@@ -13,6 +13,14 @@ export interface FormErrorSummaryProps {
|
|
|
13
13
|
* error immediately as fields change — not gated by `touched`, unlike the
|
|
14
14
|
* inline per-field errors.
|
|
15
15
|
*
|
|
16
|
+
* 🛑 It IS gated on `ctx.submitAttempted`, and must stay that way. The
|
|
17
|
+
* summary speaks about fields the user has not reached yet, so before a
|
|
18
|
+
* submit it reads as a list of accusations rather than of mistakes — and
|
|
19
|
+
* ~20 views run `validate(draft)` in a mount effect, so an untouched empty
|
|
20
|
+
* draft fails every `.min(1)` on first paint. Gate the DISPLAY only: the
|
|
21
|
+
* live validation underneath is what keeps this list shrinking as the user
|
|
22
|
+
* fixes things after a failed submit, which is the whole point of it.
|
|
23
|
+
*
|
|
16
24
|
* For multi-step forms whose step engine populates
|
|
17
25
|
* `FormShellContextValue.fieldToStepIndex`, each entry names its owning step
|
|
18
26
|
* and is clickable to jump there. Falls back to a flat list when no step
|