synapse-react-client 4.0.32 → 4.0.33
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/SWC.index.js +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/DataAccessRequestAccessorsEditor.d.ts.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/DataAccessRequestAccessorsEditor.js +48 -36
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/DataAccessRequestAccessorsEditor.js.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/DataAccessRequestAccessorsFilesForm/DataAccessRequestAccessorsFilesForm.d.ts.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/DataAccessRequestAccessorsFilesForm/DataAccessRequestAccessorsFilesForm.js +217 -143
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/DataAccessRequestAccessorsFilesForm/DataAccessRequestAccessorsFilesForm.js.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/DocumentTemplate.d.ts.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/DocumentTemplate.js +28 -24
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/DocumentTemplate.js.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/ResearchProjectForm/ResearchProjectForm.d.ts.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/ResearchProjectForm/ResearchProjectForm.js +180 -94
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/ResearchProjectForm/ResearchProjectForm.js.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/styles.d.ts +3 -0
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/styles.d.ts.map +1 -0
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/styles.js +9 -0
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/styles.js.map +1 -0
- package/dist/components/CopyToClipboardIcon.d.ts +2 -1
- package/dist/components/CopyToClipboardIcon.d.ts.map +1 -1
- package/dist/components/CopyToClipboardIcon.js +6 -6
- package/dist/components/CopyToClipboardIcon.js.map +1 -1
- package/dist/components/DataGrid/SynapseGrid.d.ts.map +1 -1
- package/dist/components/DataGrid/SynapseGrid.js +230 -215
- package/dist/components/DataGrid/SynapseGrid.js.map +1 -1
- package/dist/components/DataGrid/SyncGridWithSourceButton.js +3 -3
- package/dist/components/DataGrid/SyncGridWithSourceButton.js.map +1 -1
- package/dist/components/DataGrid/columns/DateTimeColumn.js +1 -1
- package/dist/components/DataGrid/columns/DateTimeColumn.js.map +1 -1
- package/dist/components/DataGrid/components/ReorderColumnsButton.d.ts +10 -0
- package/dist/components/DataGrid/components/ReorderColumnsButton.d.ts.map +1 -0
- package/dist/components/DataGrid/components/ReorderColumnsButton.js +37 -0
- package/dist/components/DataGrid/components/ReorderColumnsButton.js.map +1 -0
- package/dist/components/DataGrid/components/ReorderColumnsDialog.d.ts +12 -0
- package/dist/components/DataGrid/components/ReorderColumnsDialog.d.ts.map +1 -0
- package/dist/components/DataGrid/components/ReorderColumnsDialog.js +93 -0
- package/dist/components/DataGrid/components/ReorderColumnsDialog.js.map +1 -0
- package/dist/components/DataGrid/hooks/useGetSchemaForGrid.js +1 -1
- package/dist/components/DataGrid/utils/applyModelChange.d.ts +3 -0
- package/dist/components/DataGrid/utils/applyModelChange.d.ts.map +1 -1
- package/dist/components/DataGrid/utils/applyModelChange.js +5 -0
- package/dist/components/DataGrid/utils/applyModelChange.js.map +1 -1
- package/dist/components/DataGrid/utils/computeDefaultColumnOrder.d.ts +8 -0
- package/dist/components/DataGrid/utils/computeDefaultColumnOrder.d.ts.map +1 -0
- package/dist/components/DataGrid/utils/computeDefaultColumnOrder.js +14 -0
- package/dist/components/DataGrid/utils/computeDefaultColumnOrder.js.map +1 -0
- package/dist/components/EntityBadgeIcons/EntityBadgeIcons.js +1 -1
- package/dist/components/EntityFinder/details/view/DetailsView.d.ts.map +1 -1
- package/dist/components/EntityFinder/details/view/DetailsView.js +119 -122
- package/dist/components/EntityFinder/details/view/DetailsView.js.map +1 -1
- package/dist/components/EntityFinder/details/view/table/AddToDownloadListCell.d.ts +5 -1
- package/dist/components/EntityFinder/details/view/table/AddToDownloadListCell.d.ts.map +1 -1
- package/dist/components/EntityFinder/details/view/table/AddToDownloadListCell.js +7 -7
- package/dist/components/EntityFinder/details/view/table/AddToDownloadListCell.js.map +1 -1
- package/dist/components/EntityLink.d.ts +2 -0
- package/dist/components/EntityLink.d.ts.map +1 -1
- package/dist/components/EntityLink.js +15 -11
- package/dist/components/EntityLink.js.map +1 -1
- package/dist/components/EntitySidebar/AccessAndPermissions.css +1 -0
- package/dist/components/EntitySidebar/AccessAndPermissions.d.ts +7 -0
- package/dist/components/EntitySidebar/AccessAndPermissions.d.ts.map +1 -0
- package/dist/components/EntitySidebar/AccessAndPermissions.js +75 -0
- package/dist/components/EntitySidebar/AccessAndPermissions.js.map +1 -0
- package/dist/components/EntitySidebar/AccessAndPermissions.module.js +15 -0
- package/dist/components/EntitySidebar/AccessAndPermissions.module.js.map +1 -0
- package/dist/components/EntitySidebar/AccessAndPermissions.module.scss +58 -0
- package/dist/components/EntitySidebar/EntitySidebar.css +1 -1
- package/dist/components/EntitySidebar/EntitySidebar.d.ts.map +1 -1
- package/dist/components/EntitySidebar/EntitySidebar.js +54 -42
- package/dist/components/EntitySidebar/EntitySidebar.js.map +1 -1
- package/dist/components/EntitySidebar/EntitySidebar.module.js +10 -11
- package/dist/components/EntitySidebar/EntitySidebar.module.js.map +1 -1
- package/dist/components/EntitySidebar/EntitySidebar.module.scss +6 -13
- package/dist/components/EntityTreeTable/EntityTreeTable.css +1 -1
- package/dist/components/EntityTreeTable/EntityTreeTable.module.js +1 -1
- package/dist/components/EntityTreeTable/EntityTreeTable.module.js.map +1 -1
- package/dist/components/EntityTreeTable/EntityTreeTable.module.scss +18 -0
- package/dist/components/EntityTreeTable/components/ColumnHeaders.d.ts.map +1 -1
- package/dist/components/EntityTreeTable/components/ColumnHeaders.js +20 -7
- package/dist/components/EntityTreeTable/components/ColumnHeaders.js.map +1 -1
- package/dist/components/EntityTreeTable/components/EntityNameCell.d.ts.map +1 -1
- package/dist/components/EntityTreeTable/components/EntityNameCell.js +3 -1
- package/dist/components/EntityTreeTable/components/EntityNameCell.js.map +1 -1
- package/dist/components/EntityTreeTable/components/EntityTreeTableView.d.ts.map +1 -1
- package/dist/components/EntityTreeTable/components/EntityTreeTableView.js +4 -1
- package/dist/components/EntityTreeTable/components/EntityTreeTableView.js.map +1 -1
- package/dist/components/EntityTreeTable/components/IdColumnHeader.d.ts.map +1 -1
- package/dist/components/EntityTreeTable/components/IdColumnHeader.js +3 -1
- package/dist/components/EntityTreeTable/components/IdColumnHeader.js.map +1 -1
- package/dist/components/EntityTreeTable/hooks/useTableColumns.d.ts.map +1 -1
- package/dist/components/EntityTreeTable/hooks/useTableColumns.js +24 -19
- package/dist/components/EntityTreeTable/hooks/useTableColumns.js.map +1 -1
- package/dist/components/Forum/DiscussionEmpty.css +1 -1
- package/dist/components/Forum/DiscussionEmpty.module.js +4 -4
- package/dist/components/Forum/DiscussionEmpty.module.js.map +1 -1
- package/dist/components/Forum/DiscussionEmpty.module.scss +3 -6
- package/dist/components/JsonSchema/JsonSchemaPicker/JsonSchemaPicker.css +1 -0
- package/dist/components/JsonSchema/JsonSchemaPicker/JsonSchemaPicker.d.ts +29 -0
- package/dist/components/JsonSchema/JsonSchemaPicker/JsonSchemaPicker.d.ts.map +1 -0
- package/dist/components/JsonSchema/JsonSchemaPicker/JsonSchemaPicker.js +229 -0
- package/dist/components/JsonSchema/JsonSchemaPicker/JsonSchemaPicker.js.map +1 -0
- package/dist/components/JsonSchema/JsonSchemaPicker/JsonSchemaPicker.module.js +9 -0
- package/dist/components/JsonSchema/JsonSchemaPicker/JsonSchemaPicker.module.js.map +1 -0
- package/dist/components/JsonSchema/JsonSchemaPicker/JsonSchemaPicker.module.scss +19 -0
- package/dist/components/JsonSchema/JsonSchemaPicker/JsonSchemaPickerModal.d.ts +23 -0
- package/dist/components/JsonSchema/JsonSchemaPicker/JsonSchemaPickerModal.d.ts.map +1 -0
- package/dist/components/JsonSchema/JsonSchemaPicker/JsonSchemaPickerModal.js +39 -0
- package/dist/components/JsonSchema/JsonSchemaPicker/JsonSchemaPickerModal.js.map +1 -0
- package/dist/components/JsonSchema/JsonSchemaPicker/JsonSchemaVersionSelectionContext.d.ts +14 -0
- package/dist/components/JsonSchema/JsonSchemaPicker/JsonSchemaVersionSelectionContext.d.ts.map +1 -0
- package/dist/components/JsonSchema/JsonSchemaPicker/JsonSchemaVersionSelectionContext.js +12 -0
- package/dist/components/JsonSchema/JsonSchemaPicker/JsonSchemaVersionSelectionContext.js.map +1 -0
- package/dist/components/JsonSchema/JsonSchemaPicker/VersionSelectionType.d.ts +17 -0
- package/dist/components/JsonSchema/JsonSchemaPicker/VersionSelectionType.d.ts.map +1 -0
- package/dist/components/JsonSchema/JsonSchemaPicker/VersionSelectionType.js +8 -0
- package/dist/components/JsonSchema/JsonSchemaPicker/VersionSelectionType.js.map +1 -0
- package/dist/components/JsonSchema/JsonSchemaPicker/index.d.ts +6 -0
- package/dist/components/JsonSchema/JsonSchemaPicker/index.d.ts.map +1 -0
- package/dist/components/JsonSchema/JsonSchemaPicker/index.js +4 -0
- package/dist/components/JsonSchema/JsonSchemaPicker/useJsonSchemaOrganizations.d.ts +20 -0
- package/dist/components/JsonSchema/JsonSchemaPicker/useJsonSchemaOrganizations.d.ts.map +1 -0
- package/dist/components/JsonSchema/JsonSchemaPicker/useJsonSchemaOrganizations.js +25 -0
- package/dist/components/JsonSchema/JsonSchemaPicker/useJsonSchemaOrganizations.js.map +1 -0
- package/dist/components/JsonSchema/JsonSchemaPicker/useJsonSchemaSelection.d.ts +35 -0
- package/dist/components/JsonSchema/JsonSchemaPicker/useJsonSchemaSelection.d.ts.map +1 -0
- package/dist/components/JsonSchema/JsonSchemaPicker/useJsonSchemaSelection.js +60 -0
- package/dist/components/JsonSchema/JsonSchemaPicker/useJsonSchemaSelection.js.map +1 -0
- package/dist/components/ProjectInfo/ProjectInfo.css +1 -1
- package/dist/components/ProjectInfo/ProjectInfo.module.js +5 -5
- package/dist/components/ProjectInfo/ProjectInfo.module.js.map +1 -1
- package/dist/components/ProjectInfo/ProjectInfo.module.scss +2 -4
- package/dist/components/ProjectInfo/ProjectInfoPopover.d.ts.map +1 -1
- package/dist/components/ProjectInfo/ProjectInfoPopover.js +17 -16
- package/dist/components/ProjectInfo/ProjectInfoPopover.js.map +1 -1
- package/dist/components/ProjectStorage/ProjectDataAvailability.d.ts.map +1 -1
- package/dist/components/ProjectStorage/ProjectDataAvailability.js +16 -16
- package/dist/components/ProjectStorage/ProjectDataAvailability.js.map +1 -1
- package/dist/components/ProvenanceGraph/ProvenanceGraph.d.ts.map +1 -1
- package/dist/components/ProvenanceGraph/ProvenanceGraph.js +95 -95
- package/dist/components/ProvenanceGraph/ProvenanceGraph.js.map +1 -1
- package/dist/components/SchemaDrivenAnnotationEditor/SchemaDrivenAnnotationEditor.js +2 -2
- package/dist/components/SetManagedAccessRequirementFields/SetManagedAccessRequirementFields.d.ts.map +1 -1
- package/dist/components/SetManagedAccessRequirementFields/SetManagedAccessRequirementFields.js +116 -91
- package/dist/components/SetManagedAccessRequirementFields/SetManagedAccessRequirementFields.js.map +1 -1
- package/dist/components/SynapseChat/SynapseChat.d.ts.map +1 -1
- package/dist/components/SynapseChat/SynapseChat.js +40 -40
- package/dist/components/SynapseChat/SynapseChat.js.map +1 -1
- package/dist/components/SynapseChat/SynapseChatInteraction.d.ts +3 -2
- package/dist/components/SynapseChat/SynapseChatInteraction.d.ts.map +1 -1
- package/dist/components/SynapseChat/SynapseChatInteraction.js.map +1 -1
- package/dist/components/SynapseChat/components/AttachmentChip/AttachmentChip.css +1 -1
- package/dist/components/SynapseChat/components/AttachmentChip/AttachmentChip.d.ts.map +1 -1
- package/dist/components/SynapseChat/components/AttachmentChip/AttachmentChip.js +0 -7
- package/dist/components/SynapseChat/components/AttachmentChip/AttachmentChip.js.map +1 -1
- package/dist/components/SynapseChat/components/AttachmentChip/AttachmentChip.module.js +2 -2
- package/dist/components/SynapseChat/components/AttachmentChip/AttachmentChip.module.js.map +1 -1
- package/dist/components/SynapseChat/components/AttachmentChip/AttachmentChip.module.scss +12 -2
- package/dist/components/SynapseChat/components/ChatAttachmentStrip/ChatAttachmentStrip.css +1 -1
- package/dist/components/SynapseChat/components/ChatAttachmentStrip/ChatAttachmentStrip.module.js +3 -3
- package/dist/components/SynapseChat/components/ChatAttachmentStrip/ChatAttachmentStrip.module.js.map +1 -1
- package/dist/components/SynapseChat/components/ChatAttachmentStrip/ChatAttachmentStrip.module.scss +5 -1
- package/dist/components/TanStackTable/ColumnHeader.d.ts +7 -0
- package/dist/components/TanStackTable/ColumnHeader.d.ts.map +1 -1
- package/dist/components/TanStackTable/ColumnHeader.js +10 -9
- package/dist/components/TanStackTable/ColumnHeader.js.map +1 -1
- package/dist/components/TanStackTable/StyledVirtualTanStackTable.d.ts +8 -0
- package/dist/components/TanStackTable/StyledVirtualTanStackTable.d.ts.map +1 -1
- package/dist/components/TanStackTable/StyledVirtualTanStackTable.js +31 -22
- package/dist/components/TanStackTable/StyledVirtualTanStackTable.js.map +1 -1
- package/dist/components/TanStackTable/useFetchNextPageOnScrollToBottom.d.ts +21 -0
- package/dist/components/TanStackTable/useFetchNextPageOnScrollToBottom.d.ts.map +1 -0
- package/dist/components/TanStackTable/useFetchNextPageOnScrollToBottom.js +22 -0
- package/dist/components/TanStackTable/useFetchNextPageOnScrollToBottom.js.map +1 -0
- package/dist/components/entity/metadata/AnnotationsTable.js +2 -2
- package/dist/components/entity/metadata/AnnotationsTable.js.map +1 -1
- package/dist/components/entity/page/breadcrumbs/EntityPageBreadcrumbs.d.ts.map +1 -1
- package/dist/components/entity/page/breadcrumbs/EntityPageBreadcrumbs.js +8 -8
- package/dist/components/entity/page/breadcrumbs/EntityPageBreadcrumbs.js.map +1 -1
- package/dist/components/entity/page/title_bar/EntityPageTitleBar.d.ts +0 -1
- package/dist/components/entity/page/title_bar/EntityPageTitleBar.d.ts.map +1 -1
- package/dist/components/entity/page/title_bar/EntityPageTitleBar.js +22 -22
- package/dist/components/entity/page/title_bar/EntityPageTitleBar.js.map +1 -1
- package/dist/components/entity/page/title_bar/useGetEntityTitleBarProperties.d.ts.map +1 -1
- package/dist/components/entity/page/title_bar/useGetEntityTitleBarProperties.js +62 -68
- package/dist/components/entity/page/title_bar/useGetEntityTitleBarProperties.js.map +1 -1
- package/dist/components/styled/StyledTableContainer.d.ts +1 -0
- package/dist/components/styled/StyledTableContainer.d.ts.map +1 -1
- package/dist/components/styled/StyledTableContainer.js +3 -3
- package/dist/components/styled/StyledTableContainer.js.map +1 -1
- package/dist/mocks/eDuc/mockEDucTemplates.d.ts +7 -0
- package/dist/mocks/eDuc/mockEDucTemplates.d.ts.map +1 -0
- package/dist/mocks/eDuc/mockEDucTemplates.js +18 -0
- package/dist/mocks/eDuc/mockEDucTemplates.js.map +1 -0
- package/dist/mocks/jsonschema/mockJsonSchemaListing.d.ts +31 -0
- package/dist/mocks/jsonschema/mockJsonSchemaListing.d.ts.map +1 -0
- package/dist/mocks/jsonschema/mockJsonSchemaListing.js +101 -0
- package/dist/mocks/jsonschema/mockJsonSchemaListing.js.map +1 -0
- package/dist/mocks/msw/handlers/eDucTemplateHandlers.d.ts +2 -0
- package/dist/mocks/msw/handlers/eDucTemplateHandlers.d.ts.map +1 -0
- package/dist/mocks/msw/handlers/eDucTemplateHandlers.js +14 -0
- package/dist/mocks/msw/handlers/eDucTemplateHandlers.js.map +1 -0
- package/dist/mocks/msw/handlers/jsonSchemaListingHandlers.d.ts +8 -0
- package/dist/mocks/msw/handlers/jsonSchemaListingHandlers.d.ts.map +1 -0
- package/dist/mocks/msw/handlers/jsonSchemaListingHandlers.js +30 -0
- package/dist/mocks/msw/handlers/jsonSchemaListingHandlers.js.map +1 -0
- package/dist/mocks/msw/handlers.d.ts.map +1 -1
- package/dist/mocks/msw/handlers.js +55 -51
- package/dist/mocks/msw/handlers.js.map +1 -1
- package/dist/style/abstracts/_cssVariables.scss +13 -0
- package/dist/style/components/entity_finder/_details-view.scss +0 -10
- package/dist/style/main.css +1 -1
- package/dist/synapse-client/SynapseClient.d.ts.map +1 -1
- package/dist/synapse-client/SynapseClient.js +2 -6
- package/dist/synapse-client/SynapseClient.js.map +1 -1
- package/dist/synapse-queries/KeyFactory.d.ts +3 -0
- package/dist/synapse-queries/KeyFactory.d.ts.map +1 -1
- package/dist/synapse-queries/KeyFactory.js +9 -0
- package/dist/synapse-queries/KeyFactory.js.map +1 -1
- package/dist/synapse-queries/dataaccess/useEDuc.d.ts +3 -3
- package/dist/synapse-queries/dataaccess/useEDuc.d.ts.map +1 -1
- package/dist/synapse-queries/dataaccess/useEDuc.js +40 -35
- package/dist/synapse-queries/dataaccess/useEDuc.js.map +1 -1
- package/dist/synapse-queries/entity/index.d.ts +0 -2
- package/dist/synapse-queries/entity/index.d.ts.map +1 -1
- package/dist/synapse-queries/entity/index.js +8 -10
- package/dist/synapse-queries/index.d.ts +1 -0
- package/dist/synapse-queries/index.d.ts.map +1 -1
- package/dist/synapse-queries/index.js +136 -128
- package/dist/synapse-queries/index.js.map +1 -1
- package/dist/synapse-queries/jsonschema/index.d.ts +6 -0
- package/dist/synapse-queries/jsonschema/index.d.ts.map +1 -0
- package/dist/synapse-queries/jsonschema/index.js +6 -0
- package/dist/synapse-queries/jsonschema/useEntityBoundSchema.d.ts.map +1 -0
- package/dist/synapse-queries/{entity → jsonschema}/useEntityBoundSchema.js +1 -1
- package/dist/synapse-queries/jsonschema/useEntityBoundSchema.js.map +1 -0
- package/dist/synapse-queries/jsonschema/useListJsonSchemaVersions.d.ts +26 -0
- package/dist/synapse-queries/jsonschema/useListJsonSchemaVersions.d.ts.map +1 -0
- package/dist/synapse-queries/jsonschema/useListJsonSchemaVersions.js +36 -0
- package/dist/synapse-queries/jsonschema/useListJsonSchemaVersions.js.map +1 -0
- package/dist/synapse-queries/jsonschema/useListJsonSchemasInfinite.d.ts +8 -0
- package/dist/synapse-queries/jsonschema/useListJsonSchemasInfinite.d.ts.map +1 -0
- package/dist/synapse-queries/jsonschema/useListJsonSchemasInfinite.js +21 -0
- package/dist/synapse-queries/jsonschema/useListJsonSchemasInfinite.js.map +1 -0
- package/dist/synapse-queries/jsonschema/useListOrganizations.d.ts +8 -0
- package/dist/synapse-queries/jsonschema/useListOrganizations.d.ts.map +1 -0
- package/dist/synapse-queries/jsonschema/useListOrganizations.js +22 -0
- package/dist/synapse-queries/jsonschema/useListOrganizations.js.map +1 -0
- package/dist/synapse-queries/jsonschema/useSchema.d.ts.map +1 -0
- package/dist/synapse-queries/{entity → jsonschema}/useSchema.js +1 -1
- package/dist/synapse-queries/jsonschema/useSchema.js.map +1 -0
- package/dist/testutils/VirtualizedTableTestUtils.js +17 -0
- package/dist/testutils/VirtualizedTableTestUtils.js.map +1 -0
- package/dist/theme/palette/Palettes.d.ts.map +1 -1
- package/dist/theme/palette/Palettes.js +13 -0
- package/dist/theme/palette/Palettes.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/utils/APIConstants.d.ts +1 -0
- package/dist/utils/APIConstants.d.ts.map +1 -1
- package/dist/utils/APIConstants.js +2 -2
- package/dist/utils/APIConstants.js.map +1 -1
- package/package.json +4 -4
- package/dist/synapse-queries/entity/useEntityBoundSchema.d.ts.map +0 -1
- package/dist/synapse-queries/entity/useEntityBoundSchema.js.map +0 -1
- package/dist/synapse-queries/entity/useSchema.d.ts.map +0 -1
- package/dist/synapse-queries/entity/useSchema.js.map +0 -1
- /package/dist/synapse-queries/{entity → jsonschema}/useEntityBoundSchema.d.ts +0 -0
- /package/dist/synapse-queries/{entity → jsonschema}/useSchema.d.ts +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SynapseChat.js","names":[],"sources":["../../../src/components/SynapseChat/SynapseChat.tsx"],"sourcesContent":["import { ChatState, useChatState } from '@/components/SynapseChat/useChatState'\nimport {\n useCreateAgentSession,\n useUpdateAgentSession,\n} from '@/synapse-queries/chat/useChat'\nimport { useSynapseContext } from '@/utils'\nimport { Alert, Box, Chip, List, Stack, Typography } from '@mui/material'\nimport {\n AgentSession,\n FileHandleAssociateType,\n GridAgentSessionContext,\n} from '@sage-bionetworks/synapse-client'\nimport { AgentAccessLevel } from '@sage-bionetworks/synapse-types'\nimport { useEffect, useRef, useState } from 'react'\nimport { SkeletonParagraph } from '../Skeleton'\nimport { displayToast } from '../ToastMessage'\nimport AccessLevelMenu from './AccessLevelMenu'\nimport { ChatAttachment } from './utils/types'\nimport { ChatInputArea } from './components/ChatInputArea/ChatInputArea'\nimport SynapseChatMessage from './SynapseChatMessage'\nimport { SmartToyTwoTone } from '@mui/icons-material'\nimport { UserCard } from '../UserCard/UserCard'\nimport { useApplicationSessionContext } from '@/utils/AppUtils'\n\nconst DEFAULT_AVATAR = (\n <Box\n sx={{\n p: '3px',\n borderRadius: '50%',\n borderStyle: 'solid',\n borderWidth: '1px',\n borderColor: 'grey.300',\n mt: '10px',\n height: '31px',\n }}\n >\n <SmartToyTwoTone sx={{ color: 'secondary.main' }} />\n </Box>\n)\n\nexport type SynapseChatProps = {\n initialMessage?: string //optional initial message\n agentRegistrationId?: string // if provided, use this agent\n chatbotName?: string // optional name of this chatbot agent\n hideTitle?: boolean\n textboxPositionOffset?: string // when embedded in a form, the textbox (form) stuck to the bottom may need to be offset due to container padding (dialog content for example!)\n /* optional session context for the agent session */\n sessionContext?: GridAgentSessionContext\n /* The current session, if state is lifted out of this component */\n externalSession?: AgentSession\n /* A callback invoked to bootstrap the current session, if state is to be lifted out of this component */\n setExternalSession?: (s: AgentSession | undefined) => void\n /* The current chat history, if state is lifted out of this component */\n externalChatState?: ChatState\n // default access level for the agent session.\n defaultAgentAccessLevel?: AgentAccessLevel\n // Whether to show the access level menu for the agent session.\n showAccessLevelMenu?: boolean\n /**\n * Optional callback invoked once when a chat response is received from the server.\n * Use this for side effects such as navigation based on the response content.\n * Called in the mutation onSuccess handler so it runs exactly once per response.\n */\n onChatResponse?: (responseText: string) => void\n /** Optional list of prompt suggestions shown as clickable pills above the text input */\n suggestedPrompts?: string[]\n /** Optional custom avatar for the chatbot agent */\n agentAvatar?: React.ReactNode\n /**\n * Whether to allow the user to attach local files to their chat message.\n * @default false\n */\n allowAttachments?: boolean\n}\n\nexport function SynapseChat({\n initialMessage,\n agentRegistrationId,\n chatbotName = 'SynapseChat',\n agentAvatar = DEFAULT_AVATAR,\n hideTitle = false,\n textboxPositionOffset = '0px',\n sessionContext,\n externalSession,\n setExternalSession,\n externalChatState,\n showAccessLevelMenu = true,\n onChatResponse,\n suggestedPrompts,\n allowAttachments = false,\n}: SynapseChatProps) {\n const { accessToken } = useSynapseContext()\n const { userId } = useApplicationSessionContext()\n\n const userAvatar = (\n <UserCard ownerId={userId} size=\"AVATAR\" avatarSize=\"MEDIUM\" />\n )\n const [localAgentSession, setLocalAgentSession] = useState<AgentSession>()\n const agentSession = externalSession ?? localAgentSession\n const setAgentSession = setExternalSession ?? setLocalAgentSession\n\n const { mutate: createAgentSession, error: createAgentSessionError } =\n useCreateAgentSession({\n onSuccess: newAgentSession => setAgentSession(newAgentSession),\n })\n\n const { mutate: updateAgentSession } = useUpdateAgentSession({\n onSuccess: updatedAgentSession => setAgentSession(updatedAgentSession),\n onError: err =>\n displayToast(\n `Unable to update the agent session: ${err.message}`,\n 'danger',\n ),\n })\n const [agentAccessLevel, setAgentAccessLevel] = useState<AgentAccessLevel>(\n sessionContext\n ? AgentAccessLevel.WRITE_YOUR_PRIVATE_DATA\n : AgentAccessLevel.PUBLICLY_ACCESSIBLE,\n )\n\n const internalChatState = useChatState(agentSession, onChatResponse)\n const chatState = externalChatState ?? internalChatState\n const { interactions, isAwaitingResponse, sendChat } = chatState\n\n // Only interactions added after this component instance mounted should play the entry\n // animation. Callers may lift state so history survives a `Dialog` closing, but the\n // `Dialog` unmounts its children, so every reopen would otherwise re-animate the whole\n // conversation.\n const presentAtMountRef = useRef<Set<string> | undefined>(undefined)\n if (presentAtMountRef.current === undefined) {\n presentAtMountRef.current = new Set(interactions.map(i => i.id))\n }\n const presentAtMount = presentAtMountRef.current\n\n // Keep track of the text that the user is currently typing into the textfield\n const [userChatTextfieldValue, setUserChatTextfieldValue] = useState('')\n const [initialMessageProcessed, setInitialMessageProcessed] = useState(false)\n\n // A copy of the attachments sent with the optimistic/pending interaction, so it can still show\n // rich (name/type) chips after ChatInputArea has cleared its own attachment state. Once the\n // interaction gains a jobId, SynapseChatMessage renders its attachments from the polled async\n // job's requestBody instead (see below), so this value is simply overwritten on the next send.\n const [lastSentAttachments, setLastSentAttachments] = useState<\n ChatAttachment[]\n >([])\n\n // Restore chat session history, if exists.\n // TODO: currently only a single page is restored. Add support for multiple pages (and detect the user scrolling up to restore the next page of results older)\n // const {\n // data: sessionHistoryInfiniteData,\n // } = //, hasNextPage: hasMoreSessionHistory, fetchNextPage: fetchNextSessionHistoryPage, isLoading: isSessionHistoryLoading } =\n // useGetAgentChatSessionHistoryInfinite(\n // {\n // sessionId: agentSession?.sessionId,\n // },\n // {\n // enabled: !!agentSession,\n // },\n // )\n\n // const sessionHistory = useMemo(\n // () =>\n // sessionHistoryInfiniteData?.pages\n // .flatMap(page => page.page)\n // /* Note: session history is ordered from most recent to least recent in each page, so reverse the order when restoring the chat interface */\n // .reverse() ?? [],\n // [sessionHistoryInfiniteData],\n // )\n\n useEffect(() => {\n // on mount, create a new agent session!\n if (createAgentSession && !agentSession) {\n createAgentSession({\n agentAccessLevel,\n agentRegistrationId,\n sessionContext,\n })\n }\n }, [\n createAgentSession,\n agentSession,\n accessToken,\n sessionContext,\n agentAccessLevel,\n agentRegistrationId,\n ])\n\n useEffect(() => {\n // on mount, resolve the initial message chat interaction (if set)\n if (agentSession && initialMessage && !initialMessageProcessed) {\n sendChat(initialMessage)\n setInitialMessageProcessed(true)\n }\n }, [agentSession, initialMessage, initialMessageProcessed, sendChat])\n\n const handleSend = (message: string, attachments: ChatAttachment[]) => {\n sendChat(\n message,\n attachments.length\n ? attachments.map(attachment => ({\n fileHandleId: attachment.fileHandleId,\n // The backend short-circuits the FileHandleAssociation auth check for a user's own\n // uploaded file handle, so associateObjectId/associateObjectType are not totally\n // accurate here. FileHandleAssociateType has no dedicated value for \"the uploader's\n // own bare file handle\", so this stubs associateObjectId to the fileHandleId itself\n // and the FileEntity associate type, which supports the short-circuit path.\n associateObjectId: attachment.fileHandleId,\n associateObjectType: FileHandleAssociateType.FileEntity,\n }))\n : undefined,\n )\n setUserChatTextfieldValue('')\n setLastSentAttachments(attachments)\n }\n\n if (createAgentSessionError) {\n return (\n <Alert severity={'error'} sx={{ my: 2 }}>\n {createAgentSessionError.reason}\n </Alert>\n )\n }\n\n return (\n <Box\n sx={{\n display: 'flex',\n flexDirection: 'column',\n justifyContent: 'space-between',\n maxWidth: '1100px',\n mx: 'auto',\n height: '100%',\n }}\n >\n {!hideTitle && (\n <Typography\n variant=\"headline1\"\n sx={{\n p: '20px',\n borderBottom: '1px solid',\n borderColor: 'grey.300',\n position: 'sticky',\n top: '0px',\n backgroundColor: 'white',\n zIndex: 1,\n }}\n >\n {chatbotName}\n </Typography>\n )}\n {showAccessLevelMenu && (\n <AccessLevelMenu\n initAccessLevel={agentAccessLevel}\n onChange={newAccessLevel => {\n setAgentAccessLevel(newAccessLevel)\n updateAgentSession({\n agentAccessLevel: newAccessLevel,\n sessionId: agentSession!.sessionId!,\n })\n }}\n />\n )}\n {!agentSession && <SkeletonParagraph numRows={10} />}\n {agentSession && (\n <Box sx={{ flexGrow: 1, overflowY: 'auto', mb: 2 }}>\n <List\n sx={{\n flex: 1,\n overflowY: 'auto',\n pt: '20px',\n display: 'flex',\n flexDirection: 'column',\n }}\n >\n {/* {sessionHistory &&\n sessionHistory.map((interaction, index) => {\n return (\n <SynapseChatInteraction\n key={index}\n userMessage={interaction.usersRequestText}\n chatResponseText={interaction.agentResponseText}\n />\n )\n })} */}\n {interactions.map((interaction, index) => {\n const isLast = index === interactions.length - 1\n // The interaction has no jobId until the async job is registered; until then,\n // show the attachments the user just sent rather than waiting on the polled job.\n const isPending = interaction.jobId == null\n return (\n <SynapseChatMessage\n agentAvatar={agentAvatar}\n userAvatar={userAvatar}\n key={interaction.id}\n userMessage={interaction.userMessage}\n chatJobId={interaction.jobId}\n onSendChat={sendChat}\n scrollIntoView={isLast}\n animateEntry={!presentAtMount.has(interaction.id)}\n isAwaitingResponse={isAwaitingResponse}\n pendingAttachments={\n isPending ? lastSentAttachments : undefined\n }\n />\n )\n })}\n </List>\n </Box>\n )}\n <Box\n sx={{\n position: 'sticky',\n bottom: textboxPositionOffset,\n backgroundColor: 'white',\n }}\n >\n {suggestedPrompts &&\n suggestedPrompts.length > 0 &&\n interactions.length === 0 && (\n <Stack\n direction=\"row\"\n spacing={1}\n sx={{ pt: '8px', flexWrap: 'wrap', gap: 1 }}\n >\n {suggestedPrompts.map(prompt => (\n <Chip\n key={prompt}\n label={prompt}\n variant=\"outlined\"\n onClick={() => setUserChatTextfieldValue(prompt)}\n disabled={!agentSession}\n sx={{ cursor: 'pointer' }}\n />\n ))}\n </Stack>\n )}\n <Box sx={{ mt: '5px' }}>\n <ChatInputArea\n value={userChatTextfieldValue}\n onValueChange={setUserChatTextfieldValue}\n onSend={handleSend}\n placeholder={`Message ${chatbotName}`}\n disabled={!agentSession || isAwaitingResponse}\n allowAttachments={allowAttachments}\n />\n </Box>\n </Box>\n <Typography variant=\"smallText1\" sx={{ pt: '8px', textAlign: 'center' }}>\n {chatbotName} can make mistakes.\n </Typography>\n </Box>\n )\n}\n\nexport default SynapseChat\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SynapseChat.js","names":[],"sources":["../../../src/components/SynapseChat/SynapseChat.tsx"],"sourcesContent":["import { ChatState, useChatState } from '@/components/SynapseChat/useChatState'\nimport {\n useCreateAgentSession,\n useUpdateAgentSession,\n} from '@/synapse-queries/chat/useChat'\nimport { useSynapseContext } from '@/utils'\nimport { Alert, Box, Chip, List, Stack, Typography } from '@mui/material'\nimport {\n AgentSession,\n FileHandleAssociateType,\n GridAgentSessionContext,\n} from '@sage-bionetworks/synapse-client'\nimport { AgentAccessLevel } from '@sage-bionetworks/synapse-types'\nimport { useEffect, useRef, useState } from 'react'\nimport { SkeletonParagraph } from '../Skeleton'\nimport { displayToast } from '../ToastMessage'\nimport AccessLevelMenu from './AccessLevelMenu'\nimport { ChatAttachment } from './utils/types'\nimport { ChatInputArea } from './components/ChatInputArea/ChatInputArea'\nimport SynapseChatMessage from './SynapseChatMessage'\nimport { SmartToyTwoTone } from '@mui/icons-material'\nimport { UserCard } from '../UserCard/UserCard'\nimport { useApplicationSessionContext } from '@/utils/AppUtils'\n\nconst DEFAULT_AVATAR = (\n <Box\n sx={{\n p: '3px',\n borderRadius: '50%',\n borderStyle: 'solid',\n borderWidth: '1px',\n borderColor: 'grey.300',\n mt: '10px',\n height: '31px',\n }}\n >\n <SmartToyTwoTone sx={{ color: 'secondary.main' }} />\n </Box>\n)\n\nexport type SynapseChatProps = {\n initialMessage?: string //optional initial message\n agentRegistrationId?: string // if provided, use this agent\n chatbotName?: string // optional name of this chatbot agent\n hideTitle?: boolean\n textboxPositionOffset?: string // when embedded in a form, the textbox (form) stuck to the bottom may need to be offset due to container padding (dialog content for example!)\n /* optional session context for the agent session */\n sessionContext?: GridAgentSessionContext\n /* The current session, if state is lifted out of this component */\n externalSession?: AgentSession\n /* A callback invoked to bootstrap the current session, if state is to be lifted out of this component */\n setExternalSession?: (s: AgentSession | undefined) => void\n /* The current chat history, if state is lifted out of this component */\n externalChatState?: ChatState\n // default access level for the agent session.\n defaultAgentAccessLevel?: AgentAccessLevel\n // Whether to show the access level menu for the agent session.\n showAccessLevelMenu?: boolean\n /**\n * Optional callback invoked once when a chat response is received from the server.\n * Use this for side effects such as navigation based on the response content.\n * Called in the mutation onSuccess handler so it runs exactly once per response.\n */\n onChatResponse?: (responseText: string) => void\n /** Optional list of prompt suggestions shown as clickable pills above the text input */\n suggestedPrompts?: string[]\n /** Optional custom avatar for the chatbot agent */\n agentAvatar?: React.ReactNode\n /**\n * Whether to allow the user to attach local files to their chat message.\n * @default false\n */\n allowAttachments?: boolean\n}\n\nexport function SynapseChat({\n initialMessage,\n agentRegistrationId,\n chatbotName = 'SynapseChat',\n agentAvatar = DEFAULT_AVATAR,\n hideTitle = false,\n textboxPositionOffset = '0px',\n sessionContext,\n externalSession,\n setExternalSession,\n externalChatState,\n showAccessLevelMenu = true,\n onChatResponse,\n suggestedPrompts,\n allowAttachments = false,\n}: SynapseChatProps) {\n const { accessToken } = useSynapseContext()\n const { userId } = useApplicationSessionContext()\n\n const userAvatar = (\n <UserCard ownerId={userId} size=\"AVATAR\" avatarSize=\"MEDIUM\" />\n )\n const [localAgentSession, setLocalAgentSession] = useState<AgentSession>()\n const agentSession = externalSession ?? localAgentSession\n const setAgentSession = setExternalSession ?? setLocalAgentSession\n\n const { mutate: createAgentSession, error: createAgentSessionError } =\n useCreateAgentSession({\n onSuccess: newAgentSession => setAgentSession(newAgentSession),\n })\n\n const { mutate: updateAgentSession } = useUpdateAgentSession({\n onSuccess: updatedAgentSession => setAgentSession(updatedAgentSession),\n onError: err =>\n displayToast(\n `Unable to update the agent session: ${err.message}`,\n 'danger',\n ),\n })\n const [agentAccessLevel, setAgentAccessLevel] = useState<AgentAccessLevel>(\n sessionContext\n ? AgentAccessLevel.WRITE_YOUR_PRIVATE_DATA\n : AgentAccessLevel.PUBLICLY_ACCESSIBLE,\n )\n\n const internalChatState = useChatState(agentSession, onChatResponse)\n const chatState = externalChatState ?? internalChatState\n const { interactions, isAwaitingResponse, sendChat } = chatState\n\n // Only interactions added after this component instance mounted should play the entry\n // animation. Callers may lift state so history survives a `Dialog` closing, but the\n // `Dialog` unmounts its children, so every reopen would otherwise re-animate the whole\n // conversation.\n const presentAtMountRef = useRef<Set<string> | undefined>(undefined)\n if (presentAtMountRef.current === undefined) {\n presentAtMountRef.current = new Set(interactions.map(i => i.id))\n }\n const presentAtMount = presentAtMountRef.current\n\n // Keep track of the text that the user is currently typing into the textfield\n const [userChatTextfieldValue, setUserChatTextfieldValue] = useState('')\n const [initialMessageProcessed, setInitialMessageProcessed] = useState(false)\n\n // A copy of the attachments sent with the last interaction, so it can still show rich\n // (name/type) chips after ChatInputArea has cleared its own attachment state. This is passed to\n // the last interaction for its entire lifetime -- sent, then processing, then completed -- as a\n // fallback filename source, since the request body (FileHandleAssociation) never carries a\n // filename and the server-resolved filename (attachmentStatuses) only arrives once the job\n // completes. It's simply overwritten on the next send.\n const [lastSentAttachments, setLastSentAttachments] = useState<\n ChatAttachment[]\n >([])\n\n // Restore chat session history, if exists.\n // TODO: currently only a single page is restored. Add support for multiple pages (and detect the user scrolling up to restore the next page of results older)\n // const {\n // data: sessionHistoryInfiniteData,\n // } = //, hasNextPage: hasMoreSessionHistory, fetchNextPage: fetchNextSessionHistoryPage, isLoading: isSessionHistoryLoading } =\n // useGetAgentChatSessionHistoryInfinite(\n // {\n // sessionId: agentSession?.sessionId,\n // },\n // {\n // enabled: !!agentSession,\n // },\n // )\n\n // const sessionHistory = useMemo(\n // () =>\n // sessionHistoryInfiniteData?.pages\n // .flatMap(page => page.page)\n // /* Note: session history is ordered from most recent to least recent in each page, so reverse the order when restoring the chat interface */\n // .reverse() ?? [],\n // [sessionHistoryInfiniteData],\n // )\n\n useEffect(() => {\n // on mount, create a new agent session!\n if (createAgentSession && !agentSession) {\n createAgentSession({\n agentAccessLevel,\n agentRegistrationId,\n sessionContext,\n })\n }\n }, [\n createAgentSession,\n agentSession,\n accessToken,\n sessionContext,\n agentAccessLevel,\n agentRegistrationId,\n ])\n\n useEffect(() => {\n // on mount, resolve the initial message chat interaction (if set)\n if (agentSession && initialMessage && !initialMessageProcessed) {\n sendChat(initialMessage)\n setInitialMessageProcessed(true)\n }\n }, [agentSession, initialMessage, initialMessageProcessed, sendChat])\n\n const handleSend = (message: string, attachments: ChatAttachment[]) => {\n sendChat(\n message,\n attachments.length\n ? attachments.map(attachment => ({\n fileHandleId: attachment.fileHandleId,\n // The backend short-circuits the FileHandleAssociation auth check for a user's own\n // uploaded file handle, so associateObjectId/associateObjectType are not totally\n // accurate here. FileHandleAssociateType has no dedicated value for \"the uploader's\n // own bare file handle\", so this stubs associateObjectId to the fileHandleId itself\n // and the FileEntity associate type, which supports the short-circuit path.\n associateObjectId: attachment.fileHandleId,\n associateObjectType: FileHandleAssociateType.FileEntity,\n }))\n : undefined,\n )\n setUserChatTextfieldValue('')\n setLastSentAttachments(attachments)\n }\n\n if (createAgentSessionError) {\n return (\n <Alert severity={'error'} sx={{ my: 2 }}>\n {createAgentSessionError.reason}\n </Alert>\n )\n }\n\n return (\n <Box\n sx={{\n display: 'flex',\n flexDirection: 'column',\n justifyContent: 'space-between',\n maxWidth: '1100px',\n mx: 'auto',\n height: '100%',\n }}\n >\n {!hideTitle && (\n <Typography\n variant=\"headline1\"\n sx={{\n p: '20px',\n borderBottom: '1px solid',\n borderColor: 'grey.300',\n position: 'sticky',\n top: '0px',\n backgroundColor: 'white',\n zIndex: 1,\n }}\n >\n {chatbotName}\n </Typography>\n )}\n {showAccessLevelMenu && (\n <AccessLevelMenu\n initAccessLevel={agentAccessLevel}\n onChange={newAccessLevel => {\n setAgentAccessLevel(newAccessLevel)\n updateAgentSession({\n agentAccessLevel: newAccessLevel,\n sessionId: agentSession!.sessionId!,\n })\n }}\n />\n )}\n {!agentSession && <SkeletonParagraph numRows={10} />}\n {agentSession && (\n <Box sx={{ flexGrow: 1, overflowY: 'auto', mb: 2 }}>\n <List\n sx={{\n flex: 1,\n overflowY: 'auto',\n pt: '20px',\n display: 'flex',\n flexDirection: 'column',\n }}\n >\n {/* {sessionHistory &&\n sessionHistory.map((interaction, index) => {\n return (\n <SynapseChatInteraction\n key={index}\n userMessage={interaction.usersRequestText}\n chatResponseText={interaction.agentResponseText}\n />\n )\n })} */}\n {interactions.map((interaction, index) => {\n const isLast = index === interactions.length - 1\n return (\n <SynapseChatMessage\n agentAvatar={agentAvatar}\n userAvatar={userAvatar}\n key={interaction.id}\n userMessage={interaction.userMessage}\n chatJobId={interaction.jobId}\n onSendChat={sendChat}\n scrollIntoView={isLast}\n animateEntry={!presentAtMount.has(interaction.id)}\n isAwaitingResponse={isAwaitingResponse}\n pendingAttachments={\n // Only one interaction can be in flight at a time (the composer is disabled\n // while isAwaitingResponse), so lastSentAttachments always corresponds to\n // whichever interaction is last.\n isLast ? lastSentAttachments : undefined\n }\n />\n )\n })}\n </List>\n </Box>\n )}\n <Box\n sx={{\n position: 'sticky',\n bottom: textboxPositionOffset,\n backgroundColor: 'white',\n }}\n >\n {suggestedPrompts &&\n suggestedPrompts.length > 0 &&\n interactions.length === 0 && (\n <Stack\n direction=\"row\"\n spacing={1}\n sx={{ pt: '8px', flexWrap: 'wrap', gap: 1 }}\n >\n {suggestedPrompts.map(prompt => (\n <Chip\n key={prompt}\n label={prompt}\n variant=\"outlined\"\n onClick={() => setUserChatTextfieldValue(prompt)}\n disabled={!agentSession}\n sx={{ cursor: 'pointer' }}\n />\n ))}\n </Stack>\n )}\n <Box sx={{ mt: '5px' }}>\n <ChatInputArea\n value={userChatTextfieldValue}\n onValueChange={setUserChatTextfieldValue}\n onSend={handleSend}\n placeholder={`Message ${chatbotName}`}\n disabled={!agentSession || isAwaitingResponse}\n allowAttachments={allowAttachments}\n />\n </Box>\n </Box>\n <Typography variant=\"smallText1\" sx={{ pt: '8px', textAlign: 'center' }}>\n {chatbotName} can make mistakes.\n </Typography>\n </Box>\n )\n}\n\nexport default SynapseChat\n"],"mappings":"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"}
|
|
@@ -2,8 +2,9 @@ import { TraceEvent } from '@sage-bionetworks/synapse-types';
|
|
|
2
2
|
import { AgentChatAttachmentStatus } from '@sage-bionetworks/synapse-client';
|
|
3
3
|
/**
|
|
4
4
|
* A chat attachment to display on a sent/pending turn. Only `fileHandleId` is guaranteed --
|
|
5
|
-
* `fileName`/`contentType` are omitted for a restored
|
|
6
|
-
* that was sent to the server is known
|
|
5
|
+
* `fileName`/`contentType` are omitted for a turn restored from history, where only the
|
|
6
|
+
* fileHandleId that was sent to the server is known, with no in-session upload record to fall
|
|
7
|
+
* back on (see SynapseChatMessage).
|
|
7
8
|
*/
|
|
8
9
|
export type SynapseChatInteractionAttachment = {
|
|
9
10
|
fileHandleId: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SynapseChatInteraction.d.ts","sourceRoot":"","sources":["../../../src/components/SynapseChat/SynapseChatInteraction.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AAQ5D,OAAO,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAA;AAE5E
|
|
1
|
+
{"version":3,"file":"SynapseChatInteraction.d.ts","sourceRoot":"","sources":["../../../src/components/SynapseChat/SynapseChatInteraction.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AAQ5D,OAAO,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAA;AAE5E;;;;;GAKG;AACH,MAAM,MAAM,gCAAgC,GAAG;IAC7C,YAAY,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,2BAA2B,GAAG;IACxC,WAAW,EAAE,MAAM,CAAA;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,iBAAiB,CAAC,EAAE,UAAU,EAAE,CAAA;IAChC,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IACtC,WAAW,EAAE,KAAK,CAAC,SAAS,CAAA;IAC5B,UAAU,EAAE,KAAK,CAAC,SAAS,CAAA;IAC3B,sFAAsF;IACtF,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,6GAA6G;IAC7G,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,2DAA2D;IAC3D,WAAW,CAAC,EAAE,gCAAgC,EAAE,CAAA;IAChD,sHAAsH;IACtH,kBAAkB,CAAC,EAAE,yBAAyB,EAAE,CAAA;CACjD,CAAA;AAqBD,wBAAgB,sBAAsB,CAAC,EACrC,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,cAAsB,EACtB,UAAU,EACV,WAAW,EACX,UAAU,EACV,YAAoB,EACpB,kBAA0B,EAC1B,WAAW,EACX,kBAAkB,GACnB,EAAE,2BAA2B,2CAmP7B;AAED,eAAe,sBAAsB,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SynapseChatInteraction.js","names":[],"sources":["../../../src/components/SynapseChat/SynapseChatInteraction.tsx"],"sourcesContent":["import { SynapseSpinner } from '@/components/LoadingScreen/LoadingScreen'\nimport extractMessageFromTraceEvent, {\n TraceMessage,\n} from '@/components/SynapseChat/extractMessageFromTraceEvent'\nimport { KeyboardArrowDown, KeyboardArrowRight } from '@mui/icons-material'\nimport {\n Alert,\n Box,\n Button,\n Chip,\n Collapse,\n ListItem,\n ListItemText,\n Stack,\n Tooltip,\n useTheme,\n} from '@mui/material'\nimport { TraceEvent } from '@sage-bionetworks/synapse-types'\nimport { useEffect, useMemo, useRef, useState } from 'react'\nimport MarkdownSynapse from '../Markdown/MarkdownSynapse'\nimport styles from './SynapseChatInteraction.module.scss'\nimport {\n AttachmentStripItem,\n ChatAttachmentStrip,\n} from './components/ChatAttachmentStrip/ChatAttachmentStrip'\nimport { AgentChatAttachmentStatus } from '@sage-bionetworks/synapse-client'\n\n/**\n * A chat attachment to display on a sent/pending turn. Only `fileHandleId` is guaranteed --\n * `fileName`/`contentType` are omitted for a restored/polled turn, where only the fileHandleId\n * that was sent to the server is known (see SynapseChatMessage).\n */\nexport type SynapseChatInteractionAttachment = {\n fileHandleId: string\n fileName?: string\n contentType?: string\n}\n\nexport type SynapseChatInteractionProps = {\n userMessage: string\n chatResponseText?: string\n chatResponseTrace?: TraceEvent[]\n scrollIntoView?: boolean\n chatErrorReason?: string\n onSendChat?: (message: string) => void\n agentAvatar: React.ReactNode\n userAvatar: React.ReactNode\n /** Whether to play the fade/rise-in entry animation for this interaction on mount. */\n animateEntry?: boolean\n /** Whether a turn is currently in flight; gates the guide-prompt chips so they can't bypass the composer. */\n isAwaitingResponse?: boolean\n /** Attachments the user sent with this message, if any. */\n attachments?: SynapseChatInteractionAttachment[]\n /** Server-reported outcome of staging each attachment, if available (see AgentChatResponseWithAttachmentStatuses). */\n attachmentStatuses?: AgentChatAttachmentStatus[]\n}\n\n// Show tool calls in the trace. Useful for development. We may want to show them to users in the future.\nconst SHOW_TOOL_USE = false\n\nfunction getMarkdownForTraceMessage(traceMessage: TraceMessage): string {\n if ('reasoningText' in traceMessage) {\n return traceMessage.reasoningText\n }\n if (SHOW_TOOL_USE && 'toolName' in traceMessage) {\n return `**Tool Used:** \\`${\n traceMessage.toolName\n }\\`\\n\\n**Tool Input:**\\n\\`\\`\\`json\\n${JSON.stringify(\n traceMessage.toolInput,\n null,\n 2,\n )}\\n\\`\\`\\`\\n`\n }\n return ''\n}\n\nexport function SynapseChatInteraction({\n userMessage,\n chatResponseText,\n chatErrorReason,\n chatResponseTrace,\n scrollIntoView = false,\n onSendChat,\n agentAvatar,\n userAvatar,\n animateEntry = false,\n isAwaitingResponse = false,\n attachments,\n attachmentStatuses,\n}: SynapseChatInteractionProps) {\n const theme = useTheme()\n const userMessageRef = useRef<HTMLLIElement | null>(null)\n const responseRef = useRef<HTMLLIElement | null>(null)\n const [showTrace, setShowTrace] = useState(false)\n\n const isLoading = !chatResponseText && !chatErrorReason\n\n useEffect(() => {\n // on mount, scroll into view if instructed. This brings the \"Thinking...\" row to the top so\n // the answer's opening lines are usually visible as soon as it starts streaming in.\n if (scrollIntoView) {\n userMessageRef.current?.scrollIntoView({ behavior: 'smooth' })\n }\n }, [scrollIntoView])\n\n useEffect(() => {\n // once the response (or an error) arrives, scroll all the way to the bottom so the full\n // answer - which may be taller than the viewport - is brought into view.\n if (scrollIntoView && !isLoading) {\n responseRef.current?.scrollIntoView({ behavior: 'smooth', block: 'end' })\n }\n }, [scrollIntoView, isLoading])\n\n const traceMessages = useMemo(\n () =>\n (chatResponseTrace ?? [])\n .flatMap(traceEvent => extractMessageFromTraceEvent(traceEvent))\n ?.filter(trace => !!trace),\n [chatResponseTrace],\n )\n\n const hasTraceInfo = traceMessages.length > 0\n\n const lastReasoningMessage = useMemo(\n () => traceMessages.filter(trace => 'reasoningText' in trace).at(-1),\n [traceMessages],\n )\n\n const traceButtonLoadingText =\n lastReasoningMessage == null\n ? 'Thinking...'\n : lastReasoningMessage.reasoningText\n\n const traceButtonText = isLoading\n ? traceButtonLoadingText\n : `${showTrace ? 'Hide' : 'Show'} Trace`\n\n const { textContent, guidePrompts } = useMemo(() => {\n try {\n const parser = new DOMParser()\n const doc = parser.parseFromString(chatResponseText ?? '', 'text/html')\n\n // Remove tool_name and actions elements (AI XML tags not for display)\n doc\n .querySelectorAll('tool_name, actions')\n .forEach(element => element.remove())\n\n // Extract guideprompts before removing them\n const extractedGuidePrompts = Array.from(\n doc.querySelectorAll('guideprompt'),\n )\n .map(el => el.textContent?.trim())\n .filter((t): t is string => !!t)\n\n // Remove guideprompt elements\n doc.querySelectorAll('guideprompt').forEach(element => element.remove())\n\n // Extract text from <chat> element if present, otherwise use full body text\n const chatElement = doc.querySelector('chat')\n return {\n textContent: chatElement\n ? (chatElement.textContent ?? '')\n : (doc.body.textContent ?? ''),\n guidePrompts: extractedGuidePrompts,\n }\n } catch (e) {\n console.error(e)\n return { textContent: chatResponseText ?? '', guidePrompts: [] }\n }\n }, [chatResponseText])\n\n const attachmentItems: AttachmentStripItem[] = useMemo(\n () =>\n (attachments ?? []).map(attachment => {\n const status = attachmentStatuses?.find(\n s => s.fileHandleId === attachment.fileHandleId,\n )\n return {\n fileHandleId: attachment.fileHandleId,\n label: attachment.fileName ?? attachment.fileHandleId,\n contentType: attachment.contentType,\n status: status?.status === 'FAILED' ? 'failed' : 'default',\n errorMessage: status?.failureMessage,\n }\n }),\n [attachments, attachmentStatuses],\n )\n\n return (\n <>\n <ListItem\n ref={userMessageRef}\n sx={{\n alignSelf: 'flex-end',\n maxWidth: '82%',\n mb: '5px',\n wordWrap: 'break-word',\n width: 'auto',\n display: 'grid',\n gridTemplateColumns: 'auto auto',\n columnGap: '16px',\n alignItems: 'start',\n justifyItems: 'end',\n }}\n >\n <Box\n className={animateEntry ? styles.entryAnimation : undefined}\n sx={{\n p: '4px 14px',\n backgroundColor: '#F3F6F7',\n borderRadius: '8px',\n }}\n >\n <ListItemText primary={userMessage} />\n </Box>\n <Box sx={{ marginTop: '4px' }}>{userAvatar}</Box>\n </ListItem>\n {attachmentItems.length > 0 && (\n <ListItem sx={{ display: 'block', p: '0px', mb: '5px' }}>\n <ChatAttachmentStrip items={attachmentItems} wrap />\n </ListItem>\n )}\n <ListItem\n ref={responseRef}\n sx={{\n display: 'grid',\n gridTemplateColumns: '50px auto',\n columnGap: '16px',\n justifyItems: 'center',\n alignItems: 'start',\n p: '0px',\n padding: '10px',\n }}\n >\n {agentAvatar}\n <Box\n sx={{\n borderRadius: '10px',\n maxWidth: '100%',\n overflow: 'auto',\n }}\n >\n <Box\n component={'aside'}\n sx={{\n '.markdown': {\n fontStyle: 'italic',\n borderLeft: `4px solid ${theme.palette.grey[300]}`,\n marginLeft: '4px',\n paddingLeft: '8px',\n mt: 1,\n mb: 2,\n },\n }}\n >\n <Button\n variant={'outlined'}\n size={'small'}\n startIcon={\n isLoading ? (\n <SynapseSpinner size={14} />\n ) : showTrace ? (\n <KeyboardArrowDown sx={{ width: '14px' }} />\n ) : (\n <KeyboardArrowRight sx={{ width: '14px' }} />\n )\n }\n disabled={!hasTraceInfo}\n onClick={() => {\n setShowTrace(v => !v)\n }}\n sx={{\n height: '20px',\n fontSize: '12px',\n fontWeight: 600,\n mb: 1,\n border: 'none !important',\n color: 'grey.700',\n justifyContent: 'flex-start',\n whiteSpace: 'nowrap',\n maxWidth: '325px',\n textTransform: 'none',\n pl: 0,\n '.MuiButton-startIcon': { mr: 0.5 },\n }}\n >\n <Box sx={{ overflow: 'hidden', textOverflow: 'ellipsis' }}>\n {traceButtonText}\n </Box>\n </Button>\n {chatResponseTrace && (\n <Collapse in={showTrace}>\n <MarkdownSynapse\n markdown={traceMessages\n .map(getMarkdownForTraceMessage)\n .filter(md => md.trim().length > 0)\n .join('<br/><br/>')}\n />\n </Collapse>\n )}\n </Box>\n {(textContent || (onSendChat && guidePrompts.length > 0)) && (\n <Box className={animateEntry ? styles.entryAnimation : undefined}>\n {textContent && <MarkdownSynapse markdown={textContent} />}\n {onSendChat && guidePrompts.length > 0 && (\n <Stack direction=\"row\" flexWrap=\"wrap\" gap={1} mt={1}>\n {guidePrompts.map(prompt => (\n <Tooltip key={prompt} title={prompt}>\n <Chip\n label={prompt}\n variant=\"outlined\"\n color=\"primary\"\n clickable\n disabled={isAwaitingResponse}\n onClick={() => onSendChat(prompt)}\n sx={{ maxWidth: 200 }}\n />\n </Tooltip>\n ))}\n </Stack>\n )}\n </Box>\n )}\n </Box>\n </ListItem>\n {chatErrorReason && (\n <Alert severity={'error'} sx={{ my: 2 }}>\n {chatErrorReason}\n </Alert>\n )}\n </>\n )\n}\n\nexport default SynapseChatInteraction\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SynapseChatInteraction.js","names":[],"sources":["../../../src/components/SynapseChat/SynapseChatInteraction.tsx"],"sourcesContent":["import { SynapseSpinner } from '@/components/LoadingScreen/LoadingScreen'\nimport extractMessageFromTraceEvent, {\n TraceMessage,\n} from '@/components/SynapseChat/extractMessageFromTraceEvent'\nimport { KeyboardArrowDown, KeyboardArrowRight } from '@mui/icons-material'\nimport {\n Alert,\n Box,\n Button,\n Chip,\n Collapse,\n ListItem,\n ListItemText,\n Stack,\n Tooltip,\n useTheme,\n} from '@mui/material'\nimport { TraceEvent } from '@sage-bionetworks/synapse-types'\nimport { useEffect, useMemo, useRef, useState } from 'react'\nimport MarkdownSynapse from '../Markdown/MarkdownSynapse'\nimport styles from './SynapseChatInteraction.module.scss'\nimport {\n AttachmentStripItem,\n ChatAttachmentStrip,\n} from './components/ChatAttachmentStrip/ChatAttachmentStrip'\nimport { AgentChatAttachmentStatus } from '@sage-bionetworks/synapse-client'\n\n/**\n * A chat attachment to display on a sent/pending turn. Only `fileHandleId` is guaranteed --\n * `fileName`/`contentType` are omitted for a turn restored from history, where only the\n * fileHandleId that was sent to the server is known, with no in-session upload record to fall\n * back on (see SynapseChatMessage).\n */\nexport type SynapseChatInteractionAttachment = {\n fileHandleId: string\n fileName?: string\n contentType?: string\n}\n\nexport type SynapseChatInteractionProps = {\n userMessage: string\n chatResponseText?: string\n chatResponseTrace?: TraceEvent[]\n scrollIntoView?: boolean\n chatErrorReason?: string\n onSendChat?: (message: string) => void\n agentAvatar: React.ReactNode\n userAvatar: React.ReactNode\n /** Whether to play the fade/rise-in entry animation for this interaction on mount. */\n animateEntry?: boolean\n /** Whether a turn is currently in flight; gates the guide-prompt chips so they can't bypass the composer. */\n isAwaitingResponse?: boolean\n /** Attachments the user sent with this message, if any. */\n attachments?: SynapseChatInteractionAttachment[]\n /** Server-reported outcome of staging each attachment, if available (see AgentChatResponseWithAttachmentStatuses). */\n attachmentStatuses?: AgentChatAttachmentStatus[]\n}\n\n// Show tool calls in the trace. Useful for development. We may want to show them to users in the future.\nconst SHOW_TOOL_USE = false\n\nfunction getMarkdownForTraceMessage(traceMessage: TraceMessage): string {\n if ('reasoningText' in traceMessage) {\n return traceMessage.reasoningText\n }\n if (SHOW_TOOL_USE && 'toolName' in traceMessage) {\n return `**Tool Used:** \\`${\n traceMessage.toolName\n }\\`\\n\\n**Tool Input:**\\n\\`\\`\\`json\\n${JSON.stringify(\n traceMessage.toolInput,\n null,\n 2,\n )}\\n\\`\\`\\`\\n`\n }\n return ''\n}\n\nexport function SynapseChatInteraction({\n userMessage,\n chatResponseText,\n chatErrorReason,\n chatResponseTrace,\n scrollIntoView = false,\n onSendChat,\n agentAvatar,\n userAvatar,\n animateEntry = false,\n isAwaitingResponse = false,\n attachments,\n attachmentStatuses,\n}: SynapseChatInteractionProps) {\n const theme = useTheme()\n const userMessageRef = useRef<HTMLLIElement | null>(null)\n const responseRef = useRef<HTMLLIElement | null>(null)\n const [showTrace, setShowTrace] = useState(false)\n\n const isLoading = !chatResponseText && !chatErrorReason\n\n useEffect(() => {\n // on mount, scroll into view if instructed. This brings the \"Thinking...\" row to the top so\n // the answer's opening lines are usually visible as soon as it starts streaming in.\n if (scrollIntoView) {\n userMessageRef.current?.scrollIntoView({ behavior: 'smooth' })\n }\n }, [scrollIntoView])\n\n useEffect(() => {\n // once the response (or an error) arrives, scroll all the way to the bottom so the full\n // answer - which may be taller than the viewport - is brought into view.\n if (scrollIntoView && !isLoading) {\n responseRef.current?.scrollIntoView({ behavior: 'smooth', block: 'end' })\n }\n }, [scrollIntoView, isLoading])\n\n const traceMessages = useMemo(\n () =>\n (chatResponseTrace ?? [])\n .flatMap(traceEvent => extractMessageFromTraceEvent(traceEvent))\n ?.filter(trace => !!trace),\n [chatResponseTrace],\n )\n\n const hasTraceInfo = traceMessages.length > 0\n\n const lastReasoningMessage = useMemo(\n () => traceMessages.filter(trace => 'reasoningText' in trace).at(-1),\n [traceMessages],\n )\n\n const traceButtonLoadingText =\n lastReasoningMessage == null\n ? 'Thinking...'\n : lastReasoningMessage.reasoningText\n\n const traceButtonText = isLoading\n ? traceButtonLoadingText\n : `${showTrace ? 'Hide' : 'Show'} Trace`\n\n const { textContent, guidePrompts } = useMemo(() => {\n try {\n const parser = new DOMParser()\n const doc = parser.parseFromString(chatResponseText ?? '', 'text/html')\n\n // Remove tool_name and actions elements (AI XML tags not for display)\n doc\n .querySelectorAll('tool_name, actions')\n .forEach(element => element.remove())\n\n // Extract guideprompts before removing them\n const extractedGuidePrompts = Array.from(\n doc.querySelectorAll('guideprompt'),\n )\n .map(el => el.textContent?.trim())\n .filter((t): t is string => !!t)\n\n // Remove guideprompt elements\n doc.querySelectorAll('guideprompt').forEach(element => element.remove())\n\n // Extract text from <chat> element if present, otherwise use full body text\n const chatElement = doc.querySelector('chat')\n return {\n textContent: chatElement\n ? (chatElement.textContent ?? '')\n : (doc.body.textContent ?? ''),\n guidePrompts: extractedGuidePrompts,\n }\n } catch (e) {\n console.error(e)\n return { textContent: chatResponseText ?? '', guidePrompts: [] }\n }\n }, [chatResponseText])\n\n const attachmentItems: AttachmentStripItem[] = useMemo(\n () =>\n (attachments ?? []).map(attachment => {\n const status = attachmentStatuses?.find(\n s => s.fileHandleId === attachment.fileHandleId,\n )\n return {\n fileHandleId: attachment.fileHandleId,\n label: attachment.fileName ?? attachment.fileHandleId,\n contentType: attachment.contentType,\n status: status?.status === 'FAILED' ? 'failed' : 'default',\n errorMessage: status?.failureMessage,\n }\n }),\n [attachments, attachmentStatuses],\n )\n\n return (\n <>\n <ListItem\n ref={userMessageRef}\n sx={{\n alignSelf: 'flex-end',\n maxWidth: '82%',\n mb: '5px',\n wordWrap: 'break-word',\n width: 'auto',\n display: 'grid',\n gridTemplateColumns: 'auto auto',\n columnGap: '16px',\n alignItems: 'start',\n justifyItems: 'end',\n }}\n >\n <Box\n className={animateEntry ? styles.entryAnimation : undefined}\n sx={{\n p: '4px 14px',\n backgroundColor: '#F3F6F7',\n borderRadius: '8px',\n }}\n >\n <ListItemText primary={userMessage} />\n </Box>\n <Box sx={{ marginTop: '4px' }}>{userAvatar}</Box>\n </ListItem>\n {attachmentItems.length > 0 && (\n <ListItem sx={{ display: 'block', p: '0px', mb: '5px' }}>\n <ChatAttachmentStrip items={attachmentItems} wrap />\n </ListItem>\n )}\n <ListItem\n ref={responseRef}\n sx={{\n display: 'grid',\n gridTemplateColumns: '50px auto',\n columnGap: '16px',\n justifyItems: 'center',\n alignItems: 'start',\n p: '0px',\n padding: '10px',\n }}\n >\n {agentAvatar}\n <Box\n sx={{\n borderRadius: '10px',\n maxWidth: '100%',\n overflow: 'auto',\n }}\n >\n <Box\n component={'aside'}\n sx={{\n '.markdown': {\n fontStyle: 'italic',\n borderLeft: `4px solid ${theme.palette.grey[300]}`,\n marginLeft: '4px',\n paddingLeft: '8px',\n mt: 1,\n mb: 2,\n },\n }}\n >\n <Button\n variant={'outlined'}\n size={'small'}\n startIcon={\n isLoading ? (\n <SynapseSpinner size={14} />\n ) : showTrace ? (\n <KeyboardArrowDown sx={{ width: '14px' }} />\n ) : (\n <KeyboardArrowRight sx={{ width: '14px' }} />\n )\n }\n disabled={!hasTraceInfo}\n onClick={() => {\n setShowTrace(v => !v)\n }}\n sx={{\n height: '20px',\n fontSize: '12px',\n fontWeight: 600,\n mb: 1,\n border: 'none !important',\n color: 'grey.700',\n justifyContent: 'flex-start',\n whiteSpace: 'nowrap',\n maxWidth: '325px',\n textTransform: 'none',\n pl: 0,\n '.MuiButton-startIcon': { mr: 0.5 },\n }}\n >\n <Box sx={{ overflow: 'hidden', textOverflow: 'ellipsis' }}>\n {traceButtonText}\n </Box>\n </Button>\n {chatResponseTrace && (\n <Collapse in={showTrace}>\n <MarkdownSynapse\n markdown={traceMessages\n .map(getMarkdownForTraceMessage)\n .filter(md => md.trim().length > 0)\n .join('<br/><br/>')}\n />\n </Collapse>\n )}\n </Box>\n {(textContent || (onSendChat && guidePrompts.length > 0)) && (\n <Box className={animateEntry ? styles.entryAnimation : undefined}>\n {textContent && <MarkdownSynapse markdown={textContent} />}\n {onSendChat && guidePrompts.length > 0 && (\n <Stack direction=\"row\" flexWrap=\"wrap\" gap={1} mt={1}>\n {guidePrompts.map(prompt => (\n <Tooltip key={prompt} title={prompt}>\n <Chip\n label={prompt}\n variant=\"outlined\"\n color=\"primary\"\n clickable\n disabled={isAwaitingResponse}\n onClick={() => onSendChat(prompt)}\n sx={{ maxWidth: 200 }}\n />\n </Tooltip>\n ))}\n </Stack>\n )}\n </Box>\n )}\n </Box>\n </ListItem>\n {chatErrorReason && (\n <Alert severity={'error'} sx={{ my: 2 }}>\n {chatErrorReason}\n </Alert>\n )}\n </>\n )\n}\n\nexport default SynapseChatInteraction\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
.
|
|
1
|
+
._chip_pr1yw_1{margin-top:var(--remove-button-offset-y,5px);margin-left:var(--remove-button-offset-x,8px);position:relative}._removeBadge_pr1yw_7.MuiButtonBase-root{border:1px solid var(--synapse-gray-300);background-color:#fff;width:16px;height:16px}._removeBadge_pr1yw_7.MuiButtonBase-root:hover{background-color:var(--synapse-gray-100)}._removeBadge_pr1yw_7.MuiButtonBase-root{top:calc(-1 * var(--remove-button-offset-y,5px));left:calc(-1 * var(--remove-button-offset-x,8px));opacity:0;transition:opacity .1s;position:absolute}._chip_pr1yw_1:hover ._removeBadge_pr1yw_7,._chip_pr1yw_1:focus-within ._removeBadge_pr1yw_7{opacity:1}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AttachmentChip.d.ts","sourceRoot":"","sources":["../../../../../src/components/SynapseChat/components/AttachmentChip/AttachmentChip.tsx"],"names":[],"mappings":"AAIA,MAAM,MAAM,oBAAoB,GAAG,SAAS,GAAG,QAAQ,CAAA;AAEvD,MAAM,MAAM,mBAAmB,GAAG;IAChC;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAA;IACb;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;OAEG;IACH,MAAM,CAAC,EAAE,oBAAoB,CAAA;IAC7B,gEAAgE;IAChE,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB,yEAAyE;IACzE,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAC3B,CAAA;AAUD,wBAAgB,mBAAmB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAKhE;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,WAAW,EACX,MAAkB,EAClB,YAAY,EACZ,QAAQ,EACR,iBAAqC,GACtC,EAAE,mBAAmB,
|
|
1
|
+
{"version":3,"file":"AttachmentChip.d.ts","sourceRoot":"","sources":["../../../../../src/components/SynapseChat/components/AttachmentChip/AttachmentChip.tsx"],"names":[],"mappings":"AAIA,MAAM,MAAM,oBAAoB,GAAG,SAAS,GAAG,QAAQ,CAAA;AAEvD,MAAM,MAAM,mBAAmB,GAAG;IAChC;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAA;IACb;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;OAEG;IACH,MAAM,CAAC,EAAE,oBAAoB,CAAA;IAC7B,gEAAgE;IAChE,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB,yEAAyE;IACzE,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAC3B,CAAA;AAUD,wBAAgB,mBAAmB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAKhE;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,WAAW,EACX,MAAkB,EAClB,YAAY,EACZ,QAAQ,EACR,iBAAqC,GACtC,EAAE,mBAAmB,2CAwDrB;AAED,eAAe,cAAc,CAAA"}
|
|
@@ -56,13 +56,6 @@ function u({ label: c, contentType: u, status: d = "default", errorMessage: f, o
|
|
|
56
56
|
onClick: p,
|
|
57
57
|
size: "small",
|
|
58
58
|
className: e.removeBadge,
|
|
59
|
-
sx: {
|
|
60
|
-
border: "1px solid",
|
|
61
|
-
borderColor: "grey.300",
|
|
62
|
-
backgroundColor: "white",
|
|
63
|
-
width: "16px",
|
|
64
|
-
height: "16px"
|
|
65
|
-
},
|
|
66
59
|
children: /* @__PURE__ */ a(s, { sx: { fontSize: "10px" } })
|
|
67
60
|
})]
|
|
68
61
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AttachmentChip.js","names":[],"sources":["../../../../../src/components/SynapseChat/components/AttachmentChip/AttachmentChip.tsx"],"sourcesContent":["import CloseIcon from '@mui/icons-material/Close'\nimport { Box, IconButton, Tooltip, Typography } from '@mui/material'\nimport styles from './AttachmentChip.module.scss'\n\nexport type AttachmentChipStatus = 'default' | 'failed'\n\nexport type AttachmentChipProps = {\n /**\n * Display name for the attachment. For a pending/just-uploaded attachment this is the real\n * filename; for a restored/polled turn where file metadata isn't available, pass the\n * fileHandleId instead.\n */\n label: string\n /**\n * MIME content type, used to derive a short type label (e.g. \"PDF\"). Omit when the type is\n * unknown (e.g. a restored turn).\n */\n contentType?: string\n /**\n * @default 'default'\n */\n status?: AttachmentChipStatus\n /** Shown in a tooltip on the chip when `status` is 'failed'. */\n errorMessage?: string\n /** If provided, renders a remove (\"x\") button; invoked when clicked. */\n onRemove?: () => void\n /** Accessible label for the remove button. @default `Remove ${label}` */\n removeButtonLabel?: string\n}\n\nconst CONTENT_TYPE_LABELS: Record<string, string> = {\n 'application/pdf': 'PDF',\n 'text/plain': 'TXT',\n 'text/csv': 'CSV',\n 'application/json': 'JSON',\n 'text/tab-separated-values': 'TSV',\n}\n\nexport function getContentTypeLabel(contentType?: string): string {\n if (!contentType) {\n return 'FILE'\n }\n return CONTENT_TYPE_LABELS[contentType] ?? 'FILE'\n}\n\n/**\n * Displays a single chat attachment as a chip with a filename and type label. Used both for\n * attachments still pending send (with a remove button) and for attachments on a sent/restored\n * chat turn (read-only, optionally showing a server-reported failure).\n */\nexport function AttachmentChip({\n label,\n contentType,\n status = 'default',\n errorMessage,\n onRemove,\n removeButtonLabel = `Remove ${label}`,\n}: AttachmentChipProps) {\n const isFailed = status === 'failed'\n\n const chip = (\n <Box\n className={styles.chip}\n sx={{\n display: 'flex',\n alignItems: 'center',\n gap: '10px',\n border: '1px solid',\n borderColor: isFailed ? 'error.main' : 'grey.300',\n borderRadius: '8px',\n boxShadow: '0px 1px 1px rgba(0,0,0,0.05)',\n p: '10px',\n }}\n >\n <Box sx={{ minWidth: 0, flex: 1 }}>\n <Typography\n variant=\"body1\"\n sx={{\n fontWeight: 700,\n fontSize: '14px',\n color: isFailed ? 'error.main' : 'grey.900',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }}\n >\n {label}\n </Typography>\n <Typography\n variant=\"body1\"\n sx={{ fontSize: '12px', color: 'grey.600' }}\n >\n {isFailed ? 'Failed' : getContentTypeLabel(contentType)}\n </Typography>\n </Box>\n {onRemove && (\n <IconButton\n type=\"button\"\n aria-label={removeButtonLabel}\n onClick={onRemove}\n size=\"small\"\n className={styles.removeBadge}\n
|
|
1
|
+
{"version":3,"file":"AttachmentChip.js","names":[],"sources":["../../../../../src/components/SynapseChat/components/AttachmentChip/AttachmentChip.tsx"],"sourcesContent":["import CloseIcon from '@mui/icons-material/Close'\nimport { Box, IconButton, Tooltip, Typography } from '@mui/material'\nimport styles from './AttachmentChip.module.scss'\n\nexport type AttachmentChipStatus = 'default' | 'failed'\n\nexport type AttachmentChipProps = {\n /**\n * Display name for the attachment. For a pending/just-uploaded attachment this is the real\n * filename; for a restored/polled turn where file metadata isn't available, pass the\n * fileHandleId instead.\n */\n label: string\n /**\n * MIME content type, used to derive a short type label (e.g. \"PDF\"). Omit when the type is\n * unknown (e.g. a restored turn).\n */\n contentType?: string\n /**\n * @default 'default'\n */\n status?: AttachmentChipStatus\n /** Shown in a tooltip on the chip when `status` is 'failed'. */\n errorMessage?: string\n /** If provided, renders a remove (\"x\") button; invoked when clicked. */\n onRemove?: () => void\n /** Accessible label for the remove button. @default `Remove ${label}` */\n removeButtonLabel?: string\n}\n\nconst CONTENT_TYPE_LABELS: Record<string, string> = {\n 'application/pdf': 'PDF',\n 'text/plain': 'TXT',\n 'text/csv': 'CSV',\n 'application/json': 'JSON',\n 'text/tab-separated-values': 'TSV',\n}\n\nexport function getContentTypeLabel(contentType?: string): string {\n if (!contentType) {\n return 'FILE'\n }\n return CONTENT_TYPE_LABELS[contentType] ?? 'FILE'\n}\n\n/**\n * Displays a single chat attachment as a chip with a filename and type label. Used both for\n * attachments still pending send (with a remove button) and for attachments on a sent/restored\n * chat turn (read-only, optionally showing a server-reported failure).\n */\nexport function AttachmentChip({\n label,\n contentType,\n status = 'default',\n errorMessage,\n onRemove,\n removeButtonLabel = `Remove ${label}`,\n}: AttachmentChipProps) {\n const isFailed = status === 'failed'\n\n const chip = (\n <Box\n className={styles.chip}\n sx={{\n display: 'flex',\n alignItems: 'center',\n gap: '10px',\n border: '1px solid',\n borderColor: isFailed ? 'error.main' : 'grey.300',\n borderRadius: '8px',\n boxShadow: '0px 1px 1px rgba(0,0,0,0.05)',\n p: '10px',\n }}\n >\n <Box sx={{ minWidth: 0, flex: 1 }}>\n <Typography\n variant=\"body1\"\n sx={{\n fontWeight: 700,\n fontSize: '14px',\n color: isFailed ? 'error.main' : 'grey.900',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }}\n >\n {label}\n </Typography>\n <Typography\n variant=\"body1\"\n sx={{ fontSize: '12px', color: 'grey.600' }}\n >\n {isFailed ? 'Failed' : getContentTypeLabel(contentType)}\n </Typography>\n </Box>\n {onRemove && (\n <IconButton\n type=\"button\"\n aria-label={removeButtonLabel}\n onClick={onRemove}\n size=\"small\"\n className={styles.removeBadge}\n >\n <CloseIcon sx={{ fontSize: '10px' }} />\n </IconButton>\n )}\n </Box>\n )\n\n if (isFailed && errorMessage) {\n return <Tooltip title={errorMessage}>{chip}</Tooltip>\n }\n return chip\n}\n\nexport default AttachmentChip\n"],"mappings":";;;;;AA8BA,IAAM,IAA8C;CAClD,mBAAmB;CACnB,cAAc;CACd,YAAY;CACZ,oBAAoB;CACpB,6BAA6B;AAC/B;AAEA,SAAgB,EAAoB,GAA8B;CAIhE,OAHK,IAGE,EAAoB,MAAgB,SAFlC;AAGX;AAOA,SAAgB,EAAe,EAC7B,UACA,gBACA,YAAS,WACT,iBACA,aACA,uBAAoB,UAAU,OACR;CACtB,IAAM,IAAW,MAAW,UAEtB,IACJ,kBAAC,GAAD;EACE,WAAW,EAAO;EAClB,IAAI;GACF,SAAS;GACT,YAAY;GACZ,KAAK;GACL,QAAQ;GACR,aAAa,IAAW,eAAe;GACvC,cAAc;GACd,WAAW;GACX,GAAG;EACL;YAXF,CAaE,kBAAC,GAAD;GAAK,IAAI;IAAE,UAAU;IAAG,MAAM;GAAE;aAAhC,CACE,kBAAC,GAAD;IACE,SAAQ;IACR,IAAI;KACF,YAAY;KACZ,UAAU;KACV,OAAO,IAAW,eAAe;KACjC,UAAU;KACV,cAAc;KACd,YAAY;IACd;cAEC;GACS,CAAA,GACZ,kBAAC,GAAD;IACE,SAAQ;IACR,IAAI;KAAE,UAAU;KAAQ,OAAO;IAAW;cAEzC,IAAW,WAAW,EAAoB,CAAW;GAC5C,CAAA,CACT;MACJ,KACC,kBAAC,GAAD;GACE,MAAK;GACL,cAAY;GACZ,SAAS;GACT,MAAK;GACL,WAAW,EAAO;aAElB,kBAAC,GAAD,EAAW,IAAI,EAAE,UAAU,OAAO,EAAI,CAAA;EAC5B,CAAA,CAEX;;CAMP,OAHI,KAAY,IACP,kBAAC,GAAD;EAAS,OAAO;YAAe;CAAc,CAAA,IAE/C;AACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AttachmentChip.module.js","names":[],"sources":["../../../../../src/components/SynapseChat/components/AttachmentChip/AttachmentChip.module.scss"],"sourcesContent":[".chip {\n position: relative;\n}\n\n.removeBadge:global(.MuiButtonBase-root) {\n position: absolute;\n top: -
|
|
1
|
+
{"version":3,"file":"AttachmentChip.module.js","names":[],"sources":["../../../../../src/components/SynapseChat/components/AttachmentChip/AttachmentChip.module.scss"],"sourcesContent":[".chip {\n position: relative;\n margin-top: var(--remove-button-offset-y, 5px);\n margin-left: var(--remove-button-offset-x, 8px);\n}\n\n.removeBadge:global(.MuiButtonBase-root) {\n border: 1px solid var(--synapse-gray-300);\n background-color: white;\n width: 16px;\n height: 16px;\n &:hover {\n background-color: var(--synapse-gray-100);\n }\n\n position: absolute;\n top: calc(-1 * var(--remove-button-offset-y, 5px));\n left: calc(-1 * var(--remove-button-offset-x, 8px));\n opacity: 0;\n transition: opacity 100ms;\n}\n\n.chip:hover .removeBadge,\n.chip:focus-within .removeBadge {\n opacity: 1;\n}\n"],"mappings":""}
|
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
.chip {
|
|
2
2
|
position: relative;
|
|
3
|
+
margin-top: var(--remove-button-offset-y, 5px);
|
|
4
|
+
margin-left: var(--remove-button-offset-x, 8px);
|
|
3
5
|
}
|
|
4
6
|
|
|
5
7
|
.removeBadge:global(.MuiButtonBase-root) {
|
|
8
|
+
border: 1px solid var(--synapse-gray-300);
|
|
9
|
+
background-color: white;
|
|
10
|
+
width: 16px;
|
|
11
|
+
height: 16px;
|
|
12
|
+
&:hover {
|
|
13
|
+
background-color: var(--synapse-gray-100);
|
|
14
|
+
}
|
|
15
|
+
|
|
6
16
|
position: absolute;
|
|
7
|
-
top: -
|
|
8
|
-
left: -
|
|
17
|
+
top: calc(-1 * var(--remove-button-offset-y, 5px));
|
|
18
|
+
left: calc(-1 * var(--remove-button-offset-x, 8px));
|
|
9
19
|
opacity: 0;
|
|
10
20
|
transition: opacity 100ms;
|
|
11
21
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
.
|
|
1
|
+
._strip_1svc8_1{--remove-button-offset-x:8px;--remove-button-offset-y:5px;column-gap:calc(10px - var(--remove-button-offset-x));row-gap:calc(10px - var(--remove-button-offset-y));display:flex;overflow-x:auto}._wrap_1svc8_10{flex-wrap:wrap;overflow-x:visible}._item_1svc8_15{flex:1 1 0;min-width:140px}
|
package/dist/components/SynapseChat/components/ChatAttachmentStrip/ChatAttachmentStrip.module.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatAttachmentStrip.module.js","names":[],"sources":["../../../../../src/components/SynapseChat/components/ChatAttachmentStrip/ChatAttachmentStrip.module.scss"],"sourcesContent":["// Minimum width for each chip so 3 attachments are visible and a 4th is partially offscreen\n// in the 480px-wide composer. Kept as a SCSS variable since CSS is its only consumer.\n$chip-min-width: 140px;\n\n.strip {\n display: flex;\n gap: 10px;\n overflow-x: auto;\n}\n\n.wrap {\n flex-wrap: wrap;\n overflow-x: visible;\n}\n\n.item {\n flex: 1 1 0;\n min-width: $chip-min-width;\n}\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"ChatAttachmentStrip.module.js","names":[],"sources":["../../../../../src/components/SynapseChat/components/ChatAttachmentStrip/ChatAttachmentStrip.module.scss"],"sourcesContent":["// Minimum width for each chip so 3 attachments are visible and a 4th is partially offscreen\n// in the 480px-wide composer. Kept as a SCSS variable since CSS is its only consumer.\n$chip-min-width: 140px;\n\n.strip {\n --remove-button-offset-x: 8px;\n --remove-button-offset-y: 5px;\n\n display: flex;\n column-gap: calc(10px - var(--remove-button-offset-x));\n row-gap: calc(10px - var(--remove-button-offset-y));\n overflow-x: auto;\n}\n\n.wrap {\n flex-wrap: wrap;\n overflow-x: visible;\n}\n\n.item {\n flex: 1 1 0;\n min-width: $chip-min-width;\n}\n"],"mappings":""}
|
package/dist/components/SynapseChat/components/ChatAttachmentStrip/ChatAttachmentStrip.module.scss
CHANGED
|
@@ -3,8 +3,12 @@
|
|
|
3
3
|
$chip-min-width: 140px;
|
|
4
4
|
|
|
5
5
|
.strip {
|
|
6
|
+
--remove-button-offset-x: 8px;
|
|
7
|
+
--remove-button-offset-y: 5px;
|
|
8
|
+
|
|
6
9
|
display: flex;
|
|
7
|
-
gap: 10px;
|
|
10
|
+
column-gap: calc(10px - var(--remove-button-offset-x));
|
|
11
|
+
row-gap: calc(10px - var(--remove-button-offset-y));
|
|
8
12
|
overflow-x: auto;
|
|
9
13
|
}
|
|
10
14
|
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import { HeaderContext } from '@tanstack/react-table';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
|
+
type SortIconRendererParams = {
|
|
4
|
+
isSorted: 'asc' | 'desc' | false;
|
|
5
|
+
};
|
|
3
6
|
type ColumnHeaderProps = {
|
|
4
7
|
title?: string;
|
|
5
8
|
helpText?: ReactNode;
|
|
6
9
|
additionalButtons?: ReactNode;
|
|
7
10
|
wrap?: boolean;
|
|
11
|
+
sortIconRenderer?: (params: SortIconRendererParams) => ReactNode;
|
|
12
|
+
iconPlacement?: 'left' | 'right';
|
|
13
|
+
iconColor?: string;
|
|
14
|
+
iconSize?: string | number;
|
|
8
15
|
filterControl?: ReactNode;
|
|
9
16
|
};
|
|
10
17
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ColumnHeader.d.ts","sourceRoot":"","sources":["../../../src/components/TanStackTable/ColumnHeader.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAIrD,OAAO,EAAE,SAAS,EAAe,MAAM,OAAO,CAAA;AAG9C,KAAK,iBAAiB,GAAG;IACvB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,iBAAiB,CAAC,EAAE,SAAS,CAAA;IAC7B,IAAI,CAAC,EAAE,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"ColumnHeader.d.ts","sourceRoot":"","sources":["../../../src/components/TanStackTable/ColumnHeader.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAIrD,OAAO,EAAE,SAAS,EAAe,MAAM,OAAO,CAAA;AAG9C,KAAK,sBAAsB,GAAG;IAC5B,QAAQ,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,CAAA;CACjC,CAAA;AAED,KAAK,iBAAiB,GAAG;IACvB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,iBAAiB,CAAC,EAAE,SAAS,CAAA;IAC7B,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,sBAAsB,KAAK,SAAS,CAAA;IAChE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;IAChC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IAG1B,aAAa,CAAC,EAAE,SAAS,CAAA;CAC1B,CAAA;AAED;;;GAGG;AACH,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,KAAK,GAAG,OAAO,EAAE,MAAM,GAAG,OAAO,EACpE,KAAK,EAAE,iBAAiB,GAAG,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC,2CA2GxD"}
|
|
@@ -6,7 +6,7 @@ import { Fragment as o, jsx as s, jsxs as c } from "react/jsx-runtime";
|
|
|
6
6
|
import { HelpTwoTone as l } from "@mui/icons-material";
|
|
7
7
|
//#region src/components/TanStackTable/ColumnHeader.tsx
|
|
8
8
|
function u(u) {
|
|
9
|
-
let { column: d, title: f = u.column.id, wrap: p = !1, helpText: m, filterControl: h, additionalButtons: g } = u,
|
|
9
|
+
let { column: d, title: f = u.column.id, wrap: p = !1, helpText: m, filterControl: h, additionalButtons: g, sortIconRenderer: _, iconPlacement: v = "right", iconColor: y, iconSize: b } = u, x = n(() => {
|
|
10
10
|
if (h) return h;
|
|
11
11
|
if (d.getCanFilter()) {
|
|
12
12
|
if (d.columnDef.meta?.filterVariant === "enumeration") return /* @__PURE__ */ s(t, {
|
|
@@ -20,13 +20,13 @@ function u(u) {
|
|
|
20
20
|
d,
|
|
21
21
|
h,
|
|
22
22
|
f
|
|
23
|
-
])();
|
|
23
|
+
])(), S = d.getIsSorted();
|
|
24
24
|
return /* @__PURE__ */ c(r, {
|
|
25
25
|
sx: {
|
|
26
26
|
display: "flex",
|
|
27
27
|
alignContent: "center",
|
|
28
28
|
alignItems: "center",
|
|
29
|
-
justifyContent: "space-between",
|
|
29
|
+
...v === "right" && { justifyContent: "space-between" },
|
|
30
30
|
overflow: "hidden",
|
|
31
31
|
minWidth: 0
|
|
32
32
|
},
|
|
@@ -45,7 +45,7 @@ function u(u) {
|
|
|
45
45
|
display: "flex",
|
|
46
46
|
alignItems: "center",
|
|
47
47
|
height: "22px",
|
|
48
|
-
ml: 2,
|
|
48
|
+
ml: v === "left" ? 1 : 2,
|
|
49
49
|
gap: .25
|
|
50
50
|
},
|
|
51
51
|
children: [
|
|
@@ -57,7 +57,7 @@ function u(u) {
|
|
|
57
57
|
children: /* @__PURE__ */ s(l, { fontSize: "inherit" })
|
|
58
58
|
})
|
|
59
59
|
}),
|
|
60
|
-
d.getCanFilter() &&
|
|
60
|
+
d.getCanFilter() && x,
|
|
61
61
|
d.getCanSort() && /* @__PURE__ */ s(a, {
|
|
62
62
|
title: `Sort by ${f}`,
|
|
63
63
|
placement: "top",
|
|
@@ -68,12 +68,13 @@ function u(u) {
|
|
|
68
68
|
tabIndex: 0,
|
|
69
69
|
onKeyPress: () => d.toggleSorting(),
|
|
70
70
|
onClick: () => d.toggleSorting(),
|
|
71
|
-
children: /* @__PURE__ */ s(e, {
|
|
72
|
-
icon:
|
|
71
|
+
children: _ ? _({ isSorted: S }) : /* @__PURE__ */ s(e, {
|
|
72
|
+
icon: S === "asc" ? "sortUp" : "sortDown",
|
|
73
73
|
wrap: !1,
|
|
74
74
|
sx: {
|
|
75
|
-
color:
|
|
76
|
-
backgroundColor: "none"
|
|
75
|
+
color: y ?? (S ? "primary.main" : "grey.700"),
|
|
76
|
+
backgroundColor: "none",
|
|
77
|
+
...b && { fontSize: b }
|
|
77
78
|
}
|
|
78
79
|
})
|
|
79
80
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ColumnHeader.js","names":[],"sources":["../../../src/components/TanStackTable/ColumnHeader.tsx"],"sourcesContent":["import { HeaderContext } from '@tanstack/react-table'\nimport { Box, IconButton, Tooltip } from '@mui/material'\nimport { HelpTwoTone } from '@mui/icons-material'\nimport IconSvg from '../IconSvg'\nimport { ReactNode, useCallback } from 'react'\nimport { ColumnHeaderEnumFilter } from './ColumnHeaderEnumFilter'\n\ntype ColumnHeaderProps = {\n title?: string\n helpText?: ReactNode\n additionalButtons?: ReactNode\n wrap?: boolean\n\n // TODO: Replace with props that can be passed to a reusable filter control\n filterControl?: ReactNode\n}\n\n/**\n * Styled table column header component for use with @tanstack/react-table, with extra optional props for additional\n * UI features\n */\nexport default function ColumnHeader<TData = unknown, TValue = unknown>(\n props: ColumnHeaderProps & HeaderContext<TData, TValue>,\n) {\n const {\n column,\n title = props.column.id,\n wrap = false,\n helpText,\n filterControl: filterControlFromProps,\n additionalButtons,\n } = props\n\n const getFilterControl = useCallback(() => {\n if (filterControlFromProps) {\n return filterControlFromProps\n }\n if (column.getCanFilter()) {\n if (column.columnDef.meta?.filterVariant === 'enumeration') {\n return <ColumnHeaderEnumFilter column={column} title={title} />\n }\n // As needed, extend ColumnMeta.filterVariant to support other types of filters\n console.warn(\n `column.getCanFilter() was true for column ID: ${column.id} but no filterControlFromProps was passed and component for filterVariant: ${column.columnDef.meta?.filterVariant} is not implemented`,\n )\n }\n return <></>\n }, [column, filterControlFromProps, title])\n\n const filterControl = getFilterControl()\n\n return (\n <Box\n sx={{\n display: 'flex',\n alignContent: 'center',\n alignItems: 'center',\n justifyContent: 'space-between',\n overflow: 'hidden',\n minWidth: 0,\n }}\n >\n <span\n style={{\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: wrap ? 'pre-wrap' : 'nowrap',\n minWidth: 0,\n }}\n title={title}\n >\n {title}\n </span>\n <Box\n role={'menubar'}\n sx={{\n display: 'flex',\n alignItems: 'center',\n height: '22px',\n ml: 2,\n gap: 0.25,\n }}\n >\n {helpText && (\n <Tooltip title={helpText} placement={'top'}>\n <IconButton size={'small'}>\n <HelpTwoTone fontSize={'inherit'} />\n </IconButton>\n </Tooltip>\n )}\n {column.getCanFilter() && filterControl}\n {column.getCanSort() && (\n <Tooltip title={`Sort by ${title}`} placement={'top'}>\n <IconButton\n role=\"button\"\n size={'small'}\n aria-label={`Sort by ${title}`}\n tabIndex={0}\n onKeyPress={() => column.toggleSorting()}\n onClick={() => column.toggleSorting()}\n >\n <IconSvg\n
|
|
1
|
+
{"version":3,"file":"ColumnHeader.js","names":[],"sources":["../../../src/components/TanStackTable/ColumnHeader.tsx"],"sourcesContent":["import { HeaderContext } from '@tanstack/react-table'\nimport { Box, IconButton, Tooltip } from '@mui/material'\nimport { HelpTwoTone } from '@mui/icons-material'\nimport IconSvg from '../IconSvg'\nimport { ReactNode, useCallback } from 'react'\nimport { ColumnHeaderEnumFilter } from './ColumnHeaderEnumFilter'\n\ntype SortIconRendererParams = {\n isSorted: 'asc' | 'desc' | false\n}\n\ntype ColumnHeaderProps = {\n title?: string\n helpText?: ReactNode\n additionalButtons?: ReactNode\n wrap?: boolean\n sortIconRenderer?: (params: SortIconRendererParams) => ReactNode\n iconPlacement?: 'left' | 'right'\n iconColor?: string\n iconSize?: string | number\n\n // TODO: Replace with props that can be passed to a reusable filter control\n filterControl?: ReactNode\n}\n\n/**\n * Styled table column header component for use with @tanstack/react-table, with extra optional props for additional\n * UI features\n */\nexport default function ColumnHeader<TData = unknown, TValue = unknown>(\n props: ColumnHeaderProps & HeaderContext<TData, TValue>,\n) {\n const {\n column,\n title = props.column.id,\n wrap = false,\n helpText,\n filterControl: filterControlFromProps,\n additionalButtons,\n sortIconRenderer,\n iconPlacement = 'right',\n iconColor,\n iconSize,\n } = props\n\n const getFilterControl = useCallback(() => {\n if (filterControlFromProps) {\n return filterControlFromProps\n }\n if (column.getCanFilter()) {\n if (column.columnDef.meta?.filterVariant === 'enumeration') {\n return <ColumnHeaderEnumFilter column={column} title={title} />\n }\n // As needed, extend ColumnMeta.filterVariant to support other types of filters\n console.warn(\n `column.getCanFilter() was true for column ID: ${column.id} but no filterControlFromProps was passed and component for filterVariant: ${column.columnDef.meta?.filterVariant} is not implemented`,\n )\n }\n return <></>\n }, [column, filterControlFromProps, title])\n\n const filterControl = getFilterControl()\n const isSorted = column.getIsSorted()\n\n return (\n <Box\n sx={{\n display: 'flex',\n alignContent: 'center',\n alignItems: 'center',\n ...(iconPlacement === 'right' && {\n justifyContent: 'space-between',\n }),\n overflow: 'hidden',\n minWidth: 0,\n }}\n >\n <span\n style={{\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: wrap ? 'pre-wrap' : 'nowrap',\n minWidth: 0,\n }}\n title={title}\n >\n {title}\n </span>\n <Box\n role={'menubar'}\n sx={{\n display: 'flex',\n alignItems: 'center',\n height: '22px',\n ml: iconPlacement === 'left' ? 1 : 2,\n gap: 0.25,\n }}\n >\n {helpText && (\n <Tooltip title={helpText} placement={'top'}>\n <IconButton size={'small'}>\n <HelpTwoTone fontSize={'inherit'} />\n </IconButton>\n </Tooltip>\n )}\n {column.getCanFilter() && filterControl}\n {column.getCanSort() && (\n <Tooltip title={`Sort by ${title}`} placement={'top'}>\n <IconButton\n role=\"button\"\n size={'small'}\n aria-label={`Sort by ${title}`}\n tabIndex={0}\n onKeyPress={() => column.toggleSorting()}\n onClick={() => column.toggleSorting()}\n >\n {sortIconRenderer ? (\n sortIconRenderer({ isSorted })\n ) : (\n <IconSvg\n icon={isSorted === 'asc' ? 'sortUp' : 'sortDown'}\n wrap={false}\n sx={{\n color:\n iconColor ?? (isSorted ? 'primary.main' : 'grey.700'),\n backgroundColor: 'none',\n ...(iconSize && { fontSize: iconSize }),\n }}\n />\n )}\n </IconButton>\n </Tooltip>\n )}\n {additionalButtons}\n </Box>\n </Box>\n )\n}\n"],"mappings":";;;;;;;AA6BA,SAAwB,EACtB,GACA;CACA,IAAM,EACJ,WACA,WAAQ,EAAM,OAAO,IACrB,UAAO,IACP,aACA,eAAe,GACf,sBACA,qBACA,mBAAgB,SAChB,cACA,gBACE,GAkBE,IAhBmB,QAAkB;EACzC,IAAI,GACF,OAAO;EAET,IAAI,EAAO,aAAa,GAAG;GACzB,IAAI,EAAO,UAAU,MAAM,kBAAkB,eAC3C,OAAO,kBAAC,GAAD;IAAgC;IAAe;GAAQ,CAAA;GAGhE,QAAQ,KACN,iDAAiD,EAAO,GAAG,6EAA6E,EAAO,UAAU,MAAM,cAAc,oBAC/K;EACF;EACA,OAAO,kBAAA,GAAA,CAAI,CAAA;CACb,GAAG;EAAC;EAAQ;EAAwB;CAAK,CAEnB,EAAiB,GACjC,IAAW,EAAO,YAAY;CAEpC,OACE,kBAAC,GAAD;EACE,IAAI;GACF,SAAS;GACT,cAAc;GACd,YAAY;GACZ,GAAI,MAAkB,WAAW,EAC/B,gBAAgB,gBAClB;GACA,UAAU;GACV,UAAU;EACZ;YAVF,CAYE,kBAAC,QAAD;GACE,OAAO;IACL,UAAU;IACV,cAAc;IACd,YAAY,IAAO,aAAa;IAChC,UAAU;GACZ;GACO;aAEN;EACG,CAAA,GACN,kBAAC,GAAD;GACE,MAAM;GACN,IAAI;IACF,SAAS;IACT,YAAY;IACZ,QAAQ;IACR,IAAI,MAAkB,SAAS,IAAI;IACnC,KAAK;GACP;aARF;IAUG,KACC,kBAAC,GAAD;KAAS,OAAO;KAAU,WAAW;eACnC,kBAAC,GAAD;MAAY,MAAM;gBAChB,kBAAC,GAAD,EAAa,UAAU,UAAY,CAAA;KACzB,CAAA;IACL,CAAA;IAEV,EAAO,aAAa,KAAK;IACzB,EAAO,WAAW,KACjB,kBAAC,GAAD;KAAS,OAAO,WAAW;KAAS,WAAW;eAC7C,kBAAC,GAAD;MACE,MAAK;MACL,MAAM;MACN,cAAY,WAAW;MACvB,UAAU;MACV,kBAAkB,EAAO,cAAc;MACvC,eAAe,EAAO,cAAc;gBAEnC,IACC,EAAiB,EAAE,YAAS,CAAC,IAE7B,kBAAC,GAAD;OACE,MAAM,MAAa,QAAQ,WAAW;OACtC,MAAM;OACN,IAAI;QACF,OACE,MAAc,IAAW,iBAAiB;QAC5C,iBAAiB;QACjB,GAAI,KAAY,EAAE,UAAU,EAAS;OACvC;MACD,CAAA;KAEO,CAAA;IACL,CAAA;IAEV;GACE;IACF;;AAET"}
|
|
@@ -4,6 +4,14 @@ import { TrProps } from './types';
|
|
|
4
4
|
type StyledVirtualTanStackTableProps<T = unknown> = Omit<StyledTanStackTableProps<T, VirtualItem>, 'slots' | 'rows' | 'rowTransform'> & {
|
|
5
5
|
rowVirtualizer: Virtualizer<any, any>;
|
|
6
6
|
onTableContainerScroll?: (target: EventTarget) => void;
|
|
7
|
+
/**
|
|
8
|
+
* When true, alternating rows are given a striped background. Unlike {@link StyledTableContainerProps.noStripedRows},
|
|
9
|
+
* this does not rely on CSS `:nth-of-type`, since a virtualized row's position in the DOM is not
|
|
10
|
+
* guaranteed to match its data index as rows are mounted/unmounted while scrolling. Instead, this
|
|
11
|
+
* stripes rows based on the `data-index` attribute that {@link VirtualizedTr} sets on each `<tr>`.
|
|
12
|
+
* @default false
|
|
13
|
+
*/
|
|
14
|
+
striped?: boolean;
|
|
7
15
|
};
|
|
8
16
|
/**
|
|
9
17
|
* A table row component modified to be used with @tanstack/react-virtual.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StyledVirtualTanStackTable.d.ts","sourceRoot":"","sources":["../../../src/components/TanStackTable/StyledVirtualTanStackTable.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"StyledVirtualTanStackTable.d.ts","sourceRoot":"","sources":["../../../src/components/TanStackTable/StyledVirtualTanStackTable.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAGlE,OAA4B,EAC1B,wBAAwB,EACzB,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AAEjC,KAAK,+BAA+B,CAAC,CAAC,GAAG,OAAO,IAAI,IAAI,CACtD,wBAAwB,CAAC,CAAC,EAAE,WAAW,CAAC,EACxC,OAAO,GAAG,MAAM,GAAG,cAAc,CAClC,GAAG;IACF,cAAc,EAAE,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;IACrC,sBAAsB,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,CAAA;IACtD;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAqBD;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,GAAG,OAAO,EAC3C,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,WAAW,CAAC,2CAmBnC;AAED;;;;GAIG;AACH,MAAM,CAAC,OAAO,UAAU,0BAA0B,CAAC,CAAC,GAAG,OAAO,EAC5D,KAAK,EAAE,+BAA+B,CAAC,CAAC,CAAC,2CA4E1C"}
|
|
@@ -4,12 +4,18 @@ import n, { useContext as r } from "react";
|
|
|
4
4
|
import { noop as i } from "lodash-es";
|
|
5
5
|
import { jsx as a } from "react/jsx-runtime";
|
|
6
6
|
//#region src/components/TanStackTable/StyledVirtualTanStackTable.tsx
|
|
7
|
-
var o =
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
var o = { [[
|
|
8
|
+
1,
|
|
9
|
+
3,
|
|
10
|
+
5,
|
|
11
|
+
7,
|
|
12
|
+
9
|
|
13
|
+
].map((e) => `&[data-index$="${e}"]:not([aria-selected="true"])`).join(", ")]: { backgroundColor: "var(--synapse-background-color-gray)" } }, s = n.createContext(void 0);
|
|
14
|
+
function c(e) {
|
|
15
|
+
let { row: t, tableRow: n, ...i } = e, o = r(s);
|
|
10
16
|
return /* @__PURE__ */ a("tr", {
|
|
11
17
|
"data-index": t.index,
|
|
12
|
-
ref: (e) =>
|
|
18
|
+
ref: (e) => o?.measureElement(e),
|
|
13
19
|
...i,
|
|
14
20
|
style: {
|
|
15
21
|
...i.style,
|
|
@@ -21,32 +27,35 @@ function s(e) {
|
|
|
21
27
|
}
|
|
22
28
|
});
|
|
23
29
|
}
|
|
24
|
-
function
|
|
25
|
-
let { table: r, styledTableContainerProps:
|
|
26
|
-
return /* @__PURE__ */ a(
|
|
27
|
-
value:
|
|
30
|
+
function l(n) {
|
|
31
|
+
let { table: r, styledTableContainerProps: l, fullWidth: u = !0, rowVirtualizer: d, slotProps: f = {}, onTableContainerScroll: p = i, striped: m = !1 } = n, h = d.getVirtualItems();
|
|
32
|
+
return /* @__PURE__ */ a(s.Provider, {
|
|
33
|
+
value: d,
|
|
28
34
|
children: /* @__PURE__ */ a(t, {
|
|
29
35
|
table: r,
|
|
30
|
-
rows:
|
|
36
|
+
rows: h,
|
|
31
37
|
rowTransform: (e) => r.getRowModel().rows[e.index],
|
|
32
|
-
fullWidth:
|
|
38
|
+
fullWidth: u,
|
|
33
39
|
styledTableContainerProps: {
|
|
34
40
|
noStripedRows: !0,
|
|
35
|
-
...
|
|
41
|
+
...l,
|
|
36
42
|
style: {
|
|
37
43
|
overflow: "auto",
|
|
38
44
|
position: "relative",
|
|
39
|
-
...
|
|
45
|
+
...l?.style
|
|
40
46
|
},
|
|
41
|
-
sx:
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
47
|
+
sx: [
|
|
48
|
+
{ "thead > tr": {
|
|
49
|
+
display: "flex",
|
|
50
|
+
width: "100%"
|
|
51
|
+
} },
|
|
52
|
+
m && { "tbody > tr": o },
|
|
53
|
+
l?.sx
|
|
54
|
+
].flat().filter(Boolean),
|
|
55
|
+
onScroll: (e) => p(e.target)
|
|
46
56
|
},
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
slotProps: e(d, {
|
|
57
|
+
slots: { Tr: c },
|
|
58
|
+
slotProps: e(f, {
|
|
50
59
|
Table: { style: { display: "grid" } },
|
|
51
60
|
Thead: { style: {
|
|
52
61
|
display: "grid",
|
|
@@ -57,7 +66,7 @@ function c(n) {
|
|
|
57
66
|
Th: { style: { display: "flex" } },
|
|
58
67
|
Tbody: { style: {
|
|
59
68
|
display: "grid",
|
|
60
|
-
height: `${
|
|
69
|
+
height: `${d.getTotalSize()}px`,
|
|
61
70
|
position: "relative"
|
|
62
71
|
} }
|
|
63
72
|
})
|
|
@@ -65,6 +74,6 @@ function c(n) {
|
|
|
65
74
|
});
|
|
66
75
|
}
|
|
67
76
|
//#endregion
|
|
68
|
-
export {
|
|
77
|
+
export { c as VirtualizedTr, l as default };
|
|
69
78
|
|
|
70
79
|
//# sourceMappingURL=StyledVirtualTanStackTable.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StyledVirtualTanStackTable.js","names":[],"sources":["../../../src/components/TanStackTable/StyledVirtualTanStackTable.tsx"],"sourcesContent":["import { mergeSlotProps } from '@/utils/slots/SlotUtils'\nimport { VirtualItem, Virtualizer } from '@tanstack/react-virtual'\nimport { noop } from 'lodash-es'\nimport React, { useContext } from 'react'\nimport StyledTanStackTable, {\n StyledTanStackTableProps,\n} from './StyledTanStackTable'\n\nimport { TrProps } from './types'\n\ntype StyledVirtualTanStackTableProps<T = unknown> = Omit<\n StyledTanStackTableProps<T, VirtualItem>,\n 'slots' | 'rows' | 'rowTransform'\n> & {\n rowVirtualizer: Virtualizer<any, any>\n onTableContainerScroll?: (target: EventTarget) => void\n}\n\n// Context to pass the row virtualizer to the Tr component\nconst RowVirtualizerContext = React.createContext<\n Virtualizer<any, any> | undefined\n>(undefined)\n\n/**\n * A table row component modified to be used with @tanstack/react-virtual.\n */\nexport function VirtualizedTr<TData = unknown>(\n props: TrProps<TData, VirtualItem>,\n) {\n const { row: virtualItem, tableRow: _tableRow, ...rest } = props\n const rowVirtualizer = useContext(RowVirtualizerContext)\n return (\n <tr\n data-index={virtualItem.index} // needed for dynamic row height measurement\n ref={node => rowVirtualizer?.measureElement(node)} //measure dynamic row height\n {...rest}\n style={{\n ...rest.style,\n display: 'flex',\n position: 'absolute',\n transform: `translateY(${virtualItem.start}px)`, //this should always be a `style` as it changes on scroll\n width: '100%',\n alignItems: 'center',\n }}\n />\n )\n}\n\n/**\n * Stylized table component that is compatible with @tanstack/react-table and @tanstack/react-virtual to display a\n * virtualized table, i.e. a table that uses a virtualizer to only render the DOM nodes that contain data that is visible\n * within the viewport. For cases where the table rows do not need to be virtualized, use {@link StyledTanStackTable}.\n */\nexport default function StyledVirtualTanStackTable<T = unknown>(\n props: StyledVirtualTanStackTableProps<T>,\n) {\n const {\n table,\n styledTableContainerProps,\n fullWidth = true,\n rowVirtualizer,\n slotProps = {},\n onTableContainerScroll = noop,\n } = props\n\n const virtualRows = rowVirtualizer.getVirtualItems()\n\n return (\n <RowVirtualizerContext.Provider value={rowVirtualizer}>\n <StyledTanStackTable<T, VirtualItem>\n table={table}\n rows={virtualRows}\n rowTransform={row => table.getRowModel().rows[row.index]}\n fullWidth={fullWidth}\n styledTableContainerProps={{\n noStripedRows: true,\n ...styledTableContainerProps,\n style: {\n overflow: 'auto', //our scrollable table container\n position: 'relative', //needed for sticky header\n ...styledTableContainerProps?.style,\n },\n sx: {\n
|
|
1
|
+
{"version":3,"file":"StyledVirtualTanStackTable.js","names":[],"sources":["../../../src/components/TanStackTable/StyledVirtualTanStackTable.tsx"],"sourcesContent":["import { mergeSlotProps } from '@/utils/slots/SlotUtils'\nimport { SxProps, Theme } from '@mui/material'\nimport { VirtualItem, Virtualizer } from '@tanstack/react-virtual'\nimport { noop } from 'lodash-es'\nimport React, { useContext } from 'react'\nimport StyledTanStackTable, {\n StyledTanStackTableProps,\n} from './StyledTanStackTable'\n\nimport { TrProps } from './types'\n\ntype StyledVirtualTanStackTableProps<T = unknown> = Omit<\n StyledTanStackTableProps<T, VirtualItem>,\n 'slots' | 'rows' | 'rowTransform'\n> & {\n rowVirtualizer: Virtualizer<any, any>\n onTableContainerScroll?: (target: EventTarget) => void\n /**\n * When true, alternating rows are given a striped background. Unlike {@link StyledTableContainerProps.noStripedRows},\n * this does not rely on CSS `:nth-of-type`, since a virtualized row's position in the DOM is not\n * guaranteed to match its data index as rows are mounted/unmounted while scrolling. Instead, this\n * stripes rows based on the `data-index` attribute that {@link VirtualizedTr} sets on each `<tr>`.\n * @default false\n */\n striped?: boolean\n}\n\n// The last digit of a `data-index` that identifies an odd row, e.g. matches indices 1, 3, 11, 23.\nconst ODD_ROW_LAST_DIGITS = [1, 3, 5, 7, 9]\n\nconst stripedRowsSx = {\n // Exclude selected rows so this doesn't outrank a caller's own `[aria-selected=\"true\"]`\n // background rule (emotion's `sx` classes are more specific than a single class+attribute\n // selector, e.g. EntityFinder's `.EntityFinderDetailsViewRow[aria-selected='true']`).\n [ODD_ROW_LAST_DIGITS.map(\n digit => `&[data-index$=\"${digit}\"]:not([aria-selected=\"true\"])`,\n ).join(', ')]: {\n backgroundColor: 'var(--synapse-background-color-gray)',\n },\n}\n\n// Context to pass the row virtualizer to the Tr component\nconst RowVirtualizerContext = React.createContext<\n Virtualizer<any, any> | undefined\n>(undefined)\n\n/**\n * A table row component modified to be used with @tanstack/react-virtual.\n */\nexport function VirtualizedTr<TData = unknown>(\n props: TrProps<TData, VirtualItem>,\n) {\n const { row: virtualItem, tableRow: _tableRow, ...rest } = props\n const rowVirtualizer = useContext(RowVirtualizerContext)\n return (\n <tr\n data-index={virtualItem.index} // needed for dynamic row height measurement\n ref={node => rowVirtualizer?.measureElement(node)} //measure dynamic row height\n {...rest}\n style={{\n ...rest.style,\n display: 'flex',\n position: 'absolute',\n transform: `translateY(${virtualItem.start}px)`, //this should always be a `style` as it changes on scroll\n width: '100%',\n alignItems: 'center',\n }}\n />\n )\n}\n\n/**\n * Stylized table component that is compatible with @tanstack/react-table and @tanstack/react-virtual to display a\n * virtualized table, i.e. a table that uses a virtualizer to only render the DOM nodes that contain data that is visible\n * within the viewport. For cases where the table rows do not need to be virtualized, use {@link StyledTanStackTable}.\n */\nexport default function StyledVirtualTanStackTable<T = unknown>(\n props: StyledVirtualTanStackTableProps<T>,\n) {\n const {\n table,\n styledTableContainerProps,\n fullWidth = true,\n rowVirtualizer,\n slotProps = {},\n onTableContainerScroll = noop,\n striped = false,\n } = props\n\n const virtualRows = rowVirtualizer.getVirtualItems()\n\n return (\n <RowVirtualizerContext.Provider value={rowVirtualizer}>\n <StyledTanStackTable<T, VirtualItem>\n table={table}\n rows={virtualRows}\n rowTransform={row => table.getRowModel().rows[row.index]}\n fullWidth={fullWidth}\n styledTableContainerProps={{\n noStripedRows: true,\n ...styledTableContainerProps,\n style: {\n overflow: 'auto', //our scrollable table container\n position: 'relative', //needed for sticky header\n ...styledTableContainerProps?.style,\n },\n sx: [\n {\n 'thead > tr': {\n display: 'flex',\n width: '100%',\n },\n },\n striped && { 'tbody > tr': stripedRowsSx },\n styledTableContainerProps?.sx,\n ]\n .flat()\n .filter(Boolean) as SxProps<Theme>,\n onScroll: e => onTableContainerScroll(e.target),\n }}\n slots={{\n Tr: VirtualizedTr,\n }}\n slotProps={mergeSlotProps(slotProps, {\n Table: {\n style: {\n display: 'grid',\n },\n },\n Thead: {\n style: {\n display: 'grid',\n position: 'sticky',\n top: 0,\n zIndex: 1,\n },\n },\n Th: {\n style: {\n display: 'flex',\n },\n },\n Tbody: {\n style: {\n display: 'grid',\n height: `${rowVirtualizer.getTotalSize()}px`, //tells scrollbar how big the table is\n position: 'relative', //needed for absolute positioning of rows\n },\n },\n })}\n />\n </RowVirtualizerContext.Provider>\n )\n}\n"],"mappings":";;;;;;AA8BA,IAAM,IAAgB,GAInB;CAN0B;CAAG;CAAG;CAAG;CAAG;AAMtC,EAAoB,KACnB,MAAS,kBAAkB,EAAM,+BACnC,EAAE,KAAK,IAAI,IAAI,EACb,iBAAiB,uCACnB,EACF,GAGM,IAAwB,EAAM,cAElC,KAAA,CAAS;AAKX,SAAgB,EACd,GACA;CACA,IAAM,EAAE,KAAK,GAAa,UAAU,GAAW,GAAG,MAAS,GACrD,IAAiB,EAAW,CAAqB;CACvD,OACE,kBAAC,MAAD;EACE,cAAY,EAAY;EACxB,MAAK,MAAQ,GAAgB,eAAe,CAAI;EAChD,GAAI;EACJ,OAAO;GACL,GAAG,EAAK;GACR,SAAS;GACT,UAAU;GACV,WAAW,cAAc,EAAY,MAAM;GAC3C,OAAO;GACP,YAAY;EACd;CACD,CAAA;AAEL;AAOA,SAAwB,EACtB,GACA;CACA,IAAM,EACJ,UACA,8BACA,eAAY,IACZ,mBACA,eAAY,CAAC,GACb,4BAAyB,GACzB,aAAU,OACR,GAEE,IAAc,EAAe,gBAAgB;CAEnD,OACE,kBAAC,EAAsB,UAAvB;EAAgC,OAAO;YACrC,kBAAC,GAAD;GACS;GACP,MAAM;GACN,eAAc,MAAO,EAAM,YAAY,EAAE,KAAK,EAAI;GACvC;GACX,2BAA2B;IACzB,eAAe;IACf,GAAG;IACH,OAAO;KACL,UAAU;KACV,UAAU;KACV,GAAG,GAA2B;IAChC;IACA,IAAI;KACF,EACE,cAAc;MACZ,SAAS;MACT,OAAO;KACT,EACF;KACA,KAAW,EAAE,cAAc,EAAc;KACzC,GAA2B;IAC7B,EACG,KAAK,EACL,OAAO,OAAO;IACjB,WAAU,MAAK,EAAuB,EAAE,MAAM;GAChD;GACA,OAAO,EACL,IAAI,EACN;GACA,WAAW,EAAe,GAAW;IACnC,OAAO,EACL,OAAO,EACL,SAAS,OACX,EACF;IACA,OAAO,EACL,OAAO;KACL,SAAS;KACT,UAAU;KACV,KAAK;KACL,QAAQ;IACV,EACF;IACA,IAAI,EACF,OAAO,EACL,SAAS,OACX,EACF;IACA,OAAO,EACL,OAAO;KACL,SAAS;KACT,QAAQ,GAAG,EAAe,aAAa,EAAE;KACzC,UAAU;IACZ,EACF;GACF,CAAC;EACF,CAAA;CAC6B,CAAA;AAEpC"}
|