@mohasinac/appkit 4.52.5 → 4.53.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 +4 -4
- package/dist/_internal/client/features/sticker-trace/canvas-codec.d.ts +2 -0
- package/dist/_internal/client/features/sticker-trace/canvas-codec.js +148 -0
- package/dist/_internal/server/features/auctions/actions.js +1 -1
- package/dist/_internal/server/features/categories/data.js +23 -7
- package/dist/_internal/server/features/checkout/actions.js +10 -3
- package/dist/_internal/server/features/checkout/data.d.ts +15 -0
- package/dist/_internal/server/features/checkout/data.js +20 -3
- package/dist/_internal/server/features/lottery/actions.js +9 -1
- package/dist/_internal/server/features/lottery/og.d.ts +40 -0
- package/dist/_internal/server/features/lottery/og.js +79 -0
- package/dist/_internal/server/features/messages/actions.js +4 -0
- package/dist/_internal/server/features/offers/adapters.js +17 -3
- package/dist/_internal/server/features/orders/actions.js +7 -2
- package/dist/_internal/server/features/raffle/actions.d.ts +19 -0
- package/dist/_internal/server/features/raffle/actions.js +25 -0
- package/dist/_internal/server/features/reviews/actions.js +1 -1
- package/dist/_internal/server/features/reviews/data.d.ts +1 -1
- package/dist/_internal/server/features/search/index-build/artifact-store.d.ts +89 -0
- package/dist/_internal/server/features/search/index-build/artifact-store.js +208 -0
- package/dist/_internal/server/features/search/index-build/build.d.ts +57 -0
- package/dist/_internal/server/features/search/index-build/build.js +285 -0
- package/dist/_internal/server/features/search/index-build/sources.d.ts +53 -0
- package/dist/_internal/server/features/search/index-build/sources.js +385 -0
- package/dist/_internal/server/features/search/search-sources.d.ts +0 -15
- package/dist/_internal/server/features/search/search-sources.js +142 -7
- package/dist/_internal/server/features/seo/robots.js +21 -1
- package/dist/_internal/server/features/seo/sitemap.js +1 -1
- package/dist/_internal/server/features/shared/listing-data-factory.js +16 -4
- package/dist/_internal/server/features/site-settings/adapters.d.ts +1 -1
- package/dist/_internal/server/features/site-settings/adapters.js +26 -0
- package/dist/_internal/server/features/sticker-trace/actions.d.ts +109 -0
- package/dist/_internal/server/features/sticker-trace/actions.js +172 -0
- package/dist/_internal/server/features/sticker-trace/adapters.d.ts +80 -0
- package/dist/_internal/server/features/sticker-trace/adapters.js +174 -0
- package/dist/_internal/server/features/sticker-trace/build-cut-file.d.ts +26 -0
- package/dist/_internal/server/features/sticker-trace/build-cut-file.js +127 -0
- package/dist/_internal/server/features/sticker-trace/coordinator.d.ts +27 -0
- package/dist/_internal/server/features/sticker-trace/coordinator.js +169 -0
- package/dist/_internal/server/features/sticker-trace/fanout.d.ts +43 -0
- package/dist/_internal/server/features/sticker-trace/fanout.js +180 -0
- package/dist/_internal/server/features/sticker-trace/finalizer.d.ts +25 -0
- package/dist/_internal/server/features/sticker-trace/finalizer.js +123 -0
- package/dist/_internal/server/features/sticker-trace/mosaic-inputs.d.ts +30 -0
- package/dist/_internal/server/features/sticker-trace/mosaic-inputs.js +112 -0
- package/dist/_internal/server/features/sticker-trace/progress.d.ts +81 -0
- package/dist/_internal/server/features/sticker-trace/progress.js +198 -0
- package/dist/_internal/server/features/sticker-trace/promote.d.ts +23 -0
- package/dist/_internal/server/features/sticker-trace/promote.js +193 -0
- package/dist/_internal/server/features/sticker-trace/shard.d.ts +50 -0
- package/dist/_internal/server/features/sticker-trace/shard.js +174 -0
- package/dist/_internal/server/features/sticker-trace/sheet-actions.d.ts +141 -0
- package/dist/_internal/server/features/sticker-trace/sheet-actions.js +279 -0
- package/dist/_internal/server/features/sticker-trace/storage.d.ts +135 -0
- package/dist/_internal/server/features/sticker-trace/storage.js +282 -0
- package/dist/_internal/server/functions/scheduled.d.ts +2 -1
- package/dist/_internal/server/functions/scheduled.js +25 -1
- package/dist/_internal/server/jobs/core/_event-ref.d.ts +51 -0
- package/dist/_internal/server/jobs/core/_event-ref.js +63 -0
- package/dist/_internal/server/jobs/core/assignSpinPrize.d.ts +18 -0
- package/dist/_internal/server/jobs/core/assignSpinPrize.js +77 -16
- package/dist/_internal/server/jobs/core/auctionSettlement.js +13 -4
- package/dist/_internal/server/jobs/core/autoPayoutEligibility.js +44 -15
- package/dist/_internal/server/jobs/core/bundleStockSync.js +3 -4
- package/dist/_internal/server/jobs/core/cleanupRtdbEvents.js +44 -0
- package/dist/_internal/server/jobs/core/event-draw-reasons.d.ts +78 -0
- package/dist/_internal/server/jobs/core/event-draw-reasons.js +133 -0
- package/dist/_internal/server/jobs/core/listingProcessor.js +28 -8
- package/dist/_internal/server/jobs/core/onOrderCreate.js +12 -1
- package/dist/_internal/server/jobs/core/onScamReportCreate.js +13 -2
- package/dist/_internal/server/jobs/core/onScamReportRejected.js +8 -2
- package/dist/_internal/server/jobs/core/onScamReportVerified.js +8 -2
- package/dist/_internal/server/jobs/core/onStoreWrite.js +11 -4
- package/dist/_internal/server/jobs/core/prizeDrawAssignWinner.js +5 -4
- package/dist/_internal/server/jobs/core/prizeDrawExpiryReveal.js +1 -4
- package/dist/_internal/server/jobs/core/prizeDrawSoldOutReveal.js +1 -2
- package/dist/_internal/server/jobs/core/promotions.js +7 -4
- package/dist/_internal/server/jobs/core/searchIndexBuild.d.ts +7 -0
- package/dist/_internal/server/jobs/core/searchIndexBuild.js +211 -0
- package/dist/_internal/server/jobs/core/triggerEventRaffle.d.ts +35 -0
- package/dist/_internal/server/jobs/core/triggerEventRaffle.js +213 -31
- package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.js +20 -14
- package/dist/_internal/server/jobs/handlers/assignSpinPrize.d.ts +8 -0
- package/dist/_internal/server/jobs/handlers/assignSpinPrize.js +15 -15
- 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/onCategoryWrite.js +18 -0
- package/dist/_internal/server/jobs/handlers/onProductWrite.js +18 -0
- package/dist/_internal/server/jobs/handlers/onReviewWrite.js +18 -0
- package/dist/_internal/server/jobs/handlers/onScamReportUpdate.js +18 -0
- package/dist/_internal/server/jobs/handlers/onStoreWrite.js +18 -0
- package/dist/_internal/server/jobs/handlers/searchIndexBuild.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/searchIndexBuild.js +2 -0
- package/dist/_internal/server/jobs/handlers/triggerEventRaffle.d.ts +8 -0
- package/dist/_internal/server/jobs/handlers/triggerEventRaffle.js +15 -6
- package/dist/_internal/shared/actions/action-registry.js +29 -0
- package/dist/_internal/shared/cache/revalidate-targets.d.ts +0 -1
- package/dist/_internal/shared/cache/revalidate-targets.js +10 -8
- package/dist/_internal/shared/features/events/config.d.ts +14 -0
- package/dist/_internal/shared/features/events/config.js +14 -0
- package/dist/_internal/shared/features/notifications/action-url.js +8 -0
- package/dist/_internal/shared/features/site-settings/types.d.ts +11 -0
- package/dist/_internal/shared/features/sticker-trace/codec.d.ts +81 -0
- package/dist/_internal/shared/features/sticker-trace/codec.js +30 -0
- package/dist/_internal/shared/features/sticker-trace/config.d.ts +81 -0
- package/dist/_internal/shared/features/sticker-trace/config.js +177 -0
- package/dist/_internal/shared/features/sticker-trace/cut-contour.d.ts +20 -0
- package/dist/_internal/shared/features/sticker-trace/cut-contour.js +60 -0
- package/dist/_internal/shared/features/sticker-trace/export/build-export-set.d.ts +65 -0
- package/dist/_internal/shared/features/sticker-trace/export/build-export-set.js +176 -0
- package/dist/_internal/shared/features/sticker-trace/export/cut-svg.d.ts +56 -0
- package/dist/_internal/shared/features/sticker-trace/export/cut-svg.js +120 -0
- package/dist/_internal/shared/features/sticker-trace/export/machine-profiles.d.ts +92 -0
- package/dist/_internal/shared/features/sticker-trace/export/machine-profiles.js +153 -0
- package/dist/_internal/shared/features/sticker-trace/export/nesting.d.ts +51 -0
- package/dist/_internal/shared/features/sticker-trace/export/nesting.js +110 -0
- package/dist/_internal/shared/features/sticker-trace/export/page-sizes.d.ts +68 -0
- package/dist/_internal/shared/features/sticker-trace/export/page-sizes.js +223 -0
- package/dist/_internal/shared/features/sticker-trace/export/part-tiling.d.ts +51 -0
- package/dist/_internal/shared/features/sticker-trace/export/part-tiling.js +178 -0
- package/dist/_internal/shared/features/sticker-trace/export/simplify-budget.d.ts +26 -0
- package/dist/_internal/shared/features/sticker-trace/export/simplify-budget.js +134 -0
- package/dist/_internal/shared/features/sticker-trace/export/vectorise-art.d.ts +40 -0
- package/dist/_internal/shared/features/sticker-trace/export/vectorise-art.js +195 -0
- package/dist/_internal/shared/features/sticker-trace/index.d.ts +2 -0
- package/dist/_internal/shared/features/sticker-trace/index.js +59 -0
- package/dist/_internal/shared/features/sticker-trace/math/catmull-rom.d.ts +11 -0
- package/dist/_internal/shared/features/sticker-trace/math/catmull-rom.js +66 -0
- package/dist/_internal/shared/features/sticker-trace/math/edt.d.ts +27 -0
- package/dist/_internal/shared/features/sticker-trace/math/edt.js +165 -0
- package/dist/_internal/shared/features/sticker-trace/math/label.d.ts +15 -0
- package/dist/_internal/shared/features/sticker-trace/math/label.js +156 -0
- package/dist/_internal/shared/features/sticker-trace/math/marching-squares.d.ts +16 -0
- package/dist/_internal/shared/features/sticker-trace/math/marching-squares.js +242 -0
- package/dist/_internal/shared/features/sticker-trace/math/morphology.d.ts +46 -0
- package/dist/_internal/shared/features/sticker-trace/math/morphology.js +168 -0
- package/dist/_internal/shared/features/sticker-trace/math/rasterize-path.d.ts +88 -0
- package/dist/_internal/shared/features/sticker-trace/math/rasterize-path.js +286 -0
- package/dist/_internal/shared/features/sticker-trace/math/rdp.d.ts +10 -0
- package/dist/_internal/shared/features/sticker-trace/math/rdp.js +74 -0
- package/dist/_internal/shared/features/sticker-trace/resume.d.ts +50 -0
- package/dist/_internal/shared/features/sticker-trace/resume.js +160 -0
- package/dist/_internal/shared/features/sticker-trace/trace/cluster.d.ts +20 -0
- package/dist/_internal/shared/features/sticker-trace/trace/cluster.js +132 -0
- package/dist/_internal/shared/features/sticker-trace/trace/cross-profile.d.ts +28 -0
- package/dist/_internal/shared/features/sticker-trace/trace/cross-profile.js +120 -0
- package/dist/_internal/shared/features/sticker-trace/trace/flood.d.ts +21 -0
- package/dist/_internal/shared/features/sticker-trace/trace/flood.js +104 -0
- package/dist/_internal/shared/features/sticker-trace/trace/geometry.d.ts +3 -0
- package/dist/_internal/shared/features/sticker-trace/trace/geometry.js +140 -0
- package/dist/_internal/shared/features/sticker-trace/trace/line-filter.d.ts +15 -0
- package/dist/_internal/shared/features/sticker-trace/trace/line-filter.js +138 -0
- package/dist/_internal/shared/features/sticker-trace/trace/merge.d.ts +27 -0
- package/dist/_internal/shared/features/sticker-trace/trace/merge.js +187 -0
- package/dist/_internal/shared/features/sticker-trace/trace/paper.d.ts +32 -0
- package/dist/_internal/shared/features/sticker-trace/trace/paper.js +147 -0
- package/dist/_internal/shared/features/sticker-trace/trace/prefilter.d.ts +30 -0
- package/dist/_internal/shared/features/sticker-trace/trace/prefilter.js +125 -0
- package/dist/_internal/shared/features/sticker-trace/trace/quantise.d.ts +10 -0
- package/dist/_internal/shared/features/sticker-trace/trace/quantise.js +153 -0
- package/dist/_internal/shared/features/sticker-trace/trace/ridge.d.ts +88 -0
- package/dist/_internal/shared/features/sticker-trace/trace/ridge.js +344 -0
- package/dist/_internal/shared/features/sticker-trace/trace/segment.d.ts +10 -0
- package/dist/_internal/shared/features/sticker-trace/trace/segment.js +251 -0
- package/dist/_internal/shared/features/sticker-trace/types.d.ts +197 -0
- package/dist/_internal/shared/features/sticker-trace/types.js +49 -0
- package/dist/_internal/shared/listing-types/_registry.d.ts +11 -0
- package/dist/_internal/shared/listing-types/art/config.d.ts +1 -0
- package/dist/_internal/shared/listing-types/art/config.js +1 -0
- package/dist/_internal/shared/listing-types/auction/config.d.ts +1 -0
- package/dist/_internal/shared/listing-types/auction/config.js +1 -0
- package/dist/_internal/shared/listing-types/classified/config.d.ts +1 -0
- package/dist/_internal/shared/listing-types/classified/config.js +1 -0
- package/dist/_internal/shared/listing-types/digital-code/config.d.ts +1 -0
- package/dist/_internal/shared/listing-types/digital-code/config.js +1 -0
- package/dist/_internal/shared/listing-types/feature-flags.d.ts +7 -0
- package/dist/_internal/shared/listing-types/feature-flags.js +9 -0
- package/dist/_internal/shared/listing-types/live/config.d.ts +1 -0
- package/dist/_internal/shared/listing-types/live/config.js +1 -0
- package/dist/_internal/shared/listing-types/pre-order/config.d.ts +1 -0
- package/dist/_internal/shared/listing-types/pre-order/config.js +1 -0
- package/dist/_internal/shared/listing-types/prize-draw/config.d.ts +1 -0
- package/dist/_internal/shared/listing-types/prize-draw/config.js +1 -0
- package/dist/_internal/shared/listing-types/standard/config.d.ts +1 -0
- package/dist/_internal/shared/listing-types/standard/config.js +1 -0
- package/dist/_internal/shared/listing-types/stickers/config.d.ts +1 -0
- package/dist/_internal/shared/listing-types/stickers/config.js +1 -0
- package/dist/_internal/shared/media/limits.d.ts +12 -2
- package/dist/_internal/shared/media/limits.js +12 -2
- package/dist/_internal/shared/search/artifact-url.d.ts +35 -0
- package/dist/_internal/shared/search/artifact-url.js +119 -0
- package/dist/_internal/shared/search/index-record.d.ts +68 -0
- package/dist/_internal/shared/search/index-record.js +96 -0
- package/dist/_internal/shared/search/match.d.ts +65 -0
- package/dist/_internal/shared/search/match.js +263 -0
- package/dist/client.d.ts +8 -7
- package/dist/client.js +12 -5
- package/dist/configs/eslint.js +22 -2
- package/dist/constants/api-endpoints.d.ts +68 -0
- package/dist/constants/api-endpoints.js +32 -0
- package/dist/constants/field-names.d.ts +7 -1
- package/dist/constants/field-names.js +36 -1
- package/dist/contracts/repository.d.ts +8 -7
- package/dist/contracts/search.d.ts +2 -2
- package/dist/contracts/table.d.ts +3 -3
- package/dist/contracts/table.js +3 -3
- package/dist/core/contact-submissions.repository.js +2 -2
- package/dist/core/integration-keys.js +7 -1
- package/dist/core/newsletter.repository.js +2 -2
- package/dist/core/site-config.js +1 -1
- package/dist/errors/error-codes.d.ts +30 -0
- package/dist/errors/error-codes.js +30 -0
- package/dist/errors/error-display-map.js +40 -1
- package/dist/features/account/api/[userId]/addresses/route.js +1 -1
- package/dist/features/account/components/UserBidsView.js +1 -1
- package/dist/features/account/components/index.d.ts +0 -8
- package/dist/features/account/components/index.js +0 -4
- package/dist/features/addresses/repository/addresses.repository.d.ts +17 -6
- package/dist/features/addresses/repository/addresses.repository.js +65 -9
- package/dist/features/addresses/schemas/firestore.d.ts +17 -6
- package/dist/features/admin/actions/notification-actions.js +15 -6
- package/dist/features/admin/api/bids/route.js +1 -1
- package/dist/features/admin/api/coupons/route.js +1 -1
- package/dist/features/admin/api/products/route.js +1 -1
- package/dist/features/admin/api/reviews/route.js +1 -1
- package/dist/features/admin/components/AdminAdEditorView.js +19 -5
- package/dist/features/admin/components/AdminAuditLogView.js +1 -1
- package/dist/features/admin/components/AdminBlogEditorView.js +0 -1
- package/dist/features/admin/components/AdminBlogView.js +1 -1
- package/dist/features/admin/components/AdminBrandsView.js +17 -1
- package/dist/features/admin/components/AdminCategoryEditorView.js +0 -1
- package/dist/features/admin/components/AdminContactView.js +1 -1
- package/dist/features/admin/components/AdminEmployeeEditorView.js +1 -3
- package/dist/features/admin/components/AdminNewsletterView.js +1 -1
- package/dist/features/admin/components/AdminOrdersView.js +9 -2
- package/dist/features/admin/components/AdminPayoutsView.js +1 -1
- package/dist/features/admin/components/AdminPrizeDrawsView.js +11 -0
- package/dist/features/admin/components/AdminProductEditorView.d.ts +10 -1
- package/dist/features/admin/components/AdminProductEditorView.js +24 -37
- package/dist/features/admin/components/AdminProductsView.js +10 -3
- package/dist/features/admin/components/AdminScammersView.js +1 -1
- package/dist/features/admin/components/AdminSectionsView.js +21 -5
- package/dist/features/admin/components/AdminSessionsView.js +1 -1
- package/dist/features/admin/components/AdminSublistingCategoriesView.js +22 -1
- package/dist/features/admin/components/AdminTeamView.js +1 -1
- package/dist/features/admin/components/AdminTesterChecklistItemEditorView.js +0 -1
- package/dist/features/admin/components/AdminUsersView.js +1 -1
- package/dist/features/admin/components/DataListingView.d.ts +2 -1
- package/dist/features/admin/components/DataListingView.js +9 -4
- package/dist/features/admin/components/analytics/AdminPageViewsReportView.js +0 -2
- package/dist/features/admin/hooks/useAdminListing.d.ts +1 -1
- package/dist/features/admin/repository/site-settings.repository.js +8 -3
- package/dist/features/admin/schemas/firestore.d.ts +62 -1
- package/dist/features/admin/schemas/firestore.js +32 -0
- package/dist/features/admin/types/index.d.ts +1 -1
- package/dist/features/auctions/actions/bid-actions.d.ts +2 -2
- package/dist/features/auctions/actions/bid-actions.js +16 -4
- package/dist/features/auctions/api/route.js +1 -1
- package/dist/features/auctions/components/AuctionBottomActions.js +4 -0
- package/dist/features/auctions/repository/bid.repository.d.ts +46 -4
- package/dist/features/auctions/repository/bid.repository.js +114 -13
- package/dist/features/auctions/schemas/firestore.d.ts +24 -4
- package/dist/features/auctions/schemas/firestore.js +1 -0
- package/dist/features/auth/actions/profile-actions.js +30 -4
- package/dist/features/auth/components/index.d.ts +0 -1
- package/dist/features/auth/components/index.js +0 -1
- package/dist/features/auth/repository/session.repository.d.ts +17 -3
- package/dist/features/auth/repository/session.repository.js +46 -5
- package/dist/features/auth/repository/token.repository.d.ts +27 -4
- package/dist/features/auth/repository/token.repository.js +65 -11
- package/dist/features/auth/repository/user.repository.d.ts +33 -7
- package/dist/features/auth/repository/user.repository.js +100 -15
- package/dist/features/auth/schemas/firestore.d.ts +63 -12
- package/dist/features/auth/schemas/firestore.js +11 -0
- package/dist/features/before-after/api/route.js +1 -1
- package/dist/features/blog/components/BlogListView.js +16 -3
- package/dist/features/blog/components/BlogPostView.js +1 -1
- package/dist/features/blog/schemas/index.d.ts +2 -2
- package/dist/features/cart/api/route.js +1 -1
- package/dist/features/catalogue/repository/catalogue.repository.d.ts +7 -7
- package/dist/features/catalogue/repository/catalogue.repository.js +28 -10
- package/dist/features/catalogue/schemas/firestore.d.ts +11 -0
- package/dist/features/categories/api/route.js +10 -10
- package/dist/features/categories/components/CategoryDetailPageView.js +35 -5
- package/dist/features/categories/components/CategorySelectorCreate.js +0 -1
- package/dist/features/categories/components/index.d.ts +0 -2
- package/dist/features/categories/components/index.js +0 -1
- package/dist/features/categories/repository/categories.repository.d.ts +1 -0
- package/dist/features/categories/repository/categories.repository.js +31 -1
- package/dist/features/categories/schemas/index.d.ts +2 -2
- package/dist/features/categories/utils/taxonomy-visual.d.ts +21 -0
- package/dist/features/categories/utils/taxonomy-visual.js +58 -0
- package/dist/features/checkout/actions/checkout-value-otp-actions.js +8 -1
- package/dist/features/collections/api/[slug]/route.js +3 -3
- package/dist/features/collections/api/route.js +1 -1
- package/dist/features/consultation/api/route.js +1 -1
- package/dist/features/consultation/repository/consultations.repository.js +1 -1
- package/dist/features/consultation/types/index.d.ts +1 -1
- package/dist/features/contact/components/ContactForm.js +1 -3
- package/dist/features/corporate/api/route.js +1 -1
- package/dist/features/corporate/repository/corporate.repository.js +1 -1
- package/dist/features/corporate/types/index.d.ts +1 -1
- package/dist/features/cron/jobs/auction-expiry.job.js +1 -1
- package/dist/features/cron/jobs/preorder-reminder.job.js +1 -1
- package/dist/features/events/actions/event-actions.d.ts +14 -0
- package/dist/features/events/actions/event-actions.js +82 -3
- package/dist/features/events/api/[id]/route.js +2 -2
- package/dist/features/events/components/AdminEventEditorView.js +22 -3
- package/dist/features/events/components/AdminEventsView.js +32 -8
- package/dist/features/events/components/EventRafflesSection.d.ts +34 -1
- package/dist/features/events/components/EventRafflesSection.js +52 -3
- package/dist/features/events/components/SpinWheelView.d.ts +2 -2
- package/dist/features/events/components/SpinWheelView.js +41 -4
- package/dist/features/events/repository/event-entry.repository.d.ts +14 -2
- package/dist/features/events/repository/event-entry.repository.js +41 -7
- package/dist/features/events/schemas/firestore.d.ts +17 -4
- package/dist/features/events/types/index.d.ts +37 -0
- package/dist/features/faq/repository/faqs.repository.js +1 -1
- package/dist/features/faq/schemas/index.d.ts +5 -2
- package/dist/features/faq/schemas/index.js +6 -0
- package/dist/features/faq/types/index.d.ts +0 -1
- package/dist/features/grouped/components/GroupedListingEditorView.js +17 -2
- package/dist/features/homepage/api/carousel/[id]/route.js +1 -1
- package/dist/features/homepage/api/carousel/route.js +4 -4
- package/dist/features/homepage/api/route.js +2 -2
- package/dist/features/homepage/api/sections/route.js +1 -1
- package/dist/features/homepage/components/AnnouncementBar.d.ts +1 -9
- package/dist/features/homepage/components/AnnouncementBar.js +13 -19
- package/dist/features/homepage/components/MarketplaceHomepageView.js +6 -1
- package/dist/features/homepage/components/index.d.ts +0 -2
- package/dist/features/homepage/components/index.js +0 -1
- package/dist/features/homepage/repository/homepage.repository.js +1 -1
- package/dist/features/homepage/schemas/firestore.d.ts +6 -0
- package/dist/features/homepage/schemas/index.d.ts +10 -10
- package/dist/features/layout/AppLayoutShell.d.ts +11 -0
- package/dist/features/layout/AppLayoutShell.js +64 -12
- package/dist/features/layout/BottomActionsContext.d.ts +16 -0
- package/dist/features/layout/BottomActionsContext.js +5 -0
- package/dist/features/layout/BottomChrome.js +48 -9
- package/dist/features/layout/BottomNavbar.d.ts +14 -0
- package/dist/features/layout/BottomNavbar.js +43 -3
- package/dist/features/layout/MainNavbar.d.ts +11 -0
- package/dist/features/layout/NavbarLayout.d.ts +3 -0
- package/dist/features/layout/NavbarLayout.js +88 -11
- package/dist/features/layout/SideActionDock.d.ts +1 -0
- package/dist/features/layout/SideActionDock.js +219 -0
- package/dist/features/layout/TitleBarLayout.js +1 -1
- package/dist/features/layout/cta-anchor.d.ts +31 -0
- package/dist/features/layout/cta-anchor.js +31 -0
- package/dist/features/layout/hooks/useBottomActions.d.ts +7 -0
- package/dist/features/layout/hooks/useBottomActions.js +6 -1
- package/dist/features/layout/index.d.ts +9 -1
- package/dist/features/layout/index.js +9 -1
- package/dist/features/layout/useCtaReveal.d.ts +24 -0
- package/dist/features/layout/useCtaReveal.js +82 -0
- package/dist/features/layout/useHoldToOpen.d.ts +41 -0
- package/dist/features/layout/useHoldToOpen.js +84 -0
- package/dist/features/lottery/repository/lottery-entry.repository.d.ts +18 -3
- package/dist/features/lottery/repository/lottery-entry.repository.js +48 -6
- package/dist/features/lottery/schemas/firestore.d.ts +33 -5
- package/dist/features/loyalty/api/balance/route.js +1 -1
- package/dist/features/loyalty/api/history/route.js +1 -1
- package/dist/features/media/MediaImage.js +0 -1
- package/dist/features/media/MediaPickerModal.js +7 -1
- package/dist/features/media/modals/ImageEditor.js +5 -1
- package/dist/features/media/modals/VideoThumbnailSelector.js +17 -1
- package/dist/features/media/repository/media-assets.repository.d.ts +19 -0
- package/dist/features/media/upload/CameraCapture.js +16 -1
- package/dist/features/media/upload/ImageUpload.js +42 -4
- package/dist/features/media/upload/MediaUploadField.js +69 -13
- package/dist/features/media/upload/downscale-image.d.ts +56 -0
- package/dist/features/media/upload/downscale-image.js +150 -0
- package/dist/features/messages/components/ConversationThreadView.js +45 -2
- package/dist/features/messages/components/MessageSellerButton.d.ts +15 -1
- package/dist/features/messages/components/MessageSellerButton.js +10 -2
- package/dist/features/messages/schemas/firestore.d.ts +15 -0
- package/dist/features/orders/hooks/useOrders.js +4 -2
- package/dist/features/orders/repository/orders.repository.d.ts +15 -4
- package/dist/features/orders/repository/orders.repository.js +52 -20
- package/dist/features/orders/schemas/firestore.d.ts +15 -4
- package/dist/features/orders/schemas/index.d.ts +8 -8
- package/dist/features/orders/types/index.d.ts +2 -2
- package/dist/features/payments/repository/payments.repository.js +2 -2
- package/dist/features/payments/repository/payout.repository.d.ts +23 -6
- package/dist/features/payments/repository/payout.repository.js +63 -23
- package/dist/features/payments/repository/saved-payment-methods.repository.d.ts +17 -6
- package/dist/features/payments/repository/saved-payment-methods.repository.js +59 -11
- package/dist/features/payments/schemas/firestore.d.ts +14 -3
- package/dist/features/payments/schemas/saved-methods-firestore.d.ts +12 -1
- package/dist/features/pre-orders/api/[slug]/route.js +1 -1
- package/dist/features/pre-orders/api/admin/route.js +1 -1
- package/dist/features/pre-orders/api/route.js +1 -1
- package/dist/features/pre-orders/repository/pre-orders.repository.d.ts +3 -3
- package/dist/features/pre-orders/repository/pre-orders.repository.js +6 -6
- package/dist/features/products/api/[id]/route.js +1 -1
- package/dist/features/products/components/ListingBottomActions.js +4 -0
- package/dist/features/products/components/ProductDetailPageView.js +2 -1
- package/dist/features/products/components/ProductGalleryClient.js +2 -2
- package/dist/features/products/components/ProductGrid.js +12 -1
- package/dist/features/products/components/index.d.ts +0 -2
- package/dist/features/products/components/index.js +0 -1
- package/dist/features/products/config/listing-type-listing-config.d.ts +0 -3
- package/dist/features/products/config/listing-type-listing-config.js +27 -2
- package/dist/features/products/constants/listing-tabs.d.ts +9 -0
- package/dist/features/products/constants/listing-tabs.js +3 -2
- package/dist/features/products/hooks/useProducts.js +2 -2
- package/dist/features/products/repository/products.repository.js +13 -1
- package/dist/features/products/schemas/index.d.ts +2 -2
- package/dist/features/products/types/index.d.ts +1 -1
- package/dist/features/promotions/api/route.js +1 -1
- package/dist/features/reviews/actions/review-actions.d.ts +6 -6
- package/dist/features/reviews/actions/review-actions.js +22 -8
- package/dist/features/reviews/components/ReviewDetailPageView.js +13 -1
- package/dist/features/reviews/components/ReviewsIndexPageView.js +21 -4
- package/dist/features/reviews/repository/reviews.repository.d.ts +19 -7
- package/dist/features/reviews/repository/reviews.repository.js +63 -12
- package/dist/features/reviews/schemas/firestore.d.ts +13 -2
- package/dist/features/reviews/schemas/index.d.ts +2 -2
- package/dist/features/scams/actions/scam-actions.js +16 -4
- package/dist/features/search/components/SearchResultsPageView.js +2 -1
- package/dist/features/search/hooks/useSearchIndex.d.ts +34 -0
- package/dist/features/search/hooks/useSearchIndex.js +172 -0
- package/dist/features/search/repository/search.repository.js +2 -2
- package/dist/features/seller/actions/offer-actions.d.ts +5 -5
- package/dist/features/seller/actions/offer-actions.js +38 -8
- package/dist/features/seller/actions/seller-actions.js +34 -7
- package/dist/features/seller/api/coupons/route.js +1 -1
- package/dist/features/seller/api/products/route.js +1 -1
- package/dist/features/seller/api/store/route.js +1 -1
- package/dist/features/seller/components/SellerBidsView.js +1 -1
- package/dist/features/seller/components/SellerCouponsView.js +1 -1
- package/dist/features/seller/components/SellerListingTypeView.js +9 -1
- package/dist/features/seller/components/SellerOrdersView.js +1 -1
- package/dist/features/seller/components/SellerPayoutSettingsView.js +0 -1
- package/dist/features/seller/components/SellerPayoutsView.js +1 -1
- package/dist/features/seller/components/SellerProductShell.js +0 -1
- package/dist/features/seller/components/SellerProductsView.js +1 -1
- package/dist/features/seller/components/SellerShippingView.js +0 -1
- package/dist/features/seller/components/SellerStorefrontView.js +0 -1
- package/dist/features/seller/components/index.d.ts +0 -4
- package/dist/features/seller/components/index.js +0 -2
- package/dist/features/seller/repository/offer.repository.d.ts +15 -3
- package/dist/features/seller/repository/offer.repository.js +43 -7
- package/dist/features/seller/schemas/firestore.d.ts +14 -3
- package/dist/features/seller/schemas/index.d.ts +4 -4
- package/dist/features/seller/schemas/order-forms.d.ts +39 -0
- package/dist/features/seller/schemas/order-forms.js +37 -0
- package/dist/features/shell/FormShell.js +6 -2
- package/dist/features/shell/QuickFormDrawer.js +15 -1
- package/dist/features/shipments/components/AdminShipmentEditorView.js +0 -1
- package/dist/features/shipments/components/AdminShipmentsView.js +1 -1
- package/dist/features/sticker-trace/components/StickerCommitPanel.d.ts +30 -0
- package/dist/features/sticker-trace/components/StickerCommitPanel.js +93 -0
- package/dist/features/sticker-trace/components/StickerPrintPanel.d.ts +33 -0
- package/dist/features/sticker-trace/components/StickerPrintPanel.js +104 -0
- package/dist/features/sticker-trace/components/StickerRetryPanel.d.ts +20 -0
- package/dist/features/sticker-trace/components/StickerRetryPanel.js +128 -0
- package/dist/features/sticker-trace/components/StickerRunHistoryPanel.d.ts +45 -0
- package/dist/features/sticker-trace/components/StickerRunHistoryPanel.js +84 -0
- package/dist/features/sticker-trace/components/StickerTraceStudio.d.ts +27 -0
- package/dist/features/sticker-trace/components/StickerTraceStudio.js +171 -0
- package/dist/features/sticker-trace/constants/help-content.d.ts +23 -0
- package/dist/features/sticker-trace/constants/help-content.js +172 -0
- package/dist/features/sticker-trace/hooks/useLiveTrace.d.ts +27 -0
- package/dist/features/sticker-trace/hooks/useLiveTrace.js +160 -0
- package/dist/features/sticker-trace/hooks/useStickerTraceProgress.d.ts +22 -0
- package/dist/features/sticker-trace/hooks/useStickerTraceProgress.js +106 -0
- package/dist/features/sticker-trace/repository/sticker-sheets.repository.d.ts +113 -0
- package/dist/features/sticker-trace/repository/sticker-sheets.repository.js +146 -0
- package/dist/features/sticker-trace/repository/sticker-trace-runs.repository.d.ts +132 -0
- package/dist/features/sticker-trace/repository/sticker-trace-runs.repository.js +174 -0
- package/dist/features/sticker-trace/schemas/firestore.d.ts +248 -0
- package/dist/features/sticker-trace/schemas/firestore.js +79 -0
- package/dist/features/sticker-trace/server.d.ts +8 -0
- package/dist/features/sticker-trace/server.js +51 -0
- package/dist/features/stores/actions/store-query-actions.d.ts +2 -2
- package/dist/features/stores/actions/store-query-actions.js +7 -2
- package/dist/features/stores/api/[storeSlug]/auctions/route.js +3 -3
- package/dist/features/stores/api/[storeSlug]/products/route.js +3 -3
- package/dist/features/stores/api/[storeSlug]/reviews/route.js +1 -1
- package/dist/features/stores/api/[storeSlug]/route.js +1 -1
- package/dist/features/stores/components/StoreNavTabs.js +17 -2
- package/dist/features/stores/manifest.js +8 -4
- package/dist/features/support/repository/support.repository.d.ts +14 -3
- package/dist/features/support/repository/support.repository.js +93 -13
- package/dist/features/support/schemas/firestore.d.ts +16 -5
- package/dist/features/tester/seed-data/authored/admin__events-raffles-spin.js +61 -19
- package/dist/features/tester/seed-data/authored/buying__browsing-search.js +19 -3
- package/dist/features/tester/seed-data/authored/content-discovery__authenticity-checker.d.ts +2 -0
- package/dist/features/tester/seed-data/authored/content-discovery__authenticity-checker.js +243 -0
- package/dist/features/tester/seed-data/authored/content-discovery__events.js +36 -10
- package/dist/features/tester/seed-data/authored/content-discovery__overflowing-pill-rows.d.ts +2 -0
- package/dist/features/tester/seed-data/authored/content-discovery__overflowing-pill-rows.js +209 -0
- package/dist/features/tester/seed-data/authored/design-ux__header-brand-mark-centring.d.ts +2 -0
- package/dist/features/tester/seed-data/authored/design-ux__header-brand-mark-centring.js +90 -0
- package/dist/features/tester/seed-data/authored/index.js +8 -0
- package/dist/features/tester/seed-data/authored/selling__media-limits.js +19 -17
- package/dist/features/tester/seed-data/authored/selling__product-upload-details.js +10 -5
- package/dist/features/tester/seed-data/authored/tools__sticker-tracer.d.ts +2 -0
- package/dist/features/tester/seed-data/authored/tools__sticker-tracer.js +283 -0
- package/dist/features/tester/seed-data/tester-checklist-seed-data.js +192 -22
- package/dist/index.d.ts +10 -23
- package/dist/index.js +27 -19
- package/dist/next/api/routeHandler.js +9 -0
- package/dist/next/routing/require-record.d.ts +13 -0
- package/dist/next/routing/require-record.js +62 -0
- package/dist/next/routing/route-map.d.ts +4 -4
- package/dist/next/routing/route-map.js +25 -3
- package/dist/providers/db-firebase/base.d.ts +4 -2
- package/dist/providers/db-firebase/base.js +21 -5
- package/dist/providers/db-firebase/base.repository.d.ts +11 -9
- package/dist/providers/db-firebase/base.repository.js +19 -0
- package/dist/providers/db-firebase/rtdb-paths.d.ts +12 -0
- package/dist/providers/db-firebase/rtdb-paths.js +12 -0
- package/dist/react/ErrorBoundary.js +6 -1
- package/dist/react/hooks/realtime-event-constants.d.ts +1 -0
- package/dist/react/hooks/realtime-event-constants.js +8 -0
- package/dist/react/hooks/useEntityDelete.js +5 -1
- package/dist/react/hooks/useMessage.js +5 -1
- package/dist/repositories/index.d.ts +2 -2
- package/dist/repositories/index.js +6 -1
- package/dist/schemas/registry.d.ts +13 -20
- package/dist/schemas/registry.js +31 -14
- package/dist/schemas/webhooks/google-oauth.d.ts +2 -2
- package/dist/security/encrypted.d.ts +117 -0
- package/dist/security/encrypted.js +100 -0
- package/dist/security/index.d.ts +5 -2
- package/dist/security/index.js +16 -2
- package/dist/security/pii-accessors.d.ts +71 -0
- package/dist/security/pii-accessors.js +150 -0
- package/dist/security/pii-encrypt.d.ts +0 -8
- package/dist/security/pii-encrypt.js +22 -15
- package/dist/security/pii-mask.d.ts +18 -0
- package/dist/security/pii-mask.js +27 -0
- package/dist/seed/_helpers/search-txt-wrappers.d.ts +6 -6
- package/dist/seed/_helpers/search-txt-wrappers.js +22 -0
- package/dist/seed/addresses-seed-data.d.ts +2 -2
- package/dist/seed/authenticity-knowledge-seed-data.d.ts +34 -0
- package/dist/seed/authenticity-knowledge-seed-data.js +1277 -0
- package/dist/seed/bids-seed-data.d.ts +2 -2
- package/dist/seed/bids-seed-data.js +23 -2
- package/dist/seed/events-seed-data.d.ts +2 -2
- package/dist/seed/events-seed-data.js +5 -0
- package/dist/seed/faq-seed-data.js +175 -5
- package/dist/seed/homepage-sections-seed-data.js +39 -23
- package/dist/seed/index.d.ts +1 -0
- package/dist/seed/index.js +1 -0
- package/dist/seed/lottery-entries-seed-data.d.ts +2 -2
- package/dist/seed/offers-seed-data.d.ts +2 -2
- package/dist/seed/offers-seed-data.js +1 -1
- package/dist/seed/orders-seed-data.d.ts +2 -2
- package/dist/seed/payouts-seed-data.d.ts +2 -2
- package/dist/seed/payouts-seed-data.js +1 -1
- package/dist/seed/reviews-seed-data.d.ts +1 -2
- package/dist/seed/seed-purpose.js +7 -0
- package/dist/seed/sessions-seed-data.d.ts +2 -2
- package/dist/seed/sessions-seed-data.js +5 -0
- package/dist/seed/site-settings-seed-data.js +1 -1
- package/dist/seed/support-tickets-seed-data.d.ts +2 -2
- package/dist/seed/support-tickets-seed-data.js +1 -1
- package/dist/seed/users-seed-data.d.ts +2 -2
- package/dist/seed/users-seed-data.js +1 -1
- package/dist/seo/json-ld.js +5 -1
- package/dist/server.d.ts +18 -3
- package/dist/server.js +59 -3
- package/dist/styles.css +237 -1
- package/dist/tailwind-utilities.css +1 -1
- package/dist/ui/components/Button.js +7 -1
- package/dist/ui/components/FilterChipGroup.d.ts +11 -0
- package/dist/ui/components/FilterChipGroup.js +1 -1
- package/dist/ui/components/ImageGallery.js +6 -1
- package/dist/ui/components/ListingLayout.js +14 -8
- package/dist/ui/components/OverflowRow.d.ts +92 -0
- package/dist/ui/components/OverflowRow.js +203 -0
- package/dist/ui/components/OverflowRow.style.css +235 -0
- package/dist/ui/components/RecordDetailModal.js +14 -1
- package/dist/ui/components/RowActionMenu.js +5 -1
- package/dist/ui/components/SideDrawer.js +5 -1
- package/dist/ui/components/SideModal.js +9 -1
- package/dist/ui/components/TabBarShell.d.ts +12 -1
- package/dist/ui/components/TabBarShell.js +3 -2
- package/dist/ui/components/Tabs.js +36 -24
- package/dist/ui/components/Toast.d.ts +3 -24
- package/dist/ui/components/Toast.js +2 -19
- package/dist/ui/components/TopBannerPortal.d.ts +15 -0
- package/dist/ui/components/TopBannerPortal.js +19 -0
- package/dist/ui/components/UnsavedChangesModal.js +5 -1
- package/dist/ui/components/index.style.css +1 -0
- package/dist/ui/components/row-collapse.d.ts +15 -0
- package/dist/ui/components/row-collapse.js +127 -0
- package/dist/ui/components/toast-context.d.ts +63 -0
- package/dist/ui/components/toast-context.js +48 -0
- package/dist/ui/components/top-banner-slot.d.ts +37 -0
- package/dist/ui/components/top-banner-slot.js +45 -0
- package/dist/ui/icons/icon-registry.d.ts +6 -0
- package/dist/ui/icons/icon-registry.js +17 -1
- package/dist/ui/index.d.ts +2 -0
- package/dist/ui/index.js +1 -0
- package/dist/utils/array.helper.d.ts +2 -2
- package/dist/utils/array.helper.js +5 -5
- package/dist/utils/id-generators.d.ts +6 -0
- package/dist/utils/id-generators.js +10 -0
- package/dist/utils/media-url.js +0 -2
- package/dist/utils/search-txt-builders.d.ts +28 -4
- package/dist/utils/search-txt-builders.js +41 -1
- package/dist/validation/schemas.d.ts +8 -8
- package/package.json +6 -2
- package/scripts/seed-cli.mjs +3 -0
- package/dist/features/account/components/UserAddressesView.d.ts +0 -13
- package/dist/features/account/components/UserAddressesView.js +0 -5
- package/dist/features/account/components/UserNotificationsView.d.ts +0 -15
- package/dist/features/account/components/UserNotificationsView.js +0 -12
- package/dist/features/account/components/UserSettingsView.d.ts +0 -16
- package/dist/features/account/components/UserSettingsView.js +0 -13
- package/dist/features/account/components/UserSupportView.d.ts +0 -3
- package/dist/features/account/components/UserSupportView.js +0 -166
- package/dist/features/admin/components/DemoSeedView.d.ts +0 -11
- package/dist/features/admin/components/DemoSeedView.js +0 -5
- package/dist/features/auth/components/AuthStatusPanel.d.ts +0 -10
- package/dist/features/auth/components/AuthStatusPanel.js +0 -22
- package/dist/features/categories/components/CategoryProductsView.d.ts +0 -45
- package/dist/features/categories/components/CategoryProductsView.js +0 -21
- package/dist/features/homepage/components/HowItWorksInfoView.d.ts +0 -36
- package/dist/features/homepage/components/HowItWorksInfoView.js +0 -10
- package/dist/features/layout/BottomActions.d.ts +0 -1
- package/dist/features/layout/BottomActions.js +0 -311
- package/dist/features/products/components/ProductsView.d.ts +0 -6
- package/dist/features/products/components/ProductsView.js +0 -5
- package/dist/features/seller/components/SellerStoreView.d.ts +0 -8
- package/dist/features/seller/components/SellerStoreView.js +0 -8
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { PartGeometry, SheetCluster } from "../types";
|
|
2
|
+
/**
|
|
3
|
+
* Group parts into physical sheets.
|
|
4
|
+
*
|
|
5
|
+
* Single-link (transitive) on purpose: stickers on one sheet form a chain of
|
|
6
|
+
* near neighbours rather than a tight blob, so requiring every pair in a
|
|
7
|
+
* cluster to be close would split one sheet into several. The risk of
|
|
8
|
+
* single-link — a chain of intermediate items merging two genuine groups —
|
|
9
|
+
* does not arise here, because the gap between sheets is physical empty space
|
|
10
|
+
* with nothing in it.
|
|
11
|
+
*
|
|
12
|
+
* 🛑 With no DPI there is no millimetre, so clustering is SKIPPED and every
|
|
13
|
+
* part lands in group 0. A pixel threshold would mean something different on
|
|
14
|
+
* every scan, and a wrong split reads as a fact about the sheet rather than as
|
|
15
|
+
* a missing measurement.
|
|
16
|
+
*/
|
|
17
|
+
export declare function clusterParts(parts: readonly PartGeometry[], pxPerMm: number | null, gapMm: number): {
|
|
18
|
+
clusters: SheetCluster[];
|
|
19
|
+
assigned: PartGeometry[];
|
|
20
|
+
};
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* WHY: One scan can hold several physical sheets — the 4948x6955 reference scan
|
|
3
|
+
* does. Presenting sixty parts as one flat list loses the fact that they
|
|
4
|
+
* came off four different sheets, which is exactly what someone cutting
|
|
5
|
+
* them needs to know.
|
|
6
|
+
* WHAT: Single-link clustering of part bounding boxes by gap distance.
|
|
7
|
+
*
|
|
8
|
+
* Gap, not centre distance. Two large stickers can have centres far apart while
|
|
9
|
+
* touching, and two small ones can have close centres while sitting on
|
|
10
|
+
* different sheets. The physical question is "how much bare space is between
|
|
11
|
+
* these", and that is the gap between their boxes.
|
|
12
|
+
*
|
|
13
|
+
* EXPORTS: clusterParts
|
|
14
|
+
*
|
|
15
|
+
* @tag domain:sticker-trace
|
|
16
|
+
* @tag layer:shared
|
|
17
|
+
* @tag pattern:none
|
|
18
|
+
* @tag access:isomorphic
|
|
19
|
+
* @tag consumers:index
|
|
20
|
+
* @tag sideEffects:none
|
|
21
|
+
*/
|
|
22
|
+
/** Axis-aligned gap; 0 when the boxes overlap or touch. */
|
|
23
|
+
function boxGap(a, b) {
|
|
24
|
+
const dx = Math.max(0, Math.max(a.x - (b.x + b.width), b.x - (a.x + a.width)));
|
|
25
|
+
const dy = Math.max(0, Math.max(a.y - (b.y + b.height), b.y - (a.y + a.height)));
|
|
26
|
+
return Math.hypot(dx, dy);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Group parts into physical sheets.
|
|
30
|
+
*
|
|
31
|
+
* Single-link (transitive) on purpose: stickers on one sheet form a chain of
|
|
32
|
+
* near neighbours rather than a tight blob, so requiring every pair in a
|
|
33
|
+
* cluster to be close would split one sheet into several. The risk of
|
|
34
|
+
* single-link — a chain of intermediate items merging two genuine groups —
|
|
35
|
+
* does not arise here, because the gap between sheets is physical empty space
|
|
36
|
+
* with nothing in it.
|
|
37
|
+
*
|
|
38
|
+
* 🛑 With no DPI there is no millimetre, so clustering is SKIPPED and every
|
|
39
|
+
* part lands in group 0. A pixel threshold would mean something different on
|
|
40
|
+
* every scan, and a wrong split reads as a fact about the sheet rather than as
|
|
41
|
+
* a missing measurement.
|
|
42
|
+
*/
|
|
43
|
+
export function clusterParts(parts, pxPerMm, gapMm) {
|
|
44
|
+
if (parts.length === 0) {
|
|
45
|
+
return { clusters: [], assigned: [] };
|
|
46
|
+
}
|
|
47
|
+
if (!pxPerMm) {
|
|
48
|
+
return {
|
|
49
|
+
clusters: [
|
|
50
|
+
{
|
|
51
|
+
index: 0,
|
|
52
|
+
bboxPx: unionBox(parts.map((p) => p.bboxPx)),
|
|
53
|
+
partOrdinals: parts.map((p) => p.ordinal),
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
assigned: parts.map((p) => ({ ...p, groupIndex: 0 })),
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
const threshold = gapMm * pxPerMm;
|
|
60
|
+
const n = parts.length;
|
|
61
|
+
const parent = new Int32Array(n);
|
|
62
|
+
for (let i = 0; i < n; i++)
|
|
63
|
+
parent[i] = i;
|
|
64
|
+
const find = (x) => {
|
|
65
|
+
let r = x;
|
|
66
|
+
while (parent[r] !== r) {
|
|
67
|
+
parent[r] = parent[parent[r]];
|
|
68
|
+
r = parent[r];
|
|
69
|
+
}
|
|
70
|
+
return r;
|
|
71
|
+
};
|
|
72
|
+
for (let i = 0; i < n; i++) {
|
|
73
|
+
for (let j = i + 1; j < n; j++) {
|
|
74
|
+
if (boxGap(parts[i].bboxPx, parts[j].bboxPx) <= threshold) {
|
|
75
|
+
const a = find(i);
|
|
76
|
+
const b = find(j);
|
|
77
|
+
if (a !== b)
|
|
78
|
+
parent[b] = a;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
const groupOf = new Map();
|
|
83
|
+
const members = new Map();
|
|
84
|
+
for (let i = 0; i < n; i++) {
|
|
85
|
+
const root = find(i);
|
|
86
|
+
let g = groupOf.get(root);
|
|
87
|
+
if (g === undefined) {
|
|
88
|
+
g = groupOf.size;
|
|
89
|
+
groupOf.set(root, g);
|
|
90
|
+
members.set(g, []);
|
|
91
|
+
}
|
|
92
|
+
members.get(g).push(i);
|
|
93
|
+
}
|
|
94
|
+
// Order groups top-to-bottom, then left-to-right — reading order, so "sheet 1"
|
|
95
|
+
// is the one a human would call the first.
|
|
96
|
+
const order = [...members.entries()].sort((a, b) => {
|
|
97
|
+
const ba = unionBox(a[1].map((i) => parts[i].bboxPx));
|
|
98
|
+
const bb = unionBox(b[1].map((i) => parts[i].bboxPx));
|
|
99
|
+
return ba.y - bb.y || ba.x - bb.x;
|
|
100
|
+
});
|
|
101
|
+
const clusters = [];
|
|
102
|
+
const assigned = [];
|
|
103
|
+
order.forEach(([, idxs], index) => {
|
|
104
|
+
const boxes = idxs.map((i) => parts[i].bboxPx);
|
|
105
|
+
clusters.push({
|
|
106
|
+
index,
|
|
107
|
+
bboxPx: unionBox(boxes),
|
|
108
|
+
partOrdinals: idxs.map((i) => parts[i].ordinal),
|
|
109
|
+
});
|
|
110
|
+
for (const i of idxs)
|
|
111
|
+
assigned.push({ ...parts[i], groupIndex: index });
|
|
112
|
+
});
|
|
113
|
+
assigned.sort((a, b) => a.ordinal - b.ordinal);
|
|
114
|
+
return { clusters, assigned };
|
|
115
|
+
}
|
|
116
|
+
function unionBox(boxes) {
|
|
117
|
+
let x0 = Infinity;
|
|
118
|
+
let y0 = Infinity;
|
|
119
|
+
let x1 = -Infinity;
|
|
120
|
+
let y1 = -Infinity;
|
|
121
|
+
for (const b of boxes) {
|
|
122
|
+
if (b.x < x0)
|
|
123
|
+
x0 = b.x;
|
|
124
|
+
if (b.y < y0)
|
|
125
|
+
y0 = b.y;
|
|
126
|
+
if (b.x + b.width > x1)
|
|
127
|
+
x1 = b.x + b.width;
|
|
128
|
+
if (b.y + b.height > y1)
|
|
129
|
+
y1 = b.y + b.height;
|
|
130
|
+
}
|
|
131
|
+
return { x: x0, y: y0, width: x1 - x0, height: y1 - y0 };
|
|
132
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { DecodedRaster } from "../types";
|
|
2
|
+
/**
|
|
3
|
+
* Filter a barrier to the pixels whose two sides are the same material.
|
|
4
|
+
*
|
|
5
|
+
* `probe` must clear the line's own width — it is sampled from the UNFILTERED
|
|
6
|
+
* raster, so landing inside the groove reads the shadow rather than the
|
|
7
|
+
* material and every cut would look like an edge. 4px is comfortable for a
|
|
8
|
+
* 1-3px kiss cut at the working resolution.
|
|
9
|
+
*
|
|
10
|
+
* `tolerance` is a weighted colour distance. Generous on purpose: the two
|
|
11
|
+
* sides of a real groove differ slightly from lighting and scanner noise, and
|
|
12
|
+
* a tight tolerance rejects genuine cuts on any gradient — which is most of
|
|
13
|
+
* this corpus.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* 🛑 This returns a per-pixel SCORE, and must not be used to filter the
|
|
17
|
+
* barrier directly. That was tried and measured: hard-dropping every barrier
|
|
18
|
+
* pixel whose sides differ breaks a cut loop wherever it happens to cross a
|
|
19
|
+
* colour boundary, the complement stops being enclosed, and the whole sheet
|
|
20
|
+
* collapses into one region — 0 parts on four of five art scans.
|
|
21
|
+
*
|
|
22
|
+
* The score is instead fed to the region merge as its boundary strength, where
|
|
23
|
+
* a broken run costs a little evidence rather than the entire outline.
|
|
24
|
+
*/
|
|
25
|
+
export declare function sameMaterialScore(raster: DecodedRaster, barrier: Uint8Array, luma: Float32Array, tolerance: number, probe?: number): {
|
|
26
|
+
score: Float32Array;
|
|
27
|
+
meanScore: number;
|
|
28
|
+
};
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* WHY: Two measured failures pointed at the same wrong assumption.
|
|
3
|
+
*
|
|
4
|
+
* (1) On art sheets a threshold sweep never converged — 209 parts at 31%
|
|
5
|
+
* barrier coverage, still 36 at 1.0%, monotonic with no minimum.
|
|
6
|
+
* (2) The colour-quantisation assist made torch-pegases WORSE (209 -> 257
|
|
7
|
+
* at default, 182 vs 36 at high threshold).
|
|
8
|
+
*
|
|
9
|
+
* Both follow from treating AMPLITUDE as the discriminator. It is not.
|
|
10
|
+
* The cut line on torch-pegases measured +22 against +-1 noise — moderate
|
|
11
|
+
* — while the sheet's own lettering and logos are far higher contrast. So
|
|
12
|
+
* raising the bar removes cuts and keeps artwork, which is exactly
|
|
13
|
+
* backwards, and a colour-boundary detector marks precisely the artwork.
|
|
14
|
+
*
|
|
15
|
+
* The physics gives the real discriminator. A kiss cut is a groove
|
|
16
|
+
* pressed into ONE piece of material: the scanner sees a shadow/highlight
|
|
17
|
+
* doublet, and then the colour RETURNS to what it was. An artwork edge
|
|
18
|
+
* separates two different colours and does not return.
|
|
19
|
+
* WHAT: Keep a barrier pixel only when the material either side of it matches.
|
|
20
|
+
*
|
|
21
|
+
* This also inverts the quantisation channel's role on art sheets: a colour
|
|
22
|
+
* boundary is EVIDENCE AGAINST a cut, not for one. The plan's "fusion must
|
|
23
|
+
* help, never hurt" check is what surfaced that, by running the corpus with
|
|
24
|
+
* the channel off and on rather than assuming a second signal can only add.
|
|
25
|
+
*
|
|
26
|
+
* EXPORTS: keepSameMaterialBarrier
|
|
27
|
+
*
|
|
28
|
+
* @tag domain:sticker-trace
|
|
29
|
+
* @tag layer:shared
|
|
30
|
+
* @tag pattern:none
|
|
31
|
+
* @tag access:isomorphic
|
|
32
|
+
* @tag consumers:segment
|
|
33
|
+
* @tag sideEffects:none
|
|
34
|
+
*/
|
|
35
|
+
function colourDistance(d, p, q) {
|
|
36
|
+
const dr = d[p] - d[q];
|
|
37
|
+
const dg = d[p + 1] - d[q + 1];
|
|
38
|
+
const db = d[p + 2] - d[q + 2];
|
|
39
|
+
return Math.sqrt(2 * dr * dr + 4 * dg * dg + 3 * db * db);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Filter a barrier to the pixels whose two sides are the same material.
|
|
43
|
+
*
|
|
44
|
+
* `probe` must clear the line's own width — it is sampled from the UNFILTERED
|
|
45
|
+
* raster, so landing inside the groove reads the shadow rather than the
|
|
46
|
+
* material and every cut would look like an edge. 4px is comfortable for a
|
|
47
|
+
* 1-3px kiss cut at the working resolution.
|
|
48
|
+
*
|
|
49
|
+
* `tolerance` is a weighted colour distance. Generous on purpose: the two
|
|
50
|
+
* sides of a real groove differ slightly from lighting and scanner noise, and
|
|
51
|
+
* a tight tolerance rejects genuine cuts on any gradient — which is most of
|
|
52
|
+
* this corpus.
|
|
53
|
+
*/
|
|
54
|
+
/**
|
|
55
|
+
* 🛑 This returns a per-pixel SCORE, and must not be used to filter the
|
|
56
|
+
* barrier directly. That was tried and measured: hard-dropping every barrier
|
|
57
|
+
* pixel whose sides differ breaks a cut loop wherever it happens to cross a
|
|
58
|
+
* colour boundary, the complement stops being enclosed, and the whole sheet
|
|
59
|
+
* collapses into one region — 0 parts on four of five art scans.
|
|
60
|
+
*
|
|
61
|
+
* The score is instead fed to the region merge as its boundary strength, where
|
|
62
|
+
* a broken run costs a little evidence rather than the entire outline.
|
|
63
|
+
*/
|
|
64
|
+
export function sameMaterialScore(raster, barrier, luma, tolerance, probe = 4) {
|
|
65
|
+
const { width, height, data } = raster;
|
|
66
|
+
const score = new Float32Array(barrier.length);
|
|
67
|
+
let total = 0;
|
|
68
|
+
let n = 0;
|
|
69
|
+
for (let y = 0; y < height; y++) {
|
|
70
|
+
for (let x = 0; x < width; x++) {
|
|
71
|
+
const i = y * width + x;
|
|
72
|
+
if (!barrier[i])
|
|
73
|
+
continue;
|
|
74
|
+
// Local gradient gives the direction ACROSS the line. Central
|
|
75
|
+
// differences on the already-prefiltered luminance, which is smooth
|
|
76
|
+
// enough that a 3-tap estimate is stable.
|
|
77
|
+
const xm = Math.max(0, x - 1);
|
|
78
|
+
const xp = Math.min(width - 1, x + 1);
|
|
79
|
+
const ym = Math.max(0, y - 1);
|
|
80
|
+
const yp = Math.min(height - 1, y + 1);
|
|
81
|
+
const gx = luma[y * width + xp] - luma[y * width + xm];
|
|
82
|
+
const gy = luma[yp * width + x] - luma[ym * width + x];
|
|
83
|
+
const mag = Math.hypot(gx, gy);
|
|
84
|
+
if (mag < 1e-3) {
|
|
85
|
+
// No orientation to sample across — score it neutral-positive rather
|
|
86
|
+
// than guessing. A barrier pixel with no local gradient is usually the
|
|
87
|
+
// interior of a thick linked run, which carries no evidence either way.
|
|
88
|
+
score[i] = 0.5;
|
|
89
|
+
total += 0.5;
|
|
90
|
+
n++;
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
const nx = gx / mag;
|
|
94
|
+
const ny = gy / mag;
|
|
95
|
+
const ax = Math.round(x + nx * probe);
|
|
96
|
+
const ay = Math.round(y + ny * probe);
|
|
97
|
+
const bx = Math.round(x - nx * probe);
|
|
98
|
+
const by = Math.round(y - ny * probe);
|
|
99
|
+
// A probe leaving the raster cannot be judged, so keep rather than drop —
|
|
100
|
+
// stickers that run to the sheet edge are common and must not lose their
|
|
101
|
+
// outline to a sampling artefact.
|
|
102
|
+
if (ax < 0 || ay < 0 || bx < 0 || by < 0 || ax >= width || ay >= height || bx >= width || by >= height) {
|
|
103
|
+
score[i] = 0.5;
|
|
104
|
+
total += 0.5;
|
|
105
|
+
n++;
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
const dist = colourDistance(data, (ay * width + ax) * 4, (by * width + bx) * 4);
|
|
109
|
+
// 1 = the two sides are the same material (a groove), 0 = plainly
|
|
110
|
+
// different colours (an artwork boundary). Continuous rather than a
|
|
111
|
+
// threshold so a boundary that is mostly groove still outweighs one that
|
|
112
|
+
// is mostly print when the two are averaged along a shared edge.
|
|
113
|
+
const v = Math.max(0, 1 - dist / Math.max(1, tolerance));
|
|
114
|
+
score[i] = v;
|
|
115
|
+
total += v;
|
|
116
|
+
n++;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return { score, meanScore: n > 0 ? total / n : 0 };
|
|
120
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface FloodResult {
|
|
2
|
+
/** 1 where the outside reached. */
|
|
3
|
+
readonly outside: Uint8Array;
|
|
4
|
+
/** `!outside` — every pixel the flood could not reach. */
|
|
5
|
+
readonly inside: Uint8Array;
|
|
6
|
+
/** Fraction of the raster the flood reached; a diagnostic. */
|
|
7
|
+
readonly reach: number;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Flood inward from the raster border.
|
|
11
|
+
*
|
|
12
|
+
* Seeded from a BAND rather than the single outermost row: a scan frequently
|
|
13
|
+
* has a dark or ragged outermost pixel line (the scanner lid edge, a crop
|
|
14
|
+
* artefact), and seeding only there can start the flood on pixels that are not
|
|
15
|
+
* background-like at all, so it never leaves the edge and the entire sheet is
|
|
16
|
+
* reported as one sticker.
|
|
17
|
+
*
|
|
18
|
+
* Explicit stack, not recursion — a clean paper scan floods millions of pixels
|
|
19
|
+
* in one connected region.
|
|
20
|
+
*/
|
|
21
|
+
export declare function floodFromBorder(backgroundLike: Uint8Array, barrier: Uint8Array, width: number, height: number, seedBand: number): FloodResult;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* WHY: This is the inversion that fixes the reported bug. The previous tracer
|
|
3
|
+
* asked "is this pixel background-COLOURED?" and so made every region
|
|
4
|
+
* inside a sticker that happened to match the paper transparent. This asks
|
|
5
|
+
* "can the outside REACH this pixel?" — and an enclosed region cannot be
|
|
6
|
+
* reached whatever colour it is.
|
|
7
|
+
* WHAT: A border-seeded flood through pixels that are background-like AND not
|
|
8
|
+
* barrier. Everything it fails to reach is sticker.
|
|
9
|
+
*
|
|
10
|
+
* The two failures this closes, stated as the properties that now hold:
|
|
11
|
+
*
|
|
12
|
+
* 1. A white sticker edge on white paper is still found, because the CUT LINE
|
|
13
|
+
* stops the flood even where the colour does not — the barrier is a ridge
|
|
14
|
+
* map, not a colour test.
|
|
15
|
+
* 2. A paper-coloured region INSIDE a sticker stays opaque, because the flood
|
|
16
|
+
* would have to cross that sticker's outline to get there.
|
|
17
|
+
*
|
|
18
|
+
* EXPORTS: FloodResult, floodFromBorder
|
|
19
|
+
*
|
|
20
|
+
* @tag domain:sticker-trace
|
|
21
|
+
* @tag layer:shared
|
|
22
|
+
* @tag pattern:none
|
|
23
|
+
* @tag access:isomorphic
|
|
24
|
+
* @tag consumers:segment
|
|
25
|
+
* @tag sideEffects:none
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* Flood inward from the raster border.
|
|
29
|
+
*
|
|
30
|
+
* Seeded from a BAND rather than the single outermost row: a scan frequently
|
|
31
|
+
* has a dark or ragged outermost pixel line (the scanner lid edge, a crop
|
|
32
|
+
* artefact), and seeding only there can start the flood on pixels that are not
|
|
33
|
+
* background-like at all, so it never leaves the edge and the entire sheet is
|
|
34
|
+
* reported as one sticker.
|
|
35
|
+
*
|
|
36
|
+
* Explicit stack, not recursion — a clean paper scan floods millions of pixels
|
|
37
|
+
* in one connected region.
|
|
38
|
+
*/
|
|
39
|
+
export function floodFromBorder(backgroundLike, barrier, width, height, seedBand) {
|
|
40
|
+
const outside = new Uint8Array(width * height);
|
|
41
|
+
const stack = [];
|
|
42
|
+
const passable = (i) => backgroundLike[i] === 1 && barrier[i] === 0;
|
|
43
|
+
const seed = (x, y) => {
|
|
44
|
+
const i = y * width + x;
|
|
45
|
+
if (outside[i] || !passable(i))
|
|
46
|
+
return;
|
|
47
|
+
outside[i] = 1;
|
|
48
|
+
stack.push(i);
|
|
49
|
+
};
|
|
50
|
+
const band = Math.max(1, seedBand);
|
|
51
|
+
for (let y = 0; y < height; y++) {
|
|
52
|
+
const edgeRow = y < band || y >= height - band;
|
|
53
|
+
for (let x = 0; x < width; x++) {
|
|
54
|
+
if (edgeRow || x < band || x >= width - band)
|
|
55
|
+
seed(x, y);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// 4-connectivity, matching the component labelling. 8-connectivity would let
|
|
59
|
+
// the flood squeeze through a barrier that touches only diagonally — i.e.
|
|
60
|
+
// through a cut line the ridge detector drew as a perfect stair-step, which
|
|
61
|
+
// is most of them.
|
|
62
|
+
while (stack.length > 0) {
|
|
63
|
+
const i = stack.pop();
|
|
64
|
+
const x = i % width;
|
|
65
|
+
const y = (i / width) | 0;
|
|
66
|
+
if (x > 0) {
|
|
67
|
+
const j = i - 1;
|
|
68
|
+
if (!outside[j] && passable(j)) {
|
|
69
|
+
outside[j] = 1;
|
|
70
|
+
stack.push(j);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (x < width - 1) {
|
|
74
|
+
const j = i + 1;
|
|
75
|
+
if (!outside[j] && passable(j)) {
|
|
76
|
+
outside[j] = 1;
|
|
77
|
+
stack.push(j);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (y > 0) {
|
|
81
|
+
const j = i - width;
|
|
82
|
+
if (!outside[j] && passable(j)) {
|
|
83
|
+
outside[j] = 1;
|
|
84
|
+
stack.push(j);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (y < height - 1) {
|
|
88
|
+
const j = i + width;
|
|
89
|
+
if (!outside[j] && passable(j)) {
|
|
90
|
+
outside[j] = 1;
|
|
91
|
+
stack.push(j);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const inside = new Uint8Array(width * height);
|
|
96
|
+
let reached = 0;
|
|
97
|
+
for (let i = 0; i < outside.length; i++) {
|
|
98
|
+
if (outside[i])
|
|
99
|
+
reached++;
|
|
100
|
+
else
|
|
101
|
+
inside[i] = 1;
|
|
102
|
+
}
|
|
103
|
+
return { outside, inside, reach: reached / outside.length };
|
|
104
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { ComponentStats } from "../math/label";
|
|
2
|
+
import type { PartGeometry, TraceParams } from "../types";
|
|
3
|
+
export declare function buildPartGeometry(labels: Int32Array, width: number, height: number, stat: ComponentStats, ordinal: number, params: TraceParams, pxPerMm: number | null, subPixel: boolean): PartGeometry | null;
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* WHY: A labelled component is a bag of pixels; a cutter needs one closed
|
|
3
|
+
* curve. This is the conversion, and it is also where every millimetre
|
|
4
|
+
* figure is either computed honestly or withheld.
|
|
5
|
+
* WHAT: Per component — isolate, offset by the cut border, trace, simplify,
|
|
6
|
+
* fit cubics, and measure.
|
|
7
|
+
*
|
|
8
|
+
* Each component is processed inside its own PADDED bounding box rather than
|
|
9
|
+
* over the whole raster. On a 9 MP sheet with sixty stickers the full-raster
|
|
10
|
+
* form would allocate sixty 9 MP masks; this allocates sixty small ones. The
|
|
11
|
+
* padding exists because the border offset and the contour both need room to
|
|
12
|
+
* step outside the component, and a contour clipped by the box edge is an open
|
|
13
|
+
* path — which is a cut the machine starts and never finishes.
|
|
14
|
+
*
|
|
15
|
+
* EXPORTS: buildPartGeometry
|
|
16
|
+
*
|
|
17
|
+
* @tag domain:sticker-trace
|
|
18
|
+
* @tag layer:shared
|
|
19
|
+
* @tag pattern:none
|
|
20
|
+
* @tag access:isomorphic
|
|
21
|
+
* @tag consumers:index
|
|
22
|
+
* @tag sideEffects:none
|
|
23
|
+
*/
|
|
24
|
+
import { catmullRomToBezier } from "../math/catmull-rom.js";
|
|
25
|
+
import { traceContours } from "../math/marching-squares.js";
|
|
26
|
+
import { dilate, minFeatureRadius } from "../math/morphology.js";
|
|
27
|
+
import { simplifyRdp } from "../math/rdp.js";
|
|
28
|
+
/**
|
|
29
|
+
* Extract one component into its own buffer, padded on every side.
|
|
30
|
+
*
|
|
31
|
+
* Padding must exceed the border offset, or the dilation runs into the box
|
|
32
|
+
* wall and the outline comes back with a flat edge where the sticker is
|
|
33
|
+
* actually round.
|
|
34
|
+
*/
|
|
35
|
+
function isolate(labels, width, height, label, bbox, pad) {
|
|
36
|
+
const x0 = Math.max(0, bbox.x - pad);
|
|
37
|
+
const y0 = Math.max(0, bbox.y - pad);
|
|
38
|
+
const x1 = Math.min(width, bbox.x + bbox.width + pad);
|
|
39
|
+
const y1 = Math.min(height, bbox.y + bbox.height + pad);
|
|
40
|
+
const w = x1 - x0;
|
|
41
|
+
const h = y1 - y0;
|
|
42
|
+
const mask = new Uint8Array(w * h);
|
|
43
|
+
for (let y = 0; y < h; y++) {
|
|
44
|
+
const src = (y0 + y) * width + x0;
|
|
45
|
+
const dst = y * w;
|
|
46
|
+
for (let x = 0; x < w; x++) {
|
|
47
|
+
if (labels[src + x] === label)
|
|
48
|
+
mask[dst + x] = 1;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return { mask, w, h, originX: x0, originY: y0 };
|
|
52
|
+
}
|
|
53
|
+
export function buildPartGeometry(labels, width, height, stat, ordinal, params, pxPerMm, subPixel) {
|
|
54
|
+
const borderPx = pxPerMm ? params.borderMm * pxPerMm : 0;
|
|
55
|
+
const pad = Math.max(3, Math.ceil(borderPx) + 3);
|
|
56
|
+
const { mask, w, h, originX, originY } = isolate(labels, width, height, stat.label, stat.bbox, pad);
|
|
57
|
+
// The CUT outline, which is the silhouette offset outward by the white
|
|
58
|
+
// border the sticker is meant to carry. With borderMm at 0 this is the
|
|
59
|
+
// silhouette itself — cut exactly on the art edge.
|
|
60
|
+
const cutMask = borderPx > 0 ? dilate(mask, w, h, borderPx) : mask;
|
|
61
|
+
/*
|
|
62
|
+
* Sub-pixel tracing needs a CONTINUOUS field to interpolate; on a binary mask
|
|
63
|
+
* every crossing lands at the midpoint and the "sub-pixel" tier buys nothing.
|
|
64
|
+
* A light blur is what makes the iso-crossing meaningful — which is why the
|
|
65
|
+
* precise/max tiers blur before tracing rather than tracing harder.
|
|
66
|
+
*/
|
|
67
|
+
const field = subPixel ? softenForSubPixel(cutMask, w, h) : cutMask;
|
|
68
|
+
const rings = traceContours(field, w, h, 0.5);
|
|
69
|
+
if (rings.length === 0)
|
|
70
|
+
return null;
|
|
71
|
+
// Outer boundary only. A kiss-cut sheet never cuts interior holes — doing so
|
|
72
|
+
// would drop the middle out of every ring-shaped sticker — so the largest
|
|
73
|
+
// ring by absolute area is the one and only path.
|
|
74
|
+
let outer = rings[0];
|
|
75
|
+
for (const ring of rings) {
|
|
76
|
+
if (Math.abs(ring.signedArea) > Math.abs(outer.signedArea))
|
|
77
|
+
outer = ring;
|
|
78
|
+
}
|
|
79
|
+
if (!outer.closed || outer.points.length < 8)
|
|
80
|
+
return null;
|
|
81
|
+
const simplifyPx = pxPerMm ? params.simplifyMm * pxPerMm : 0.6;
|
|
82
|
+
const simplified = simplifyRdp(outer.points, simplifyPx);
|
|
83
|
+
// Translate back into raster coordinates before fitting, so the emitted path
|
|
84
|
+
// is in the same space as everything else and no consumer has to know this
|
|
85
|
+
// function worked in a local box.
|
|
86
|
+
const absolute = simplified.map((p) => ({
|
|
87
|
+
x: p.x + originX,
|
|
88
|
+
y: p.y + originY,
|
|
89
|
+
}));
|
|
90
|
+
const path = catmullRomToBezier(absolute);
|
|
91
|
+
if (!path)
|
|
92
|
+
return null;
|
|
93
|
+
const featurePx = minFeatureRadius(cutMask, w, h) * 2;
|
|
94
|
+
const bboxPx = stat.bbox;
|
|
95
|
+
return {
|
|
96
|
+
ordinal,
|
|
97
|
+
groupIndex: 0,
|
|
98
|
+
bboxPx,
|
|
99
|
+
areaPx: stat.area,
|
|
100
|
+
bboxMm: pxPerMm
|
|
101
|
+
? {
|
|
102
|
+
x: bboxPx.x / pxPerMm,
|
|
103
|
+
y: bboxPx.y / pxPerMm,
|
|
104
|
+
width: bboxPx.width / pxPerMm,
|
|
105
|
+
height: bboxPx.height / pxPerMm,
|
|
106
|
+
}
|
|
107
|
+
: null,
|
|
108
|
+
areaMm2: pxPerMm ? stat.area / (pxPerMm * pxPerMm) : null,
|
|
109
|
+
minFeatureMm: pxPerMm ? featurePx / pxPerMm : null,
|
|
110
|
+
path,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* A 3x3 binary-average, turning a hard mask into a field whose 0.5 crossing
|
|
115
|
+
* sits between pixels rather than on one. Deliberately tiny: a wider kernel
|
|
116
|
+
* would start moving the edge rather than merely locating it more precisely.
|
|
117
|
+
*/
|
|
118
|
+
function softenForSubPixel(mask, width, height) {
|
|
119
|
+
const out = new Float32Array(mask.length);
|
|
120
|
+
for (let y = 0; y < height; y++) {
|
|
121
|
+
for (let x = 0; x < width; x++) {
|
|
122
|
+
let sum = 0;
|
|
123
|
+
let n = 0;
|
|
124
|
+
for (let dy = -1; dy <= 1; dy++) {
|
|
125
|
+
const sy = y + dy;
|
|
126
|
+
if (sy < 0 || sy >= height)
|
|
127
|
+
continue;
|
|
128
|
+
for (let dx = -1; dx <= 1; dx++) {
|
|
129
|
+
const sx = x + dx;
|
|
130
|
+
if (sx < 0 || sx >= width)
|
|
131
|
+
continue;
|
|
132
|
+
sum += mask[sy * width + sx];
|
|
133
|
+
n++;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
out[y * width + x] = n > 0 ? sum / n : 0;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return out;
|
|
140
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface LineFilterResult {
|
|
2
|
+
/** Line-ness per pixel. Large on a groove, ~0 on a step edge or flat ink. */
|
|
3
|
+
readonly response: Float32Array;
|
|
4
|
+
readonly maxResponse: number;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Multi-scale line detection.
|
|
8
|
+
*
|
|
9
|
+
* A scan's cut lines are not all one width — resolution, paper and how hard
|
|
10
|
+
* the die pressed all vary — so a single scale finds the ones it is tuned to
|
|
11
|
+
* and misses the rest, producing exactly the broken outlines that make a
|
|
12
|
+
* region partition collapse. Taking the per-pixel maximum across a few scales
|
|
13
|
+
* is the standard answer and costs one Gaussian per scale.
|
|
14
|
+
*/
|
|
15
|
+
export declare function detectLines(luma: Float32Array, width: number, height: number, scales?: readonly number[]): LineFilterResult;
|