@mohasinac/appkit 4.62.0 → 4.63.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/.build-stamp.json +3 -3
- package/dist/_internal/client/features/layout/DashboardLayoutClient.js +8 -29
- package/dist/_internal/client/features/layout/filterNavItems.d.ts +28 -0
- package/dist/_internal/client/features/layout/filterNavItems.js +35 -0
- package/dist/_internal/server/features/ads/booking.d.ts +118 -0
- package/dist/_internal/server/features/ads/booking.js +326 -0
- package/dist/_internal/server/features/checkout/actions.d.ts +129 -9
- package/dist/_internal/server/features/checkout/actions.js +850 -79
- package/dist/_internal/server/features/checkout/expand-order-items.d.ts +1 -2
- package/dist/_internal/server/features/checkout/expand-order-items.js +32 -0
- package/dist/_internal/server/features/checkout/freeze-parts.d.ts +50 -0
- package/dist/_internal/server/features/checkout/freeze-parts.js +94 -0
- package/dist/_internal/server/features/checkout/value-otp-gate.d.ts +55 -0
- package/dist/_internal/server/features/checkout/value-otp-gate.js +60 -0
- package/dist/_internal/server/features/dashboard/attention.d.ts +128 -0
- package/dist/_internal/server/features/dashboard/attention.js +183 -0
- package/dist/_internal/server/features/dashboard/data.d.ts +47 -0
- package/dist/_internal/server/features/dashboard/data.js +82 -0
- package/dist/_internal/server/features/inventory/reservations.d.ts +99 -0
- package/dist/_internal/server/features/inventory/reservations.js +273 -0
- package/dist/_internal/server/features/invoicing/allocate.d.ts +63 -0
- package/dist/_internal/server/features/invoicing/allocate.js +162 -0
- package/dist/_internal/server/features/invoicing/credit-note.d.ts +57 -0
- package/dist/_internal/server/features/invoicing/credit-note.js +126 -0
- package/dist/_internal/server/features/invoicing/gstr1.d.ts +74 -0
- package/dist/_internal/server/features/invoicing/gstr1.js +251 -0
- package/dist/_internal/server/features/invoicing/issue.d.ts +96 -0
- package/dist/_internal/server/features/invoicing/issue.js +202 -0
- package/dist/_internal/server/features/offers/destinations.d.ts +40 -0
- package/dist/_internal/server/features/offers/destinations.js +65 -0
- package/dist/_internal/server/features/orders/actions.d.ts +8 -1
- package/dist/_internal/server/features/orders/actions.js +81 -8
- package/dist/_internal/server/features/orders/adapters.js +54 -0
- package/dist/_internal/server/features/orders/amend-delivery.d.ts +56 -0
- package/dist/_internal/server/features/orders/amend-delivery.js +124 -0
- package/dist/_internal/server/features/orders/balance.d.ts +89 -0
- package/dist/_internal/server/features/orders/balance.js +256 -0
- package/dist/_internal/server/features/orders/cancellation-refund.d.ts +15 -9
- package/dist/_internal/server/features/orders/cancellation-refund.js +15 -9
- package/dist/_internal/server/features/points/award.js +46 -4
- package/dist/_internal/server/features/pricing/actions.d.ts +58 -0
- package/dist/_internal/server/features/pricing/actions.js +144 -0
- package/dist/_internal/server/features/refunds/actions.js +26 -0
- package/dist/_internal/server/features/shipping/book-split.d.ts +86 -0
- package/dist/_internal/server/features/shipping/book-split.js +130 -0
- package/dist/_internal/server/features/shipping/book.d.ts +61 -0
- package/dist/_internal/server/features/shipping/book.js +176 -0
- package/dist/_internal/server/features/shipping/courier-block.d.ts +69 -0
- package/dist/_internal/server/features/shipping/courier-block.js +264 -0
- package/dist/_internal/server/features/site-settings/adapters.d.ts +2 -2
- package/dist/_internal/server/features/site-settings/adapters.js +29 -0
- package/dist/_internal/server/features/stores/adapters.d.ts +2 -2
- package/dist/_internal/server/features/stores/adapters.js +65 -0
- package/dist/_internal/server/functions/scheduled.d.ts +2 -1
- package/dist/_internal/server/functions/scheduled.js +95 -2
- package/dist/_internal/server/jobs/core/autoPayoutEligibility.js +11 -2
- package/dist/_internal/server/jobs/core/dailyStatusDigest.d.ts +4 -0
- package/dist/_internal/server/jobs/core/dailyStatusDigest.js +19 -2
- package/dist/_internal/server/jobs/core/index.d.ts +2 -1
- package/dist/_internal/server/jobs/core/index.js +2 -1
- package/dist/_internal/server/jobs/core/jobRunners.js +45 -0
- package/dist/_internal/server/jobs/core/onJobCreated.d.ts +30 -7
- package/dist/_internal/server/jobs/core/onJobCreated.js +78 -45
- package/dist/_internal/server/jobs/core/onOrderStatusChange.d.ts +7 -0
- package/dist/_internal/server/jobs/core/onOrderStatusChange.js +65 -0
- package/dist/_internal/server/jobs/core/paymentWindowTimeout.js +33 -0
- package/dist/_internal/server/jobs/core/reservationExpiry.d.ts +17 -0
- package/dist/_internal/server/jobs/core/reservationExpiry.js +40 -0
- package/dist/_internal/server/jobs/core/runJobOnce.d.ts +48 -0
- package/dist/_internal/server/jobs/core/runJobOnce.js +195 -0
- package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.js +25 -2
- package/dist/_internal/server/jobs/handlers/index.d.ts +1 -0
- package/dist/_internal/server/jobs/handlers/index.js +1 -0
- package/dist/_internal/server/jobs/handlers/onOrderStatusChange.js +17 -0
- package/dist/_internal/server/jobs/handlers/reservationExpiry.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/reservationExpiry.js +2 -0
- package/dist/_internal/server/notifications/channel-health.d.ts +26 -3
- package/dist/_internal/shared/actions/action-registry.d.ts +1 -1
- package/dist/_internal/shared/actions/action-registry.js +296 -0
- package/dist/_internal/shared/checkout/coupon-discount.d.ts +43 -1
- package/dist/_internal/shared/checkout/coupon-discount.js +26 -1
- package/dist/_internal/shared/checkout/order-math.d.ts +174 -0
- package/dist/_internal/shared/checkout/order-math.js +159 -0
- package/dist/_internal/shared/checkout/refundable-base.d.ts +25 -0
- package/dist/_internal/shared/checkout/refundable-base.js +13 -1
- package/dist/_internal/shared/checkout/rules/index.d.ts +1 -1
- package/dist/_internal/shared/checkout/rules/index.js +1 -1
- package/dist/_internal/shared/checkout/rules/payment-gate.d.ts +18 -0
- package/dist/_internal/shared/checkout/rules/payment-gate.js +25 -0
- package/dist/_internal/shared/checkout/split.d.ts +75 -0
- package/dist/_internal/shared/checkout/split.js +120 -0
- package/dist/_internal/shared/content/disclaimers.d.ts +88 -0
- package/dist/_internal/shared/content/disclaimers.js +217 -0
- package/dist/_internal/shared/content/published-values.d.ts +93 -0
- package/dist/_internal/shared/content/published-values.js +206 -0
- package/dist/_internal/shared/features/admin/integrations.d.ts +139 -0
- package/dist/_internal/shared/features/admin/integrations.js +263 -0
- package/dist/_internal/shared/features/dashboard/hub-sections.d.ts +72 -0
- package/dist/_internal/shared/features/dashboard/hub-sections.js +75 -0
- package/dist/_internal/shared/features/emi/choice.d.ts +98 -0
- package/dist/_internal/shared/features/emi/choice.js +69 -0
- package/dist/_internal/shared/features/emi/group.d.ts +84 -0
- package/dist/_internal/shared/features/emi/group.js +126 -0
- package/dist/_internal/shared/features/ledger/posting.d.ts +107 -0
- package/dist/_internal/shared/features/ledger/posting.js +165 -0
- package/dist/_internal/shared/features/ledger/reports.d.ts +76 -0
- package/dist/_internal/shared/features/ledger/reports.js +127 -0
- package/dist/_internal/shared/features/ledger/rules.d.ts +170 -0
- package/dist/_internal/shared/features/ledger/rules.js +221 -0
- package/dist/_internal/shared/features/offers/coordination.d.ts +122 -0
- package/dist/_internal/shared/features/offers/coordination.js +80 -0
- package/dist/_internal/shared/features/orders/delivery-snapshot.d.ts +114 -0
- package/dist/_internal/shared/features/orders/delivery-snapshot.js +116 -0
- package/dist/_internal/shared/features/orders/dispute-reasons.d.ts +113 -0
- package/dist/_internal/shared/features/orders/dispute-reasons.js +181 -0
- package/dist/_internal/shared/features/orders/refund-copy.d.ts +1 -1
- package/dist/_internal/shared/features/orders/refund-copy.js +18 -1
- package/dist/_internal/shared/features/payouts/pay-period.d.ts +91 -0
- package/dist/_internal/shared/features/payouts/pay-period.js +104 -0
- package/dist/_internal/shared/features/points/accepts.d.ts +29 -0
- package/dist/_internal/shared/features/points/accepts.js +49 -0
- package/dist/_internal/shared/features/pricing/rate-registry.d.ts +150 -0
- package/dist/_internal/shared/features/pricing/rate-registry.js +246 -0
- package/dist/_internal/shared/features/shipping/parcel.d.ts +123 -0
- package/dist/_internal/shared/features/shipping/parcel.js +139 -0
- package/dist/_internal/shared/features/shipping/shared-purchase.d.ts +91 -0
- package/dist/_internal/shared/features/shipping/shared-purchase.js +108 -0
- package/dist/_internal/shared/features/site-settings/fees.d.ts +16 -8
- package/dist/_internal/shared/features/site-settings/fees.js +12 -8
- package/dist/_internal/shared/features/site-settings/types.d.ts +11 -0
- package/dist/_internal/shared/fees/calculator.d.ts +33 -1
- package/dist/_internal/shared/fees/calculator.js +32 -2
- package/dist/_internal/shared/fees/explain.d.ts +81 -0
- package/dist/_internal/shared/fees/explain.js +101 -0
- package/dist/_internal/shared/history/index.d.ts +1 -1
- package/dist/_internal/shared/history/index.js +1 -1
- package/dist/_internal/shared/history/types.d.ts +7 -1
- package/dist/_internal/shared/history/types.js +25 -0
- package/dist/client.d.ts +21 -0
- package/dist/client.js +43 -0
- package/dist/constants/api-endpoints.d.ts +114 -0
- package/dist/constants/api-endpoints.js +55 -0
- package/dist/constants/field-names.d.ts +42 -0
- package/dist/constants/field-names.js +52 -0
- package/dist/contracts/index.d.ts +1 -1
- package/dist/contracts/shipping.d.ts +45 -0
- package/dist/contracts/shipping.js +15 -0
- package/dist/features/about/components/AboutView.js +1 -1
- package/dist/features/account/components/BuyerAuctionsGuideView.js +4 -1
- package/dist/features/account/components/UserOrdersView.js +47 -35
- package/dist/features/admin/components/AdminCouponEditorView.js +17 -0
- package/dist/features/admin/components/AdminIntegrationsView.d.ts +55 -0
- package/dist/features/admin/components/AdminIntegrationsView.js +74 -0
- package/dist/features/admin/components/AdminInvoicingView.d.ts +2 -0
- package/dist/features/admin/components/AdminInvoicingView.js +65 -0
- package/dist/features/admin/components/AdminOrderEditorView.d.ts +33 -1
- package/dist/features/admin/components/AdminOrderEditorView.js +81 -3
- package/dist/features/admin/components/AdminOrdersGuideView.js +23 -2
- package/dist/features/admin/components/AdminOrdersView.js +86 -5
- package/dist/features/admin/components/OwnerQuickActions.js +24 -2
- package/dist/features/admin/constants/filter-tabs.d.ts +6 -0
- package/dist/features/admin/constants/filter-tabs.js +6 -0
- package/dist/features/admin/constants/site-settings-tabs.d.ts +1 -1
- package/dist/features/admin/hooks/useAdminListingData.js +16 -0
- package/dist/features/admin/schemas/admin-user-form.d.ts +2 -2
- package/dist/features/admin/schemas/firestore.d.ts +62 -0
- package/dist/features/admin/schemas/firestore.js +5 -0
- package/dist/features/ads/schemas/booking-write.d.ts +120 -0
- package/dist/features/ads/schemas/booking-write.js +75 -0
- package/dist/features/ads/schemas/creative-form.d.ts +18 -0
- package/dist/features/ads/schemas/creative-form.js +51 -0
- package/dist/features/ads/schemas/firestore.d.ts +140 -0
- package/dist/features/ads/schemas/firestore.js +109 -0
- package/dist/features/auctions/repository/bid.repository.js +3 -1
- package/dist/features/audit-log/schemas/firestore.d.ts +140 -0
- package/dist/features/audit-log/schemas/firestore.js +89 -0
- package/dist/features/auth/actions/profile-actions.d.ts +69 -1
- package/dist/features/auth/actions/profile-actions.js +62 -1
- package/dist/features/auth/permissions/constants.js +13 -0
- package/dist/features/auth/schemas/firestore.d.ts +16 -2
- package/dist/features/auth/schemas/firestore.js +2 -1
- package/dist/features/blog/actions/blog-actions.d.ts +6 -0
- package/dist/features/blog/actions/blog-actions.js +17 -2
- package/dist/features/blog/api/route.js +4 -1
- package/dist/features/blog/columns/index.js +5 -0
- package/dist/features/blog/components/BlogIndexPageView.js +2 -1
- package/dist/features/blog/repository/blog.repository.d.ts +4 -0
- package/dist/features/blog/repository/blog.repository.js +5 -0
- package/dist/features/blog/schemas/blog-form.d.ts +3 -0
- package/dist/features/blog/schemas/blog-form.js +1 -0
- package/dist/features/blog/schemas/firestore.d.ts +38 -1
- package/dist/features/blog/schemas/firestore.js +23 -0
- package/dist/features/blog/schemas/index.d.ts +6 -0
- package/dist/features/blog/schemas/index.js +2 -0
- package/dist/features/blog/types/index.d.ts +2 -0
- package/dist/features/cart/components/CartPriceBreakdown.d.ts +25 -1
- package/dist/features/cart/components/CartPriceBreakdown.js +29 -6
- package/dist/features/cart/components/PointsTenderPicker.d.ts +61 -0
- package/dist/features/cart/components/PointsTenderPicker.js +15 -0
- package/dist/features/cart/components/StoreAddonsPicker.js +2 -1
- package/dist/features/cart/components/index.d.ts +2 -0
- package/dist/features/cart/components/index.js +1 -0
- package/dist/features/cart/repository/cart.repository.d.ts +33 -0
- package/dist/features/cart/repository/cart.repository.js +47 -0
- package/dist/features/cart/schemas/firestore.d.ts +116 -0
- package/dist/features/contact/email.d.ts +27 -10
- package/dist/features/contact/email.js +20 -3
- package/dist/features/dashboard/components/DashboardHubView.d.ts +83 -0
- package/dist/features/dashboard/components/DashboardHubView.js +56 -0
- package/dist/features/dashboard/components/DashboardSectionsClient.d.ts +23 -0
- package/dist/features/dashboard/components/DashboardSectionsClient.js +66 -0
- package/dist/features/dispute-reasons/components/AdminDisputeReasonsView.d.ts +55 -0
- package/dist/features/dispute-reasons/components/AdminDisputeReasonsView.js +175 -0
- package/dist/features/dispute-reasons/repository/dispute-reasons.repository.d.ts +62 -0
- package/dist/features/dispute-reasons/repository/dispute-reasons.repository.js +108 -0
- package/dist/features/dispute-reasons/schemas/firestore.d.ts +62 -0
- package/dist/features/dispute-reasons/schemas/firestore.js +40 -0
- package/dist/features/events/components/EventSaleBanner.js +1 -1
- package/dist/features/faq/components/FAQAccordion.d.ts +13 -1
- package/dist/features/faq/components/FAQAccordion.js +29 -4
- package/dist/features/faq/components/FAQPageContent.js +2 -2
- package/dist/features/gateway-events/schemas/index.d.ts +2 -2
- package/dist/features/homepage/schemas/index.d.ts +8 -8
- package/dist/features/inventory/schemas/stock-reservation.d.ts +114 -0
- package/dist/features/inventory/schemas/stock-reservation.js +103 -0
- package/dist/features/invoicing/schemas/firestore.d.ts +112 -0
- package/dist/features/invoicing/schemas/firestore.js +45 -0
- package/dist/features/invoicing/utils/financial-year.d.ts +43 -0
- package/dist/features/invoicing/utils/financial-year.js +53 -0
- package/dist/features/jobs/actions/enqueue-job.js +18 -1
- package/dist/features/jobs/repository/jobs.repository.d.ts +62 -1
- package/dist/features/jobs/repository/jobs.repository.js +84 -1
- package/dist/features/jobs/schemas/firestore.d.ts +80 -0
- package/dist/features/jobs/schemas/firestore.js +37 -0
- package/dist/features/layout/AppLayoutShell.d.ts +9 -1
- package/dist/features/layout/AppLayoutShell.js +12 -4
- package/dist/features/layout/BottomActions.js +2 -1
- package/dist/features/layout/BottomNavbar.d.ts +10 -2
- package/dist/features/layout/SideActionDock.js +52 -2
- package/dist/features/layout/TitleBarLayout.js +13 -4
- package/dist/features/layout/TitleBarLayout.style.css +59 -0
- package/dist/features/layout/useCtaReveal.d.ts +16 -1
- package/dist/features/layout/useCtaReveal.js +17 -26
- package/dist/features/ledger/repository/journal.repository.d.ts +110 -0
- package/dist/features/ledger/repository/journal.repository.js +312 -0
- package/dist/features/ledger/schemas/expenses.d.ts +87 -0
- package/dist/features/ledger/schemas/expenses.js +27 -0
- package/dist/features/ledger/schemas/firestore.d.ts +183 -0
- package/dist/features/ledger/schemas/firestore.js +69 -0
- package/dist/features/lottery/schemas/zod.d.ts +6 -6
- package/dist/features/media/MediaImage.js +22 -1
- package/dist/features/media/upload/ImageUpload.js +1 -1
- package/dist/features/obligations/constants/policies.js +24 -1
- package/dist/features/orders/components/BalancePaymentPanel.d.ts +12 -0
- package/dist/features/orders/components/BalancePaymentPanel.js +94 -0
- package/dist/features/orders/components/OrderPaymentSummary.js +10 -1
- package/dist/features/orders/components/OrderProvenanceCard.d.ts +8 -0
- package/dist/features/orders/components/OrderProvenanceCard.js +185 -0
- package/dist/features/orders/components/RaiseDisputeForm.d.ts +14 -0
- package/dist/features/orders/components/RaiseDisputeForm.js +119 -0
- package/dist/features/orders/components/RefundRequestView.js +19 -1
- package/dist/features/orders/components/index.d.ts +4 -0
- package/dist/features/orders/components/index.js +2 -0
- package/dist/features/orders/constants/order-lane-tabs.d.ts +69 -0
- package/dist/features/orders/constants/order-lane-tabs.js +88 -0
- package/dist/features/orders/repository/orders.repository.d.ts +85 -1
- package/dist/features/orders/repository/orders.repository.js +205 -6
- package/dist/features/orders/schemas/balance.d.ts +40 -0
- package/dist/features/orders/schemas/balance.js +47 -0
- package/dist/features/orders/schemas/firestore.d.ts +398 -1
- package/dist/features/orders/schemas/firestore.js +43 -0
- package/dist/features/orders/schemas/index.d.ts +56 -8
- package/dist/features/orders/schemas/index.js +12 -0
- package/dist/features/orders/types/index.d.ts +47 -0
- package/dist/features/orders/utils/courier-block.d.ts +25 -0
- package/dist/features/orders/utils/courier-block.js +23 -0
- package/dist/features/payment-cases/schemas/firestore.d.ts +26 -1
- package/dist/features/payment-cases/schemas/firestore.js +1 -0
- package/dist/features/payments/repository/payout.repository.js +3 -2
- package/dist/features/payments/schemas/firestore.d.ts +92 -1
- package/dist/features/payments/schemas/firestore.js +23 -0
- package/dist/features/pricing/components/AdminPricingView.d.ts +13 -0
- package/dist/features/pricing/components/AdminPricingView.js +157 -0
- package/dist/features/products/components/PrizeDrawDetailPageView.js +2 -2
- package/dist/features/products/components/ProductDetailPageView.d.ts +17 -1
- package/dist/features/products/components/ProductDetailPageView.js +2 -2
- package/dist/features/products/schemas/firestore.d.ts +26 -1
- package/dist/features/products/schemas/firestore.js +2 -0
- package/dist/features/products/schemas/index.d.ts +2 -2
- package/dist/features/products/schemas/product-features.validators.d.ts +10 -10
- package/dist/features/promotions/actions/coupon-stacking.d.ts +30 -3
- package/dist/features/promotions/actions/coupon-stacking.js +21 -2
- package/dist/features/promotions/components/CouponCard.js +13 -0
- package/dist/features/promotions/constants/coupon-help.d.ts +2 -2
- package/dist/features/promotions/constants/coupon-help.js +9 -1
- package/dist/features/promotions/schemas/firestore.d.ts +24 -0
- package/dist/features/promotions/schemas/firestore.js +4 -0
- package/dist/features/promotions/types/index.d.ts +19 -1
- package/dist/features/reviews/repository/reviews.repository.d.ts +14 -0
- package/dist/features/reviews/repository/reviews.repository.js +16 -0
- package/dist/features/scams/components/ScamProfileView.js +2 -2
- package/dist/features/scams/components/ScamRegistryView.js +2 -2
- package/dist/features/scams/repository/scammer.repository.js +2 -1
- package/dist/features/scams/schemas/firestore.d.ts +2 -1
- package/dist/features/scams/schemas/firestore.js +2 -1
- package/dist/features/search/action-index/tab-entries.js +1 -1
- package/dist/features/seller/actions/offer-actions.js +56 -0
- package/dist/features/seller/actions/seller-actions.d.ts +1 -1
- package/dist/features/seller/actions/seller-actions.js +37 -3
- package/dist/features/seller/components/DispatchForm.d.ts +11 -0
- package/dist/features/seller/components/DispatchForm.js +190 -0
- package/dist/features/seller/components/SellerOrdersView.js +221 -27
- package/dist/features/seller/components/index.d.ts +1 -0
- package/dist/features/seller/components/index.js +1 -0
- package/dist/features/seller/hooks/useSellerListingData.js +25 -0
- package/dist/features/seller/repository/offer.repository.js +4 -3
- package/dist/features/seller/schemas/firestore.d.ts +23 -2
- package/dist/features/seller/schemas/firestore.js +3 -2
- package/dist/features/seller/schemas/index.d.ts +4 -4
- package/dist/features/seller/schemas/order-forms.d.ts +61 -4
- package/dist/features/seller/schemas/order-forms.js +41 -8
- package/dist/features/shipments/schemas/firestore.d.ts +25 -0
- package/dist/features/shipments/schemas/validation.d.ts +4 -4
- package/dist/features/shipping-boxes/repository/shipping-boxes.repository.d.ts +82 -0
- package/dist/features/shipping-boxes/repository/shipping-boxes.repository.js +145 -0
- package/dist/features/shipping-boxes/schemas/firestore.d.ts +80 -0
- package/dist/features/shipping-boxes/schemas/firestore.js +53 -0
- package/dist/features/store-extensions/schemas/report-create-form.d.ts +2 -2
- package/dist/features/store-extensions/schemas/shipping-config-form.d.ts +2 -2
- package/dist/features/stores/components/StoreOrdersGuideView.js +6 -1
- package/dist/features/stores/repository/store.repository.d.ts +18 -0
- package/dist/features/stores/repository/store.repository.js +27 -1
- package/dist/features/stores/schemas/firestore.d.ts +112 -0
- package/dist/features/stores/schemas/firestore.js +20 -0
- package/dist/features/stores/schemas/index.d.ts +6 -6
- package/dist/features/stores/types/index.d.ts +19 -0
- package/dist/features/support/repository/support.repository.js +72 -6
- package/dist/features/support/schemas/firestore.d.ts +17 -0
- package/dist/features/support/schemas/index.d.ts +8 -8
- package/dist/features/wishlist/hooks/useWishlistWithGuest.d.ts +1 -1
- package/dist/index.d.ts +11 -1
- package/dist/index.js +33 -1
- package/dist/next/routing/route-map.d.ts +112 -0
- package/dist/next/routing/route-map.js +63 -0
- package/dist/providers/shipping-shiprocket/index.d.ts +27 -1
- package/dist/providers/shipping-shiprocket/index.js +84 -1
- package/dist/react/contexts/SessionContext.d.ts +17 -1
- package/dist/schemas/registry.d.ts +69 -34
- package/dist/schemas/sieve.d.ts +2 -2
- package/dist/security/pii-schemas.d.ts +1 -1
- package/dist/security/pii-schemas.js +45 -0
- package/dist/server-entry.d.ts +2 -2
- package/dist/server-entry.js +8 -1
- package/dist/server.d.ts +36 -1
- package/dist/server.js +183 -1
- package/dist/styles.css +412 -80
- package/dist/tailwind-utilities.css +1 -1
- package/dist/tokens/themes/default-dark.js +1 -0
- package/dist/tokens/themes/default-light.js +1 -0
- package/dist/tokens/themes/required.d.ts +1 -1
- package/dist/tokens/themes/required.js +1 -0
- package/dist/tokens/tokens.css +15 -0
- package/dist/ui/components/Button.d.ts +10 -1
- package/dist/ui/components/Button.js +25 -3
- package/dist/ui/components/Chart.d.ts +63 -0
- package/dist/ui/components/Chart.js +169 -0
- package/dist/ui/components/Chart.style.css +214 -0
- package/dist/ui/components/Disclaimer.d.ts +19 -0
- package/dist/ui/components/Disclaimer.js +83 -0
- package/dist/ui/components/OverflowRow.js +54 -2
- package/dist/ui/components/OverflowRow.style.css +38 -0
- package/dist/ui/components/RichTextEditor.js +99 -8
- package/dist/ui/components/chart-spec.d.ts +68 -0
- package/dist/ui/components/chart-spec.js +140 -0
- package/dist/ui/components/index.style.css +1 -0
- package/dist/ui/components/surface-tokens.d.ts +1 -1
- package/dist/ui/components/surface-tokens.js +9 -0
- package/dist/ui/components/tabs-overflow.js +64 -11
- package/dist/ui/components/toolbar-collapse.d.ts +13 -0
- package/dist/ui/components/toolbar-collapse.js +10 -1
- package/dist/ui/index.d.ts +8 -0
- package/dist/ui/index.js +9 -0
- package/dist/ui/rich-text/RichText.d.ts +10 -1
- package/dist/ui/rich-text/RichText.js +33 -2
- package/dist/ui/rich-text/RichText.style.css +83 -79
- package/dist/ui/rich-text/RichTextRenderer.d.ts +30 -1
- package/dist/ui/rich-text/RichTextRenderer.js +34 -2
- package/dist/ui/rich-text/chart-blocks.d.ts +62 -0
- package/dist/ui/rich-text/chart-blocks.js +87 -0
- package/package.json +1 -1
- package/scripts/seed-cli.mjs +1834 -1822
|
@@ -20,9 +20,16 @@
|
|
|
20
20
|
*/
|
|
21
21
|
import { useCallback, useEffect, useLayoutEffect, useRef, useState } from "react";
|
|
22
22
|
/**
|
|
23
|
-
* Slack used by the hysteresis rule below, in px.
|
|
24
|
-
* 2 x --appkit-tabs-arrow-size (2rem)
|
|
25
|
-
*
|
|
23
|
+
* Slack used by the hysteresis rule below, in px. Nominally
|
|
24
|
+
* 2 x --appkit-tabs-arrow-size (2rem), the width of the two in-flow arrows.
|
|
25
|
+
*
|
|
26
|
+
* 🛑 It is a SAFETY MARGIN, not a measurement, and the distinction is what
|
|
27
|
+
* this file got wrong badly enough to crash production. The arrows are not
|
|
28
|
+
* the only thing `data-arrows="true"` changes — it also hides the list's
|
|
29
|
+
* scrollbar — so the real width reclaimed on unmount is this number minus the
|
|
30
|
+
* platform scrollbar, and on a machine with overlay scrollbars it is this
|
|
31
|
+
* number exactly. The rule below is written to be stable for every value in
|
|
32
|
+
* that range rather than assuming one of them.
|
|
26
33
|
*/
|
|
27
34
|
const ARROW_SLACK_PX = 64;
|
|
28
35
|
/** Sub-pixel tolerance: scrollWidth/clientWidth can differ by <1px at some zooms. */
|
|
@@ -51,19 +58,65 @@ export function useTabsOverflow(listRef, activeKey) {
|
|
|
51
58
|
const overflow = el.scrollWidth - el.clientWidth;
|
|
52
59
|
const previous = stateRef.current.hasArrows;
|
|
53
60
|
/*
|
|
54
|
-
* 🛑 HYSTERESIS — do not collapse this to a single threshold
|
|
61
|
+
* 🛑 HYSTERESIS — do not collapse this to a single threshold, and do not
|
|
62
|
+
* "tidy" the negative one below back to a positive number.
|
|
55
63
|
*
|
|
56
64
|
* The arrows are IN-FLOW, so mounting them shrinks the list's clientWidth
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
65
|
+
* and INCREASES the measured overflow. With one threshold a strip 10px
|
|
66
|
+
* wider than its container oscillates forever.
|
|
67
|
+
*
|
|
68
|
+
* ## 🛑 THE PREVIOUS RULE WAS `overflow > ARROW_SLACK_PX` AND IT CRASHED
|
|
69
|
+
* ## EVERY STORE PAGE IN PRODUCTION WITH React #185 (max update depth).
|
|
61
70
|
*
|
|
62
|
-
*
|
|
71
|
+
* Its stability proof — "they may only come down if the content would
|
|
63
72
|
* STILL fit after reclaiming their width, which by construction leaves
|
|
64
|
-
* overflow <= 0
|
|
73
|
+
* overflow <= 0" — rests on mounting the arrows changing the measured
|
|
74
|
+
* overflow by EXACTLY `ARROW_SLACK_PX`. That is true of the arrows alone
|
|
75
|
+
* and FALSE of the net effect, because of a rule 100 lines away in
|
|
76
|
+
* `Tabs.style.css`:
|
|
77
|
+
*
|
|
78
|
+
* .appkit-tabs-shell[data-arrows="true"] .appkit-tabs-list {
|
|
79
|
+
* scrollbar-width: none;
|
|
80
|
+
* }
|
|
81
|
+
* …__arrow is 2rem; …-list::-webkit-scrollbar { display: none }
|
|
82
|
+
*
|
|
83
|
+
* The same `data-arrows="true"` that mounts the arrows also HIDES the
|
|
84
|
+
* scrollbar, handing the list back ~15px of clientWidth. So the net
|
|
85
|
+
* reclaimed width is ~49px, not 64 — and for any strip overflowing by
|
|
86
|
+
* 2..15px the two thresholds each imply the other:
|
|
87
|
+
*
|
|
88
|
+
* hidden, overflow 10 -> 10 > 1 -> SHOW
|
|
89
|
+
* shown, overflow 59 -> 59 > 64? -> no -> HIDE
|
|
90
|
+
* hidden, overflow 10 -> …forever
|
|
91
|
+
*
|
|
92
|
+
* `useLayoutEffect` below runs on every render by design, so the loop is
|
|
93
|
+
* unbounded and React tears the tree down. The `sameState` guard cannot
|
|
94
|
+
* help: the state genuinely differs each pass.
|
|
95
|
+
*
|
|
96
|
+
* ## The rule now, stable for ANY reclaimed width
|
|
97
|
+
*
|
|
98
|
+
* Let r = whatever mounting the arrows adds to `overflow` (unknown, and
|
|
99
|
+
* provably NOT a constant — it depends on CSS this file cannot see, the
|
|
100
|
+
* platform's scrollbar width, and whether the user has overlay
|
|
101
|
+
* scrollbars). All we know is 0 <= r.
|
|
102
|
+
*
|
|
103
|
+
* show: hidden AND overflow > EPSILON
|
|
104
|
+
* hide: shown AND overflow <= -ARROW_SLACK_PX
|
|
105
|
+
*
|
|
106
|
+
* After SHOWING: overflow' = overflow + r > EPSILON >= -ARROW_SLACK_PX,
|
|
107
|
+
* so the hide test cannot fire. No loop.
|
|
108
|
+
* After HIDING: overflow' = overflow - r <= -ARROW_SLACK_PX <= EPSILON,
|
|
109
|
+
* so the show test cannot fire. No loop.
|
|
110
|
+
*
|
|
111
|
+
* Stable for every r >= 0, which is the point: the previous rule was
|
|
112
|
+
* stable only for one exact value of r that nothing enforced.
|
|
113
|
+
*
|
|
114
|
+
* The cost is deliberate conservatism — once up, the arrows stay up until
|
|
115
|
+
* the strip has a full ARROW_SLACK_PX of genuine slack. An arrow that
|
|
116
|
+
* lingers on a strip that just fits is a cosmetic blemish; the thing it
|
|
117
|
+
* replaces is a white screen.
|
|
65
118
|
*/
|
|
66
|
-
const hasArrows = previous ? overflow > ARROW_SLACK_PX : overflow > EPSILON;
|
|
119
|
+
const hasArrows = previous ? overflow > -ARROW_SLACK_PX : overflow > EPSILON;
|
|
67
120
|
const max = el.scrollWidth - el.clientWidth;
|
|
68
121
|
// Math.abs: scrollLeft is negative (or inverted) in RTL depending on engine.
|
|
69
122
|
const position = Math.abs(el.scrollLeft);
|
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
/** Below this the toolbar defaults to collapsed. Matches the `lg` boundary
|
|
2
|
+
* that both toolbars already use to switch between their mobile and desktop
|
|
3
|
+
* rows, so the default flips at the same width the layout does. */
|
|
4
|
+
/**
|
|
5
|
+
* Below `lg` — the complement of `DESKTOP_QUERY` in `features/layout`.
|
|
6
|
+
*
|
|
7
|
+
* Exported so `OverflowRow` can dock its collapsed control into the bottom bar
|
|
8
|
+
* at exactly the width the tab bar exists at. It is NOT imported from
|
|
9
|
+
* `features/layout`: this is `ui/`, and a `ui → features` edge inverts the
|
|
10
|
+
* layering and is how `audit-import-cycles` regressions start. One literal in
|
|
11
|
+
* the lower layer, shared, beats two that can drift apart.
|
|
12
|
+
*/
|
|
13
|
+
export declare const MOBILE_QUERY = "(max-width: 1023px)";
|
|
1
14
|
/**
|
|
2
15
|
* Tri-state on purpose: `null` means "the user has never chosen", which is
|
|
3
16
|
* what lets the viewport supply the default. A plain boolean cannot express
|
|
@@ -19,7 +19,16 @@ const STORAGE_PREFIX = "appkit:sticky-toolbar-collapsed:";
|
|
|
19
19
|
/** Below this the toolbar defaults to collapsed. Matches the `lg` boundary
|
|
20
20
|
* that both toolbars already use to switch between their mobile and desktop
|
|
21
21
|
* rows, so the default flips at the same width the layout does. */
|
|
22
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Below `lg` — the complement of `DESKTOP_QUERY` in `features/layout`.
|
|
24
|
+
*
|
|
25
|
+
* Exported so `OverflowRow` can dock its collapsed control into the bottom bar
|
|
26
|
+
* at exactly the width the tab bar exists at. It is NOT imported from
|
|
27
|
+
* `features/layout`: this is `ui/`, and a `ui → features` edge inverts the
|
|
28
|
+
* layering and is how `audit-import-cycles` regressions start. One literal in
|
|
29
|
+
* the lower layer, shared, beats two that can drift apart.
|
|
30
|
+
*/
|
|
31
|
+
export const MOBILE_QUERY = "(max-width: 1023px)";
|
|
23
32
|
/**
|
|
24
33
|
* Tri-state on purpose: `null` means "the user has never chosen", which is
|
|
25
34
|
* what lets the viewport supply the default. A plain boolean cannot express
|
package/dist/ui/index.d.ts
CHANGED
|
@@ -16,6 +16,8 @@ export type { SectionProps, SectionBackgroundConfig, ArticleProps, MainProps, As
|
|
|
16
16
|
export { Section, sectionBackgroundStyle, Article, Main, Aside, Nav, BlockHeader, BlockFooter, Ul, Ol, Li, Table, Thead, Tbody, Tr, Th, Td, Code, Pre, Blockquote, Figure, Figcaption, Dl, Dt, Dd, } from "./components/Semantic";
|
|
17
17
|
export type { DivProps } from "./components/Div";
|
|
18
18
|
export { Div } from "./components/Div";
|
|
19
|
+
export { Disclaimer } from "./components/Disclaimer";
|
|
20
|
+
export type { DisclaimerProps } from "./components/Disclaimer";
|
|
19
21
|
export type { SpecTableProps, SpecTableRow } from "./components/SpecTable";
|
|
20
22
|
export { SpecTable } from "./components/SpecTable";
|
|
21
23
|
export type { ColorVariant } from "./components/Typography";
|
|
@@ -93,6 +95,10 @@ export type { SliderProps } from "./components/Slider";
|
|
|
93
95
|
export { Slider } from "./components/Slider";
|
|
94
96
|
export type { CheckboxProps } from "./components/Checkbox";
|
|
95
97
|
export { Checkbox } from "./components/Checkbox";
|
|
98
|
+
export type { ChartProps } from "./components/Chart";
|
|
99
|
+
export { Chart, ChartFromJson } from "./components/Chart";
|
|
100
|
+
export type { ChartKind, ChartSeries, ChartSpec, ChartSpecResult, } from "./components/chart-spec";
|
|
101
|
+
export { CHART_KINDS, CHART_MAX_SERIES, exceedsSeriesLimit, parseChartAttr, parseChartSpec, } from "./components/chart-spec";
|
|
96
102
|
export type { RadioGroupProps, RadioOption, RadioItemProps } from "./components/Radio";
|
|
97
103
|
export { RadioGroup, RadioItem } from "./components/Radio";
|
|
98
104
|
export type { ToggleProps } from "./components/Toggle";
|
|
@@ -209,6 +215,8 @@ export type { RichTextProps } from "./rich-text/RichText";
|
|
|
209
215
|
export { RichText } from "./rich-text/RichText";
|
|
210
216
|
export type { RichTextRendererProps } from "./rich-text/RichTextRenderer";
|
|
211
217
|
export { RichTextRenderer } from "./rich-text/RichTextRenderer";
|
|
218
|
+
export type { RichTextSegment } from "./rich-text/chart-blocks";
|
|
219
|
+
export { chartFigureHtml, hasChartBlock, splitChartBlocks, } from "./rich-text/chart-blocks";
|
|
212
220
|
export type { RichTextEditorProps } from "./components/RichTextEditor";
|
|
213
221
|
export { RichTextEditor } from "./components/RichTextEditor";
|
|
214
222
|
export type { ListingLayoutProps, ListingLayoutLabels, } from "./components/ListingLayout";
|
package/dist/ui/index.js
CHANGED
|
@@ -30,6 +30,12 @@ export { FormErrorSummary } from "./forms/index.js";
|
|
|
30
30
|
export { buildColumns, createColumnBuilder, renderBoolean, renderCurrency, renderCurrencyCompact, renderCount, renderNullable, renderRating, getStatusTone, getResourceIcon, } from "./columns/index.js";
|
|
31
31
|
export { Section, sectionBackgroundStyle, Article, Main, Aside, Nav, BlockHeader, BlockFooter, Ul, Ol, Li, Table, Thead, Tbody, Tr, Th, Td, Code, Pre, Blockquote, Figure, Figcaption, Dl, Dt, Dd, } from "./components/Semantic.js";
|
|
32
32
|
export { Div } from "./components/Div.js";
|
|
33
|
+
/*
|
|
34
|
+
* Phase 12 — the one way to render a disclaimer. `id` only: there is no `text`
|
|
35
|
+
* prop, because an escape hatch would make it a styled box and the legally
|
|
36
|
+
* material disclaimers would be written at their call sites again.
|
|
37
|
+
*/
|
|
38
|
+
export { Disclaimer } from "./components/Disclaimer.js";
|
|
33
39
|
export { SpecTable } from "./components/SpecTable.js";
|
|
34
40
|
export { Heading, Text, Label, Caption, Span } from "./components/Typography.js";
|
|
35
41
|
// --- Filter chip group (SB10-C completion, S8 2026-05-13) --------------------
|
|
@@ -76,6 +82,8 @@ export { DateInput, DateRangeInput } from "./components/DateInput.js";
|
|
|
76
82
|
export { Textarea } from "./components/Textarea.js";
|
|
77
83
|
export { Slider } from "./components/Slider.js";
|
|
78
84
|
export { Checkbox } from "./components/Checkbox.js";
|
|
85
|
+
export { Chart, ChartFromJson } from "./components/Chart.js";
|
|
86
|
+
export { CHART_KINDS, CHART_MAX_SERIES, exceedsSeriesLimit, parseChartAttr, parseChartSpec, } from "./components/chart-spec.js";
|
|
79
87
|
export { RadioGroup, RadioItem } from "./components/Radio.js";
|
|
80
88
|
export { Toggle } from "./components/Toggle.js";
|
|
81
89
|
export { QuantityStepper } from "./components/QuantityStepper.js";
|
|
@@ -142,6 +150,7 @@ export { classNames, mergeTailwindClasses } from "./style.helper.js";
|
|
|
142
150
|
export { SideModal } from "./components/SideModal.js";
|
|
143
151
|
export { RichText } from "./rich-text/RichText.js";
|
|
144
152
|
export { RichTextRenderer } from "./rich-text/RichTextRenderer.js";
|
|
153
|
+
export { chartFigureHtml, hasChartBlock, splitChartBlocks, } from "./rich-text/chart-blocks.js";
|
|
145
154
|
export { RichTextEditor } from "./components/RichTextEditor.js";
|
|
146
155
|
export { ListingLayout } from "./components/ListingLayout.js";
|
|
147
156
|
export { SlottedListingView } from "./components/SlottedListingView.js";
|
|
@@ -29,6 +29,15 @@ export interface RichTextProps {
|
|
|
29
29
|
* ```
|
|
30
30
|
*/
|
|
31
31
|
highlightCode?: (code: string, lang: string) => string;
|
|
32
|
+
/**
|
|
33
|
+
* Render `<figure data-chart>` placeholders as live charts. Default true.
|
|
34
|
+
*
|
|
35
|
+
* Set `false` for untrusted user-generated content where an author should not
|
|
36
|
+
* be able to mount a component at all — the placeholder then renders as the
|
|
37
|
+
* empty `<figure>` it is. The JSON is still validated either way; this is
|
|
38
|
+
* about whether a chart is an affordance on that surface.
|
|
39
|
+
*/
|
|
40
|
+
charts?: boolean;
|
|
32
41
|
}
|
|
33
42
|
/**
|
|
34
43
|
* RichText renders sanitised HTML from a CMS / ProseMirror output.
|
|
@@ -42,4 +51,4 @@ export interface RichTextProps {
|
|
|
42
51
|
* <RichText html={desc} copyableCode />
|
|
43
52
|
* ```
|
|
44
53
|
*/
|
|
45
|
-
export declare function RichText({ html, className, proseClass, copyableCode, highlightCode, }: RichTextProps): import("react").JSX.Element;
|
|
54
|
+
export declare function RichText({ html, className, proseClass, copyableCode, highlightCode, charts, }: RichTextProps): import("react").JSX.Element;
|
|
@@ -3,6 +3,8 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
3
3
|
import { useMemo } from "react";
|
|
4
4
|
import { Div } from "../components/Div.js";
|
|
5
5
|
import { normalizeRichTextHtml } from "../../utils/string.formatter.js";
|
|
6
|
+
import { splitChartBlocks } from "./chart-blocks.js";
|
|
7
|
+
import { ChartFromJson } from "../components/Chart.js";
|
|
6
8
|
// --- Allowed HTML tags (safe subset — no script/object; iframe allowed for YouTube only) -------
|
|
7
9
|
const ALLOWED_TAGS = new Set([
|
|
8
10
|
"p",
|
|
@@ -52,6 +54,19 @@ const ALLOWED_ATTRS = {
|
|
|
52
54
|
"*": ["class", "id", "lang", "dir", "aria-label", "role", "tabindex"],
|
|
53
55
|
a: ["href", "title", "target", "rel"],
|
|
54
56
|
img: ["src", "alt", "width", "height", "loading", "data-align"],
|
|
57
|
+
/*
|
|
58
|
+
* `data-chart` carries a JSON ChartSpec that the renderer hydrates into
|
|
59
|
+
* <Chart>. Safe to allow because it is DATA, never markup: it is read with
|
|
60
|
+
* `getAttribute`, run through `JSON.parse`, and then validated field-by-field
|
|
61
|
+
* by `parseChartSpec`, which accepts only a fixed `kind` enum, string labels
|
|
62
|
+
* and finite numbers. Nothing in it reaches `innerHTML`, so a script payload
|
|
63
|
+
* smuggled into the string fails validation and renders as an error message.
|
|
64
|
+
*
|
|
65
|
+
* 🛑 It must stay on `figure` only. Allowing it via "*" would let it ride on
|
|
66
|
+
* an <a> or <iframe>, where the surrounding element's own attack surface is
|
|
67
|
+
* the problem rather than the attribute.
|
|
68
|
+
*/
|
|
69
|
+
figure: ["data-chart"],
|
|
55
70
|
td: ["colspan", "rowspan"],
|
|
56
71
|
th: ["colspan", "rowspan", "scope"],
|
|
57
72
|
ol: ["type", "start"],
|
|
@@ -167,7 +182,7 @@ function attachCopyButtons(container) {
|
|
|
167
182
|
* <RichText html={desc} copyableCode />
|
|
168
183
|
* ```
|
|
169
184
|
*/
|
|
170
|
-
export function RichText({ html, className = "", proseClass = "prose max-w-none dark:prose-invert", copyableCode = false, highlightCode, }) {
|
|
185
|
+
export function RichText({ html, className = "", proseClass = "prose max-w-none dark:prose-invert", copyableCode = false, highlightCode, charts = true, }) {
|
|
171
186
|
const safe = useMemo(() => {
|
|
172
187
|
const sanitized = sanitiseHtml(normalizeRichTextHtml(html));
|
|
173
188
|
if (!highlightCode || typeof document === "undefined")
|
|
@@ -186,5 +201,21 @@ export function RichText({ html, className = "", proseClass = "prose max-w-none
|
|
|
186
201
|
attachCopyButtons(el);
|
|
187
202
|
}
|
|
188
203
|
};
|
|
189
|
-
|
|
204
|
+
/*
|
|
205
|
+
* Split AFTER sanitising, never before.
|
|
206
|
+
*
|
|
207
|
+
* The sanitiser round-trips through `DOMParser` and re-serialises, which
|
|
208
|
+
* rewrites the single-quoted `data-chart='{"k":1}'` we emit into
|
|
209
|
+
* double-quoted `data-chart="{"k":1}"`. `splitChartBlocks` handles
|
|
210
|
+
* both spellings precisely because of this step — splitting first would
|
|
211
|
+
* leave chart segments that the sanitiser never got to inspect.
|
|
212
|
+
*/
|
|
213
|
+
const segments = useMemo(() => (charts ? splitChartBlocks(safe) : [{ type: "html", html: safe }]), [safe, charts]);
|
|
214
|
+
// Fast path: no charts. Byte-identical to the pre-chart render.
|
|
215
|
+
if (segments.length === 1 && segments[0].type === "html") {
|
|
216
|
+
return (_jsx(Div, { ref: ref, className: `appkit-rich-text ${proseClass} ${className}`, dangerouslySetInnerHTML: { __html: segments[0].html } }));
|
|
217
|
+
}
|
|
218
|
+
return (_jsx(Div, { ref: ref, className: `appkit-rich-text ${proseClass} ${className}`, children: segments.map((seg, i) => seg.type === "html" ? (_jsx("div", { className: "appkit-rich-text__seg", dangerouslySetInnerHTML: { __html: seg.html } }, `h${i}`)) : (
|
|
219
|
+
// eslint-disable-next-line react/no-array-index-key
|
|
220
|
+
_jsx(ChartFromJson, { json: seg.json }, `c${i}`))) }));
|
|
190
221
|
}
|
|
@@ -25,6 +25,24 @@
|
|
|
25
25
|
border-bottom-color: var(--appkit-color-border);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
/*
|
|
29
|
+
* The chart-draft panel the toolbar's "Chart" button opens.
|
|
30
|
+
*
|
|
31
|
+
* It sits between the toolbar and the editable area, so it needs the same
|
|
32
|
+
* recessive surface the toolbar has — without it the panel reads as part of the
|
|
33
|
+
* document being edited rather than as editor chrome, which is misleading when
|
|
34
|
+
* the thing inside it is a block of JSON.
|
|
35
|
+
*/
|
|
36
|
+
.appkit-rich-text-editor__chart {
|
|
37
|
+
background-color: var(--appkit-color-surface-raised);
|
|
38
|
+
border-bottom: 1px solid var(--appkit-color-border);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.dark .appkit-rich-text-editor__chart {
|
|
42
|
+
background-color: var(--appkit-color-slate-900);
|
|
43
|
+
border-bottom-color: var(--appkit-color-border);
|
|
44
|
+
}
|
|
45
|
+
|
|
28
46
|
.appkit-rich-text-editor__btn {
|
|
29
47
|
border: 1px solid var(--appkit-color-border);
|
|
30
48
|
color: var(--appkit-color-zinc-700);
|
|
@@ -43,77 +61,42 @@
|
|
|
43
61
|
|
|
44
62
|
|
|
45
63
|
/* --------------------------------------------------------------------------
|
|
46
|
-
* THE PROSE PALETTE
|
|
47
|
-
*
|
|
48
|
-
* 🛑 `dark:prose-invert` CANNOT COMPILE IN THIS PROJECT. Do not "fix" dark-mode
|
|
49
|
-
* rich text by adding it to a call site, and do not add
|
|
50
|
-
* `@source inline("dark:prose-invert")` to globals.css.
|
|
64
|
+
* THE PROSE PALETTE LIVES IN THE CONSUMER, NOT HERE.
|
|
51
65
|
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
* - the consumer build excludes appkit from scanning
|
|
55
|
-
* (`src/app/globals.css` → `@source not "../../appkit"`), and
|
|
56
|
-
* - `appkit/tailwind.config.js` does not load `@tailwindcss/typography`,
|
|
57
|
-
* so appkit's own `dist/tailwind-utilities.css` cannot emit it either.
|
|
66
|
+
* 🛑 Do NOT reinstate a `:root .prose { --tw-prose-*: ... !important }` block
|
|
67
|
+
* in this file. One lived here for months and it NEVER APPLIED.
|
|
58
68
|
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
* dark page. The links were effectively invisible.
|
|
69
|
+
* The typography plugin emits `.prose { --tw-prose-*: <tailwind gray> }`, and
|
|
70
|
+
* the consumer's `important: true` makes each of those `!important` inside
|
|
71
|
+
* `@layer utilities`. The block here was unlayered, and justified itself with
|
|
72
|
+
* "`:root .prose` is (0,2,0) against `.prose`'s (0,1,0), so specificity
|
|
73
|
+
* decides and the outcome does not depend on bundle order."
|
|
65
74
|
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
75
|
+
* Specificity is never consulted. For the IMPORTANT tier, cascade-layer order
|
|
76
|
+
* is REVERSED and unlayered sorts LOWEST, so a layered `!important` beats an
|
|
77
|
+
* unlayered one at any specificity (Root Cause #106, measured in a browser).
|
|
78
|
+
* The plugin's hardcoded light-mode grays therefore won in every theme —
|
|
79
|
+
* links at gray-900, i.e. near-black on the near-black dark page, and
|
|
80
|
+
* black-instead-of-teal in light. The fix was invisible to every gate because
|
|
81
|
+
* the CSS was present and correct-looking in `dist/styles.css`; only a
|
|
82
|
+
* rendered page shows it losing.
|
|
70
83
|
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
84
|
+
* Owner is now `tailwind.config.js` → `theme.extend.typography`, which makes
|
|
85
|
+
* the plugin emit the appkit tokens in the first place so there is exactly
|
|
86
|
+
* one declaration and no contest. Each binds to an `--appkit-color-*` that is
|
|
87
|
+
* redefined per theme, so prose re-themes for the built-in themes and for any
|
|
88
|
+
* admin-authored one.
|
|
76
89
|
*
|
|
77
|
-
* 🛑
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
* FAQ page apply `prose` to a bare `<div>` and had the identical defect.
|
|
90
|
+
* 🛑 `dark:prose-invert` CANNOT COMPILE IN THIS PROJECT. Do not "fix" dark
|
|
91
|
+
* rich text by adding it to a call site, and do not add
|
|
92
|
+
* `@source inline("dark:prose-invert")` to globals.css. Every `proseClass`
|
|
93
|
+
* string in appkit carries it and none has ever generated a rule, because the
|
|
94
|
+
* consumer build excludes appkit from scanning (`src/app/globals.css` →
|
|
95
|
+
* `@source not "../../appkit"`) and `appkit/tailwind.config.js` does not load
|
|
96
|
+
* `@tailwindcss/typography`, so appkit's own `dist/tailwind-utilities.css`
|
|
97
|
+
* cannot emit it either. It is moot now regardless: the tokens above invert on
|
|
98
|
+
* their own, which `prose-invert` could never do with its hardcoded grays.
|
|
87
99
|
* -------------------------------------------------------------------------- */
|
|
88
|
-
:root .prose {
|
|
89
|
-
--tw-prose-body: var(--appkit-color-text-muted) !important;
|
|
90
|
-
--tw-prose-headings: var(--appkit-color-text) !important;
|
|
91
|
-
--tw-prose-lead: var(--appkit-color-text-muted) !important;
|
|
92
|
-
--tw-prose-links: var(--appkit-color-primary-600) !important;
|
|
93
|
-
--tw-prose-bold: var(--appkit-color-text) !important;
|
|
94
|
-
--tw-prose-counters: var(--appkit-color-text-faint) !important;
|
|
95
|
-
--tw-prose-bullets: var(--appkit-color-text-faint) !important;
|
|
96
|
-
--tw-prose-hr: var(--appkit-color-border) !important;
|
|
97
|
-
--tw-prose-quotes: var(--appkit-color-text) !important;
|
|
98
|
-
--tw-prose-quote-borders: var(--appkit-color-primary) !important;
|
|
99
|
-
--tw-prose-captions: var(--appkit-color-text-faint) !important;
|
|
100
|
-
--tw-prose-kbd: var(--appkit-color-text) !important;
|
|
101
|
-
--tw-prose-kbd-shadows: 24 24 27 !important;
|
|
102
|
-
--tw-prose-code: var(--appkit-color-text) !important;
|
|
103
|
-
--tw-prose-pre-code: var(--appkit-color-slate-200) !important;
|
|
104
|
-
--tw-prose-pre-bg: var(--appkit-color-slate-800) !important;
|
|
105
|
-
--tw-prose-th-borders: var(--appkit-color-border) !important;
|
|
106
|
-
--tw-prose-td-borders: var(--appkit-color-border) !important;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/* Only the values that are genuinely theme-specific. Everything above already
|
|
110
|
-
* inverts, because `--appkit-color-text`/`-text-muted`/`-border` are redefined
|
|
111
|
-
* per theme in tokens.css — which is the whole point of binding to them. */
|
|
112
|
-
:root.dark .prose {
|
|
113
|
-
--tw-prose-links: var(--appkit-color-secondary-400) !important;
|
|
114
|
-
--tw-prose-kbd-shadows: 250 250 250 !important;
|
|
115
|
-
--tw-prose-pre-bg: var(--appkit-color-surface) !important;
|
|
116
|
-
}
|
|
117
100
|
|
|
118
101
|
/* --------------------------------------------------------------------------
|
|
119
102
|
* Base wrapper. All selectors are scoped to .appkit-rich-text so they
|
|
@@ -200,27 +183,31 @@
|
|
|
200
183
|
}
|
|
201
184
|
|
|
202
185
|
/* --- Links ---------------------------------------------------------------- */
|
|
186
|
+
/* No `.dark` variant, deliberately: `--appkit-color-link` is redefined per
|
|
187
|
+
* theme, so one rule covers every theme including admin-authored ones. The two
|
|
188
|
+
* `.dark .appkit-rich-text a` rules that used to sit here were also dead —
|
|
189
|
+
* non-important against the plugin's `.prose :where(a){color:…!important}`.
|
|
190
|
+
*
|
|
191
|
+
* Decoration binds to `currentColor` rather than naming the token a second
|
|
192
|
+
* time. That matters beyond brevity: the colour here IS still overridden by
|
|
193
|
+
* the plugin on any element that also carries `.prose`, so a hardcoded
|
|
194
|
+
* decoration colour could disagree with the ink actually rendered. With
|
|
195
|
+
* `currentColor` the underline follows whatever won. */
|
|
203
196
|
.appkit-rich-text a {
|
|
204
|
-
color: var(--appkit-color-
|
|
197
|
+
color: var(--appkit-color-link);
|
|
205
198
|
text-decoration: underline;
|
|
206
|
-
text-decoration-color: color-mix(in srgb,
|
|
199
|
+
text-decoration-color: color-mix(in srgb, currentColor 60%, transparent);
|
|
207
200
|
text-underline-offset: 2px;
|
|
208
201
|
transition: color 150ms, text-decoration-color 150ms;
|
|
209
202
|
}
|
|
210
203
|
|
|
204
|
+
/* Hover moves the link toward the page's own text colour, which darkens it in
|
|
205
|
+
* a light theme and lightens it in a dark one — so this needs no per-theme
|
|
206
|
+
* pair either. The plugin sets no `a:hover`, so unlike the resting colour
|
|
207
|
+
* above this rule is genuinely the one in effect. */
|
|
211
208
|
.appkit-rich-text a:hover {
|
|
212
|
-
color: var(--appkit-color-
|
|
213
|
-
text-decoration-color:
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
.dark .appkit-rich-text a {
|
|
217
|
-
color: var(--appkit-color-secondary-400);
|
|
218
|
-
text-decoration-color: color-mix(in srgb, var(--appkit-color-secondary-400) 60%, transparent);
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
.dark .appkit-rich-text a:hover {
|
|
222
|
-
color: var(--appkit-color-secondary-300);
|
|
223
|
-
text-decoration-color: color-mix(in srgb, var(--appkit-color-secondary-300) 60%, transparent);
|
|
209
|
+
color: color-mix(in srgb, var(--appkit-color-link) 80%, var(--appkit-color-text));
|
|
210
|
+
text-decoration-color: currentColor;
|
|
224
211
|
}
|
|
225
212
|
|
|
226
213
|
/* --- Tables --------------------------------------------------------------- */
|
|
@@ -362,3 +349,20 @@
|
|
|
362
349
|
.dark .appkit-rich-text del {
|
|
363
350
|
color: var(--appkit-color-zinc-400);
|
|
364
351
|
}
|
|
352
|
+
|
|
353
|
+
/*
|
|
354
|
+
* Chart-block segment wrapper.
|
|
355
|
+
*
|
|
356
|
+
* `RichTextRenderer` has to split the HTML around `<figure data-chart>` and
|
|
357
|
+
* each resulting run needs an element to carry `dangerouslySetInnerHTML` —
|
|
358
|
+
* there is no way to inject HTML without one. `display: contents` removes that
|
|
359
|
+
* element from the box tree so the runs lay out exactly as they did when they
|
|
360
|
+
* were one `innerHTML` dump.
|
|
361
|
+
*
|
|
362
|
+
* 🛑 Without this, `prose`'s adjacency and first/last-child margin rules
|
|
363
|
+
* restart at every chart, so paragraphs either side of a chart space
|
|
364
|
+
* differently from paragraphs anywhere else on the page.
|
|
365
|
+
*/
|
|
366
|
+
.appkit-rich-text__seg {
|
|
367
|
+
display: contents;
|
|
368
|
+
}
|
|
@@ -3,6 +3,14 @@ export interface RichTextRendererProps {
|
|
|
3
3
|
html?: string | null;
|
|
4
4
|
className?: string;
|
|
5
5
|
proseClass?: string;
|
|
6
|
+
/**
|
|
7
|
+
* Render `<figure data-chart>` placeholders as live charts. Default true.
|
|
8
|
+
*
|
|
9
|
+
* Pass `false` where a chart cannot work — an email body, a plain-text
|
|
10
|
+
* export, an OG image — so the placeholder is simply dropped rather than
|
|
11
|
+
* mounting a client component into a context that cannot hydrate it.
|
|
12
|
+
*/
|
|
13
|
+
charts?: boolean;
|
|
6
14
|
}
|
|
7
15
|
/**
|
|
8
16
|
* SSR-safe HTML renderer for admin/CMS-authored rich text content.
|
|
@@ -12,5 +20,26 @@ export interface RichTextRendererProps {
|
|
|
12
20
|
*
|
|
13
21
|
* For user-generated content or untrusted HTML, use <RichText> instead
|
|
14
22
|
* (client-only, runs the DOM-based sanitizer).
|
|
23
|
+
*
|
|
24
|
+
* ## 🛑 It is no longer a single `innerHTML` dump, and why that is safe
|
|
25
|
+
*
|
|
26
|
+
* Chart blocks are stored as `<figure data-chart='{json}'>` and have to become
|
|
27
|
+
* real components to be theme-aware, so the HTML is split and the chart
|
|
28
|
+
* segments are replaced with `<ChartFromJson>`. Two properties keep this from
|
|
29
|
+
* being a regression:
|
|
30
|
+
*
|
|
31
|
+
* - **The fast path is unchanged.** `splitChartBlocks` rejects on a substring
|
|
32
|
+
* test, so content with no chart returns one segment and renders through the
|
|
33
|
+
* same single `dangerouslySetInnerHTML` as before.
|
|
34
|
+
* - **Splitting cannot introduce markup.** Segments are slices of the original
|
|
35
|
+
* string, concatenated in document order; nothing is rewritten. A malformed
|
|
36
|
+
* chart figure fails the match and stays ordinary HTML.
|
|
37
|
+
*
|
|
38
|
+
* 🛑 The prose wrapper stays on the OUTER element, and each segment's own
|
|
39
|
+
* wrapper is `display: contents` (`.appkit-rich-text__seg`). A segment needs an
|
|
40
|
+
* element to carry `dangerouslySetInnerHTML`, but leaving that element in the
|
|
41
|
+
* box tree restarts `prose`'s adjacency and first/last-child margin rules at
|
|
42
|
+
* every chart — so paragraphs either side of a chart would space differently
|
|
43
|
+
* from paragraphs anywhere else on the page.
|
|
15
44
|
*/
|
|
16
|
-
export declare function RichTextRenderer({ html, className, proseClass, }: RichTextRendererProps): React.JSX.Element | null;
|
|
45
|
+
export declare function RichTextRenderer({ html, className, proseClass, charts, }: RichTextRendererProps): React.JSX.Element | null;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { splitChartBlocks } from "./chart-blocks.js";
|
|
3
|
+
import { ChartFromJson } from "../components/Chart.js";
|
|
2
4
|
/**
|
|
3
5
|
* SSR-safe HTML renderer for admin/CMS-authored rich text content.
|
|
4
6
|
*
|
|
@@ -7,9 +9,39 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
7
9
|
*
|
|
8
10
|
* For user-generated content or untrusted HTML, use <RichText> instead
|
|
9
11
|
* (client-only, runs the DOM-based sanitizer).
|
|
12
|
+
*
|
|
13
|
+
* ## 🛑 It is no longer a single `innerHTML` dump, and why that is safe
|
|
14
|
+
*
|
|
15
|
+
* Chart blocks are stored as `<figure data-chart='{json}'>` and have to become
|
|
16
|
+
* real components to be theme-aware, so the HTML is split and the chart
|
|
17
|
+
* segments are replaced with `<ChartFromJson>`. Two properties keep this from
|
|
18
|
+
* being a regression:
|
|
19
|
+
*
|
|
20
|
+
* - **The fast path is unchanged.** `splitChartBlocks` rejects on a substring
|
|
21
|
+
* test, so content with no chart returns one segment and renders through the
|
|
22
|
+
* same single `dangerouslySetInnerHTML` as before.
|
|
23
|
+
* - **Splitting cannot introduce markup.** Segments are slices of the original
|
|
24
|
+
* string, concatenated in document order; nothing is rewritten. A malformed
|
|
25
|
+
* chart figure fails the match and stays ordinary HTML.
|
|
26
|
+
*
|
|
27
|
+
* 🛑 The prose wrapper stays on the OUTER element, and each segment's own
|
|
28
|
+
* wrapper is `display: contents` (`.appkit-rich-text__seg`). A segment needs an
|
|
29
|
+
* element to carry `dangerouslySetInnerHTML`, but leaving that element in the
|
|
30
|
+
* box tree restarts `prose`'s adjacency and first/last-child margin rules at
|
|
31
|
+
* every chart — so paragraphs either side of a chart would space differently
|
|
32
|
+
* from paragraphs anywhere else on the page.
|
|
10
33
|
*/
|
|
11
|
-
export function RichTextRenderer({ html, className = "", proseClass = "prose max-w-none dark:prose-invert", }) {
|
|
34
|
+
export function RichTextRenderer({ html, className = "", proseClass = "prose max-w-none dark:prose-invert", charts = true, }) {
|
|
12
35
|
if (!html)
|
|
13
36
|
return null;
|
|
14
|
-
|
|
37
|
+
const wrapperClass = `appkit-rich-text ${proseClass} ${className}`.trim();
|
|
38
|
+
const segments = charts ? splitChartBlocks(html) : [{ type: "html", html }];
|
|
39
|
+
// Single HTML segment — the overwhelmingly common case. Identical to the
|
|
40
|
+
// pre-chart behaviour, down to the element shape.
|
|
41
|
+
if (segments.length === 1 && segments[0].type === "html") {
|
|
42
|
+
return (_jsx("div", { className: wrapperClass, dangerouslySetInnerHTML: { __html: segments[0].html } }));
|
|
43
|
+
}
|
|
44
|
+
return (_jsx("div", { className: wrapperClass, children: segments.map((seg, i) => seg.type === "html" ? (_jsx("div", { className: "appkit-rich-text__seg", dangerouslySetInnerHTML: { __html: seg.html } }, `h${i}`)) : (
|
|
45
|
+
// eslint-disable-next-line react/no-array-index-key
|
|
46
|
+
_jsx(ChartFromJson, { json: seg.json }, `c${i}`))) }));
|
|
15
47
|
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Splitting rich-text HTML around `<figure data-chart>` placeholders.
|
|
3
|
+
*
|
|
4
|
+
* ## 🛑 Why this is regex and not a DOM parse
|
|
5
|
+
*
|
|
6
|
+
* `RichTextRenderer` is a React Server Component — no `DOMParser`, no
|
|
7
|
+
* `document`. So the split has to work on the string, and it is only safe to do
|
|
8
|
+
* that because the shape being matched is one we WRITE: a childless
|
|
9
|
+
* `<figure data-chart='…'></figure>` emitted by the chart toolbar button.
|
|
10
|
+
*
|
|
11
|
+
* This is deliberately not a general HTML parser and must not grow into one. It
|
|
12
|
+
* matches exactly one element shape and hands everything else through
|
|
13
|
+
* untouched, so a malformed chart figure degrades to "rendered as ordinary
|
|
14
|
+
* HTML" rather than corrupting the document around it.
|
|
15
|
+
*
|
|
16
|
+
* ## 🛑 Why the JSON needs entity decoding
|
|
17
|
+
*
|
|
18
|
+
* A `ChartSpec` is full of `"` characters, so the attribute is written
|
|
19
|
+
* single-quoted. But anything that round-trips the HTML through a DOM — the
|
|
20
|
+
* client sanitiser's `DOMParser`, a contenteditable surface, an admin preview —
|
|
21
|
+
* re-serialises it double-quoted with the inner quotes as `"`. Both
|
|
22
|
+
* spellings therefore occur in stored content, and a renderer that handles only
|
|
23
|
+
* the one it writes will fail on its own saved output.
|
|
24
|
+
*
|
|
25
|
+
* Pure. No React, no DOM, safe on the server.
|
|
26
|
+
*/
|
|
27
|
+
import type { ChartSpec } from "../components/chart-spec";
|
|
28
|
+
/** A run of ordinary HTML, or a chart placeholder's raw JSON payload. */
|
|
29
|
+
export type RichTextSegment = {
|
|
30
|
+
type: "html";
|
|
31
|
+
html: string;
|
|
32
|
+
} | {
|
|
33
|
+
type: "chart";
|
|
34
|
+
json: string;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Decode the entity subset an HTML serialiser can introduce inside an
|
|
38
|
+
* attribute value.
|
|
39
|
+
*
|
|
40
|
+
* 🛑 `&` is decoded LAST. Decoding it first turns a legitimately encoded
|
|
41
|
+
* `&quot;` into `"` and then into `"`, which injects a quote the
|
|
42
|
+
* author never wrote and breaks the JSON parse — the classic double-decode bug.
|
|
43
|
+
*/
|
|
44
|
+
export declare function decodeAttrEntities(s: string): string;
|
|
45
|
+
/**
|
|
46
|
+
* Split HTML into alternating prose and chart segments, in document order.
|
|
47
|
+
*
|
|
48
|
+
* Returns a single `html` segment when there are no charts, so the common case
|
|
49
|
+
* costs one regex test and the caller's fast path stays a plain innerHTML
|
|
50
|
+
* render.
|
|
51
|
+
*/
|
|
52
|
+
export declare function splitChartBlocks(html: string): RichTextSegment[];
|
|
53
|
+
/** True when the content carries at least one chart placeholder. Stateless. */
|
|
54
|
+
export declare function hasChartBlock(html: string | null | undefined): boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Build the placeholder a toolbar or a seed fixture should emit.
|
|
57
|
+
*
|
|
58
|
+
* Single-quoted, with any single quote in the payload escaped as `'` so the
|
|
59
|
+
* attribute cannot be terminated early by a label containing an apostrophe —
|
|
60
|
+
* "Blader's choice" is an entirely ordinary series label.
|
|
61
|
+
*/
|
|
62
|
+
export declare function chartFigureHtml(spec: ChartSpec): string;
|