@arbidocs/blocks 0.4.147 → 0.4.151
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/ConnectedNativeDocxComparison-OFPIXNJB.js +35 -0
- package/dist/ConnectedNativeDocxComparison-OFPIXNJB.js.map +1 -0
- package/dist/ConnectedNativeDocxComparison-Y5BNLNH6.cjs +44 -0
- package/dist/ConnectedNativeDocxComparison-Y5BNLNH6.cjs.map +1 -0
- package/dist/ConnectedNativeDocxEditor-HTEW5JAH.cjs +46 -0
- package/dist/ConnectedNativeDocxEditor-HTEW5JAH.cjs.map +1 -0
- package/dist/ConnectedNativeDocxEditor-LRYU5HPA.js +33 -0
- package/dist/ConnectedNativeDocxEditor-LRYU5HPA.js.map +1 -0
- package/dist/ConnectedStreamedWordArtifact-QAUVUCSX.js +35 -0
- package/dist/ConnectedStreamedWordArtifact-QAUVUCSX.js.map +1 -0
- package/dist/ConnectedStreamedWordArtifact-QW74LKHN.cjs +44 -0
- package/dist/ConnectedStreamedWordArtifact-QW74LKHN.cjs.map +1 -0
- package/dist/FactTextEditor-YESAU2IJ.js +25 -0
- package/dist/FactTextEditor-YESAU2IJ.js.map +1 -0
- package/dist/FactTextEditor-YUPBCTXK.cjs +27 -0
- package/dist/FactTextEditor-YUPBCTXK.cjs.map +1 -0
- package/dist/{NativeDocxEditor-BE2OEOTJ.cjs → NativeDocxEditor-5VBNM5I7.cjs} +8 -8
- package/dist/{NativeDocxEditor-BE2OEOTJ.cjs.map → NativeDocxEditor-5VBNM5I7.cjs.map} +1 -1
- package/dist/{NativeDocxEditor-KOPFMRYW.js → NativeDocxEditor-XT5ZLFGU.js} +4 -4
- package/dist/{NativeDocxEditor-KOPFMRYW.js.map → NativeDocxEditor-XT5ZLFGU.js.map} +1 -1
- package/dist/agents/index.cjs +263 -264
- package/dist/agents/index.js +6 -7
- package/dist/calendar/index.cjs +117 -125
- package/dist/calendar/index.d.ts +0 -1
- package/dist/calendar/index.js +1 -1
- package/dist/chat/index.cjs +78 -78
- package/dist/chat/index.js +3 -3
- package/dist/{chunk-2FL7QJKJ.js → chunk-265GOG4W.js} +3 -3
- package/dist/{chunk-2FL7QJKJ.js.map → chunk-265GOG4W.js.map} +1 -1
- package/dist/{chunk-LTU35TQN.cjs → chunk-2FLWPM3B.cjs} +636 -31
- package/dist/chunk-2FLWPM3B.cjs.map +1 -0
- package/dist/{chunk-SUUPR735.js → chunk-3PCBYOIZ.js} +4 -4
- package/dist/{chunk-SUUPR735.js.map → chunk-3PCBYOIZ.js.map} +1 -1
- package/dist/{chunk-WIZ7Z7FN.js → chunk-4236BRZK.js} +46 -221
- package/dist/chunk-4236BRZK.js.map +1 -0
- package/dist/{chunk-IL3WB3YX.cjs → chunk-4JNKXOFZ.cjs} +3 -3
- package/dist/{chunk-IL3WB3YX.cjs.map → chunk-4JNKXOFZ.cjs.map} +1 -1
- package/dist/{chunk-ODRHHWHY.cjs → chunk-4KMLM3GY.cjs} +4 -4
- package/dist/chunk-4KMLM3GY.cjs.map +1 -0
- package/dist/chunk-6I6CVX5G.cjs +22 -0
- package/dist/chunk-6I6CVX5G.cjs.map +1 -0
- package/dist/{chunk-MHFF5N65.cjs → chunk-757OYF6G.cjs} +4 -38
- package/dist/chunk-757OYF6G.cjs.map +1 -0
- package/dist/chunk-B3FMUFAW.cjs +1956 -0
- package/dist/chunk-B3FMUFAW.cjs.map +1 -0
- package/dist/{chunk-B3AHCIV5.js → chunk-BJ24VPOA.js} +4 -55
- package/dist/chunk-BJ24VPOA.js.map +1 -0
- package/dist/chunk-C7PTF6BQ.cjs +172 -0
- package/dist/chunk-C7PTF6BQ.cjs.map +1 -0
- package/dist/{chunk-LZRMXJIE.js → chunk-COA3S3CZ.js} +3 -3
- package/dist/{chunk-LZRMXJIE.js.map → chunk-COA3S3CZ.js.map} +1 -1
- package/dist/{chunk-VUR63NMQ.js → chunk-CROTH2BS.js} +6 -6
- package/dist/{chunk-VUR63NMQ.js.map → chunk-CROTH2BS.js.map} +1 -1
- package/dist/{chunk-AO7SK6WP.cjs → chunk-CU2O32Z4.cjs} +31 -31
- package/dist/{chunk-AO7SK6WP.cjs.map → chunk-CU2O32Z4.cjs.map} +1 -1
- package/dist/chunk-D3WFIFRY.cjs +659 -0
- package/dist/chunk-D3WFIFRY.cjs.map +1 -0
- package/dist/{chunk-DAHCRVPM.js → chunk-DB2OXRQC.js} +84 -82
- package/dist/chunk-DB2OXRQC.js.map +1 -0
- package/dist/{chunk-QXMR5YHC.js → chunk-DIB4JYUY.js} +19 -3
- package/dist/chunk-DIB4JYUY.js.map +1 -0
- package/dist/chunk-DVB5ZKOF.js +22 -0
- package/dist/chunk-DVB5ZKOF.js.map +1 -0
- package/dist/chunk-EYJMMGXF.js +19 -0
- package/dist/chunk-EYJMMGXF.js.map +1 -0
- package/dist/chunk-FAXXN7KI.cjs +213 -0
- package/dist/chunk-FAXXN7KI.cjs.map +1 -0
- package/dist/{chunk-2MJWWPHY.js → chunk-G4IYES7G.js} +140 -15
- package/dist/chunk-G4IYES7G.js.map +1 -0
- package/dist/{chunk-T5I4NRFP.cjs → chunk-GFOEWPAP.cjs} +8 -8
- package/dist/{chunk-T5I4NRFP.cjs.map → chunk-GFOEWPAP.cjs.map} +1 -1
- package/dist/{chunk-QI6AIHWP.cjs → chunk-GOWXP5KT.cjs} +145 -14
- package/dist/chunk-GOWXP5KT.cjs.map +1 -0
- package/dist/chunk-HALD6ZB5.cjs +18 -0
- package/dist/chunk-HALD6ZB5.cjs.map +1 -0
- package/dist/chunk-HUJF2XM2.js +6584 -0
- package/dist/chunk-HUJF2XM2.js.map +1 -0
- package/dist/{chunk-NRFAWUVD.js → chunk-JAANWQGB.js} +157 -157
- package/dist/chunk-JAANWQGB.js.map +1 -0
- package/dist/{chunk-7RJTEWYM.js → chunk-JGOST4IL.js} +350 -64
- package/dist/chunk-JGOST4IL.js.map +1 -0
- package/dist/chunk-KHXEIEXN.js +41 -0
- package/dist/chunk-KHXEIEXN.js.map +1 -0
- package/dist/chunk-KQYPP72K.js +644 -0
- package/dist/chunk-KQYPP72K.js.map +1 -0
- package/dist/chunk-KUT2Y7JF.cjs +43 -0
- package/dist/chunk-KUT2Y7JF.cjs.map +1 -0
- package/dist/{chunk-6YTHQ73P.cjs → chunk-LLYZGH3L.cjs} +3 -56
- package/dist/chunk-LLYZGH3L.cjs.map +1 -0
- package/dist/{chunk-YSHIC4NJ.cjs → chunk-LXTOOUEN.cjs} +159 -154
- package/dist/chunk-LXTOOUEN.cjs.map +1 -0
- package/dist/{chunk-EVUEIBNU.js → chunk-M4S75AEJ.js} +44 -5
- package/dist/chunk-M4S75AEJ.js.map +1 -0
- package/dist/{chunk-V5OAXIBN.cjs → chunk-NPR5BGFF.cjs} +11 -11
- package/dist/{chunk-V5OAXIBN.cjs.map → chunk-NPR5BGFF.cjs.map} +1 -1
- package/dist/{chunk-PLJ7PHWU.cjs → chunk-NS7NVX4E.cjs} +3 -3
- package/dist/{chunk-PLJ7PHWU.cjs.map → chunk-NS7NVX4E.cjs.map} +1 -1
- package/dist/{chunk-AINU3EJ6.cjs → chunk-Q4BY2CQQ.cjs} +92 -90
- package/dist/chunk-Q4BY2CQQ.cjs.map +1 -0
- package/dist/chunk-QN47Q4N7.js +16 -0
- package/dist/chunk-QN47Q4N7.js.map +1 -0
- package/dist/{chunk-I2QSDQQV.cjs → chunk-QT3A4PFC.cjs} +21 -2
- package/dist/chunk-QT3A4PFC.cjs.map +1 -0
- package/dist/{chunk-ZM26YEOT.js → chunk-RY2SODRN.js} +3 -3
- package/dist/{chunk-ZM26YEOT.js.map → chunk-RY2SODRN.js.map} +1 -1
- package/dist/chunk-SDOEHEJP.js +208 -0
- package/dist/chunk-SDOEHEJP.js.map +1 -0
- package/dist/{chunk-DETZZBG2.cjs → chunk-SIB6C7P7.cjs} +43 -2
- package/dist/chunk-SIB6C7P7.cjs.map +1 -0
- package/dist/{chunk-MFY2ZNP6.cjs → chunk-SMN32BQ3.cjs} +4 -4
- package/dist/chunk-SMN32BQ3.cjs.map +1 -0
- package/dist/chunk-T74Q3MCZ.cjs +6751 -0
- package/dist/chunk-T74Q3MCZ.cjs.map +1 -0
- package/dist/{chunk-AOSUHWIL.js → chunk-TZOQKV64.js} +4 -37
- package/dist/chunk-TZOQKV64.js.map +1 -0
- package/dist/{chunk-U37AYUPI.cjs → chunk-U6JQ4KMX.cjs} +46 -233
- package/dist/chunk-U6JQ4KMX.cjs.map +1 -0
- package/dist/chunk-WFA2GVZJ.js +16 -0
- package/dist/chunk-WFA2GVZJ.js.map +1 -0
- package/dist/chunk-WU34CHU5.js +1907 -0
- package/dist/chunk-WU34CHU5.js.map +1 -0
- package/dist/{chunk-O4YPVYPO.cjs → chunk-YAEXSCUW.cjs} +364 -60
- package/dist/chunk-YAEXSCUW.cjs.map +1 -0
- package/dist/{chunk-H74HEPKT.js → chunk-YXNNNP57.js} +598 -13
- package/dist/chunk-YXNNNP57.js.map +1 -0
- package/dist/chunk-Z27QMJ6S.cjs +25 -0
- package/dist/chunk-Z27QMJ6S.cjs.map +1 -0
- package/dist/{chunk-CSI2B2H5.js → chunk-Z4NQ3TED.js} +4 -4
- package/dist/chunk-Z4NQ3TED.js.map +1 -0
- package/dist/{chunk-DGV7HQA7.js → chunk-ZLEYLCE4.js} +4 -4
- package/dist/chunk-ZLEYLCE4.js.map +1 -0
- package/dist/chunk-ZNLTEZEF.js +170 -0
- package/dist/chunk-ZNLTEZEF.js.map +1 -0
- package/dist/chunk-ZP6Q3KXU.cjs +18 -0
- package/dist/chunk-ZP6Q3KXU.cjs.map +1 -0
- package/dist/citations/index.cjs +14 -14
- package/dist/citations/index.js +2 -2
- package/dist/collaboration/index.cjs +35 -35
- package/dist/collaboration/index.js +1 -1
- package/dist/connect/docx.cjs +21 -26
- package/dist/connect/docx.cjs.map +1 -1
- package/dist/connect/docx.js +10 -26
- package/dist/connect/docx.js.map +1 -1
- package/dist/connect/index.cjs +8662 -2824
- package/dist/connect/index.cjs.map +1 -1
- package/dist/connect/index.d.ts +10 -2
- package/dist/connect/index.js +8467 -2670
- package/dist/connect/index.js.map +1 -1
- package/dist/connect/viewer.cjs +2357 -0
- package/dist/connect/viewer.cjs.map +1 -0
- package/dist/connect/viewer.d.ts +8 -0
- package/dist/connect/viewer.js +2350 -0
- package/dist/connect/viewer.js.map +1 -0
- package/dist/connection/ConnectedWorkflowsTable.d.ts +2 -12
- package/dist/connection/ai.d.ts +2 -9
- package/dist/connection/billing/AddAddonDialog.d.ts +24 -0
- package/dist/connection/billing/BillingCard.d.ts +18 -0
- package/dist/connection/billing/BillingProjectEntity.d.ts +9 -0
- package/dist/connection/billing/ChangePlanDialog.d.ts +20 -0
- package/dist/connection/billing/ChangeProPlan.d.ts +20 -0
- package/dist/connection/billing/CheckoutTotal.d.ts +12 -0
- package/dist/connection/billing/DailyCapEditor.d.ts +4 -0
- package/dist/connection/billing/InvoicesModal.d.ts +6 -0
- package/dist/connection/billing/NewProjectFlow.d.ts +14 -0
- package/dist/connection/billing/PlanChangeLines.d.ts +13 -0
- package/dist/connection/billing/PlanSelector.d.ts +50 -0
- package/dist/connection/billing/ProjectBilling.d.ts +24 -0
- package/dist/connection/billing/ProjectDetail.d.ts +16 -0
- package/dist/connection/billing/ProjectUsageCard.d.ts +21 -0
- package/dist/connection/billing/ProjectUsageContent.d.ts +18 -0
- package/dist/connection/billing/ProjectsTable.d.ts +13 -0
- package/dist/connection/billing/ReduceAddonDialog.d.ts +18 -0
- package/dist/connection/billing/ReferralReward.d.ts +32 -0
- package/dist/connection/billing/SharedProjects.d.ts +13 -0
- package/dist/connection/billing/StripeCheckoutModal.d.ts +32 -0
- package/dist/connection/billing/SubscriptionPlans.d.ts +15 -0
- package/dist/connection/billing/SubscriptionStatus.d.ts +10 -0
- package/dist/connection/billing/addon-pricing.d.ts +97 -0
- package/dist/connection/billing/api-error.d.ts +6 -0
- package/dist/connection/billing/billing-country.d.ts +14 -0
- package/dist/connection/billing/billing-focus.d.ts +11 -0
- package/dist/connection/billing/index.d.ts +22 -0
- package/dist/connection/billing/plan-badge.d.ts +15 -0
- package/dist/connection/billing/plan-change-outcome.d.ts +15 -0
- package/dist/connection/billing/plan-constants.d.ts +29 -0
- package/dist/connection/billing/plan-pricing.d.ts +67 -0
- package/dist/connection/billing/quota-items.d.ts +33 -0
- package/dist/connection/billing/referral-reward.d.ts +28 -0
- package/dist/connection/billing/refusal-copy.d.ts +5 -0
- package/dist/connection/billing/reward-balance.d.ts +19 -0
- package/dist/connection/billing/support.d.ts +35 -0
- package/dist/connection/billing/tax-quote.d.ts +36 -0
- package/dist/connection/billing/useAddonPurchase.d.ts +32 -0
- package/dist/connection/billing/useAutoRefreshPendingProjects.d.ts +11 -0
- package/dist/connection/billing/useCheckoutQuote.d.ts +30 -0
- package/dist/connection/billing/useOpenBillingPortal.d.ts +12 -0
- package/dist/connection/calendar/CalendarSettingsDialog.d.ts +1 -1
- package/dist/connection/facts/ConnectedFactsPage.d.ts +50 -0
- package/dist/connection/facts/FactMarkdownEditor.d.ts +57 -0
- package/dist/connection/facts/FactSourcesPopover.d.ts +38 -0
- package/dist/connection/facts/FactTextEditor.d.ts +2 -0
- package/dist/connection/facts/factNouns.d.ts +4 -0
- package/dist/connection/facts/factPageColumns.d.ts +37 -0
- package/dist/connection/facts/types.d.ts +127 -0
- package/dist/connection/facts/useFactActions.d.ts +10 -0
- package/dist/connection/facts/useFactComposer.d.ts +54 -0
- package/dist/connection/facts/useFactFilters.d.ts +101 -0
- package/dist/connection/facts/useFactSelection.d.ts +82 -0
- package/dist/connection/facts/useFactsGrid.d.ts +87 -0
- package/dist/connection/facts/useFactsPageView.d.ts +4 -0
- package/dist/connection/mail/ConnectedMailComposer.d.ts +3 -1
- package/dist/connection/mail/ConnectedMailbox.d.ts +4 -2
- package/dist/connection/mail/MailComposerForm.d.ts +4 -2
- package/dist/connection/mail/MailRecipientInput.d.ts +14 -0
- package/dist/connection/mail/index.d.ts +1 -1
- package/dist/connection/mail/types.d.ts +10 -0
- package/dist/connection/search/ConnectedSearchPage.d.ts +64 -0
- package/dist/connection/search/SearchResultRows.d.ts +38 -0
- package/dist/connection/search/index.d.ts +2 -0
- package/dist/connection/tags/ConnectedTagTable.d.ts +108 -0
- package/dist/connection/tags/ConnectedTagsPage.d.ts +55 -0
- package/dist/connection/tags/DocTagPassages.d.ts +25 -0
- package/dist/connection/tags/GlossaryExport.d.ts +7 -0
- package/dist/connection/tags/TagCombineFilter.d.ts +14 -0
- package/dist/connection/tags/TagPlacement.d.ts +16 -0
- package/dist/connection/tags/TagsPageSections.d.ts +36 -0
- package/dist/connection/tags/tagCombine.d.ts +55 -0
- package/dist/connection/useConnectedWorkNotifications.d.ts +7 -24
- package/dist/connection/viewer/ConnectedDocumentToolsProvider.d.ts +11 -0
- package/dist/connection/viewer/ConnectedDocumentViewer.d.ts +21 -0
- package/dist/connection/viewer/FinaliseTranslationButton.d.ts +15 -0
- package/dist/connection/viewer/ViewerPdfPane.d.ts +46 -0
- package/dist/connection/viewer/parsed/ParsedPassage.d.ts +48 -0
- package/dist/connection/viewer/parsed/ParsedTextView.d.ts +17 -0
- package/dist/connection/viewer/parsed/PassageTagPanel.d.ts +18 -0
- package/dist/connection/viewer/parsed/citation-line.d.ts +17 -0
- package/dist/connection/viewer/parsed/document-tags.d.ts +8 -0
- package/dist/connection/viewer/parsed/useChunkTagging.d.ts +46 -0
- package/dist/connection/viewer/parsed/useCitationSelection.d.ts +27 -0
- package/dist/connection/viewer/parsed/useDocumentLabels.d.ts +38 -0
- package/dist/connection/viewer/parsed/useLazyPages.d.ts +18 -0
- package/dist/connection/viewer/parsed/usePageScrollSync.d.ts +17 -0
- package/dist/connection/viewer/parsed/usePassageCopy.d.ts +25 -0
- package/dist/connection/viewer/support.d.ts +97 -0
- package/dist/connection/viewer/useImageCrop.d.ts +13 -0
- package/dist/connection/viewer/useViewedDocument.d.ts +70 -0
- package/dist/connection/viewer/useViewerBlobs.d.ts +15 -0
- package/dist/connection/viewer/useViewerTabs.d.ts +18 -0
- package/dist/connection/viewer/useViewerVersions.d.ts +11 -0
- package/dist/connection/workspace-settings/useConnectedWorkspaceSettings.d.ts +6 -0
- package/dist/document-tools/index.cjs +59 -652
- package/dist/document-tools/index.cjs.map +1 -1
- package/dist/document-tools/index.js +2 -641
- package/dist/document-tools/index.js.map +1 -1
- package/dist/docx/index.cjs +48 -47
- package/dist/docx/index.js +4 -3
- package/dist/facts/FactsBulkBar.d.ts +6 -3
- package/dist/facts/cited-version-ref.d.ts +1 -0
- package/dist/facts/index.cjs +204 -1940
- package/dist/facts/index.cjs.map +1 -1
- package/dist/facts/index.d.ts +1 -0
- package/dist/facts/index.js +13 -1895
- package/dist/facts/index.js.map +1 -1
- package/dist/files/TagPassagePanel.d.ts +2 -1
- package/dist/files/ViewerChrome.d.ts +5 -4
- package/dist/files/ViewerControlBar.d.ts +12 -0
- package/dist/files/doc-labels.d.ts +35 -0
- package/dist/files/grid/FilterButton.d.ts +12 -0
- package/dist/files/grid/RowDensityControl.d.ts +18 -0
- package/dist/files/grid/row-density.d.ts +27 -0
- package/dist/files/index.cjs +778 -7099
- package/dist/files/index.cjs.map +1 -1
- package/dist/files/index.d.ts +5 -0
- package/dist/files/index.js +13 -6918
- package/dist/files/index.js.map +1 -1
- package/dist/index.cjs +993 -1209
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +22 -355
- package/dist/index.js.map +1 -1
- package/dist/retrieval/SearchSnippet.d.ts +6 -0
- package/dist/retrieval/index.cjs +74 -41
- package/dist/retrieval/index.d.ts +2 -0
- package/dist/retrieval/index.js +2 -1
- package/dist/retrieval/search-results.d.ts +46 -0
- package/dist/settings/Billing.d.ts +0 -66
- package/dist/settings/SubscriptionParts.d.ts +1 -50
- package/dist/settings/index.cjs +166 -214
- package/dist/settings/index.d.ts +3 -2
- package/dist/settings/index.js +1 -1
- package/dist/settings/inverted-index-filter.d.ts +26 -0
- package/dist/studio/index.cjs +3 -3
- package/dist/studio/index.js +2 -2
- package/dist/tags/definitions.d.ts +10 -0
- package/dist/tags/index.d.ts +4 -1
- package/dist/tags/page/ExtractEntitiesDialog.d.ts +24 -0
- package/dist/tags/page/TagPicker.d.ts +16 -0
- package/dist/tags/page/tagsPageLabels.d.ts +36 -0
- package/dist/workflow-canvas/index.cjs +19 -20
- package/dist/workflow-canvas/index.cjs.map +1 -1
- package/dist/workflow-canvas/index.js +6 -7
- package/dist/workflow-canvas/index.js.map +1 -1
- package/node_modules/@arbidocs/coedit/package.json +1 -1
- package/package.json +13 -4
- package/dist/calendar/access-setup.d.ts +0 -8
- package/dist/chunk-2MJWWPHY.js.map +0 -1
- package/dist/chunk-3AFWGEDJ.cjs +0 -53
- package/dist/chunk-3AFWGEDJ.cjs.map +0 -1
- package/dist/chunk-6YTHQ73P.cjs.map +0 -1
- package/dist/chunk-7RJTEWYM.js.map +0 -1
- package/dist/chunk-AINU3EJ6.cjs.map +0 -1
- package/dist/chunk-AOSUHWIL.js.map +0 -1
- package/dist/chunk-B3AHCIV5.js.map +0 -1
- package/dist/chunk-CSI2B2H5.js.map +0 -1
- package/dist/chunk-DAHCRVPM.js.map +0 -1
- package/dist/chunk-DETZZBG2.cjs.map +0 -1
- package/dist/chunk-DGV7HQA7.js.map +0 -1
- package/dist/chunk-EVUEIBNU.js.map +0 -1
- package/dist/chunk-H74HEPKT.js.map +0 -1
- package/dist/chunk-I2QSDQQV.cjs.map +0 -1
- package/dist/chunk-J5CWKFSC.js +0 -170
- package/dist/chunk-J5CWKFSC.js.map +0 -1
- package/dist/chunk-LTU35TQN.cjs.map +0 -1
- package/dist/chunk-MFY2ZNP6.cjs.map +0 -1
- package/dist/chunk-MHFF5N65.cjs.map +0 -1
- package/dist/chunk-NRFAWUVD.js.map +0 -1
- package/dist/chunk-O4YPVYPO.cjs.map +0 -1
- package/dist/chunk-ODRHHWHY.cjs.map +0 -1
- package/dist/chunk-QI6AIHWP.cjs.map +0 -1
- package/dist/chunk-QXMR5YHC.js.map +0 -1
- package/dist/chunk-RFXJYIDV.js +0 -50
- package/dist/chunk-RFXJYIDV.js.map +0 -1
- package/dist/chunk-U37AYUPI.cjs.map +0 -1
- package/dist/chunk-WIZ7Z7FN.js.map +0 -1
- package/dist/chunk-XVUOMWMD.cjs +0 -177
- package/dist/chunk-XVUOMWMD.cjs.map +0 -1
- package/dist/chunk-YSHIC4NJ.cjs.map +0 -1
- package/dist/connection/ConnectedTagTable.d.ts +0 -32
- package/dist/connection/calendar/CopyField.d.ts +0 -9
- package/dist/connection/calendar/OpenAccessPanel.d.ts +0 -7
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var chunkSIB6C7P7_cjs = require('./chunk-SIB6C7P7.cjs');
|
|
5
|
+
var react = require('react');
|
|
6
|
+
var lucideReact = require('lucide-react');
|
|
7
|
+
var ui = require('@arbidocs/react/ui');
|
|
8
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
9
|
+
|
|
10
|
+
var CHIP_ROW_H = 24;
|
|
11
|
+
var CHIP_GAP = 4;
|
|
12
|
+
function labelChipClampHeight(rowHeight) {
|
|
13
|
+
const rows = Math.max(1, Math.floor((rowHeight + CHIP_GAP) / (CHIP_ROW_H + CHIP_GAP)));
|
|
14
|
+
return CHIP_ROW_H * rows + CHIP_GAP * (rows - 1);
|
|
15
|
+
}
|
|
16
|
+
var DEFAULT_LABEL_MULTI_SELECT_LABELS = {
|
|
17
|
+
searchPlaceholder: "Search or create...",
|
|
18
|
+
noLabels: "No labels yet",
|
|
19
|
+
create: (name) => `Create \u201C${name}\u201D`,
|
|
20
|
+
editLabel: "Edit field"
|
|
21
|
+
};
|
|
22
|
+
var CHECK_BOX = "flex shrink-0 items-center justify-center rounded border-2";
|
|
23
|
+
function LabelPickerList({
|
|
24
|
+
options,
|
|
25
|
+
appliedIds,
|
|
26
|
+
mixedIds,
|
|
27
|
+
onToggle,
|
|
28
|
+
onCreate,
|
|
29
|
+
moreCreates,
|
|
30
|
+
onEditLabels,
|
|
31
|
+
labels
|
|
32
|
+
}) {
|
|
33
|
+
const l = react.useMemo(() => ({ ...DEFAULT_LABEL_MULTI_SELECT_LABELS, ...labels }), [labels]);
|
|
34
|
+
const [search, setSearch] = react.useState("");
|
|
35
|
+
const trimmed = search.trim();
|
|
36
|
+
const matchesExisting = options.some((o) => o.name.toLowerCase() === trimmed.toLowerCase());
|
|
37
|
+
const create = () => {
|
|
38
|
+
onCreate?.(trimmed);
|
|
39
|
+
setSearch("");
|
|
40
|
+
};
|
|
41
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Command, { shouldFilter: true, children: [
|
|
42
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
43
|
+
ui.CommandInput,
|
|
44
|
+
{
|
|
45
|
+
placeholder: l.searchPlaceholder,
|
|
46
|
+
value: search,
|
|
47
|
+
onValueChange: setSearch,
|
|
48
|
+
onKeyDown: (e) => {
|
|
49
|
+
if (e.key === "Enter" && onCreate && trimmed && !matchesExisting) {
|
|
50
|
+
e.preventDefault();
|
|
51
|
+
create();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
),
|
|
56
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.CommandList, { children: [
|
|
57
|
+
!(trimmed && onCreate) && /* @__PURE__ */ jsxRuntime.jsx(ui.CommandEmpty, { children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: l.noLabels }) }),
|
|
58
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.CommandGroup, { children: options.map((o) => {
|
|
59
|
+
const isApplied = appliedIds.has(o.id);
|
|
60
|
+
const isMixed = mixedIds?.has(o.id);
|
|
61
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
62
|
+
ui.CommandItem,
|
|
63
|
+
{
|
|
64
|
+
value: o.name,
|
|
65
|
+
onSelect: () => onToggle(o.id),
|
|
66
|
+
onPointerDown: (e) => e.preventDefault(),
|
|
67
|
+
className: "group/label cursor-pointer",
|
|
68
|
+
"data-testid": `label-select-${o.id}`,
|
|
69
|
+
children: [
|
|
70
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
71
|
+
"span",
|
|
72
|
+
{
|
|
73
|
+
className: `mr-2 size-4 ${CHECK_BOX} ${isApplied ? "" : "bg-background"}`,
|
|
74
|
+
style: {
|
|
75
|
+
borderColor: o.color,
|
|
76
|
+
backgroundColor: isApplied ? o.color : void 0
|
|
77
|
+
},
|
|
78
|
+
children: [
|
|
79
|
+
isApplied && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "size-3 text-white", strokeWidth: 3 }),
|
|
80
|
+
isMixed && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Minus, { className: "size-3", style: { color: o.color } })
|
|
81
|
+
]
|
|
82
|
+
}
|
|
83
|
+
),
|
|
84
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 text-sm", children: o.name }),
|
|
85
|
+
onEditLabels && /* @__PURE__ */ jsxRuntime.jsx(
|
|
86
|
+
"button",
|
|
87
|
+
{
|
|
88
|
+
type: "button",
|
|
89
|
+
onClick: (e) => {
|
|
90
|
+
e.stopPropagation();
|
|
91
|
+
onEditLabels();
|
|
92
|
+
},
|
|
93
|
+
onPointerDown: (e) => e.preventDefault(),
|
|
94
|
+
className: "shrink-0 rounded p-0.5 opacity-0 hover:bg-muted focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring group-hover/label:opacity-100 group-data-[selected=true]/label:opacity-100 pointer-coarse:flex pointer-coarse:size-11 pointer-coarse:items-center pointer-coarse:justify-center pointer-coarse:opacity-100",
|
|
95
|
+
title: l.editLabel,
|
|
96
|
+
"aria-label": l.editLabel,
|
|
97
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PencilLine, { className: "size-3 text-muted-foreground" })
|
|
98
|
+
}
|
|
99
|
+
)
|
|
100
|
+
]
|
|
101
|
+
},
|
|
102
|
+
o.id
|
|
103
|
+
);
|
|
104
|
+
}) })
|
|
105
|
+
] }),
|
|
106
|
+
trimmed && onCreate && !matchesExisting && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-border p-1", "data-slot": "label-picker-create", children: [{ label: l.create, onCreate }, ...moreCreates ?? []].map((c, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
107
|
+
"button",
|
|
108
|
+
{
|
|
109
|
+
type: "button",
|
|
110
|
+
onClick: () => {
|
|
111
|
+
c.onCreate(trimmed);
|
|
112
|
+
setSearch("");
|
|
113
|
+
},
|
|
114
|
+
onPointerDown: (e) => e.preventDefault(),
|
|
115
|
+
className: "w-full cursor-pointer rounded px-2 py-1.5 text-left text-sm text-primary hover:bg-accent pointer-coarse:min-h-11",
|
|
116
|
+
children: c.label(trimmed)
|
|
117
|
+
},
|
|
118
|
+
i
|
|
119
|
+
)) })
|
|
120
|
+
] });
|
|
121
|
+
}
|
|
122
|
+
var LabelMultiSelectView = react.memo(function LabelMultiSelectView2({
|
|
123
|
+
options,
|
|
124
|
+
appliedIds,
|
|
125
|
+
onToggle,
|
|
126
|
+
onCreate,
|
|
127
|
+
onEditLabels,
|
|
128
|
+
rowHeight = 52,
|
|
129
|
+
labels
|
|
130
|
+
}) {
|
|
131
|
+
const [open, setOpen] = react.useState(false);
|
|
132
|
+
const applied = options.filter((o) => appliedIds.has(o.id));
|
|
133
|
+
const maxHeight = labelChipClampHeight(rowHeight);
|
|
134
|
+
const chipsRef = react.useRef(null);
|
|
135
|
+
const [hasOverflow, setHasOverflow] = react.useState(false);
|
|
136
|
+
react.useEffect(() => {
|
|
137
|
+
const el = chipsRef.current;
|
|
138
|
+
if (!el) return;
|
|
139
|
+
const measure = () => setHasOverflow(el.scrollHeight > el.clientHeight + 1);
|
|
140
|
+
measure();
|
|
141
|
+
const ro = new ResizeObserver(measure);
|
|
142
|
+
ro.observe(el);
|
|
143
|
+
return () => ro.disconnect();
|
|
144
|
+
}, [appliedIds, maxHeight, options]);
|
|
145
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Popover, { open, onOpenChange: setOpen, children: [
|
|
146
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
147
|
+
"button",
|
|
148
|
+
{
|
|
149
|
+
type: "button",
|
|
150
|
+
"data-slot": "label-multi-select",
|
|
151
|
+
className: "group relative flex h-full w-full min-w-0 cursor-pointer items-center gap-1 pr-4 text-left hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring",
|
|
152
|
+
children: applied.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(chunkSIB6C7P7_cjs.CellHoverIcon, {}) }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
153
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
154
|
+
"div",
|
|
155
|
+
{
|
|
156
|
+
ref: chipsRef,
|
|
157
|
+
className: "flex min-w-0 flex-1 flex-wrap content-start gap-1 overflow-hidden",
|
|
158
|
+
style: { maxHeight },
|
|
159
|
+
"data-testid": "label-multi-select-chips",
|
|
160
|
+
children: applied.map((o) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
161
|
+
"span",
|
|
162
|
+
{
|
|
163
|
+
className: "inline-flex shrink-0 items-center gap-1 rounded border px-1.5 py-0.5 text-xs font-medium",
|
|
164
|
+
title: o.name,
|
|
165
|
+
style: { borderColor: o.color },
|
|
166
|
+
children: [
|
|
167
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
168
|
+
"span",
|
|
169
|
+
{
|
|
170
|
+
className: "flex size-3.5 shrink-0 items-center justify-center rounded",
|
|
171
|
+
style: { backgroundColor: o.color },
|
|
172
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "size-2.5 text-white", strokeWidth: 3 })
|
|
173
|
+
}
|
|
174
|
+
),
|
|
175
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "max-w-[80px] truncate", children: o.name })
|
|
176
|
+
]
|
|
177
|
+
},
|
|
178
|
+
o.id
|
|
179
|
+
))
|
|
180
|
+
}
|
|
181
|
+
),
|
|
182
|
+
hasOverflow && /* @__PURE__ */ jsxRuntime.jsx(
|
|
183
|
+
"span",
|
|
184
|
+
{
|
|
185
|
+
className: "pointer-events-none absolute bottom-0.5 right-0.5 text-xs font-semibold leading-none text-muted-foreground",
|
|
186
|
+
"aria-hidden": true,
|
|
187
|
+
"data-testid": "label-multi-select-overflow",
|
|
188
|
+
children: "\u2026"
|
|
189
|
+
}
|
|
190
|
+
)
|
|
191
|
+
] })
|
|
192
|
+
}
|
|
193
|
+
) }),
|
|
194
|
+
open && /* @__PURE__ */ jsxRuntime.jsx(ui.PopoverContent, { className: "w-[360px] p-0", align: "start", side: "bottom", sideOffset: 4, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
195
|
+
LabelPickerList,
|
|
196
|
+
{
|
|
197
|
+
options,
|
|
198
|
+
appliedIds,
|
|
199
|
+
onToggle,
|
|
200
|
+
onCreate,
|
|
201
|
+
onEditLabels,
|
|
202
|
+
labels
|
|
203
|
+
}
|
|
204
|
+
) })
|
|
205
|
+
] });
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
exports.DEFAULT_LABEL_MULTI_SELECT_LABELS = DEFAULT_LABEL_MULTI_SELECT_LABELS;
|
|
209
|
+
exports.LabelMultiSelectView = LabelMultiSelectView;
|
|
210
|
+
exports.LabelPickerList = LabelPickerList;
|
|
211
|
+
exports.labelChipClampHeight = labelChipClampHeight;
|
|
212
|
+
//# sourceMappingURL=chunk-FAXXN7KI.cjs.map
|
|
213
|
+
//# sourceMappingURL=chunk-FAXXN7KI.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/files/cells/LabelMultiSelect.tsx"],"names":["useMemo","useState","jsxs","Command","jsx","CommandInput","CommandList","CommandEmpty","CommandGroup","CommandItem","Check","Minus","PencilLine","memo","LabelMultiSelectView","useRef","useEffect","Popover","PopoverTrigger","CellHoverIcon","Fragment","PopoverContent"],"mappings":";;;;;;;;AAgBA,IAAM,UAAA,GAAa,EAAA;AACnB,IAAM,QAAA,GAAW,CAAA;AAGV,SAAS,qBAAqB,SAAA,EAA2B;AAC9D,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,OAAO,SAAA,GAAY,QAAA,KAAa,UAAA,GAAa,QAAA,CAAS,CAAC,CAAA;AACrF,EAAA,OAAO,UAAA,GAAa,IAAA,GAAO,QAAA,IAAY,IAAA,GAAO,CAAA,CAAA;AAChD;AAiBO,IAAM,iCAAA,GAA4D;AAAA,EACvE,iBAAA,EAAmB,qBAAA;AAAA,EACnB,QAAA,EAAU,eAAA;AAAA,EACV,MAAA,EAAQ,CAAC,IAAA,KAAS,CAAA,aAAA,EAAW,IAAI,CAAA,MAAA,CAAA;AAAA,EACjC,SAAA,EAAW;AACb;AAgBA,IAAM,SAAA,GAAY,4DAAA;AAuBX,SAAS,eAAA,CAAgB;AAAA,EAC9B,OAAA;AAAA,EACA,UAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,WAAA;AAAA,EACA,YAAA;AAAA,EACA;AACF,CAAA,EAAyB;AACvB,EAAA,MAAM,CAAA,GAAIA,aAAA,CAAQ,OAAO,EAAE,GAAG,iCAAA,EAAmC,GAAG,MAAA,EAAO,CAAA,EAAI,CAAC,MAAM,CAAC,CAAA;AACvF,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAIC,eAAS,EAAE,CAAA;AACvC,EAAA,MAAM,OAAA,GAAU,OAAO,IAAA,EAAK;AAC5B,EAAA,MAAM,eAAA,GAAkB,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,IAAA,CAAK,WAAA,EAAY,KAAM,OAAA,CAAQ,WAAA,EAAa,CAAA;AAE1F,EAAA,MAAM,SAAS,MAAM;AACnB,IAAA,QAAA,GAAW,OAAO,CAAA;AAClB,IAAA,SAAA,CAAU,EAAE,CAAA;AAAA,EACd,CAAA;AAEA,EAAA,uBACEC,eAAA,CAACC,UAAA,EAAA,EAAQ,YAAA,EAAY,IAAA,EACnB,QAAA,EAAA;AAAA,oBAAAC,cAAA;AAAA,MAACC,eAAA;AAAA,MAAA;AAAA,QACC,aAAa,CAAA,CAAE,iBAAA;AAAA,QACf,KAAA,EAAO,MAAA;AAAA,QACP,aAAA,EAAe,SAAA;AAAA,QACf,SAAA,EAAW,CAAC,CAAA,KAAM;AAChB,UAAA,IAAI,EAAE,GAAA,KAAQ,OAAA,IAAW,QAAA,IAAY,OAAA,IAAW,CAAC,eAAA,EAAiB;AAChE,YAAA,CAAA,CAAE,cAAA,EAAe;AACjB,YAAA,MAAA,EAAO;AAAA,UACT;AAAA,QACF;AAAA;AAAA,KACF;AAAA,oCACCC,cAAA,EAAA,EAEE,QAAA,EAAA;AAAA,MAAA,EAAE,OAAA,IAAW,QAAA,CAAA,oBACZF,cAAA,CAACG,eAAA,EAAA,EACC,QAAA,kBAAAH,cAAA,CAAC,UAAK,SAAA,EAAU,uBAAA,EAAyB,QAAA,EAAA,CAAA,CAAE,QAAA,EAAS,CAAA,EACtD,CAAA;AAAA,sBAEFA,cAAA,CAACI,eAAA,EAAA,EACE,QAAA,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,KAAM;AAClB,QAAA,MAAM,SAAA,GAAY,UAAA,CAAW,GAAA,CAAI,CAAA,CAAE,EAAE,CAAA;AACrC,QAAA,MAAM,OAAA,GAAU,QAAA,EAAU,GAAA,CAAI,CAAA,CAAE,EAAE,CAAA;AAClC,QAAA,uBACEN,eAAA;AAAA,UAACO,cAAA;AAAA,UAAA;AAAA,YAEC,OAAO,CAAA,CAAE,IAAA;AAAA,YACT,QAAA,EAAU,MAAM,QAAA,CAAS,CAAA,CAAE,EAAE,CAAA;AAAA,YAC7B,aAAA,EAAe,CAAC,CAAA,KAAM,CAAA,CAAE,cAAA,EAAe;AAAA,YACvC,SAAA,EAAU,4BAAA;AAAA,YACV,aAAA,EAAa,CAAA,aAAA,EAAgB,CAAA,CAAE,EAAE,CAAA,CAAA;AAAA,YAEjC,QAAA,EAAA;AAAA,8BAAAP,eAAA;AAAA,gBAAC,MAAA;AAAA,gBAAA;AAAA,kBACC,WAAW,CAAA,YAAA,EAAe,SAAS,CAAA,CAAA,EAAI,SAAA,GAAY,KAAK,eAAe,CAAA,CAAA;AAAA,kBACvE,KAAA,EAAO;AAAA,oBACL,aAAa,CAAA,CAAE,KAAA;AAAA,oBACf,eAAA,EAAiB,SAAA,GAAY,CAAA,CAAE,KAAA,GAAQ;AAAA,mBACzC;AAAA,kBAEC,QAAA,EAAA;AAAA,oBAAA,SAAA,oBAAaE,cAAA,CAACM,iBAAA,EAAA,EAAM,SAAA,EAAU,mBAAA,EAAoB,aAAa,CAAA,EAAG,CAAA;AAAA,oBAClE,OAAA,oBAAWN,cAAA,CAACO,iBAAA,EAAA,EAAM,SAAA,EAAU,QAAA,EAAS,OAAO,EAAE,KAAA,EAAO,CAAA,CAAE,KAAA,EAAM,EAAG;AAAA;AAAA;AAAA,eACnE;AAAA,8BACAP,cAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,gBAAA,EAAkB,YAAE,IAAA,EAAK,CAAA;AAAA,cACxC,YAAA,oBACCA,cAAA;AAAA,gBAAC,QAAA;AAAA,gBAAA;AAAA,kBACC,IAAA,EAAK,QAAA;AAAA,kBACL,OAAA,EAAS,CAAC,CAAA,KAAM;AACd,oBAAA,CAAA,CAAE,eAAA,EAAgB;AAClB,oBAAA,YAAA,EAAa;AAAA,kBACf,CAAA;AAAA,kBACA,aAAA,EAAe,CAAC,CAAA,KAAM,CAAA,CAAE,cAAA,EAAe;AAAA,kBACvC,SAAA,EAAU,8VAAA;AAAA,kBACV,OAAO,CAAA,CAAE,SAAA;AAAA,kBACT,cAAY,CAAA,CAAE,SAAA;AAAA,kBAEd,QAAA,kBAAAA,cAAA,CAACQ,sBAAA,EAAA,EAAW,SAAA,EAAU,8BAAA,EAA+B;AAAA;AAAA;AACvD;AAAA,WAAA;AAAA,UA/BG,CAAA,CAAE;AAAA,SAiCT;AAAA,MAEJ,CAAC,CAAA,EACH;AAAA,KAAA,EACF,CAAA;AAAA,IACC,OAAA,IAAW,QAAA,IAAY,CAAC,eAAA,oBACvBR,cAAA,CAAC,SAAI,SAAA,EAAU,4BAAA,EAA6B,WAAA,EAAU,qBAAA,EACnD,QAAA,EAAA,CAAC,EAAE,OAAO,CAAA,CAAE,MAAA,EAAQ,QAAA,EAAS,EAAG,GAAI,WAAA,IAAe,EAAG,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,EAAG,CAAA,qBAC/DA,cAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QAEC,IAAA,EAAK,QAAA;AAAA,QACL,SAAS,MAAM;AACb,UAAA,CAAA,CAAE,SAAS,OAAO,CAAA;AAClB,UAAA,SAAA,CAAU,EAAE,CAAA;AAAA,QACd,CAAA;AAAA,QACA,aAAA,EAAe,CAAC,CAAA,KAAM,CAAA,CAAE,cAAA,EAAe;AAAA,QACvC,SAAA,EAAU,kHAAA;AAAA,QAET,QAAA,EAAA,CAAA,CAAE,MAAM,OAAO;AAAA,OAAA;AAAA,MATX;AAAA,KAWR,CAAA,EACH;AAAA,GAAA,EAEJ,CAAA;AAEJ;AAOO,IAAM,oBAAA,GAAuBS,UAAA,CAAK,SAASC,qBAAAA,CAAqB;AAAA,EACrE,OAAA;AAAA,EACA,UAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,YAAA;AAAA,EACA,SAAA,GAAY,EAAA;AAAA,EACZ;AACF,CAAA,EAA8B;AAC5B,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAIb,eAAS,KAAK,CAAA;AAEtC,EAAA,MAAM,OAAA,GAAU,QAAQ,MAAA,CAAO,CAAC,MAAM,UAAA,CAAW,GAAA,CAAI,CAAA,CAAE,EAAE,CAAC,CAAA;AAC1D,EAAA,MAAM,SAAA,GAAY,qBAAqB,SAAS,CAAA;AAChD,EAAA,MAAM,QAAA,GAAWc,aAAuB,IAAI,CAAA;AAC5C,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAId,eAAS,KAAK,CAAA;AACpD,EAAAe,eAAA,CAAU,MAAM;AACd,IAAA,MAAM,KAAK,QAAA,CAAS,OAAA;AACpB,IAAA,IAAI,CAAC,EAAA,EAAI;AACT,IAAA,MAAM,UAAU,MAAM,cAAA,CAAe,GAAG,YAAA,GAAe,EAAA,CAAG,eAAe,CAAC,CAAA;AAC1E,IAAA,OAAA,EAAQ;AACR,IAAA,MAAM,EAAA,GAAK,IAAI,cAAA,CAAe,OAAO,CAAA;AACrC,IAAA,EAAA,CAAG,QAAQ,EAAE,CAAA;AACb,IAAA,OAAO,MAAM,GAAG,UAAA,EAAW;AAAA,EAC7B,CAAA,EAAG,CAAC,UAAA,EAAY,SAAA,EAAW,OAAO,CAAC,CAAA;AAEnC,EAAA,uBACEd,eAAA,CAACe,UAAA,EAAA,EAAQ,IAAA,EAAY,YAAA,EAAc,OAAA,EACjC,QAAA,EAAA;AAAA,oBAAAb,cAAA,CAACc,iBAAA,EAAA,EAAe,SAAO,IAAA,EACrB,QAAA,kBAAAd,cAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,IAAA,EAAK,QAAA;AAAA,QACL,WAAA,EAAU,oBAAA;AAAA,QAGV,SAAA,EAAU,4MAAA;AAAA,QAET,QAAA,EAAA,OAAA,CAAQ,MAAA,KAAW,CAAA,mBAClBA,cAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,QAAA,EACd,QAAA,kBAAAA,cAAA,CAACe,+BAAA,EAAA,EAAc,CAAA,EACjB,CAAA,mBAEAjB,eAAA,CAAAkB,mBAAA,EAAA,EACE,QAAA,EAAA;AAAA,0BAAAhB,cAAA;AAAA,YAAC,KAAA;AAAA,YAAA;AAAA,cACC,GAAA,EAAK,QAAA;AAAA,cACL,SAAA,EAAU,mEAAA;AAAA,cACV,KAAA,EAAO,EAAE,SAAA,EAAU;AAAA,cACnB,aAAA,EAAY,0BAAA;AAAA,cAEX,QAAA,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,qBACZF,eAAA;AAAA,gBAAC,MAAA;AAAA,gBAAA;AAAA,kBAEC,SAAA,EAAU,0FAAA;AAAA,kBACV,OAAO,CAAA,CAAE,IAAA;AAAA,kBACT,KAAA,EAAO,EAAE,WAAA,EAAa,CAAA,CAAE,KAAA,EAAM;AAAA,kBAE9B,QAAA,EAAA;AAAA,oCAAAE,cAAA;AAAA,sBAAC,MAAA;AAAA,sBAAA;AAAA,wBACC,SAAA,EAAU,4DAAA;AAAA,wBACV,KAAA,EAAO,EAAE,eAAA,EAAiB,CAAA,CAAE,KAAA,EAAM;AAAA,wBAElC,QAAA,kBAAAA,cAAA,CAACM,iBAAA,EAAA,EAAM,SAAA,EAAU,qBAAA,EAAsB,aAAa,CAAA,EAAG;AAAA;AAAA,qBACzD;AAAA,oCACAN,cAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,uBAAA,EAAyB,YAAE,IAAA,EAAK;AAAA;AAAA,iBAAA;AAAA,gBAX3C,CAAA,CAAE;AAAA,eAaV;AAAA;AAAA,WACH;AAAA,UACC,WAAA,oBACCA,cAAA;AAAA,YAAC,MAAA;AAAA,YAAA;AAAA,cACC,SAAA,EAAU,4GAAA;AAAA,cACV,aAAA,EAAW,IAAA;AAAA,cACX,aAAA,EAAY,6BAAA;AAAA,cACb,QAAA,EAAA;AAAA;AAAA;AAED,SAAA,EAEJ;AAAA;AAAA,KAEJ,EACF,CAAA;AAAA,IACC,IAAA,oBACCA,cAAA,CAACiB,iBAAA,EAAA,EAAe,SAAA,EAAU,eAAA,EAAgB,OAAM,OAAA,EAAQ,IAAA,EAAK,QAAA,EAAS,UAAA,EAAY,CAAA,EAChF,QAAA,kBAAAjB,cAAA;AAAA,MAAC,eAAA;AAAA,MAAA;AAAA,QACC,OAAA;AAAA,QACA,UAAA;AAAA,QACA,QAAA;AAAA,QACA,QAAA;AAAA,QACA,YAAA;AAAA,QACA;AAAA;AAAA,KACF,EACF;AAAA,GAAA,EAEJ,CAAA;AAEJ,CAAC","file":"chunk-FAXXN7KI.cjs","sourcesContent":["import { memo, useEffect, useMemo, useRef, useState } from 'react'\nimport { Check, Minus, PencilLine } from 'lucide-react'\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from '@arbidocs/react/ui'\nimport { CellHoverIcon } from './HoverIconCell'\n\n/** Chip row metrics (px): a chip is 24px tall with a 4px gap, as in the Facts labels cell. */\nconst CHIP_ROW_H = 24\nconst CHIP_GAP = 4\n\n/** Max height of the chip container: whole chip rows that fit `rowHeight`, never half a row. */\nexport function labelChipClampHeight(rowHeight: number): number {\n const rows = Math.max(1, Math.floor((rowHeight + CHIP_GAP) / (CHIP_ROW_H + CHIP_GAP)))\n return CHIP_ROW_H * rows + CHIP_GAP * (rows - 1)\n}\n\n/** One label a document can carry. `color` is any CSS colour (the host derives it from the id). */\nexport interface LabelOption {\n id: string\n name: string\n color: string\n}\n\n/** Every fixed string of the label picker. */\nexport interface LabelMultiSelectLabels {\n searchPlaceholder: string\n noLabels: string\n create: (name: string) => string\n editLabel: string\n}\n\nexport const DEFAULT_LABEL_MULTI_SELECT_LABELS: LabelMultiSelectLabels = {\n searchPlaceholder: 'Search or create...',\n noLabels: 'No labels yet',\n create: (name) => `Create “${name}”`,\n editLabel: 'Edit field',\n}\n\nexport interface LabelMultiSelectViewProps {\n options: LabelOption[]\n /** Ids of the labels applied to the row. */\n appliedIds: ReadonlySet<string>\n onToggle: (id: string) => void\n /** Create a label named `name` and apply it (the host decides what a non-member may do). */\n onCreate: (name: string) => void\n /** Opens the label editor; omit to hide the per-option edit button. */\n onEditLabels?: () => void\n /** The grid row height: clamps the chips to the rows that fully fit, with an ellipsis. */\n rowHeight?: number\n labels?: Partial<LabelMultiSelectLabels>\n}\n\nconst CHECK_BOX = 'flex shrink-0 items-center justify-center rounded border-2'\n\nexport interface LabelPickerListProps {\n options: LabelOption[]\n appliedIds: ReadonlySet<string>\n mixedIds?: ReadonlySet<string>\n onToggle: (id: string) => void\n /** Create a label named `name`; omit to hide \"Create ...\" (the picker only toggles). */\n onCreate?: (name: string) => void\n /**\n * Further ways to create from the typed name, each its own row under \"Create ...\" (e.g. one per\n * kind of tag). Enter still runs `onCreate`.\n */\n moreCreates?: { label: (name: string) => string; onCreate: (name: string) => void }[]\n /** Opens the label editor; omit to hide the per-option edit button. */\n onEditLabels?: () => void\n labels?: Partial<LabelMultiSelectLabels>\n}\n\n/**\n * Searchable list of labels with check boxes: type to filter, Enter (or the \"Create ...\" row, shown\n * whenever the typed name is not a label yet, below any labels that partly match it) creates it. Used by the grid cell and the document form field.\n */\nexport function LabelPickerList({\n options,\n appliedIds,\n mixedIds,\n onToggle,\n onCreate,\n moreCreates,\n onEditLabels,\n labels,\n}: LabelPickerListProps) {\n const l = useMemo(() => ({ ...DEFAULT_LABEL_MULTI_SELECT_LABELS, ...labels }), [labels])\n const [search, setSearch] = useState('')\n const trimmed = search.trim()\n const matchesExisting = options.some((o) => o.name.toLowerCase() === trimmed.toLowerCase())\n\n const create = () => {\n onCreate?.(trimmed)\n setSearch('')\n }\n\n return (\n <Command shouldFilter>\n <CommandInput\n placeholder={l.searchPlaceholder}\n value={search}\n onValueChange={setSearch}\n onKeyDown={(e) => {\n if (e.key === 'Enter' && onCreate && trimmed && !matchesExisting) {\n e.preventDefault()\n create()\n }\n }}\n />\n <CommandList>\n {/* Nothing matches and nothing to create: say so. A new name is offered below instead. */}\n {!(trimmed && onCreate) && (\n <CommandEmpty>\n <span className=\"text-muted-foreground\">{l.noLabels}</span>\n </CommandEmpty>\n )}\n <CommandGroup>\n {options.map((o) => {\n const isApplied = appliedIds.has(o.id)\n const isMixed = mixedIds?.has(o.id)\n return (\n <CommandItem\n key={o.id}\n value={o.name}\n onSelect={() => onToggle(o.id)}\n onPointerDown={(e) => e.preventDefault()}\n className=\"group/label cursor-pointer\"\n data-testid={`label-select-${o.id}`}\n >\n <span\n className={`mr-2 size-4 ${CHECK_BOX} ${isApplied ? '' : 'bg-background'}`}\n style={{\n borderColor: o.color,\n backgroundColor: isApplied ? o.color : undefined,\n }}\n >\n {isApplied && <Check className=\"size-3 text-white\" strokeWidth={3} />}\n {isMixed && <Minus className=\"size-3\" style={{ color: o.color }} />}\n </span>\n <span className=\"flex-1 text-sm\">{o.name}</span>\n {onEditLabels && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation()\n onEditLabels()\n }}\n onPointerDown={(e) => e.preventDefault()}\n className=\"shrink-0 rounded p-0.5 opacity-0 hover:bg-muted focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring group-hover/label:opacity-100 group-data-[selected=true]/label:opacity-100 pointer-coarse:flex pointer-coarse:size-11 pointer-coarse:items-center pointer-coarse:justify-center pointer-coarse:opacity-100\"\n title={l.editLabel}\n aria-label={l.editLabel}\n >\n <PencilLine className=\"size-3 text-muted-foreground\" />\n </button>\n )}\n </CommandItem>\n )\n })}\n </CommandGroup>\n </CommandList>\n {trimmed && onCreate && !matchesExisting && (\n <div className=\"border-t border-border p-1\" data-slot=\"label-picker-create\">\n {[{ label: l.create, onCreate }, ...(moreCreates ?? [])].map((c, i) => (\n <button\n key={i}\n type=\"button\"\n onClick={() => {\n c.onCreate(trimmed)\n setSearch('')\n }}\n onPointerDown={(e) => e.preventDefault()}\n className=\"w-full cursor-pointer rounded px-2 py-1.5 text-left text-sm text-primary hover:bg-accent pointer-coarse:min-h-11\"\n >\n {c.label(trimmed)}\n </button>\n ))}\n </div>\n )}\n </Command>\n )\n}\n\n/**\n * Labels column cell: applied labels as bordered chips; click (or Enter) opens a popover to\n * toggle labels or type a new name and press Enter to create it. Empty cells show a pencil on\n * hover, keyboard focus and touch.\n */\nexport const LabelMultiSelectView = memo(function LabelMultiSelectView({\n options,\n appliedIds,\n onToggle,\n onCreate,\n onEditLabels,\n rowHeight = 52,\n labels,\n}: LabelMultiSelectViewProps) {\n const [open, setOpen] = useState(false)\n\n const applied = options.filter((o) => appliedIds.has(o.id))\n const maxHeight = labelChipClampHeight(rowHeight)\n const chipsRef = useRef<HTMLDivElement>(null)\n const [hasOverflow, setHasOverflow] = useState(false)\n useEffect(() => {\n const el = chipsRef.current\n if (!el) return\n const measure = () => setHasOverflow(el.scrollHeight > el.clientHeight + 1)\n measure()\n const ro = new ResizeObserver(measure)\n ro.observe(el)\n return () => ro.disconnect()\n }, [appliedIds, maxHeight, options])\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n data-slot=\"label-multi-select\"\n // No vertical clip/padding: at the minimum row height an `overflow-hidden` button would\n // crop the pills. The chip container is clamped to whole chip rows instead.\n className=\"group relative flex h-full w-full min-w-0 cursor-pointer items-center gap-1 pr-4 text-left hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring\"\n >\n {applied.length === 0 ? (\n <span className=\"flex-1\">\n <CellHoverIcon />\n </span>\n ) : (\n <>\n <div\n ref={chipsRef}\n className=\"flex min-w-0 flex-1 flex-wrap content-start gap-1 overflow-hidden\"\n style={{ maxHeight }}\n data-testid=\"label-multi-select-chips\"\n >\n {applied.map((o) => (\n <span\n key={o.id}\n className=\"inline-flex shrink-0 items-center gap-1 rounded border px-1.5 py-0.5 text-xs font-medium\"\n title={o.name}\n style={{ borderColor: o.color }}\n >\n <span\n className=\"flex size-3.5 shrink-0 items-center justify-center rounded\"\n style={{ backgroundColor: o.color }}\n >\n <Check className=\"size-2.5 text-white\" strokeWidth={3} />\n </span>\n <span className=\"max-w-[80px] truncate\">{o.name}</span>\n </span>\n ))}\n </div>\n {hasOverflow && (\n <span\n className=\"pointer-events-none absolute bottom-0.5 right-0.5 text-xs font-semibold leading-none text-muted-foreground\"\n aria-hidden\n data-testid=\"label-multi-select-overflow\"\n >\n …\n </span>\n )}\n </>\n )}\n </button>\n </PopoverTrigger>\n {open && (\n <PopoverContent className=\"w-[360px] p-0\" align=\"start\" side=\"bottom\" sideOffset={4}>\n <LabelPickerList\n options={options}\n appliedIds={appliedIds}\n onToggle={onToggle}\n onCreate={onCreate}\n onEditLabels={onEditLabels}\n labels={labels}\n />\n </PopoverContent>\n )}\n </Popover>\n )\n})\n"]}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { testIdOr, prefixedTestId } from './chunk-7F6CBP3Z.js';
|
|
3
|
-
import { memo, useMemo, useRef, useCallback, useLayoutEffect
|
|
3
|
+
import { memo, useMemo, useRef, useCallback, useLayoutEffect } from 'react';
|
|
4
4
|
import { ChevronLeft, ChevronRight, FileUp, Plus, Search, Blend, Quote, X, Loader2, AlertCircle, TagIcon } from 'lucide-react';
|
|
5
|
-
import { Button, cn, Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, Input, DialogFooter } from '@arbidocs/react/ui';
|
|
5
|
+
import { Button, cn, MarkdownRenderer, Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, Input, DialogFooter } from '@arbidocs/react/ui';
|
|
6
6
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
7
7
|
|
|
8
8
|
// src/retrieval/highlight.ts
|
|
@@ -744,19 +744,144 @@ function ApplyLabelButton({
|
|
|
744
744
|
}
|
|
745
745
|
);
|
|
746
746
|
}
|
|
747
|
-
function
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
return
|
|
747
|
+
var SearchSnippet = memo(function SearchSnippet2({
|
|
748
|
+
content,
|
|
749
|
+
terms
|
|
750
|
+
}) {
|
|
751
|
+
return /* @__PURE__ */ jsx(MarkdownRenderer, { children: highlightTerms(content, terms) });
|
|
752
|
+
});
|
|
753
|
+
var renderSearchSnippet = (content, terms) => /* @__PURE__ */ jsx(SearchSnippet, { content, terms });
|
|
754
|
+
|
|
755
|
+
// src/retrieval/search-results.ts
|
|
756
|
+
function extractQuotedTerms(query) {
|
|
757
|
+
const doubleQuoted = query.match(/"([^"]+)"/g) || [];
|
|
758
|
+
const singleQuoted = query.match(/'([^']+)'/g) || [];
|
|
759
|
+
const allMatches = [...doubleQuoted, ...singleQuoted];
|
|
760
|
+
if (allMatches.length === 0) return [];
|
|
761
|
+
return allMatches.map((m) => m.slice(1, -1).toLowerCase()).filter((t) => t.length > 0);
|
|
752
762
|
}
|
|
753
|
-
function
|
|
754
|
-
const
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
763
|
+
function getSearchMatchHint(query) {
|
|
764
|
+
const thresholdHint = "Low shows all matches; High keeps the strongest and any passage with your words.";
|
|
765
|
+
if (extractQuotedTerms(query).length > 0) {
|
|
766
|
+
return `Showing exact matches for the quoted text. Remove the quotes to also include passages that match by meaning. ${thresholdHint}`;
|
|
767
|
+
}
|
|
768
|
+
return `Matches keywords and meaning, so some hits won't contain the word. Quote a phrase for exact matches only. ${thresholdHint}`;
|
|
769
|
+
}
|
|
770
|
+
var HIGHLIGHT_STOPWORDS = /* @__PURE__ */ new Set([
|
|
771
|
+
"the",
|
|
772
|
+
"a",
|
|
773
|
+
"an",
|
|
774
|
+
"and",
|
|
775
|
+
"or",
|
|
776
|
+
"but",
|
|
777
|
+
"of",
|
|
778
|
+
"to",
|
|
779
|
+
"in",
|
|
780
|
+
"on",
|
|
781
|
+
"for",
|
|
782
|
+
"with",
|
|
783
|
+
"as",
|
|
784
|
+
"at",
|
|
785
|
+
"by",
|
|
786
|
+
"from",
|
|
787
|
+
"is",
|
|
788
|
+
"are",
|
|
789
|
+
"was",
|
|
790
|
+
"were",
|
|
791
|
+
"be",
|
|
792
|
+
"been",
|
|
793
|
+
"being",
|
|
794
|
+
"what",
|
|
795
|
+
"which",
|
|
796
|
+
"who",
|
|
797
|
+
"whom",
|
|
798
|
+
"whose",
|
|
799
|
+
"how",
|
|
800
|
+
"when",
|
|
801
|
+
"where",
|
|
802
|
+
"why",
|
|
803
|
+
"did",
|
|
804
|
+
"do",
|
|
805
|
+
"does",
|
|
806
|
+
"his",
|
|
807
|
+
"her",
|
|
808
|
+
"their",
|
|
809
|
+
"its",
|
|
810
|
+
"this",
|
|
811
|
+
"that",
|
|
812
|
+
"these",
|
|
813
|
+
"those",
|
|
814
|
+
"it",
|
|
815
|
+
"he",
|
|
816
|
+
"she",
|
|
817
|
+
"they",
|
|
818
|
+
"we",
|
|
819
|
+
"you",
|
|
820
|
+
"about",
|
|
821
|
+
"into",
|
|
822
|
+
"over",
|
|
823
|
+
"than",
|
|
824
|
+
"then",
|
|
825
|
+
"them",
|
|
826
|
+
"have",
|
|
827
|
+
"has",
|
|
828
|
+
"had",
|
|
829
|
+
"will",
|
|
830
|
+
"would",
|
|
831
|
+
"can",
|
|
832
|
+
"could",
|
|
833
|
+
"should",
|
|
834
|
+
"may",
|
|
835
|
+
"might"
|
|
836
|
+
]);
|
|
837
|
+
function extractHighlightTerms(query) {
|
|
838
|
+
const quoted = extractQuotedTerms(query);
|
|
839
|
+
const withoutQuoted = query.replace(/"[^"]+"|'[^']+'/g, " ");
|
|
840
|
+
const words = withoutQuoted.toLowerCase().split(/[^\p{L}\p{N}]+/u).filter((w) => w.length > 2 && !HIGHLIGHT_STOPWORDS.has(w));
|
|
841
|
+
return Array.from(/* @__PURE__ */ new Set([...quoted, ...words]));
|
|
842
|
+
}
|
|
843
|
+
function isMeaningMatch(content, terms) {
|
|
844
|
+
if (terms.length === 0) return false;
|
|
845
|
+
const lowered = content.toLowerCase();
|
|
846
|
+
return !terms.some((term) => lowered.includes(term));
|
|
847
|
+
}
|
|
848
|
+
function passesRelevanceCutoff(hit, cutoff, terms) {
|
|
849
|
+
if (hit.score >= cutoff) return true;
|
|
850
|
+
return terms.length > 0 && !isMeaningMatch(hit.content, terms);
|
|
851
|
+
}
|
|
852
|
+
function groupSearchResults(hits, terms = []) {
|
|
853
|
+
const groups = /* @__PURE__ */ new Map();
|
|
854
|
+
const docIds = [];
|
|
855
|
+
for (const hit of hits) {
|
|
856
|
+
let group = groups.get(hit.docId);
|
|
857
|
+
if (!group) {
|
|
858
|
+
group = { docId: hit.docId, docTitle: hit.docTitle, maxScore: hit.score, results: [] };
|
|
859
|
+
groups.set(hit.docId, group);
|
|
860
|
+
docIds.push(hit.docId);
|
|
861
|
+
}
|
|
862
|
+
group.results.push(hit);
|
|
863
|
+
if (hit.score > group.maxScore) group.maxScore = hit.score;
|
|
864
|
+
}
|
|
865
|
+
const tierOf = (hit) => isMeaningMatch(hit.content, terms) ? 1 : 0;
|
|
866
|
+
const groupTier = /* @__PURE__ */ new Map();
|
|
867
|
+
for (const group of groups.values()) {
|
|
868
|
+
group.results.sort((a, b) => {
|
|
869
|
+
const pageA = a.page || 0;
|
|
870
|
+
const pageB = b.page || 0;
|
|
871
|
+
if (pageA !== pageB) return pageA - pageB;
|
|
872
|
+
return a.index - b.index;
|
|
873
|
+
});
|
|
874
|
+
if (terms.length > 0) {
|
|
875
|
+
group.results.sort((a, b) => tierOf(a) - tierOf(b));
|
|
876
|
+
groupTier.set(group, tierOf(group.results[0]));
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
const sorted = Array.from(groups.values()).sort(
|
|
880
|
+
(a, b) => (groupTier.get(a) ?? 0) - (groupTier.get(b) ?? 0) || b.maxScore - a.maxScore
|
|
881
|
+
);
|
|
882
|
+
return { groups: sorted, docIds };
|
|
758
883
|
}
|
|
759
884
|
|
|
760
|
-
export { ApplyLabelButton, ApplyLabelDialog, DEFAULT_APPLY_LABEL_DIALOG_LABELS, DEFAULT_RELEVANCE_STEPS, DEFAULT_SEARCH_BAR_LABELS, DEFAULT_SEARCH_EMPTY_STATE_LABELS, DEFAULT_SEARCH_GROUP_HEADER_LABELS, DEFAULT_SEARCH_NO_RESULTS_LABELS, DEFAULT_SEARCH_PAGINATION_LABELS, DEFAULT_SEARCH_TOTALS_LABELS, DOCUMENT_SEARCH_NOUNS,
|
|
761
|
-
//# sourceMappingURL=chunk-
|
|
762
|
-
//# sourceMappingURL=chunk-
|
|
885
|
+
export { ApplyLabelButton, ApplyLabelDialog, DEFAULT_APPLY_LABEL_DIALOG_LABELS, DEFAULT_RELEVANCE_STEPS, DEFAULT_SEARCH_BAR_LABELS, DEFAULT_SEARCH_EMPTY_STATE_LABELS, DEFAULT_SEARCH_GROUP_HEADER_LABELS, DEFAULT_SEARCH_NO_RESULTS_LABELS, DEFAULT_SEARCH_PAGINATION_LABELS, DEFAULT_SEARCH_TOTALS_LABELS, DOCUMENT_SEARCH_NOUNS, RelevanceThreshold, SearchBar, SearchControlsBar, SearchEmptyState, SearchErrorBanner, SearchGroupCard, SearchGroupHeader, SearchNoResults, SearchPageBody, SearchPageFrame, SearchPageHeader, SearchPagination, SearchPillToggle, SearchResultList, SearchResultsInner, SearchResultsMain, SearchSnippet, SearchToolbarRow, SearchTotalsHeadline, extractHighlightTerms, extractQuotedTerms, getPageNumbers, getSearchMatchHint, groupSearchResults, highlightTerms, isMeaningMatch, passesRelevanceCutoff, renderSearchSnippet, searchNouns, stripMarkdownLinks };
|
|
886
|
+
//# sourceMappingURL=chunk-G4IYES7G.js.map
|
|
887
|
+
//# sourceMappingURL=chunk-G4IYES7G.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/retrieval/highlight.ts","../src/retrieval/SearchPagination.tsx","../src/retrieval/SearchGroupHeader.tsx","../src/retrieval/SearchEmptyState.tsx","../src/retrieval/SearchPage.tsx","../src/retrieval/SearchSnippet.tsx","../src/retrieval/search-results.ts"],"names":["SearchPagination","memo","SearchGroupHeader","jsxs","cn","jsx","ChevronRight","Button","Search","Fragment","SearchSnippet"],"mappings":"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","file":"chunk-G4IYES7G.js","sourcesContent":["/**\n * Flatten inline markdown links to their visible label: `[label](url)` -> `label`\n * (and image `` -> `alt`).\n *\n * Search snippets must not navigate away when clicked, and highlighting wraps matches in\n * `<mark>`: doing that over raw markdown would inject `<mark>` inside link URLs that contain a\n * query word, corrupting both the href and the text. Removing the URLs first makes it safe.\n */\nexport function stripMarkdownLinks(text: string): string {\n return text.replace(/!?\\[([^\\]]+)\\]\\([^)]*\\)/g, '$1')\n}\n\n/**\n * Prepare a snippet for markdown rendering: links flattened, and every (case-insensitive)\n * occurrence of a query term wrapped in `<mark>`. The renderer must allow `mark` through its\n * sanitizer.\n */\nexport function highlightTerms(content: string, terms: string[]): string {\n const plain = stripMarkdownLinks(content)\n if (terms.length === 0) return plain\n const escaped = terms.map((t) => t.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'))\n return plain.replace(new RegExp(`(${escaped.join('|')})`, 'gi'), '<mark>$1</mark>')\n}\n\n/**\n * Page numbers for a pagination control: first + last + a window around the current page.\n * getPageNumbers(1, 3) -> [1, 2, 3]\n * getPageNumbers(7, 50) -> [1, 'ellipsis', 6, 7, 8, 'ellipsis', 50]\n */\nexport function getPageNumbers(current: number, total: number): (number | 'ellipsis')[] {\n if (total <= 7) return Array.from({ length: total }, (_, i) => i + 1)\n\n const pages: (number | 'ellipsis')[] = [1]\n const windowStart = Math.max(2, current - 1)\n const windowEnd = Math.min(total - 1, current + 1)\n\n if (windowStart > 2) pages.push('ellipsis')\n for (let p = windowStart; p <= windowEnd; p++) pages.push(p)\n if (windowEnd < total - 1) pages.push('ellipsis')\n\n pages.push(total)\n return pages\n}\n","import { memo } from 'react'\nimport { ChevronLeft, ChevronRight } from 'lucide-react'\nimport { Button, cn } from '@arbidocs/react/ui'\nimport { testIdOr } from '../chat/test-id'\nimport { getPageNumbers } from './highlight'\n\nexport interface SearchPaginationLabels {\n navigation: string\n previous: string\n next: string\n page: (page: number) => string\n}\n\nexport const DEFAULT_SEARCH_PAGINATION_LABELS: SearchPaginationLabels = {\n navigation: 'Search results pagination',\n previous: 'Previous page',\n next: 'Next page',\n page: (page) => `Page ${page}`,\n}\n\nexport interface SearchPaginationTestIds {\n root: string\n /** Builds the id of a page button from its number. */\n page: (page: number) => string\n}\n\nexport interface SearchPaginationProps {\n currentPage: number\n totalPages: number\n onPageChange: (page: number) => void\n labels?: Partial<SearchPaginationLabels>\n testIds?: Partial<SearchPaginationTestIds>\n className?: string\n}\n\nexport const SearchPagination = memo(function SearchPagination({\n currentPage,\n totalPages,\n onPageChange,\n labels,\n testIds,\n className,\n}: SearchPaginationProps) {\n const l = { ...DEFAULT_SEARCH_PAGINATION_LABELS, ...labels }\n if (totalPages <= 1) return null\n const pages = getPageNumbers(currentPage, totalPages)\n return (\n <nav\n className={cn('mt-6 mb-2 flex items-center justify-center gap-1', className)}\n aria-label={l.navigation}\n data-testid={testIdOr(testIds?.root, { testId: 'smart-search-pagination' })}\n data-slot=\"search-pagination\"\n >\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-8 px-2 pointer-coarse:h-11 pointer-coarse:min-w-11\"\n onClick={() => onPageChange(currentPage - 1)}\n disabled={currentPage <= 1}\n aria-label={l.previous}\n >\n <ChevronLeft className=\"size-4\" />\n </Button>\n {pages.map((p, i) =>\n p === 'ellipsis' ? (\n <span\n key={`ellipsis-${i}`}\n className=\"select-none px-2 text-sm text-muted-foreground\"\n aria-hidden\n >\n …\n </span>\n ) : (\n <Button\n key={p}\n variant={p === currentPage ? 'default' : 'ghost'}\n size=\"sm\"\n className=\"h-8 min-w-8 px-2 pointer-coarse:h-11 pointer-coarse:min-w-11\"\n onClick={() => onPageChange(p)}\n aria-current={p === currentPage ? 'page' : undefined}\n aria-label={l.page(p)}\n data-testid={testIdOr(testIds?.page?.(p), { testId: `smart-search-page-${p}` })}\n >\n {p}\n </Button>\n )\n )}\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-8 px-2 pointer-coarse:h-11 pointer-coarse:min-w-11\"\n onClick={() => onPageChange(currentPage + 1)}\n disabled={currentPage >= totalPages}\n aria-label={l.next}\n >\n <ChevronRight className=\"size-4\" />\n </Button>\n </nav>\n )\n})\n","import { memo, type ReactNode } from 'react'\nimport { ChevronRight } from 'lucide-react'\nimport { cn } from '@arbidocs/react/ui'\nimport { testIdOr } from '../chat/test-id'\n\nexport interface SearchGroupHeaderLabels {\n hit: string\n hits: string\n}\n\nexport const DEFAULT_SEARCH_GROUP_HEADER_LABELS: SearchGroupHeaderLabels = {\n hit: 'hit',\n hits: 'hits',\n}\n\nexport interface SearchGroupHeaderProps {\n /** Group key, handed back to `onToggle`. */\n groupId: string\n hitCount: number\n isExpanded: boolean\n onToggle: (groupId: string) => void\n /** The source pill; clicks on it do not toggle the group. */\n source: ReactNode\n labels?: Partial<SearchGroupHeaderLabels>\n /** Defaults to `search-result-group-toggle-${groupId}`. */\n testId?: string\n className?: string\n}\n\n/** Collapsible group row: chevron + source + hit count. The whole row toggles. */\nexport const SearchGroupHeader = memo(function SearchGroupHeader({\n groupId,\n hitCount,\n isExpanded,\n onToggle,\n source,\n labels,\n testId,\n className,\n}: SearchGroupHeaderProps) {\n const l = { ...DEFAULT_SEARCH_GROUP_HEADER_LABELS, ...labels }\n const toggle = () => onToggle(groupId)\n return (\n <div\n role=\"button\"\n tabIndex={0}\n onClick={toggle}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n toggle()\n }\n }}\n aria-expanded={isExpanded}\n className={cn(\n 'flex cursor-pointer items-center gap-2 px-3 py-1.5 pointer-coarse:min-h-11 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',\n isExpanded && 'border-b border-border',\n className\n )}\n data-testid={testIdOr(testId, { testId: `search-result-group-toggle-${groupId}` })}\n data-slot=\"search-group-header\"\n >\n <ChevronRight\n className={cn(\n 'size-4 shrink-0 text-muted-foreground transition-transform',\n isExpanded && 'rotate-90'\n )}\n />\n <span className=\"min-w-0\" onClick={(e) => e.stopPropagation()}>\n {source}\n </span>\n <span className=\"shrink-0 text-sm text-muted-foreground\">\n {hitCount} {hitCount === 1 ? l.hit : l.hits}\n </span>\n </div>\n )\n})\n","import type { ReactNode } from 'react'\nimport { Blend, FileUp, Plus, Quote, Search, type LucideIcon } from 'lucide-react'\nimport { cn } from '@arbidocs/react/ui'\nimport { testIdOr } from '../chat/test-id'\n\nexport interface SearchEmptyNouns {\n singular: string\n plural: string\n /** The unit a hit returns (passage / fact). */\n hit: string\n hits: string\n emptyTitle: string\n emptyHint: ReactNode\n EmptyIcon: LucideIcon\n}\n\nexport const DOCUMENT_SEARCH_NOUNS: SearchEmptyNouns = {\n singular: 'document',\n plural: 'documents',\n hit: 'passage',\n hits: 'passages',\n emptyTitle: 'No documents to search yet',\n emptyHint: (\n <>\n Add files under <span className=\"font-medium text-foreground/80\">“Files”</span>, then come\n back to search their full text by keyword or meaning.\n </>\n ),\n EmptyIcon: FileUp,\n}\n\n/** Nouns for searching a custom collection (e.g. facts). `singular`/`plural` are lower case. */\nexport function searchNouns(\n singular: string,\n plural: string,\n addHint: ReactNode,\n EmptyIcon: LucideIcon = Plus\n): SearchEmptyNouns {\n return {\n singular,\n plural,\n hit: singular,\n hits: plural,\n emptyTitle: `No ${plural} to search yet`,\n emptyHint: addHint,\n EmptyIcon,\n }\n}\n\nexport interface SearchEmptyStateLabels {\n /** Title when there are items. */\n title: (nouns: SearchEmptyNouns) => string\n /** Intro sentence; receives the count and the nouns. */\n intro: (count: number, nouns: SearchEmptyNouns) => ReactNode\n hybridTitle: string\n hybridBody: (nouns: SearchEmptyNouns) => string\n phraseTitle: string\n phraseBefore: string\n phraseExample: string\n phraseAfter: (nouns: SearchEmptyNouns) => string\n}\n\nexport const DEFAULT_SEARCH_EMPTY_STATE_LABELS: SearchEmptyStateLabels = {\n title: (n) => `Search across your ${n.plural}`,\n intro: (count, n) => (\n <>\n Find any {n.hit} across{' '}\n <span className=\"font-medium text-foreground/80\">\n {count.toLocaleString()} {count === 1 ? n.singular : n.plural}\n </span>{' '}\n — by keyword, by meaning, or both.\n </>\n ),\n hybridTitle: 'Words and meaning, together',\n hybridBody: (n) =>\n `Every search matches exact words and meaning, so ${n.hits} worded differently are still found.`,\n phraseTitle: 'Quote an exact phrase',\n phraseBefore: 'Wrap a phrase in double quotes, like ',\n phraseExample: '\"force majeure\"',\n phraseAfter: (n) => `, to return only ${n.hits} containing it.`,\n}\n\nexport interface SearchEmptyStateProps {\n /** Number of searchable items in the workspace. */\n count: number\n /** Defaults to documents. */\n nouns?: SearchEmptyNouns\n labels?: Partial<SearchEmptyStateLabels>\n testId?: string\n className?: string\n}\n\n/** Shown before the first search: explains hybrid matching and quoted phrases. */\nexport function SearchEmptyState({\n count,\n nouns = DOCUMENT_SEARCH_NOUNS,\n labels,\n testId,\n className,\n}: SearchEmptyStateProps) {\n const l = { ...DEFAULT_SEARCH_EMPTY_STATE_LABELS, ...labels }\n const hasItems = count > 0\n const Icon = hasItems ? Search : nouns.EmptyIcon\n\n return (\n <div\n className={cn('flex justify-center px-10 pb-10 pt-6', className)}\n data-testid={testIdOr(testId, { testId: 'smart-search-empty-state' })}\n data-slot=\"search-empty-state\"\n >\n <div className=\"w-full max-w-xl text-center\">\n <div\n className={cn(\n 'mx-auto mb-4 flex size-12 items-center justify-center rounded-lg',\n hasItems ? 'bg-ai-soft text-ai-ink' : 'bg-muted text-muted-foreground'\n )}\n >\n <Icon className=\"size-6\" />\n </div>\n\n {hasItems ? (\n <>\n <h2 className=\"mt-2 text-xl font-semibold text-foreground\">{l.title(nouns)}</h2>\n <p className=\"mt-2 text-sm text-muted-foreground\">{l.intro(count, nouns)}</p>\n\n <div className=\"mt-7 grid gap-3 text-left @xl:grid-cols-2\">\n <div className=\"rounded-lg bg-muted p-3\">\n <div className=\"flex items-center gap-1.5 text-sm font-medium text-foreground\">\n <Blend className=\"size-4 text-ai-ink\" />\n {l.hybridTitle}\n </div>\n <p className=\"mt-1 text-sm leading-snug text-muted-foreground\">\n {l.hybridBody(nouns)}\n </p>\n </div>\n <div className=\"rounded-lg bg-muted p-3\">\n <div className=\"flex items-center gap-1.5 text-sm font-medium text-foreground\">\n <Quote className=\"size-4 text-ai-ink\" />\n {l.phraseTitle}\n </div>\n <p className=\"mt-1 text-sm leading-snug text-muted-foreground\">\n {l.phraseBefore}\n <code className=\"rounded bg-background px-1 py-0.5 font-mono text-sm text-foreground/90\">\n {l.phraseExample}\n </code>\n {l.phraseAfter(nouns)}\n </p>\n </div>\n </div>\n </>\n ) : (\n <>\n <h2 className=\"text-xl font-semibold text-foreground\">{nouns.emptyTitle}</h2>\n <p className=\"mx-auto mt-1.5 max-w-sm text-sm text-muted-foreground\">\n {nouns.emptyHint}\n </p>\n </>\n )}\n </div>\n </div>\n )\n}\n","import { useCallback, useLayoutEffect, useMemo, useRef, type ReactNode, type Ref } from 'react'\nimport { AlertCircle, Loader2, Search, TagIcon, X } from 'lucide-react'\nimport {\n Button,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n Input,\n cn,\n} from '@arbidocs/react/ui'\nimport { prefixedTestId, testIdOr } from '../chat/test-id'\n\n/* -------------------------------------------------------------------------- */\n/* Page frame */\n/* -------------------------------------------------------------------------- */\n\n/** Column that fills the Smart Search page (padded when standalone, flush when embedded). */\nexport function SearchPageFrame({\n isEmbedded,\n testId = 'smart-search',\n children,\n}: {\n isEmbedded?: boolean\n testId?: string\n children: ReactNode\n}) {\n return (\n <div\n data-slot=\"search-page\"\n data-testid={testId}\n className={cn('flex h-full flex-col', !isEmbedded && 'px-4')}\n >\n {children}\n </div>\n )\n}\n\n/** Sticky header slot; `-mx-4` cancels the frame's padding so the tab sits at the page inset. */\nexport function SearchPageHeader({ children }: { children: ReactNode }) {\n return (\n <div data-slot=\"search-page-header\" className=\"sticky top-0 z-10 -mx-4 bg-background\">\n {children}\n </div>\n )\n}\n\n/** Everything under the header. */\nexport function SearchPageBody({ children }: { children: ReactNode }) {\n return (\n <div data-slot=\"search-page-body\" className=\"flex min-h-0 flex-1 flex-col\">\n {children}\n </div>\n )\n}\n\n/** Thin row above the search bar (the embedded view puts the grouping toggle here). */\nexport function SearchToolbarRow({ children }: { children: ReactNode }) {\n return (\n <div\n data-slot=\"search-toolbar-row\"\n className=\"group flex h-8 items-center gap-2 border-b border-border/60 bg-background pl-5 pr-3\"\n >\n <div className=\"ml-auto flex shrink-0 items-center\">{children}</div>\n </div>\n )\n}\n\n/** Scrolling results area with its inner padding. */\nexport function SearchResultsMain({ children }: { children: ReactNode }) {\n return (\n <main data-slot=\"search-results-main\" className=\"flex-1 overflow-auto\">\n {children}\n </main>\n )\n}\n\n/** Padded wrapper of the hits. */\nexport function SearchResultsInner({ children }: { children: ReactNode }) {\n return <div className=\"w-full px-6 pb-6 pt-1\">{children}</div>\n}\n\n/** Vertical list of result rows or group cards. */\nexport function SearchResultList({ testId, children }: { testId?: string; children: ReactNode }) {\n return (\n <div className=\"space-y-3\" data-testid={testId}>\n {children}\n </div>\n )\n}\n\n/** One document's collapsible group: header (the toggle) plus the expanded hits. */\nexport function SearchGroupCard({\n testId,\n header,\n isExpanded,\n children,\n}: {\n testId?: string\n header: ReactNode\n isExpanded: boolean\n children: ReactNode\n}) {\n return (\n <div\n data-slot=\"search-group-card\"\n className=\"rounded border border-border transition-colors\"\n data-testid={testId}\n >\n {header}\n {isExpanded && <div className=\"space-y-3 p-3\">{children}</div>}\n </div>\n )\n}\n\n/* -------------------------------------------------------------------------- */\n/* Search bar */\n/* -------------------------------------------------------------------------- */\n\nexport interface SearchBarLabels {\n search: string\n clear: string\n submit: string\n}\n\nexport const DEFAULT_SEARCH_BAR_LABELS: SearchBarLabels = {\n search: 'Search:',\n clear: 'Clear search',\n submit: 'Search',\n}\n\nexport interface SearchBarProps {\n query: string\n onQueryChange: (query: string) => void\n /** Enter (without Shift) or the submit button. */\n onSubmit: () => void\n onClear: () => void\n canSubmit: boolean\n isSearching: boolean\n placeholder?: string\n /** Tooltip of the submit button (e.g. why it is disabled). */\n submitTitle?: string\n /** Message under the box (e.g. \"too many documents selected\"). */\n notice?: ReactNode\n noticeTestId?: string\n inputId?: string\n testIds?: { input?: string; clear?: string; submit?: string }\n /** Lets the host refocus the box and reset its height after a clear. */\n inputRef?: Ref<HTMLTextAreaElement>\n isEmbedded?: boolean\n labels?: Partial<SearchBarLabels>\n}\n\n/** The bordered, auto-growing query box with an inline clear and submit. */\nexport function SearchBar({\n query,\n onQueryChange,\n onSubmit,\n onClear,\n canSubmit,\n isSearching,\n placeholder,\n submitTitle,\n notice,\n noticeTestId,\n inputId = 'smart-search-input',\n testIds,\n inputRef,\n isEmbedded,\n labels,\n}: SearchBarProps) {\n const l = useMemo(() => ({ ...DEFAULT_SEARCH_BAR_LABELS, ...labels }), [labels])\n // The field grows with its content, and an empty field with its (possibly wrapping) placeholder:\n // a fixed single row cut the second line of a long placeholder on phones.\n const fieldRef = useRef<HTMLTextAreaElement | null>(null)\n const setRefs = useCallback(\n (el: HTMLTextAreaElement | null) => {\n fieldRef.current = el\n if (typeof inputRef === 'function') inputRef(el)\n else if (inputRef) (inputRef as { current: HTMLTextAreaElement | null }).current = el\n },\n [inputRef]\n )\n useLayoutEffect(() => {\n const el = fieldRef.current\n if (!el) return\n const resize = () => {\n el.style.height = 'auto'\n el.style.height = `${el.scrollHeight}px`\n }\n resize()\n if (typeof ResizeObserver === 'undefined') return\n let lastWidth = el.clientWidth\n const observer = new ResizeObserver(() => {\n if (el.clientWidth === lastWidth) return\n lastWidth = el.clientWidth\n resize()\n })\n observer.observe(el)\n return () => observer.disconnect()\n }, [query, placeholder])\n return (\n <div data-slot=\"search-bar\" className={cn('pl-6 pr-4', isEmbedded ? 'pb-4 pt-6' : 'py-4')}>\n <form\n onSubmit={(e) => {\n e.preventDefault()\n onSubmit()\n }}\n className=\"mx-auto flex w-full max-w-2xl items-center gap-3\"\n >\n <label htmlFor={inputId} className=\"sr-only\">\n {l.search}\n </label>\n <div className=\"flex min-w-0 flex-1 items-start gap-2 rounded-lg border border-border bg-background px-3.5 py-2.5 transition-colors focus-within:border-ring focus-within:ring-2 focus-within:ring-ring\">\n <textarea\n id={inputId}\n ref={setRefs}\n rows={1}\n value={query}\n onChange={(e) => {\n onQueryChange(e.target.value)\n e.target.style.height = 'auto'\n e.target.style.height = `${e.target.scrollHeight}px`\n }}\n onKeyDown={(e) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n onSubmit()\n }\n }}\n placeholder={placeholder}\n className=\"flex-1 resize-none overflow-hidden border-0 bg-transparent p-0 pointer-coarse:min-h-11 pointer-coarse:py-2.5 text-base leading-relaxed text-foreground outline-none placeholder:text-muted-foreground\"\n data-testid={testIdOr(testIds?.input, { testId: 'smart-search-input' })}\n />\n <div className=\"flex shrink-0 items-center gap-1\">\n {query && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"size-7 text-muted-foreground hover:text-foreground pointer-coarse:size-11\"\n onClick={onClear}\n aria-label={l.clear}\n title={l.clear}\n data-testid={testIdOr(testIds?.clear, { testId: 'smart-search-clear-button' })}\n >\n <X className=\"size-4\" />\n </Button>\n )}\n <Button\n type=\"submit\"\n size=\"sm\"\n disabled={!canSubmit}\n className=\"h-8 gap-1.5 px-3 text-sm pointer-coarse:h-11\"\n data-testid={testIdOr(testIds?.submit, { testId: 'smart-search-submit-button' })}\n title={submitTitle ?? l.submit}\n aria-label={l.submit}\n >\n {isSearching ? (\n <Loader2 className=\"size-4 animate-spin\" />\n ) : (\n <Search className=\"size-4\" />\n )}\n {l.submit}\n </Button>\n </div>\n {notice && (\n <p\n className=\"mt-2 text-sm text-destructive\"\n data-testid={testIdOr(noticeTestId, { testId: 'smart-search-selection-too-large' })}\n >\n {notice}\n </p>\n )}\n </div>\n </form>\n </div>\n )\n}\n\n/* -------------------------------------------------------------------------- */\n/* Controls: grouping toggle, relevance threshold, totals */\n/* -------------------------------------------------------------------------- */\n\nexport interface SearchPillOption {\n value: string\n /** Visible content (icon + text). */\n content: ReactNode\n /** Tooltip. */\n title: string\n}\n\nexport interface SearchPillToggleProps {\n options: SearchPillOption[]\n value: string\n onChange: (value: string) => void\n ariaLabel: string\n /** Prefix of the option buttons' test ids (`<prefix>-<value>-button`); default `smart-search-view`. */\n testIdPrefix?: string\n}\n\n/** Pill-shaped segmented toggle of `aria-pressed` buttons. */\nexport function SearchPillToggle({\n options,\n value,\n onChange,\n ariaLabel,\n testIdPrefix,\n}: SearchPillToggleProps) {\n return (\n <div\n className=\"inline-flex items-center rounded-full bg-muted p-0.5\"\n role=\"group\"\n aria-label={ariaLabel}\n data-slot=\"search-pill-toggle\"\n >\n {options.map((o) => {\n const active = o.value === value\n return (\n <button\n key={o.value}\n type=\"button\"\n onClick={() => onChange(o.value)}\n aria-pressed={active}\n title={o.title}\n data-testid={prefixedTestId(\n testIdPrefix,\n o.value,\n { testId: `smart-search-view-${o.value}-button` },\n '-button'\n )}\n className={cn(\n 'flex min-h-8 items-center gap-1.5 rounded-full px-3 py-1 text-xs font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring pointer-coarse:min-h-11',\n active\n ? 'bg-background text-foreground'\n : 'text-muted-foreground hover:text-foreground'\n )}\n >\n {o.content}\n </button>\n )\n })}\n </div>\n )\n}\n\nexport interface RelevanceStep {\n /** Minimum score kept at this step. */\n value: number\n label: string\n}\n\nexport const DEFAULT_RELEVANCE_STEPS: RelevanceStep[] = [\n { value: 0, label: 'Low' },\n { value: 0.7, label: 'High' },\n]\n\n// Accents match the relevance colours used for chunk borders and score pills elsewhere.\nconst STEP_DOT_CLASS = ['bg-muted-foreground/40', 'bg-primary']\nconst STEP_LABEL_CLASS = ['text-foreground', 'text-primary']\n\nexport interface RelevanceThresholdProps {\n value: number\n onChange: (value: number) => void\n steps?: RelevanceStep[]\n title?: string\n ariaLabel?: string\n}\n\n/** Compact segmented control (Low / High) with a colour-coded dot on the active step. */\nexport function RelevanceThreshold({\n value,\n onChange,\n steps = DEFAULT_RELEVANCE_STEPS,\n title = 'Relevance Threshold',\n ariaLabel = 'Search relevance threshold',\n}: RelevanceThresholdProps) {\n const active = steps.reduce((best, s, i) => (value >= s.value ? i : best), 0)\n return (\n <div className=\"flex items-center gap-1.5\" data-slot=\"relevance-threshold\">\n <span className=\"whitespace-nowrap text-xs font-medium uppercase tracking-wide text-muted-foreground\">\n {title}\n </span>\n <div\n className=\"inline-flex items-center rounded-full bg-muted p-0.5\"\n role=\"group\"\n aria-label={ariaLabel}\n >\n {steps.map((step, i) => {\n const isActive = i === active\n return (\n <button\n key={step.label}\n type=\"button\"\n onClick={() => onChange(step.value)}\n aria-pressed={isActive}\n data-testid={`smart-search-threshold-${step.label.toLowerCase()}`}\n className={cn(\n 'flex items-center gap-1 rounded-full px-2 py-0.5 text-xs font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring pointer-coarse:min-h-11 pointer-coarse:px-3',\n isActive\n ? cn('bg-background', STEP_LABEL_CLASS[i] ?? STEP_LABEL_CLASS[0])\n : 'text-muted-foreground hover:text-foreground'\n )}\n >\n <span\n className={cn(\n 'size-1.5 rounded-full transition-colors',\n isActive ? (STEP_DOT_CLASS[i] ?? STEP_DOT_CLASS[0]) : 'bg-muted-foreground/30'\n )}\n />\n {step.label}\n </button>\n )\n })}\n </div>\n </div>\n )\n}\n\n/** Result controls pinned between the search bar and the scrolling results. */\nexport function SearchControlsBar({\n start,\n end,\n children,\n}: {\n /** Left side: the totals headline. */\n start: ReactNode\n /** Right side: threshold and toggle. */\n end: ReactNode\n children?: ReactNode\n}) {\n return (\n <div\n data-slot=\"search-controls-bar\"\n className=\"flex flex-wrap items-center justify-between gap-x-4 gap-y-2 pb-3 pl-6 pr-4\"\n >\n <div className=\"flex flex-wrap items-center gap-x-3 gap-y-2\">{start}</div>\n <div className=\"flex items-center gap-3\">{end}</div>\n {children}\n </div>\n )\n}\n\nexport interface SearchTotalsHeadlineLabels {\n hit: string\n hits: string\n document: string\n documents: string\n passages: string\n}\n\nexport const DEFAULT_SEARCH_TOTALS_LABELS: SearchTotalsHeadlineLabels = {\n hit: 'hit',\n hits: 'hits',\n document: 'document',\n documents: 'documents',\n passages: 'passages',\n}\n\nexport interface SearchTotalsHeadlineProps {\n /** Hits passing the relevance threshold. */\n shownHits: number\n totalHits: number\n /** Documents among the shown hits. */\n shownDocuments: number\n totalDocuments: number\n /** Shown hits whose passage contains none of the query words (matched by meaning). */\n meaningHits?: number\n /** Paging range, shown when there is more than one page. */\n range?: { start: number; end: number; total: number; unit: 'passages' | 'documents' } | null\n /** Inline action after the sentence (e.g. Apply label). */\n action?: ReactNode\n testId?: string\n labels?: Partial<SearchTotalsHeadlineLabels>\n}\n\nconst fmt = (n: number) => n.toLocaleString()\n\n/** \"N hits (M total) across K documents\", plus optional keyword/meaning split, action and range. */\nexport function SearchTotalsHeadline({\n shownHits,\n totalHits,\n shownDocuments,\n totalDocuments,\n meaningHits = 0,\n range,\n action,\n testId = 'smart-search-totals',\n labels,\n}: SearchTotalsHeadlineProps) {\n const l = useMemo(() => ({ ...DEFAULT_SEARCH_TOTALS_LABELS, ...labels }), [labels])\n const hitWord = (n: number) => (n === 1 ? l.hit : l.hits)\n const docWord = (n: number) => (n === 1 ? l.document : l.documents)\n return (\n <p\n className=\"flex flex-wrap items-baseline gap-x-2 font-sans text-base font-semibold tabular-nums text-foreground\"\n data-testid={testId}\n >\n <span>\n {shownHits < totalHits ? (\n <>\n {fmt(shownHits)} {hitWord(shownHits)}{' '}\n <span className=\"font-normal text-muted-foreground\">({fmt(totalHits)} total)</span>{' '}\n across {fmt(shownDocuments)} {docWord(shownDocuments)}\n </>\n ) : (\n <>\n {fmt(totalHits)} {hitWord(totalHits)} across {fmt(totalDocuments)}{' '}\n {docWord(totalDocuments)}\n </>\n )}\n </span>\n {meaningHits > 0 && (\n <>\n {' '}\n <span className=\"text-sm font-normal text-muted-foreground\">\n · {fmt(shownHits - meaningHits)} contain your words, {fmt(meaningHits)} matched by\n meaning\n </span>\n </>\n )}\n {action && (\n <span className=\"inline-flex items-center gap-2 text-sm font-normal text-muted-foreground\">\n –{action}\n </span>\n )}\n {range && range.total > 0 && (\n <span className=\"text-sm font-normal text-muted-foreground\">\n · showing {fmt(range.start)}–{fmt(range.end)} of {fmt(range.total)}{' '}\n {range.unit === 'passages' ? l.passages : l.documents}\n </span>\n )}\n </p>\n )\n}\n\n/* -------------------------------------------------------------------------- */\n/* States */\n/* -------------------------------------------------------------------------- */\n\n/** Inline error of a failed search. */\nexport function SearchErrorBanner({ message }: { message: string }) {\n return (\n <div\n role=\"alert\"\n className=\"flex items-center gap-2 rounded-md bg-destructive/10 p-4 text-destructive\"\n >\n <AlertCircle className=\"size-5 flex-shrink-0\" />\n <p>{message}</p>\n </div>\n )\n}\n\nexport interface SearchNoResultsProps {\n /** Hits that exist but fall below the threshold; 0 when the search found nothing. */\n hiddenHits: number\n onLowerThreshold: () => void\n labels?: Partial<SearchNoResultsLabels>\n testId?: string\n}\n\nexport interface SearchNoResultsLabels {\n none: string\n hidden: (count: number) => string\n lower: string\n}\n\nexport const DEFAULT_SEARCH_NO_RESULTS_LABELS: SearchNoResultsLabels = {\n none: 'No results found for your search query.',\n hidden: (n) =>\n `All ${fmt(n)} ${n === 1 ? 'hit is' : 'hits are'} below the current relevance threshold.`,\n lower: 'Lower threshold to Low',\n}\n\n/** Nothing to list: either no hits, or all hits are under the relevance threshold. */\nexport function SearchNoResults({\n hiddenHits,\n onLowerThreshold,\n labels,\n testId = 'smart-search-no-results',\n}: SearchNoResultsProps) {\n const l = useMemo(() => ({ ...DEFAULT_SEARCH_NO_RESULTS_LABELS, ...labels }), [labels])\n return (\n <div className=\"py-12 text-center\" data-testid={testId}>\n <Search className=\"mx-auto mb-4 size-12 text-muted-foreground\" />\n {hiddenHits > 0 ? (\n <>\n <p className=\"text-muted-foreground\">{l.hidden(hiddenHits)}</p>\n <Button variant=\"link\" size=\"sm\" className=\"mt-2\" onClick={onLowerThreshold}>\n {l.lower}\n </Button>\n </>\n ) : (\n <p className=\"text-muted-foreground\">{l.none}</p>\n )}\n </div>\n )\n}\n\n/* -------------------------------------------------------------------------- */\n/* Apply label dialog */\n/* -------------------------------------------------------------------------- */\n\nexport interface ApplyLabelDialogLabels {\n title: string\n description: (documents: number, passages: number) => string\n placeholder: string\n cancel: string\n apply: string\n}\n\nexport const DEFAULT_APPLY_LABEL_DIALOG_LABELS: ApplyLabelDialogLabels = {\n title: 'Apply label',\n description: (documents, passages) =>\n `Labels ${documents} ${documents === 1 ? 'document' : 'documents'} with ${passages} passage ${passages === 1 ? 'reference' : 'references'}.`,\n placeholder: 'Label name',\n cancel: 'Cancel',\n apply: 'Apply label',\n}\n\nexport interface ApplyLabelDialogProps {\n open: boolean\n onOpenChange: (open: boolean) => void\n name: string\n onNameChange: (name: string) => void\n onApply: (name: string) => void\n isApplying: boolean\n documentCount: number\n passageCount: number\n labels?: Partial<ApplyLabelDialogLabels>\n}\n\n/** Name a label and apply it to every document in the results. */\nexport function ApplyLabelDialog({\n open,\n onOpenChange,\n name,\n onNameChange,\n onApply,\n isApplying,\n documentCount,\n passageCount,\n labels,\n}: ApplyLabelDialogProps) {\n const l = useMemo(() => ({ ...DEFAULT_APPLY_LABEL_DIALOG_LABELS, ...labels }), [labels])\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>{l.title}</DialogTitle>\n <DialogDescription>{l.description(documentCount, passageCount)}</DialogDescription>\n </DialogHeader>\n <div className=\"py-2\">\n <Input\n value={name}\n onChange={(e) => onNameChange(e.target.value)}\n placeholder={l.placeholder}\n aria-label={l.placeholder}\n autoFocus\n onKeyDown={(e) => {\n if (e.key === 'Enter' && name.trim()) onApply(name)\n }}\n />\n </div>\n <DialogFooter>\n <Button variant=\"outline\" onClick={() => onOpenChange(false)}>\n {l.cancel}\n </Button>\n <Button onClick={() => onApply(name)} disabled={isApplying || !name.trim()}>\n {isApplying && <Loader2 className=\"mr-2 size-4 animate-spin\" />}\n {l.apply}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n )\n}\n\n/** Small outlined \"Apply label\" button used inside the totals sentence. */\nexport function ApplyLabelButton({\n onClick,\n label = 'Apply label',\n testId = 'smart-search-apply-label-button',\n}: {\n onClick: () => void\n label?: string\n testId?: string\n}) {\n return (\n <Button\n onClick={onClick}\n size=\"sm\"\n variant=\"outline\"\n className=\"h-6 px-2 text-sm font-normal pointer-coarse:h-11\"\n data-testid={testId}\n >\n <TagIcon className=\"mr-1 size-3\" />\n {label}\n </Button>\n )\n}\n","/**\n * A search hit's text as markdown, with the query's terms marked (`<mark>`, which the kit's\n * sanitizer lets through). One snippet for every search list: documents' and facts'.\n */\nimport { memo } from 'react'\nimport { MarkdownRenderer } from '@arbidocs/react/ui'\nimport { highlightTerms } from './highlight'\n\nexport const SearchSnippet = memo(function SearchSnippet({\n content,\n terms,\n}: {\n content: string\n terms: string[]\n}) {\n return <MarkdownRenderer>{highlightTerms(content, terms)}</MarkdownRenderer>\n})\n\n/** `SearchHit`'s `renderSnippet`. */\nexport const renderSearchSnippet = (content: string, terms: string[]) => (\n <SearchSnippet content={content} terms={terms} />\n)\n","/**\n * What a search page does with the passages a search found: the terms to highlight, which hits\n * survive the relevance threshold, and the hits grouped by document. Pure; the page binds them.\n */\n\nimport type { SearchChunk } from '@arbidocs/react'\n\nexport interface SearchDocumentGroup {\n docId: string\n docTitle: string\n maxScore: number\n results: SearchChunk[]\n}\n\n/** Quoted phrases in a query (\"double\" or 'single'), lower-cased. */\nexport function extractQuotedTerms(query: string): string[] {\n const doubleQuoted = query.match(/\"([^\"]+)\"/g) || []\n const singleQuoted = query.match(/'([^']+)'/g) || []\n const allMatches = [...doubleQuoted, ...singleQuoted]\n if (allMatches.length === 0) return []\n return allMatches.map((m) => m.slice(1, -1).toLowerCase()).filter((t) => t.length > 0)\n}\n\n/**\n * One-line explainer shown above the results: what quotes change and what the relevance\n * threshold does. Unquoted queries also match by meaning, so some hits will not contain the word.\n */\nexport function getSearchMatchHint(query: string): string {\n const thresholdHint =\n 'Low shows all matches; High keeps the strongest and any passage with your words.'\n if (extractQuotedTerms(query).length > 0) {\n return `Showing exact matches for the quoted text. Remove the quotes to also include passages that match by meaning. ${thresholdHint}`\n }\n return `Matches keywords and meaning, so some hits won't contain the word. Quote a phrase for exact matches only. ${thresholdHint}`\n}\n\n// Common words we never want to highlight — they'd light up most of a passage\n// and drown out the meaningful matches.\nconst HIGHLIGHT_STOPWORDS = new Set([\n 'the',\n 'a',\n 'an',\n 'and',\n 'or',\n 'but',\n 'of',\n 'to',\n 'in',\n 'on',\n 'for',\n 'with',\n 'as',\n 'at',\n 'by',\n 'from',\n 'is',\n 'are',\n 'was',\n 'were',\n 'be',\n 'been',\n 'being',\n 'what',\n 'which',\n 'who',\n 'whom',\n 'whose',\n 'how',\n 'when',\n 'where',\n 'why',\n 'did',\n 'do',\n 'does',\n 'his',\n 'her',\n 'their',\n 'its',\n 'this',\n 'that',\n 'these',\n 'those',\n 'it',\n 'he',\n 'she',\n 'they',\n 'we',\n 'you',\n 'about',\n 'into',\n 'over',\n 'than',\n 'then',\n 'them',\n 'have',\n 'has',\n 'had',\n 'will',\n 'would',\n 'can',\n 'could',\n 'should',\n 'may',\n 'might',\n])\n\n/**\n * Terms to highlight in snippets: quoted phrases verbatim, and the significant words (longer than\n * two letters, not a stopword) of the rest, so a plain question still shows why a passage matched.\n */\nexport function extractHighlightTerms(query: string): string[] {\n const quoted = extractQuotedTerms(query)\n const withoutQuoted = query.replace(/\"[^\"]+\"|'[^']+'/g, ' ')\n const words = withoutQuoted\n .toLowerCase()\n .split(/[^\\p{L}\\p{N}]+/u)\n .filter((w) => w.length > 2 && !HIGHLIGHT_STOPWORDS.has(w))\n return Array.from(new Set([...quoted, ...words]))\n}\n\n/**\n * True when a passage contains none of the query's terms: the hybrid search returned it for its\n * meaning rather than for a visible word. A query with no terms can't tell, so never.\n */\nexport function isMeaningMatch(content: string, terms: string[]): boolean {\n if (terms.length === 0) return false\n const lowered = content.toLowerCase()\n return !terms.some((term) => lowered.includes(term))\n}\n\n/**\n * Whether a hit survives the relevance threshold. Exact keyword hits often score below the High\n * cutoff, so when the query has terms a passage containing one is kept at any threshold; only\n * meaning-only matches are cut by the score.\n */\nexport function passesRelevanceCutoff(hit: SearchChunk, cutoff: number, terms: string[]): boolean {\n if (hit.score >= cutoff) return true\n return terms.length > 0 && !isMeaningMatch(hit.content, terms)\n}\n\nexport interface SearchAggregation {\n groups: SearchDocumentGroup[]\n /** The documents listed, in first-hit order. */\n docIds: string[]\n}\n\n/**\n * The hits grouped by document in one pass. With `terms`, passages containing a term rank above\n * meaning-only ones inside each group, and groups with a keyword hit come before groups that only\n * matched by meaning. Both sorts are stable, so page order inside a group and relevance across\n * groups hold within each tier.\n */\nexport function groupSearchResults(hits: SearchChunk[], terms: string[] = []): SearchAggregation {\n const groups = new Map<string, SearchDocumentGroup>()\n const docIds: string[] = []\n\n for (const hit of hits) {\n let group = groups.get(hit.docId)\n if (!group) {\n group = { docId: hit.docId, docTitle: hit.docTitle, maxScore: hit.score, results: [] }\n groups.set(hit.docId, group)\n docIds.push(hit.docId)\n }\n group.results.push(hit)\n if (hit.score > group.maxScore) group.maxScore = hit.score\n }\n\n // 0 = contains a query term, 1 = matched by meaning only.\n const tierOf = (hit: SearchChunk) => (isMeaningMatch(hit.content, terms) ? 1 : 0)\n const groupTier = new Map<SearchDocumentGroup, number>()\n\n for (const group of groups.values()) {\n group.results.sort((a, b) => {\n const pageA = a.page || 0\n const pageB = b.page || 0\n if (pageA !== pageB) return pageA - pageB\n return a.index - b.index\n })\n if (terms.length > 0) {\n group.results.sort((a, b) => tierOf(a) - tierOf(b))\n groupTier.set(group, tierOf(group.results[0]))\n }\n }\n\n const sorted = Array.from(groups.values()).sort(\n (a, b) => (groupTier.get(a) ?? 0) - (groupTier.get(b) ?? 0) || b.maxScore - a.maxScore\n )\n return { groups: sorted, docIds }\n}\n"]}
|