@stigmer/react 0.0.71 → 0.0.73
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/agent/AgentEnvForm.d.ts +2 -0
- package/agent/AgentEnvForm.d.ts.map +1 -1
- package/agent/AgentEnvForm.js.map +1 -1
- package/agent/AgentPicker.d.ts +2 -0
- package/agent/AgentPicker.d.ts.map +1 -1
- package/agent/AgentPicker.js.map +1 -1
- package/agent/agentSetupReducer.d.ts +69 -7
- package/agent/agentSetupReducer.d.ts.map +1 -1
- package/agent/agentSetupReducer.js.map +1 -1
- package/agent/useAgentCount.d.ts +2 -0
- package/agent/useAgentCount.d.ts.map +1 -1
- package/agent/useAgentCount.js.map +1 -1
- package/attachment/AttachmentChipList.d.ts +15 -0
- package/attachment/AttachmentChipList.d.ts.map +1 -1
- package/attachment/AttachmentChipList.js +15 -0
- package/attachment/AttachmentChipList.js.map +1 -1
- package/attachment/useAttachments.d.ts +14 -0
- package/attachment/useAttachments.d.ts.map +1 -1
- package/attachment/useAttachments.js.map +1 -1
- package/composer/useComposer.d.ts +5 -0
- package/composer/useComposer.d.ts.map +1 -1
- package/composer/useComposer.js.map +1 -1
- package/execution/ExecutionPhaseBadge.d.ts +1 -1
- package/execution/ExecutionPhaseBadge.js +1 -1
- package/execution/McpToolDetail.d.ts +16 -8
- package/execution/McpToolDetail.d.ts.map +1 -1
- package/execution/McpToolDetail.js +0 -6
- package/execution/McpToolDetail.js.map +1 -1
- package/execution/TodoList.d.ts +8 -0
- package/execution/TodoList.d.ts.map +1 -1
- package/execution/TodoList.js +8 -0
- package/execution/TodoList.js.map +1 -1
- package/execution/ToolArgsView.d.ts +1 -0
- package/execution/ToolArgsView.d.ts.map +1 -1
- package/execution/ToolArgsView.js.map +1 -1
- package/execution/UsageWidget.d.ts +1 -1
- package/execution/UsageWidget.js +1 -1
- package/execution/file-path-resolver.d.ts +10 -0
- package/execution/file-path-resolver.d.ts.map +1 -1
- package/execution/file-path-resolver.js.map +1 -1
- package/execution/index.d.ts +1 -1
- package/execution/index.d.ts.map +1 -1
- package/execution/index.js.map +1 -1
- package/execution/useArtifactContent.d.ts +33 -0
- package/execution/useArtifactContent.d.ts.map +1 -1
- package/execution/useArtifactContent.js +33 -0
- package/execution/useArtifactContent.js.map +1 -1
- package/execution/useSubmitApproval.d.ts +2 -0
- package/execution/useSubmitApproval.d.ts.map +1 -1
- package/execution/useSubmitApproval.js.map +1 -1
- package/github/GitHubRepoPicker.d.ts +13 -0
- package/github/GitHubRepoPicker.d.ts.map +1 -1
- package/github/GitHubRepoPicker.js +13 -0
- package/github/GitHubRepoPicker.js.map +1 -1
- package/github/useGitHubConnection.d.ts +29 -1
- package/github/useGitHubConnection.d.ts.map +1 -1
- package/github/useGitHubConnection.js +29 -1
- package/github/useGitHubConnection.js.map +1 -1
- package/github/useGitHubRepos.d.ts +31 -0
- package/github/useGitHubRepos.d.ts.map +1 -1
- package/github/useGitHubRepos.js +31 -0
- package/github/useGitHubRepos.js.map +1 -1
- package/github/useGitHubSearch.d.ts +25 -0
- package/github/useGitHubSearch.d.ts.map +1 -1
- package/github/useGitHubSearch.js +25 -0
- package/github/useGitHubSearch.js.map +1 -1
- package/iam-policy/GrantAccessForm.d.ts +39 -0
- package/iam-policy/GrantAccessForm.d.ts.map +1 -0
- package/iam-policy/GrantAccessForm.js +75 -0
- package/iam-policy/GrantAccessForm.js.map +1 -0
- package/iam-policy/OrgMembersPanel.d.ts +28 -0
- package/iam-policy/OrgMembersPanel.d.ts.map +1 -0
- package/iam-policy/OrgMembersPanel.js +192 -0
- package/iam-policy/OrgMembersPanel.js.map +1 -0
- package/iam-policy/RoleSelector.d.ts +37 -0
- package/iam-policy/RoleSelector.d.ts.map +1 -0
- package/iam-policy/RoleSelector.js +42 -0
- package/iam-policy/RoleSelector.js.map +1 -0
- package/iam-policy/index.d.ts +12 -0
- package/iam-policy/index.d.ts.map +1 -0
- package/iam-policy/index.js +12 -0
- package/iam-policy/index.js.map +1 -0
- package/iam-policy/useCreateIamPolicy.d.ts +35 -0
- package/iam-policy/useCreateIamPolicy.d.ts.map +1 -0
- package/iam-policy/useCreateIamPolicy.js +46 -0
- package/iam-policy/useCreateIamPolicy.js.map +1 -0
- package/iam-policy/useDeleteIamPolicy.d.ts +34 -0
- package/iam-policy/useDeleteIamPolicy.d.ts.map +1 -0
- package/iam-policy/useDeleteIamPolicy.js +45 -0
- package/iam-policy/useDeleteIamPolicy.js.map +1 -0
- package/iam-policy/useGrantableRoles.d.ts +28 -0
- package/iam-policy/useGrantableRoles.d.ts.map +1 -0
- package/iam-policy/useGrantableRoles.js +32 -0
- package/iam-policy/useGrantableRoles.js.map +1 -0
- package/iam-policy/usePrincipalsCount.d.ts +31 -0
- package/iam-policy/usePrincipalsCount.d.ts.map +1 -0
- package/iam-policy/usePrincipalsCount.js +72 -0
- package/iam-policy/usePrincipalsCount.js.map +1 -0
- package/iam-policy/useResourceAccess.d.ts +51 -0
- package/iam-policy/useResourceAccess.d.ts.map +1 -0
- package/iam-policy/useResourceAccess.js +85 -0
- package/iam-policy/useResourceAccess.js.map +1 -0
- package/iam-policy/useRevokeOrgAccess.d.ts +36 -0
- package/iam-policy/useRevokeOrgAccess.d.ts.map +1 -0
- package/iam-policy/useRevokeOrgAccess.js +48 -0
- package/iam-policy/useRevokeOrgAccess.js.map +1 -0
- package/iam-policy/useRoleSelector.d.ts +52 -0
- package/iam-policy/useRoleSelector.d.ts.map +1 -0
- package/iam-policy/useRoleSelector.js +50 -0
- package/iam-policy/useRoleSelector.js.map +1 -0
- package/iam-policy/useWhoAmI.d.ts +30 -0
- package/iam-policy/useWhoAmI.d.ts.map +1 -0
- package/iam-policy/useWhoAmI.js +56 -0
- package/iam-policy/useWhoAmI.js.map +1 -0
- package/identity-provider/CreateIdentityProviderForm.d.ts +39 -0
- package/identity-provider/CreateIdentityProviderForm.d.ts.map +1 -0
- package/identity-provider/CreateIdentityProviderForm.js +102 -0
- package/identity-provider/CreateIdentityProviderForm.js.map +1 -0
- package/identity-provider/IdentityProviderDetailPanel.d.ts +42 -0
- package/identity-provider/IdentityProviderDetailPanel.d.ts.map +1 -0
- package/identity-provider/IdentityProviderDetailPanel.js +156 -0
- package/identity-provider/IdentityProviderDetailPanel.js.map +1 -0
- package/identity-provider/IdentityProviderListPanel.d.ts +41 -0
- package/identity-provider/IdentityProviderListPanel.d.ts.map +1 -0
- package/identity-provider/IdentityProviderListPanel.js +110 -0
- package/identity-provider/IdentityProviderListPanel.js.map +1 -0
- package/identity-provider/IdentityProviderWizard.d.ts +40 -0
- package/identity-provider/IdentityProviderWizard.d.ts.map +1 -0
- package/identity-provider/IdentityProviderWizard.js +180 -0
- package/identity-provider/IdentityProviderWizard.js.map +1 -0
- package/identity-provider/ProviderPicker.d.ts +28 -0
- package/identity-provider/ProviderPicker.d.ts.map +1 -0
- package/identity-provider/ProviderPicker.js +64 -0
- package/identity-provider/ProviderPicker.js.map +1 -0
- package/identity-provider/SsoLoginPrompt.d.ts +51 -0
- package/identity-provider/SsoLoginPrompt.d.ts.map +1 -0
- package/identity-provider/SsoLoginPrompt.js +119 -0
- package/identity-provider/SsoLoginPrompt.js.map +1 -0
- package/identity-provider/index.d.ts +14 -0
- package/identity-provider/index.d.ts.map +1 -0
- package/identity-provider/index.js +14 -0
- package/identity-provider/index.js.map +1 -0
- package/identity-provider/presets.d.ts +65 -0
- package/identity-provider/presets.d.ts.map +1 -0
- package/identity-provider/presets.js +200 -0
- package/identity-provider/presets.js.map +1 -0
- package/identity-provider/useCreateIdentityProvider.d.ts +37 -0
- package/identity-provider/useCreateIdentityProvider.d.ts.map +1 -0
- package/identity-provider/useCreateIdentityProvider.js +48 -0
- package/identity-provider/useCreateIdentityProvider.js.map +1 -0
- package/identity-provider/useDeleteIdentityProvider.d.ts +34 -0
- package/identity-provider/useDeleteIdentityProvider.d.ts.map +1 -0
- package/identity-provider/useDeleteIdentityProvider.js +45 -0
- package/identity-provider/useDeleteIdentityProvider.js.map +1 -0
- package/identity-provider/useIdentityProvider.d.ts +37 -0
- package/identity-provider/useIdentityProvider.d.ts.map +1 -0
- package/identity-provider/useIdentityProvider.js +62 -0
- package/identity-provider/useIdentityProvider.js.map +1 -0
- package/identity-provider/useIdentityProviderList.d.ts +48 -0
- package/identity-provider/useIdentityProviderList.d.ts.map +1 -0
- package/identity-provider/useIdentityProviderList.js +75 -0
- package/identity-provider/useIdentityProviderList.js.map +1 -0
- package/identity-provider/useOidcDiscovery.d.ts +39 -0
- package/identity-provider/useOidcDiscovery.d.ts.map +1 -0
- package/identity-provider/useOidcDiscovery.js +76 -0
- package/identity-provider/useOidcDiscovery.js.map +1 -0
- package/identity-provider/useSsoProvider.d.ts +50 -0
- package/identity-provider/useSsoProvider.d.ts.map +1 -0
- package/identity-provider/useSsoProvider.js +83 -0
- package/identity-provider/useSsoProvider.js.map +1 -0
- package/identity-provider/useUpdateIdentityProvider.d.ts +38 -0
- package/identity-provider/useUpdateIdentityProvider.d.ts.map +1 -0
- package/identity-provider/useUpdateIdentityProvider.js +49 -0
- package/identity-provider/useUpdateIdentityProvider.js.map +1 -0
- package/index.d.ts +14 -5
- package/index.d.ts.map +1 -1
- package/index.js +10 -2
- package/index.js.map +1 -1
- package/internal/CloudFeatureNotice.d.ts +12 -0
- package/internal/CloudFeatureNotice.d.ts.map +1 -1
- package/internal/CloudFeatureNotice.js +12 -0
- package/internal/CloudFeatureNotice.js.map +1 -1
- package/invitation/InvitationCreatedAlert.d.ts +35 -0
- package/invitation/InvitationCreatedAlert.d.ts.map +1 -0
- package/invitation/InvitationCreatedAlert.js +60 -0
- package/invitation/InvitationCreatedAlert.js.map +1 -0
- package/invitation/InvitationManager.d.ts +44 -0
- package/invitation/InvitationManager.d.ts.map +1 -0
- package/invitation/InvitationManager.js +248 -0
- package/invitation/InvitationManager.js.map +1 -0
- package/invitation/InvitationRedemption.d.ts +69 -0
- package/invitation/InvitationRedemption.d.ts.map +1 -0
- package/invitation/InvitationRedemption.js +140 -0
- package/invitation/InvitationRedemption.js.map +1 -0
- package/invitation/index.d.ts +17 -0
- package/invitation/index.d.ts.map +1 -0
- package/invitation/index.js +9 -0
- package/invitation/index.js.map +1 -0
- package/invitation/useCreateInvitation.d.ts +52 -0
- package/invitation/useCreateInvitation.d.ts.map +1 -0
- package/invitation/useCreateInvitation.js +55 -0
- package/invitation/useCreateInvitation.js.map +1 -0
- package/invitation/useInvitationPreview.d.ts +51 -0
- package/invitation/useInvitationPreview.d.ts.map +1 -0
- package/invitation/useInvitationPreview.js +80 -0
- package/invitation/useInvitationPreview.js.map +1 -0
- package/invitation/useOrgInvitations.d.ts +36 -0
- package/invitation/useOrgInvitations.d.ts.map +1 -0
- package/invitation/useOrgInvitations.js +65 -0
- package/invitation/useOrgInvitations.js.map +1 -0
- package/invitation/useRedeemInvitation.d.ts +47 -0
- package/invitation/useRedeemInvitation.d.ts.map +1 -0
- package/invitation/useRedeemInvitation.js +53 -0
- package/invitation/useRedeemInvitation.js.map +1 -0
- package/invitation/useRevokeInvitation.d.ts +35 -0
- package/invitation/useRevokeInvitation.d.ts.map +1 -0
- package/invitation/useRevokeInvitation.js +47 -0
- package/invitation/useRevokeInvitation.js.map +1 -0
- package/library/detect-skill-package.d.ts +1 -0
- package/library/detect-skill-package.d.ts.map +1 -1
- package/library/detect-skill-package.js.map +1 -1
- package/library/detect-stigmer-resource.d.ts +1 -0
- package/library/detect-stigmer-resource.d.ts.map +1 -1
- package/library/detect-stigmer-resource.js.map +1 -1
- package/library/parse-resource-yaml.d.ts +4 -0
- package/library/parse-resource-yaml.d.ts.map +1 -1
- package/library/parse-resource-yaml.js.map +1 -1
- package/mcp-server/McpServerDetailView.d.ts +2 -2
- package/mcp-server/McpServerDetailView.d.ts.map +1 -1
- package/mcp-server/McpServerDetailView.js.map +1 -1
- package/mcp-server/index.d.ts +1 -1
- package/mcp-server/index.d.ts.map +1 -1
- package/mcp-server/index.js.map +1 -1
- package/mcp-server/mcpServerSetupReducer.d.ts +54 -0
- package/mcp-server/mcpServerSetupReducer.d.ts.map +1 -1
- package/mcp-server/mcpServerSetupReducer.js.map +1 -1
- package/models/ModelSelector.d.ts +9 -0
- package/models/ModelSelector.d.ts.map +1 -1
- package/models/ModelSelector.js +9 -0
- package/models/ModelSelector.js.map +1 -1
- package/models/registry.d.ts +11 -1
- package/models/registry.d.ts.map +1 -1
- package/models/registry.js.map +1 -1
- package/models/useModelRegistry.d.ts +20 -0
- package/models/useModelRegistry.d.ts.map +1 -1
- package/models/useModelRegistry.js +20 -0
- package/models/useModelRegistry.js.map +1 -1
- package/organization/OrgProfilePanel.d.ts +31 -0
- package/organization/OrgProfilePanel.d.ts.map +1 -0
- package/organization/OrgProfilePanel.js +147 -0
- package/organization/OrgProfilePanel.js.map +1 -0
- package/organization/index.d.ts +6 -0
- package/organization/index.d.ts.map +1 -1
- package/organization/index.js +3 -0
- package/organization/index.js.map +1 -1
- package/organization/useOrganization.d.ts +31 -0
- package/organization/useOrganization.d.ts.map +1 -0
- package/organization/useOrganization.js +56 -0
- package/organization/useOrganization.js.map +1 -0
- package/organization/useUpdateOrganization.d.ts +40 -0
- package/organization/useUpdateOrganization.d.ts.map +1 -0
- package/organization/useUpdateOrganization.js +51 -0
- package/organization/useUpdateOrganization.js.map +1 -0
- package/package.json +4 -4
- package/provider.d.ts +1 -0
- package/provider.d.ts.map +1 -1
- package/provider.js.map +1 -1
- package/search/useResourceList.d.ts +4 -2
- package/search/useResourceList.d.ts.map +1 -1
- package/search/useResourceList.js +2 -1
- package/search/useResourceList.js.map +1 -1
- package/search/useResourceSearch.d.ts +10 -2
- package/search/useResourceSearch.d.ts.map +1 -1
- package/search/useResourceSearch.js +2 -1
- package/search/useResourceSearch.js.map +1 -1
- package/session/group-sessions.d.ts +23 -0
- package/session/group-sessions.d.ts.map +1 -1
- package/session/group-sessions.js +23 -0
- package/session/group-sessions.js.map +1 -1
- package/session/index.d.ts +1 -1
- package/session/index.d.ts.map +1 -1
- package/session/index.js.map +1 -1
- package/session/useCreateSession.d.ts +11 -2
- package/session/useCreateSession.d.ts.map +1 -1
- package/session/useCreateSession.js.map +1 -1
- package/session/useSession.d.ts +24 -0
- package/session/useSession.d.ts.map +1 -1
- package/session/useSession.js +24 -0
- package/session/useSession.js.map +1 -1
- package/session/useSessionArtifacts.d.ts +1 -0
- package/session/useSessionArtifacts.d.ts.map +1 -1
- package/session/useSessionArtifacts.js.map +1 -1
- package/session/useSessionConversation.d.ts +7 -0
- package/session/useSessionConversation.d.ts.map +1 -1
- package/session/useSessionConversation.js.map +1 -1
- package/session/useSessionExecutions.d.ts +23 -0
- package/session/useSessionExecutions.d.ts.map +1 -1
- package/session/useSessionExecutions.js +23 -0
- package/session/useSessionExecutions.js.map +1 -1
- package/session/useSessionList.d.ts +19 -0
- package/session/useSessionList.d.ts.map +1 -1
- package/session/useSessionList.js +19 -0
- package/session/useSessionList.js.map +1 -1
- package/session/useSessionWriteBacks.d.ts +1 -0
- package/session/useSessionWriteBacks.d.ts.map +1 -1
- package/session/useSessionWriteBacks.js.map +1 -1
- package/session/useUpdateSession.d.ts +22 -0
- package/session/useUpdateSession.d.ts.map +1 -1
- package/session/useUpdateSession.js +22 -0
- package/session/useUpdateSession.js.map +1 -1
- package/skill/SkillPicker.d.ts +15 -0
- package/skill/SkillPicker.d.ts.map +1 -1
- package/skill/SkillPicker.js +15 -0
- package/skill/SkillPicker.js.map +1 -1
- package/src/agent/AgentEnvForm.tsx +2 -0
- package/src/agent/AgentPicker.tsx +2 -0
- package/src/agent/agentSetupReducer.ts +109 -20
- package/src/agent/useAgentCount.ts +2 -0
- package/src/attachment/AttachmentChipList.tsx +15 -0
- package/src/attachment/useAttachments.ts +14 -0
- package/src/composer/useComposer.ts +5 -0
- package/src/execution/ExecutionPhaseBadge.tsx +1 -1
- package/src/execution/McpToolDetail.tsx +18 -6
- package/src/execution/TodoList.tsx +8 -0
- package/src/execution/ToolArgsView.tsx +1 -0
- package/src/execution/UsageWidget.tsx +1 -1
- package/src/execution/file-path-resolver.ts +28 -4
- package/src/execution/index.ts +5 -1
- package/src/execution/useArtifactContent.ts +33 -0
- package/src/execution/useSubmitApproval.ts +2 -0
- package/src/github/GitHubRepoPicker.tsx +13 -0
- package/src/github/useGitHubConnection.ts +29 -1
- package/src/github/useGitHubRepos.ts +31 -0
- package/src/github/useGitHubSearch.ts +25 -0
- package/src/iam-policy/GrantAccessForm.tsx +198 -0
- package/src/iam-policy/OrgMembersPanel.tsx +572 -0
- package/src/iam-policy/RoleSelector.tsx +105 -0
- package/src/iam-policy/index.ts +51 -0
- package/src/iam-policy/useCreateIamPolicy.ts +66 -0
- package/src/iam-policy/useDeleteIamPolicy.ts +65 -0
- package/src/iam-policy/useGrantableRoles.ts +45 -0
- package/src/iam-policy/usePrincipalsCount.ts +96 -0
- package/src/iam-policy/useResourceAccess.ts +128 -0
- package/src/iam-policy/useRevokeOrgAccess.ts +74 -0
- package/src/iam-policy/useRoleSelector.ts +97 -0
- package/src/iam-policy/useWhoAmI.ts +78 -0
- package/src/identity-provider/CreateIdentityProviderForm.tsx +308 -0
- package/src/identity-provider/IdentityProviderDetailPanel.tsx +583 -0
- package/src/identity-provider/IdentityProviderListPanel.tsx +370 -0
- package/src/identity-provider/IdentityProviderWizard.tsx +684 -0
- package/src/identity-provider/ProviderPicker.tsx +152 -0
- package/src/identity-provider/SsoLoginPrompt.tsx +404 -0
- package/src/identity-provider/index.ts +67 -0
- package/src/identity-provider/presets.ts +262 -0
- package/src/identity-provider/useCreateIdentityProvider.ts +68 -0
- package/src/identity-provider/useDeleteIdentityProvider.ts +65 -0
- package/src/identity-provider/useIdentityProvider.ts +86 -0
- package/src/identity-provider/useIdentityProviderList.ts +100 -0
- package/src/identity-provider/useOidcDiscovery.ts +124 -0
- package/src/identity-provider/useSsoProvider.ts +99 -0
- package/src/identity-provider/useUpdateIdentityProvider.ts +69 -0
- package/src/index.ts +121 -1
- package/src/internal/CloudFeatureNotice.tsx +12 -0
- package/src/invitation/InvitationCreatedAlert.tsx +185 -0
- package/src/invitation/InvitationManager.tsx +842 -0
- package/src/invitation/InvitationRedemption.tsx +434 -0
- package/src/invitation/index.ts +16 -0
- package/src/invitation/useCreateInvitation.ts +83 -0
- package/src/invitation/useInvitationPreview.ts +103 -0
- package/src/invitation/useOrgInvitations.ts +88 -0
- package/src/invitation/useRedeemInvitation.ts +82 -0
- package/src/invitation/useRevokeInvitation.ts +66 -0
- package/src/library/detect-skill-package.ts +4 -1
- package/src/library/detect-stigmer-resource.ts +4 -1
- package/src/library/parse-resource-yaml.ts +12 -2
- package/src/mcp-server/McpServerDetailView.tsx +2 -1
- package/src/mcp-server/index.ts +4 -1
- package/src/mcp-server/mcpServerSetupReducer.ts +86 -8
- package/src/models/ModelSelector.tsx +9 -0
- package/src/models/registry.ts +11 -1
- package/src/models/useModelRegistry.ts +20 -0
- package/src/organization/OrgProfilePanel.tsx +451 -0
- package/src/organization/index.ts +6 -0
- package/src/organization/useOrganization.ts +79 -0
- package/src/organization/useUpdateOrganization.ts +71 -0
- package/src/provider.tsx +1 -0
- package/src/search/useResourceList.ts +6 -3
- package/src/search/useResourceSearch.ts +12 -3
- package/src/session/group-sessions.ts +23 -0
- package/src/session/index.ts +1 -0
- package/src/session/useCreateSession.ts +19 -3
- package/src/session/useSession.ts +24 -0
- package/src/session/useSessionArtifacts.ts +1 -0
- package/src/session/useSessionConversation.ts +7 -0
- package/src/session/useSessionExecutions.ts +23 -0
- package/src/session/useSessionList.ts +19 -0
- package/src/session/useSessionWriteBacks.ts +1 -0
- package/src/session/useUpdateSession.ts +22 -0
- package/src/skill/SkillPicker.tsx +15 -0
- package/src/usage/OrgUsagePanel.tsx +465 -0
- package/src/usage/date-range.ts +86 -0
- package/src/usage/index.ts +13 -0
- package/src/usage/useOrgUsageReport.ts +110 -0
- package/src/workspace/FolderBrowser.tsx +9 -0
- package/src/workspace/WorkspaceEditor.tsx +17 -0
- package/src/workspace/useFolderListing.ts +24 -0
- package/src/workspace/useWorkspaceEntries.ts +38 -0
- package/styles.css +1 -1
- package/usage/OrgUsagePanel.d.ts +24 -0
- package/usage/OrgUsagePanel.d.ts.map +1 -0
- package/usage/OrgUsagePanel.js +134 -0
- package/usage/OrgUsagePanel.js.map +1 -0
- package/usage/date-range.d.ts +36 -0
- package/usage/date-range.d.ts.map +1 -0
- package/usage/date-range.js +69 -0
- package/usage/date-range.js.map +1 -0
- package/usage/index.d.ts +7 -0
- package/usage/index.d.ts.map +1 -0
- package/usage/index.js +4 -0
- package/usage/index.js.map +1 -0
- package/usage/useOrgUsageReport.d.ts +48 -0
- package/usage/useOrgUsageReport.d.ts.map +1 -0
- package/usage/useOrgUsageReport.js +72 -0
- package/usage/useOrgUsageReport.js.map +1 -0
- package/workspace/FolderBrowser.d.ts +9 -0
- package/workspace/FolderBrowser.d.ts.map +1 -1
- package/workspace/FolderBrowser.js +9 -0
- package/workspace/FolderBrowser.js.map +1 -1
- package/workspace/WorkspaceEditor.d.ts +17 -0
- package/workspace/WorkspaceEditor.d.ts.map +1 -1
- package/workspace/WorkspaceEditor.js +17 -0
- package/workspace/WorkspaceEditor.js.map +1 -1
- package/workspace/useFolderListing.d.ts +24 -0
- package/workspace/useFolderListing.d.ts.map +1 -1
- package/workspace/useFolderListing.js +24 -0
- package/workspace/useFolderListing.js.map +1 -1
- package/workspace/useWorkspaceEntries.d.ts +38 -0
- package/workspace/useWorkspaceEntries.d.ts.map +1 -1
- package/workspace/useWorkspaceEntries.js +25 -0
- package/workspace/useWorkspaceEntries.js.map +1 -1
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback, useState } from "react";
|
|
4
|
+
import { cn } from "@stigmer/theme";
|
|
5
|
+
/**
|
|
6
|
+
* One-time banner displayed after a new invitation link is created.
|
|
7
|
+
*
|
|
8
|
+
* Shows the invite URL in a monospace read-only field with a **Copy**
|
|
9
|
+
* button. While invite URLs are always retrievable from the invitation
|
|
10
|
+
* list, surfacing the URL immediately after creation provides the
|
|
11
|
+
* critical "copy and share" moment that admins expect.
|
|
12
|
+
*
|
|
13
|
+
* This is a standalone alert component, not a modal — the parent
|
|
14
|
+
* decides how to present and position it.
|
|
15
|
+
*
|
|
16
|
+
* All visual properties flow through `--stgm-*` design tokens.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```tsx
|
|
20
|
+
* <InvitationCreatedAlert
|
|
21
|
+
* inviteUrl="https://app.stigmer.ai/invite/abc123..."
|
|
22
|
+
* label="Engineering team invite"
|
|
23
|
+
* onDismiss={() => setCreatedUrl(null)}
|
|
24
|
+
* />
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export function InvitationCreatedAlert({ inviteUrl, label, onDismiss, className, }) {
|
|
28
|
+
const [copied, setCopied] = useState(false);
|
|
29
|
+
const handleCopy = useCallback(async () => {
|
|
30
|
+
try {
|
|
31
|
+
await navigator.clipboard.writeText(inviteUrl);
|
|
32
|
+
setCopied(true);
|
|
33
|
+
setTimeout(() => setCopied(false), 2000);
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
const el = document.getElementById("stgm-invite-url-reveal");
|
|
37
|
+
if (el) {
|
|
38
|
+
const selection = window.getSelection();
|
|
39
|
+
const range = document.createRange();
|
|
40
|
+
range.selectNodeContents(el);
|
|
41
|
+
selection?.removeAllRanges();
|
|
42
|
+
selection?.addRange(range);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}, [inviteUrl]);
|
|
46
|
+
return (_jsxs("div", { role: "alert", className: cn("rounded-lg border border-primary/30 bg-primary-subtle p-4", className), children: [_jsxs("div", { className: "mb-2 flex items-start justify-between gap-3", children: [_jsxs("div", { className: "min-w-0", children: [_jsxs("p", { className: "text-sm font-medium text-foreground", children: ["Invite link created: ", label] }), _jsx("p", { className: "mt-0.5 text-xs text-muted-foreground", children: "Share this link to invite people to your organization." })] }), _jsx("button", { type: "button", onClick: onDismiss, "aria-label": "Dismiss", className: cn("shrink-0 rounded p-1", "text-muted-foreground hover:text-foreground hover:bg-accent/50", "transition-colors"), children: _jsx(CloseIcon, {}) })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("code", { id: "stgm-invite-url-reveal", className: cn("min-w-0 flex-1 select-all truncate rounded-md", "border border-input bg-background px-2.5 py-1.5", "font-mono text-xs text-foreground"), children: inviteUrl }), _jsxs("button", { type: "button", onClick: handleCopy, className: cn("inline-flex shrink-0 items-center gap-1.5 rounded-md px-3 py-1.5 text-xs font-medium", "bg-primary text-primary-foreground hover:bg-primary/90", "transition-colors"), children: [copied ? _jsx(CheckIcon, {}) : _jsx(CopyIcon, {}), copied ? "Copied" : "Copy"] })] })] }));
|
|
47
|
+
}
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
// Icons
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
function CopyIcon() {
|
|
52
|
+
return (_jsxs("svg", { width: "12", height: "12", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [_jsx("rect", { x: "5", y: "5", width: "9", height: "9", rx: "1.5" }), _jsx("path", { d: "M5 11H3.5A1.5 1.5 0 0 1 2 9.5V3.5A1.5 1.5 0 0 1 3.5 2h6A1.5 1.5 0 0 1 11 3.5V5" })] }));
|
|
53
|
+
}
|
|
54
|
+
function CheckIcon() {
|
|
55
|
+
return (_jsx("svg", { width: "12", height: "12", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: _jsx("path", { d: "M3 8.5l3.5 3.5L13 5" }) }));
|
|
56
|
+
}
|
|
57
|
+
function CloseIcon() {
|
|
58
|
+
return (_jsx("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", "aria-hidden": "true", children: _jsx("path", { d: "M4 4l8 8M12 4l-8 8" }) }));
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=InvitationCreatedAlert.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InvitationCreatedAlert.js","sourceRoot":"","sources":["../../src/invitation/InvitationCreatedAlert.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC9C,OAAO,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AAkBpC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,sBAAsB,CAAC,EACrC,SAAS,EACT,KAAK,EACL,SAAS,EACT,SAAS,GACmB;IAC5B,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE5C,MAAM,UAAU,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QACxC,IAAI,CAAC;YACH,MAAM,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;YAC/C,SAAS,CAAC,IAAI,CAAC,CAAC;YAChB,UAAU,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;QAC3C,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,EAAE,GAAG,QAAQ,CAAC,cAAc,CAAC,wBAAwB,CAAC,CAAC;YAC7D,IAAI,EAAE,EAAE,CAAC;gBACP,MAAM,SAAS,GAAG,MAAM,CAAC,YAAY,EAAE,CAAC;gBACxC,MAAM,KAAK,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;gBACrC,KAAK,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC;gBAC7B,SAAS,EAAE,eAAe,EAAE,CAAC;gBAC7B,SAAS,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;YAC7B,CAAC;QACH,CAAC;IACH,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC;IAEhB,OAAO,CACL,eACE,IAAI,EAAC,OAAO,EACZ,SAAS,EAAE,EAAE,CACX,2DAA2D,EAC3D,SAAS,CACV,aAED,eAAK,SAAS,EAAC,6CAA6C,aAC1D,eAAK,SAAS,EAAC,SAAS,aACtB,aAAG,SAAS,EAAC,qCAAqC,sCAC1B,KAAK,IACzB,EACJ,YAAG,SAAS,EAAC,sCAAsC,uEAE/C,IACA,EACN,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,SAAS,gBACP,SAAS,EACpB,SAAS,EAAE,EAAE,CACX,sBAAsB,EACtB,gEAAgE,EAChE,mBAAmB,CACpB,YAED,KAAC,SAAS,KAAG,GACN,IACL,EAEN,eAAK,SAAS,EAAC,yBAAyB,aACtC,eACE,EAAE,EAAC,wBAAwB,EAC3B,SAAS,EAAE,EAAE,CACX,+CAA+C,EAC/C,iDAAiD,EACjD,mCAAmC,CACpC,YAEA,SAAS,GACL,EAEP,kBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,UAAU,EACnB,SAAS,EAAE,EAAE,CACX,sFAAsF,EACtF,wDAAwD,EACxD,mBAAmB,CACpB,aAEA,MAAM,CAAC,CAAC,CAAC,KAAC,SAAS,KAAG,CAAC,CAAC,CAAC,KAAC,QAAQ,KAAG,EACrC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,IACpB,IACL,IACF,CACP,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,QAAQ;AACR,8EAA8E;AAE9E,SAAS,QAAQ;IACf,OAAO,CACL,eACE,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,EACX,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,KAAK,EACjB,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,iBACV,MAAM,aAElB,eAAM,CAAC,EAAC,GAAG,EAAC,CAAC,EAAC,GAAG,EAAC,KAAK,EAAC,GAAG,EAAC,MAAM,EAAC,GAAG,EAAC,EAAE,EAAC,KAAK,GAAG,EAClD,eAAM,CAAC,EAAC,gFAAgF,GAAG,IACvF,CACP,CAAC;AACJ,CAAC;AAED,SAAS,SAAS;IAChB,OAAO,CACL,cACE,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,EACX,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,GAAG,EACf,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,iBACV,MAAM,YAElB,eAAM,CAAC,EAAC,qBAAqB,GAAG,GAC5B,CACP,CAAC;AACJ,CAAC;AAED,SAAS,SAAS;IAChB,OAAO,CACL,cACE,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,EACX,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,KAAK,EACjB,aAAa,EAAC,OAAO,iBACT,MAAM,YAElB,eAAM,CAAC,EAAC,oBAAoB,GAAG,GAC3B,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/** Props for {@link InvitationManager}. */
|
|
2
|
+
export interface InvitationManagerProps {
|
|
3
|
+
/** Organization slug whose invitations to manage. */
|
|
4
|
+
readonly org: string;
|
|
5
|
+
/**
|
|
6
|
+
* Build the full invite URL from a token.
|
|
7
|
+
*
|
|
8
|
+
* Platform builders override this when their invite route differs
|
|
9
|
+
* from the default `/invite/<token>` path or runs on a different
|
|
10
|
+
* domain.
|
|
11
|
+
*
|
|
12
|
+
* @default `${window.location.origin}/invite/${token}`
|
|
13
|
+
*/
|
|
14
|
+
readonly buildInviteUrl?: (token: string) => string;
|
|
15
|
+
/** Additional CSS class names for the root container. */
|
|
16
|
+
readonly className?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Self-contained panel for managing organization invitation links.
|
|
20
|
+
*
|
|
21
|
+
* Displays all invitations for the organization with inline actions
|
|
22
|
+
* (copy link, revoke) and a create form for generating new invite
|
|
23
|
+
* links. Follows the same pattern as {@link OrgMembersPanel}: a
|
|
24
|
+
* single embeddable component that handles the full management flow.
|
|
25
|
+
*
|
|
26
|
+
* The component composes three invitation hooks internally:
|
|
27
|
+
* - {@link useOrgInvitations} for listing
|
|
28
|
+
* - {@link useCreateInvitation} for creation
|
|
29
|
+
* - {@link useRevokeInvitation} for revocation
|
|
30
|
+
*
|
|
31
|
+
* All visual properties flow through `--stgm-*` design tokens.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```tsx
|
|
35
|
+
* <InvitationManager org="acme" />
|
|
36
|
+
*
|
|
37
|
+
* <InvitationManager
|
|
38
|
+
* org="acme"
|
|
39
|
+
* buildInviteUrl={(token) => `https://myapp.com/join/${token}`}
|
|
40
|
+
* />
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export declare function InvitationManager({ org, buildInviteUrl, className, }: InvitationManagerProps): import("react/jsx-runtime").JSX.Element;
|
|
44
|
+
//# sourceMappingURL=InvitationManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InvitationManager.d.ts","sourceRoot":"","sources":["../../src/invitation/InvitationManager.tsx"],"names":[],"mappings":"AAuBA,2CAA2C;AAC3C,MAAM,WAAW,sBAAsB;IACrC,qDAAqD;IACrD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB;;;;;;;;OAQG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACpD,yDAAyD;IACzD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAcD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,GAAG,EACH,cAAsC,EACtC,SAAS,GACV,EAAE,sBAAsB,2CA2HxB"}
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback, useState } from "react";
|
|
4
|
+
import { cn } from "@stigmer/theme";
|
|
5
|
+
import { getUserMessage, iamRoleDisplayName, } from "@stigmer/sdk";
|
|
6
|
+
import { IamRole } from "@stigmer/protos/ai/stigmer/iam/v1/enum_pb";
|
|
7
|
+
import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
|
|
8
|
+
import { InvitationState } from "@stigmer/protos/ai/stigmer/iam/invitation/v1/enum_pb";
|
|
9
|
+
import { timestampDate } from "@bufbuild/protobuf/wkt";
|
|
10
|
+
import { useOrgInvitations } from "./useOrgInvitations";
|
|
11
|
+
import { useCreateInvitation } from "./useCreateInvitation";
|
|
12
|
+
import { useRevokeInvitation } from "./useRevokeInvitation";
|
|
13
|
+
import { InvitationCreatedAlert } from "./InvitationCreatedAlert";
|
|
14
|
+
import { RoleSelector } from "../iam-policy/RoleSelector";
|
|
15
|
+
function defaultBuildInviteUrl(token) {
|
|
16
|
+
if (typeof window !== "undefined") {
|
|
17
|
+
return `${window.location.origin}/invite/${token}`;
|
|
18
|
+
}
|
|
19
|
+
return `/invite/${token}`;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Self-contained panel for managing organization invitation links.
|
|
23
|
+
*
|
|
24
|
+
* Displays all invitations for the organization with inline actions
|
|
25
|
+
* (copy link, revoke) and a create form for generating new invite
|
|
26
|
+
* links. Follows the same pattern as {@link OrgMembersPanel}: a
|
|
27
|
+
* single embeddable component that handles the full management flow.
|
|
28
|
+
*
|
|
29
|
+
* The component composes three invitation hooks internally:
|
|
30
|
+
* - {@link useOrgInvitations} for listing
|
|
31
|
+
* - {@link useCreateInvitation} for creation
|
|
32
|
+
* - {@link useRevokeInvitation} for revocation
|
|
33
|
+
*
|
|
34
|
+
* All visual properties flow through `--stgm-*` design tokens.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```tsx
|
|
38
|
+
* <InvitationManager org="acme" />
|
|
39
|
+
*
|
|
40
|
+
* <InvitationManager
|
|
41
|
+
* org="acme"
|
|
42
|
+
* buildInviteUrl={(token) => `https://myapp.com/join/${token}`}
|
|
43
|
+
* />
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export function InvitationManager({ org, buildInviteUrl = defaultBuildInviteUrl, className, }) {
|
|
47
|
+
const { invitations, isLoading, error, refetch } = useOrgInvitations(org);
|
|
48
|
+
const [flow, setFlow] = useState({ phase: "idle" });
|
|
49
|
+
const [revokingId, setRevokingId] = useState(null);
|
|
50
|
+
const activeCount = invitations.filter((inv) => inv.status?.state === InvitationState.active).length;
|
|
51
|
+
const handleCreated = useCallback((invitation) => {
|
|
52
|
+
const token = invitation.status?.token ?? "";
|
|
53
|
+
const label = invitation.spec?.label || invitation.metadata?.name || "Invite link";
|
|
54
|
+
setFlow({ phase: "created", inviteUrl: buildInviteUrl(token), label });
|
|
55
|
+
refetch();
|
|
56
|
+
}, [buildInviteUrl, refetch]);
|
|
57
|
+
const handleRevoked = useCallback(() => {
|
|
58
|
+
setRevokingId(null);
|
|
59
|
+
refetch();
|
|
60
|
+
}, [refetch]);
|
|
61
|
+
if (isLoading) {
|
|
62
|
+
return (_jsx("div", { className: cn("space-y-2", className), "aria-busy": "true", "aria-label": "Loading invitations", children: Array.from({ length: 2 }, (_, i) => (_jsx("div", { className: "bg-muted/40 h-14 animate-pulse rounded-lg" }, i))) }));
|
|
63
|
+
}
|
|
64
|
+
if (error) {
|
|
65
|
+
return (_jsx("p", { className: cn("text-destructive text-xs", className), role: "alert", children: getUserMessage(error) }));
|
|
66
|
+
}
|
|
67
|
+
return (_jsxs("div", { className: cn("space-y-3", className), children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-sm font-semibold text-foreground", children: "Invite Links" }), activeCount > 0 && (_jsxs("span", { className: "inline-flex items-center rounded-full bg-muted px-2 py-0.5 text-[0.65rem] font-medium text-muted-foreground", children: [activeCount, " active"] }))] }), flow.phase === "idle" && (_jsx("button", { type: "button", onClick: () => setFlow({ phase: "creating" }), className: "text-primary hover:text-foreground text-xs font-medium transition-colors", children: "+ Create invite link" }))] }), flow.phase === "created" && (_jsx(InvitationCreatedAlert, { inviteUrl: flow.inviteUrl, label: flow.label, onDismiss: () => setFlow({ phase: "idle" }) })), flow.phase === "creating" && (_jsx("div", { className: "border-border bg-card rounded-lg border p-4", children: _jsx(CreateInvitationForm, { org: org, onCreated: handleCreated, onCancel: () => setFlow({ phase: "idle" }) }) })), invitations.length === 0 ? (_jsx("p", { className: "text-muted-foreground py-4 text-center text-xs", children: "No invite links yet. Create one to start inviting people." })) : (_jsx("div", { role: "list", "aria-label": "Invitation links", className: "space-y-2", children: invitations.map((inv) => {
|
|
68
|
+
const id = inv.metadata?.id ?? "";
|
|
69
|
+
return (_jsx(InvitationRow, { invitation: inv, buildInviteUrl: buildInviteUrl, isRevoking: revokingId === id, onStartRevoke: () => setRevokingId(id), onCancelRevoke: () => setRevokingId(null), onRevoked: handleRevoked }, id));
|
|
70
|
+
}) }))] }));
|
|
71
|
+
}
|
|
72
|
+
const EXPIRY_OPTIONS = [
|
|
73
|
+
{ value: "7", label: "7 days" },
|
|
74
|
+
{ value: "14", label: "14 days" },
|
|
75
|
+
{ value: "30", label: "30 days" },
|
|
76
|
+
];
|
|
77
|
+
function CreateInvitationForm({ org, onCreated, onCancel, }) {
|
|
78
|
+
const { create, isCreating, error, clearError } = useCreateInvitation();
|
|
79
|
+
const [label, setLabel] = useState("");
|
|
80
|
+
const [role, setRole] = useState(IamRole.viewer);
|
|
81
|
+
const [expiry, setExpiry] = useState("30");
|
|
82
|
+
const [redemptionMode, setRedemptionMode] = useState("unlimited");
|
|
83
|
+
const canSubmit = !isCreating;
|
|
84
|
+
const handleSubmit = useCallback(async (e) => {
|
|
85
|
+
e.preventDefault();
|
|
86
|
+
if (!canSubmit)
|
|
87
|
+
return;
|
|
88
|
+
clearError();
|
|
89
|
+
try {
|
|
90
|
+
const invitation = await create({
|
|
91
|
+
name: label.trim() || `invite-${Date.now()}`,
|
|
92
|
+
org,
|
|
93
|
+
role,
|
|
94
|
+
expiresAt: daysFromNow(Number(expiry)),
|
|
95
|
+
maxRedemptions: redemptionMode === "single" ? 1 : 0,
|
|
96
|
+
label: label.trim() || undefined,
|
|
97
|
+
});
|
|
98
|
+
onCreated(invitation);
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
// error state is managed by useCreateInvitation
|
|
102
|
+
}
|
|
103
|
+
}, [canSubmit, label, org, role, expiry, redemptionMode, create, clearError, onCreated]);
|
|
104
|
+
return (_jsxs("form", { onSubmit: handleSubmit, className: "space-y-3", children: [_jsxs("div", { className: "space-y-1", children: [_jsxs("label", { htmlFor: "stgm-new-invite-label", className: "text-xs font-medium text-foreground", children: ["Label", " ", _jsx("span", { className: "font-normal text-muted-foreground", children: "(optional)" })] }), _jsx("input", { id: "stgm-new-invite-label", type: "text", value: label, onChange: (e) => setLabel(e.target.value), placeholder: "e.g. Engineering team link", disabled: isCreating, autoFocus: true, maxLength: 200, className: cn("w-full rounded-md border border-input bg-background px-2.5 py-1.5 text-xs text-foreground", "placeholder:text-muted-foreground", "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring", "disabled:pointer-events-none disabled:opacity-50") })] }), _jsx(RoleSelector, { kind: ApiResourceKind.organization, selected: role, onSelect: (r) => setRole(r), disabled: isCreating }), _jsxs("fieldset", { className: "space-y-1.5", children: [_jsx("legend", { className: "text-xs font-medium text-foreground", children: "Expires in" }), _jsx("div", { className: "flex flex-wrap gap-2", children: EXPIRY_OPTIONS.map(({ value, label: optLabel }) => (_jsx(ExpiryRadio, { value: value, label: optLabel, checked: expiry === value, disabled: isCreating, onChange: setExpiry }, value))) })] }), _jsxs("fieldset", { className: "space-y-1.5", children: [_jsx("legend", { className: "text-xs font-medium text-foreground", children: "Usage limit" }), _jsxs("div", { className: "flex flex-wrap gap-2", children: [_jsx(RedemptionRadio, { value: "unlimited", label: "Unlimited", description: "Anyone with the link can join", checked: redemptionMode === "unlimited", disabled: isCreating, onChange: setRedemptionMode }), _jsx(RedemptionRadio, { value: "single", label: "Single use", description: "One person only", checked: redemptionMode === "single", disabled: isCreating, onChange: setRedemptionMode })] })] }), error && (_jsx("p", { className: "text-destructive text-[0.65rem]", role: "alert", children: getUserMessage(error) })), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs("button", { type: "submit", disabled: !canSubmit, className: cn("inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-xs font-medium", "bg-primary text-primary-foreground hover:bg-primary/90", "disabled:pointer-events-none disabled:opacity-40"), children: [isCreating && _jsx(SpinnerIcon, {}), "Create invite link"] }), _jsx("button", { type: "button", onClick: onCancel, disabled: isCreating, className: cn("rounded-md px-3 py-1.5 text-xs", "text-muted-foreground hover:text-foreground hover:bg-accent/50", "disabled:pointer-events-none disabled:opacity-50"), children: "Cancel" })] })] }));
|
|
105
|
+
}
|
|
106
|
+
// ---------------------------------------------------------------------------
|
|
107
|
+
// InvitationRow (internal)
|
|
108
|
+
// ---------------------------------------------------------------------------
|
|
109
|
+
function InvitationRow({ invitation, buildInviteUrl, isRevoking, onStartRevoke, onCancelRevoke, onRevoked, }) {
|
|
110
|
+
const [copied, setCopied] = useState(false);
|
|
111
|
+
const id = invitation.metadata?.id ?? "";
|
|
112
|
+
const label = invitation.spec?.label || invitation.metadata?.name || "Unnamed invite";
|
|
113
|
+
const role = invitation.spec?.role ?? IamRole.iam_role_unspecified;
|
|
114
|
+
const state = invitation.status?.state ?? InvitationState.invitation_state_unspecified;
|
|
115
|
+
const token = invitation.status?.token ?? "";
|
|
116
|
+
const redemptionCount = invitation.status?.redemptionCount ?? 0;
|
|
117
|
+
const maxRedemptions = invitation.spec?.maxRedemptions ?? 0;
|
|
118
|
+
const expiresAt = invitation.spec?.expiresAt;
|
|
119
|
+
const isActive = state === InvitationState.active;
|
|
120
|
+
const handleCopy = useCallback(async () => {
|
|
121
|
+
try {
|
|
122
|
+
await navigator.clipboard.writeText(buildInviteUrl(token));
|
|
123
|
+
setCopied(true);
|
|
124
|
+
setTimeout(() => setCopied(false), 2000);
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
// silently fail — copy is a convenience, not critical
|
|
128
|
+
}
|
|
129
|
+
}, [token, buildInviteUrl]);
|
|
130
|
+
if (isRevoking) {
|
|
131
|
+
return (_jsx(RevokeConfirmation, { invitationId: id, label: label, onRevoked: onRevoked, onCancel: onCancelRevoke }));
|
|
132
|
+
}
|
|
133
|
+
return (_jsxs("div", { role: "listitem", className: "flex items-center gap-3 rounded-lg border border-border/60 px-3 py-2.5 hover:border-border transition-colors", children: [_jsx(LinkIcon, { active: isActive }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("span", { className: cn("block truncate text-sm font-medium", isActive ? "text-foreground" : "text-muted-foreground"), children: label }), _jsx("span", { className: "block text-xs text-muted-foreground", children: formatRedemptions(redemptionCount, maxRedemptions) })] }), _jsxs("div", { className: "hidden sm:flex shrink-0 items-center gap-3", children: [_jsx("span", { className: "inline-flex items-center rounded-md border border-border bg-muted px-2 py-0.5 text-[0.65rem] font-medium text-foreground", children: iamRoleDisplayName(role) }), _jsx(StateBadge, { state: state }), expiresAt && (_jsx("span", { className: "text-xs text-muted-foreground", title: timestampDate(expiresAt).toISOString(), children: isActive
|
|
134
|
+
? formatRelativeExpiry(timestampDate(expiresAt))
|
|
135
|
+
: formatShortDate(timestampDate(expiresAt)) }))] }), _jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [isActive && (_jsx("button", { type: "button", onClick: handleCopy, "aria-label": copied ? "Link copied" : `Copy invite link for ${label}`, className: cn("shrink-0 rounded p-1 transition-colors", copied
|
|
136
|
+
? "text-primary"
|
|
137
|
+
: "text-muted-foreground hover:text-foreground hover:bg-accent/50"), children: copied ? _jsx(CheckIcon, {}) : _jsx(CopyIcon, {}) })), isActive && (_jsx("button", { type: "button", onClick: onStartRevoke, "aria-label": `Revoke ${label}`, className: "shrink-0 rounded p-1 text-muted-foreground hover:text-destructive hover:bg-destructive/10 transition-colors", children: _jsx(RevokeIcon, {}) }))] })] }));
|
|
138
|
+
}
|
|
139
|
+
// ---------------------------------------------------------------------------
|
|
140
|
+
// RevokeConfirmation (internal)
|
|
141
|
+
// ---------------------------------------------------------------------------
|
|
142
|
+
function RevokeConfirmation({ invitationId, label, onRevoked, onCancel, }) {
|
|
143
|
+
const { revoke, isRevoking, error } = useRevokeInvitation();
|
|
144
|
+
const handleConfirm = useCallback(async () => {
|
|
145
|
+
try {
|
|
146
|
+
await revoke(invitationId);
|
|
147
|
+
onRevoked();
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
// error state is surfaced via the hook
|
|
151
|
+
}
|
|
152
|
+
}, [invitationId, revoke, onRevoked]);
|
|
153
|
+
return (_jsxs("div", { role: "listitem", className: "flex items-center justify-between rounded-lg border border-destructive/30 bg-destructive/5 px-3 py-2.5", children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("p", { className: "text-xs text-foreground", children: ["Revoke ", _jsx("span", { className: "font-medium", children: label }), "? The link will stop working immediately."] }), error && (_jsx("p", { className: "mt-0.5 text-[0.65rem] text-destructive", children: getUserMessage(error) }))] }), _jsxs("div", { className: "flex shrink-0 items-center gap-1.5 ml-3", children: [_jsxs("button", { type: "button", onClick: handleConfirm, disabled: isRevoking, className: cn("inline-flex items-center gap-1 rounded-md px-2.5 py-1 text-xs font-medium", "bg-destructive text-destructive-foreground hover:bg-destructive/90", "disabled:pointer-events-none disabled:opacity-50"), children: [isRevoking && _jsx(SpinnerIcon, {}), "Revoke"] }), _jsx("button", { type: "button", onClick: onCancel, disabled: isRevoking, className: cn("rounded-md px-2.5 py-1 text-xs", "text-muted-foreground hover:text-foreground hover:bg-accent/50", "disabled:pointer-events-none disabled:opacity-50"), children: "Cancel" })] })] }));
|
|
154
|
+
}
|
|
155
|
+
// ---------------------------------------------------------------------------
|
|
156
|
+
// StateBadge (internal)
|
|
157
|
+
// ---------------------------------------------------------------------------
|
|
158
|
+
function StateBadge({ state }) {
|
|
159
|
+
const config = STATE_BADGE_CONFIG[state] ?? STATE_BADGE_CONFIG[InvitationState.invitation_state_unspecified];
|
|
160
|
+
return (_jsx("span", { className: cn("inline-flex items-center rounded-full px-2 py-0.5 text-[0.6rem] font-medium", config.className), children: config.label }));
|
|
161
|
+
}
|
|
162
|
+
const STATE_BADGE_CONFIG = {
|
|
163
|
+
[InvitationState.invitation_state_unspecified]: {
|
|
164
|
+
label: "Unknown",
|
|
165
|
+
className: "bg-muted text-muted-foreground",
|
|
166
|
+
},
|
|
167
|
+
[InvitationState.active]: {
|
|
168
|
+
label: "Active",
|
|
169
|
+
className: "bg-primary-subtle text-primary",
|
|
170
|
+
},
|
|
171
|
+
[InvitationState.expired]: {
|
|
172
|
+
label: "Expired",
|
|
173
|
+
className: "bg-muted text-muted-foreground",
|
|
174
|
+
},
|
|
175
|
+
[InvitationState.revoked]: {
|
|
176
|
+
label: "Revoked",
|
|
177
|
+
className: "bg-muted text-muted-foreground",
|
|
178
|
+
},
|
|
179
|
+
[InvitationState.fully_redeemed]: {
|
|
180
|
+
label: "Fully redeemed",
|
|
181
|
+
className: "bg-muted text-muted-foreground",
|
|
182
|
+
},
|
|
183
|
+
};
|
|
184
|
+
// ---------------------------------------------------------------------------
|
|
185
|
+
// Radio helpers (internal)
|
|
186
|
+
// ---------------------------------------------------------------------------
|
|
187
|
+
function ExpiryRadio({ value, label, checked, disabled, onChange, }) {
|
|
188
|
+
return (_jsxs("label", { className: cn("inline-flex cursor-pointer items-center rounded-md border px-2.5 py-1 text-xs transition-colors", checked
|
|
189
|
+
? "border-primary bg-primary-subtle text-primary font-medium"
|
|
190
|
+
: "border-input bg-background text-muted-foreground hover:border-border hover:text-foreground", disabled && "pointer-events-none opacity-50"), children: [_jsx("input", { type: "radio", name: "stgm-invite-expiry", value: value, checked: checked, disabled: disabled, onChange: () => onChange(value), className: "sr-only" }), label] }));
|
|
191
|
+
}
|
|
192
|
+
function RedemptionRadio({ value, label, description, checked, disabled, onChange, }) {
|
|
193
|
+
return (_jsxs("label", { className: cn("inline-flex cursor-pointer flex-col rounded-md border px-3 py-1.5 text-xs transition-colors", checked
|
|
194
|
+
? "border-primary bg-primary-subtle text-primary font-medium"
|
|
195
|
+
: "border-input bg-background text-muted-foreground hover:border-border hover:text-foreground", disabled && "pointer-events-none opacity-50"), children: [_jsx("input", { type: "radio", name: "stgm-invite-redemption", value: value, checked: checked, disabled: disabled, onChange: () => onChange(value), className: "sr-only" }), _jsx("span", { children: label }), _jsx("span", { className: "text-[0.625rem] text-muted-foreground font-normal mt-0.5", children: description })] }));
|
|
196
|
+
}
|
|
197
|
+
// ---------------------------------------------------------------------------
|
|
198
|
+
// Formatting helpers
|
|
199
|
+
// ---------------------------------------------------------------------------
|
|
200
|
+
function daysFromNow(days) {
|
|
201
|
+
const date = new Date();
|
|
202
|
+
date.setDate(date.getDate() + days);
|
|
203
|
+
return date;
|
|
204
|
+
}
|
|
205
|
+
function formatRedemptions(count, max) {
|
|
206
|
+
if (max === 0) {
|
|
207
|
+
return count === 0 ? "No redemptions yet" : `${count} redeemed`;
|
|
208
|
+
}
|
|
209
|
+
return `${count} / ${max} redeemed`;
|
|
210
|
+
}
|
|
211
|
+
function formatRelativeExpiry(date) {
|
|
212
|
+
const now = Date.now();
|
|
213
|
+
const diffMs = date.getTime() - now;
|
|
214
|
+
if (diffMs <= 0)
|
|
215
|
+
return "Expired";
|
|
216
|
+
const days = Math.ceil(diffMs / 86_400_000);
|
|
217
|
+
if (days === 1)
|
|
218
|
+
return "Expires tomorrow";
|
|
219
|
+
if (days <= 30)
|
|
220
|
+
return `Expires in ${days} days`;
|
|
221
|
+
return `Expires ${formatShortDate(date)}`;
|
|
222
|
+
}
|
|
223
|
+
function formatShortDate(date) {
|
|
224
|
+
return date.toLocaleDateString(undefined, {
|
|
225
|
+
month: "short",
|
|
226
|
+
day: "numeric",
|
|
227
|
+
year: "numeric",
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
// ---------------------------------------------------------------------------
|
|
231
|
+
// Icons
|
|
232
|
+
// ---------------------------------------------------------------------------
|
|
233
|
+
function LinkIcon({ active }) {
|
|
234
|
+
return (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", className: cn("shrink-0", active ? "text-primary" : "text-muted-foreground"), children: [_jsx("path", { d: "M6.5 9.5a3.5 3.5 0 0 0 5 0l2-2a3.5 3.5 0 0 0-5-5l-1 1" }), _jsx("path", { d: "M9.5 6.5a3.5 3.5 0 0 0-5 0l-2 2a3.5 3.5 0 0 0 5 5l1-1" })] }));
|
|
235
|
+
}
|
|
236
|
+
function CopyIcon() {
|
|
237
|
+
return (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [_jsx("rect", { x: "5", y: "5", width: "9", height: "9", rx: "1.5" }), _jsx("path", { d: "M5 11H3.5A1.5 1.5 0 0 1 2 9.5V3.5A1.5 1.5 0 0 1 3.5 2h6A1.5 1.5 0 0 1 11 3.5V5" })] }));
|
|
238
|
+
}
|
|
239
|
+
function CheckIcon() {
|
|
240
|
+
return (_jsx("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: _jsx("path", { d: "M3 8.5l3.5 3.5L13 5" }) }));
|
|
241
|
+
}
|
|
242
|
+
function RevokeIcon() {
|
|
243
|
+
return (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [_jsx("circle", { cx: "8", cy: "8", r: "6" }), _jsx("path", { d: "M4.5 11.5l7-7" })] }));
|
|
244
|
+
}
|
|
245
|
+
function SpinnerIcon() {
|
|
246
|
+
return (_jsx("svg", { width: "12", height: "12", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", className: "animate-spin", "aria-hidden": "true", children: _jsx("path", { d: "M8 2a6 6 0 1 0 6 6" }) }));
|
|
247
|
+
}
|
|
248
|
+
//# sourceMappingURL=InvitationManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InvitationManager.js","sourceRoot":"","sources":["../../src/invitation/InvitationManager.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { Invitation } from "@stigmer/protos/ai/stigmer/iam/invitation/v1/api_pb";
|
|
2
|
+
/** Props for {@link InvitationRedemption}. */
|
|
3
|
+
export interface InvitationRedemptionProps {
|
|
4
|
+
/** The invitation token from the invite URL. */
|
|
5
|
+
readonly token: string;
|
|
6
|
+
/**
|
|
7
|
+
* Whether the current user is authenticated.
|
|
8
|
+
*
|
|
9
|
+
* When `false`, the component shows a "Sign in to accept" CTA
|
|
10
|
+
* instead of the accept button. When `true` or omitted, the
|
|
11
|
+
* accept button calls `redeem` directly.
|
|
12
|
+
*
|
|
13
|
+
* @default true
|
|
14
|
+
*/
|
|
15
|
+
readonly isAuthenticated?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Fired after the invitation is successfully redeemed.
|
|
18
|
+
*
|
|
19
|
+
* The returned {@link Invitation} contains the organization and
|
|
20
|
+
* role information needed for post-redemption navigation
|
|
21
|
+
* (e.g. redirecting to the org dashboard).
|
|
22
|
+
*/
|
|
23
|
+
readonly onAccepted?: (invitation: Invitation) => void;
|
|
24
|
+
/**
|
|
25
|
+
* Fired when an unauthenticated user clicks "Sign in to accept".
|
|
26
|
+
*
|
|
27
|
+
* The host application controls what "sign in" means — this
|
|
28
|
+
* callback typically triggers a redirect to the login page with
|
|
29
|
+
* a return URL back to the invite page.
|
|
30
|
+
*/
|
|
31
|
+
readonly onAuthRequired?: () => void;
|
|
32
|
+
/** Additional CSS class names for the root container. */
|
|
33
|
+
readonly className?: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Self-contained invite acceptance flow.
|
|
37
|
+
*
|
|
38
|
+
* Fetches the invitation preview by token (public endpoint, no auth
|
|
39
|
+
* required), displays the organization info and role being offered,
|
|
40
|
+
* and provides an accept button that redeems the invitation.
|
|
41
|
+
*
|
|
42
|
+
* Handles all states: loading, invalid (expired / revoked / fully
|
|
43
|
+
* redeemed), authentication required, redemption in flight,
|
|
44
|
+
* success, and error — with appropriate UX for each.
|
|
45
|
+
*
|
|
46
|
+
* The component is auth-agnostic: it delegates authentication
|
|
47
|
+
* decisions to the host application via `isAuthenticated` and
|
|
48
|
+
* `onAuthRequired` props. Platform builders who render this
|
|
49
|
+
* component only for authenticated users can ignore both props.
|
|
50
|
+
*
|
|
51
|
+
* All visual properties flow through `--stgm-*` design tokens.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```tsx
|
|
55
|
+
* <InvitationRedemption
|
|
56
|
+
* token={tokenFromUrl}
|
|
57
|
+
* onAccepted={(inv) => router.push("/dashboard")}
|
|
58
|
+
* />
|
|
59
|
+
*
|
|
60
|
+
* <InvitationRedemption
|
|
61
|
+
* token={tokenFromUrl}
|
|
62
|
+
* isAuthenticated={!!currentUser}
|
|
63
|
+
* onAccepted={(inv) => router.push(`/org/${inv.metadata?.org}`)}
|
|
64
|
+
* onAuthRequired={() => router.push(`/login?return=/invite/${token}`)}
|
|
65
|
+
* />
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export declare function InvitationRedemption({ token, isAuthenticated, onAccepted, onAuthRequired, className, }: InvitationRedemptionProps): import("react/jsx-runtime").JSX.Element;
|
|
69
|
+
//# sourceMappingURL=InvitationRedemption.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InvitationRedemption.d.ts","sourceRoot":"","sources":["../../src/invitation/InvitationRedemption.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qDAAqD,CAAC;AAStF,8CAA8C;AAC9C,MAAM,WAAW,yBAAyB;IACxC,gDAAgD;IAChD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;;;;;;;OAQG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;IACnC;;;;;;OAMG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IACvD;;;;;;OAMG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IACrC,yDAAyD;IACzD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,KAAK,EACL,eAAsB,EACtB,UAAU,EACV,cAAc,EACd,SAAS,GACV,EAAE,yBAAyB,2CAqK3B"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback, useState } from "react";
|
|
4
|
+
import { cn } from "@stigmer/theme";
|
|
5
|
+
import { getUserMessage, iamRoleDisplayName } from "@stigmer/sdk";
|
|
6
|
+
import { timestampDate } from "@bufbuild/protobuf/wkt";
|
|
7
|
+
import { useInvitationPreview } from "./useInvitationPreview";
|
|
8
|
+
import { useRedeemInvitation } from "./useRedeemInvitation";
|
|
9
|
+
/**
|
|
10
|
+
* Self-contained invite acceptance flow.
|
|
11
|
+
*
|
|
12
|
+
* Fetches the invitation preview by token (public endpoint, no auth
|
|
13
|
+
* required), displays the organization info and role being offered,
|
|
14
|
+
* and provides an accept button that redeems the invitation.
|
|
15
|
+
*
|
|
16
|
+
* Handles all states: loading, invalid (expired / revoked / fully
|
|
17
|
+
* redeemed), authentication required, redemption in flight,
|
|
18
|
+
* success, and error — with appropriate UX for each.
|
|
19
|
+
*
|
|
20
|
+
* The component is auth-agnostic: it delegates authentication
|
|
21
|
+
* decisions to the host application via `isAuthenticated` and
|
|
22
|
+
* `onAuthRequired` props. Platform builders who render this
|
|
23
|
+
* component only for authenticated users can ignore both props.
|
|
24
|
+
*
|
|
25
|
+
* All visual properties flow through `--stgm-*` design tokens.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```tsx
|
|
29
|
+
* <InvitationRedemption
|
|
30
|
+
* token={tokenFromUrl}
|
|
31
|
+
* onAccepted={(inv) => router.push("/dashboard")}
|
|
32
|
+
* />
|
|
33
|
+
*
|
|
34
|
+
* <InvitationRedemption
|
|
35
|
+
* token={tokenFromUrl}
|
|
36
|
+
* isAuthenticated={!!currentUser}
|
|
37
|
+
* onAccepted={(inv) => router.push(`/org/${inv.metadata?.org}`)}
|
|
38
|
+
* onAuthRequired={() => router.push(`/login?return=/invite/${token}`)}
|
|
39
|
+
* />
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export function InvitationRedemption({ token, isAuthenticated = true, onAccepted, onAuthRequired, className, }) {
|
|
43
|
+
const { preview, isLoading, error: fetchError, refetch } = useInvitationPreview(token);
|
|
44
|
+
const { redeem, isRedeeming, error: redeemError, clearError } = useRedeemInvitation();
|
|
45
|
+
const [accepted, setAccepted] = useState(null);
|
|
46
|
+
const handleAccept = useCallback(async () => {
|
|
47
|
+
clearError();
|
|
48
|
+
try {
|
|
49
|
+
const invitation = await redeem(token);
|
|
50
|
+
setAccepted(invitation);
|
|
51
|
+
onAccepted?.(invitation);
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
// error state is managed by useRedeemInvitation
|
|
55
|
+
}
|
|
56
|
+
}, [token, redeem, clearError, onAccepted]);
|
|
57
|
+
// Loading state
|
|
58
|
+
if (isLoading) {
|
|
59
|
+
return (_jsx("div", { className: cn("mx-auto max-w-sm", className), "aria-busy": "true", "aria-label": "Loading invitation", children: _jsx(LoadingSkeleton, {}) }));
|
|
60
|
+
}
|
|
61
|
+
// Fetch error
|
|
62
|
+
if (fetchError) {
|
|
63
|
+
return (_jsx("div", { className: cn("mx-auto max-w-sm", className), children: _jsx(ErrorCard, { message: getUserMessage(fetchError), onRetry: refetch }) }));
|
|
64
|
+
}
|
|
65
|
+
// No preview returned
|
|
66
|
+
if (!preview) {
|
|
67
|
+
return (_jsx("div", { className: cn("mx-auto max-w-sm", className), children: _jsx(ErrorCard, { message: "This invitation could not be found." }) }));
|
|
68
|
+
}
|
|
69
|
+
// Redemption success
|
|
70
|
+
if (accepted) {
|
|
71
|
+
const orgName = preview.organizationName || "the organization";
|
|
72
|
+
const roleName = iamRoleDisplayName(preview.role);
|
|
73
|
+
return (_jsx("div", { className: cn("mx-auto max-w-sm", className), children: _jsxs("div", { className: "rounded-lg border border-primary/30 bg-primary-subtle p-6 text-center", children: [_jsx(SuccessIcon, {}), _jsxs("h2", { className: "mt-3 text-base font-semibold text-foreground", children: ["You\u2019ve joined ", orgName] }), _jsxs("p", { className: "mt-1 text-sm text-muted-foreground", children: ["You now have ", _jsx("span", { className: "font-medium text-foreground", children: roleName }), " access."] })] }) }));
|
|
74
|
+
}
|
|
75
|
+
const orgName = preview.organizationName || "Unknown organization";
|
|
76
|
+
const orgLogo = preview.organizationLogoUrl;
|
|
77
|
+
const orgInitial = orgName.charAt(0).toUpperCase();
|
|
78
|
+
const roleName = iamRoleDisplayName(preview.role);
|
|
79
|
+
const expiresAt = preview.expiresAt ? timestampDate(preview.expiresAt) : null;
|
|
80
|
+
return (_jsx("div", { className: cn("mx-auto max-w-sm", className), children: _jsxs("div", { className: "rounded-lg border border-border bg-card p-6", children: [_jsxs("div", { className: "flex flex-col items-center text-center", children: [orgLogo ? (_jsx("img", { src: orgLogo, alt: `${orgName} logo`, className: "size-12 rounded-full object-cover" })) : (_jsx("div", { className: "flex size-12 items-center justify-center rounded-full bg-muted text-lg font-semibold text-muted-foreground", children: orgInitial })), _jsxs("h2", { className: "mt-3 text-base font-semibold text-foreground", children: ["Join ", orgName] }), preview.label && (_jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: preview.label }))] }), _jsxs("div", { className: "mt-4 flex items-center justify-center gap-3 text-xs text-muted-foreground", children: [_jsxs("span", { className: "inline-flex items-center gap-1", children: [_jsx(ShieldIcon, {}), roleName, " access"] }), expiresAt && (_jsxs(_Fragment, { children: [_jsx(Separator, {}), _jsx("span", { children: formatExpiry(expiresAt) })] }))] }), !preview.isValid && (_jsx(InvalidNotice, { reason: preview.invalidReason })), preview.isValid && (_jsx("div", { className: "mt-5", children: isAuthenticated ? (_jsxs(_Fragment, { children: [_jsxs("button", { type: "button", onClick: handleAccept, disabled: isRedeeming, className: cn("w-full inline-flex items-center justify-center gap-1.5 rounded-md px-4 py-2 text-sm font-medium", "bg-primary text-primary-foreground hover:bg-primary/90", "disabled:pointer-events-none disabled:opacity-50", "transition-colors"), children: [isRedeeming && _jsx(SpinnerIcon, {}), isRedeeming ? "Accepting\u2026" : "Accept Invitation"] }), redeemError && (_jsx("p", { className: "mt-2 text-center text-[0.65rem] text-destructive", role: "alert", children: getUserMessage(redeemError) }))] })) : (_jsx("button", { type: "button", onClick: onAuthRequired, className: cn("w-full inline-flex items-center justify-center gap-1.5 rounded-md px-4 py-2 text-sm font-medium", "bg-primary text-primary-foreground hover:bg-primary/90", "transition-colors"), children: "Sign in to accept" })) }))] }) }));
|
|
81
|
+
}
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
// InvalidNotice (internal)
|
|
84
|
+
// ---------------------------------------------------------------------------
|
|
85
|
+
function InvalidNotice({ reason }) {
|
|
86
|
+
return (_jsxs("div", { className: "mt-4 rounded-md bg-muted/50 px-3 py-2.5 text-center", children: [_jsx(WarningIcon, {}), _jsx("p", { className: "mt-1 text-xs text-muted-foreground", children: reason || "This invitation is no longer valid." })] }));
|
|
87
|
+
}
|
|
88
|
+
// ---------------------------------------------------------------------------
|
|
89
|
+
// ErrorCard (internal)
|
|
90
|
+
// ---------------------------------------------------------------------------
|
|
91
|
+
function ErrorCard({ message, onRetry, }) {
|
|
92
|
+
return (_jsxs("div", { className: "rounded-lg border border-destructive/30 bg-destructive/5 p-6 text-center", children: [_jsx("p", { className: "text-sm text-destructive", children: message }), onRetry && (_jsx("button", { type: "button", onClick: onRetry, className: cn("mt-3 inline-flex items-center rounded-md px-3 py-1.5 text-xs font-medium", "text-muted-foreground hover:text-foreground hover:bg-accent/50", "transition-colors"), children: "Try again" }))] }));
|
|
93
|
+
}
|
|
94
|
+
// ---------------------------------------------------------------------------
|
|
95
|
+
// LoadingSkeleton (internal)
|
|
96
|
+
// ---------------------------------------------------------------------------
|
|
97
|
+
function LoadingSkeleton() {
|
|
98
|
+
return (_jsxs("div", { className: "rounded-lg border border-border bg-card p-6 space-y-4", children: [_jsxs("div", { className: "flex flex-col items-center gap-3", children: [_jsx("div", { className: "size-12 rounded-full bg-muted/40 animate-pulse" }), _jsx("div", { className: "h-5 w-40 rounded bg-muted/40 animate-pulse" }), _jsx("div", { className: "h-4 w-56 rounded bg-muted/40 animate-pulse" })] }), _jsxs("div", { className: "flex justify-center gap-3", children: [_jsx("div", { className: "h-4 w-24 rounded bg-muted/40 animate-pulse" }), _jsx("div", { className: "h-4 w-24 rounded bg-muted/40 animate-pulse" })] }), _jsx("div", { className: "h-10 w-full rounded-md bg-muted/40 animate-pulse" })] }));
|
|
99
|
+
}
|
|
100
|
+
// ---------------------------------------------------------------------------
|
|
101
|
+
// Formatting helpers
|
|
102
|
+
// ---------------------------------------------------------------------------
|
|
103
|
+
function formatExpiry(date) {
|
|
104
|
+
const now = Date.now();
|
|
105
|
+
const diffMs = date.getTime() - now;
|
|
106
|
+
if (diffMs <= 0)
|
|
107
|
+
return "Expired";
|
|
108
|
+
const days = Math.ceil(diffMs / 86_400_000);
|
|
109
|
+
if (days === 1)
|
|
110
|
+
return "Expires tomorrow";
|
|
111
|
+
if (days <= 30)
|
|
112
|
+
return `Expires in ${days} days`;
|
|
113
|
+
return `Expires ${date.toLocaleDateString(undefined, {
|
|
114
|
+
month: "short",
|
|
115
|
+
day: "numeric",
|
|
116
|
+
year: "numeric",
|
|
117
|
+
})}`;
|
|
118
|
+
}
|
|
119
|
+
// ---------------------------------------------------------------------------
|
|
120
|
+
// Separator (internal)
|
|
121
|
+
// ---------------------------------------------------------------------------
|
|
122
|
+
function Separator() {
|
|
123
|
+
return (_jsx("span", { className: "text-border", "aria-hidden": "true", children: "\u00B7" }));
|
|
124
|
+
}
|
|
125
|
+
// ---------------------------------------------------------------------------
|
|
126
|
+
// Icons
|
|
127
|
+
// ---------------------------------------------------------------------------
|
|
128
|
+
function ShieldIcon() {
|
|
129
|
+
return (_jsx("svg", { width: "12", height: "12", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", className: "shrink-0", children: _jsx("path", { d: "M8 1.5l5.5 2v4.5c0 3.5-2.5 5.5-5.5 7-3-1.5-5.5-3.5-5.5-7V3.5L8 1.5z" }) }));
|
|
130
|
+
}
|
|
131
|
+
function WarningIcon() {
|
|
132
|
+
return (_jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", className: "mx-auto text-muted-foreground", children: [_jsx("circle", { cx: "8", cy: "8", r: "6" }), _jsx("path", { d: "M8 5v3.5M8 10.5v.5" })] }));
|
|
133
|
+
}
|
|
134
|
+
function SuccessIcon() {
|
|
135
|
+
return (_jsxs("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", className: "mx-auto text-primary", children: [_jsx("circle", { cx: "12", cy: "12", r: "10" }), _jsx("path", { d: "M8 12l2.5 2.5L16 9" })] }));
|
|
136
|
+
}
|
|
137
|
+
function SpinnerIcon() {
|
|
138
|
+
return (_jsx("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", className: "animate-spin", "aria-hidden": "true", children: _jsx("path", { d: "M8 2a6 6 0 1 0 6 6" }) }));
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=InvitationRedemption.js.map
|