@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,434 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useCallback, useState } from "react";
|
|
4
|
+
import { cn } from "@stigmer/theme";
|
|
5
|
+
import { getUserMessage, iamRoleDisplayName } from "@stigmer/sdk";
|
|
6
|
+
import type { Invitation } from "@stigmer/protos/ai/stigmer/iam/invitation/v1/api_pb";
|
|
7
|
+
import { timestampDate } from "@bufbuild/protobuf/wkt";
|
|
8
|
+
import { useInvitationPreview } from "./useInvitationPreview";
|
|
9
|
+
import { useRedeemInvitation } from "./useRedeemInvitation";
|
|
10
|
+
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
// Public API
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
|
|
15
|
+
/** Props for {@link InvitationRedemption}. */
|
|
16
|
+
export interface InvitationRedemptionProps {
|
|
17
|
+
/** The invitation token from the invite URL. */
|
|
18
|
+
readonly token: string;
|
|
19
|
+
/**
|
|
20
|
+
* Whether the current user is authenticated.
|
|
21
|
+
*
|
|
22
|
+
* When `false`, the component shows a "Sign in to accept" CTA
|
|
23
|
+
* instead of the accept button. When `true` or omitted, the
|
|
24
|
+
* accept button calls `redeem` directly.
|
|
25
|
+
*
|
|
26
|
+
* @default true
|
|
27
|
+
*/
|
|
28
|
+
readonly isAuthenticated?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Fired after the invitation is successfully redeemed.
|
|
31
|
+
*
|
|
32
|
+
* The returned {@link Invitation} contains the organization and
|
|
33
|
+
* role information needed for post-redemption navigation
|
|
34
|
+
* (e.g. redirecting to the org dashboard).
|
|
35
|
+
*/
|
|
36
|
+
readonly onAccepted?: (invitation: Invitation) => void;
|
|
37
|
+
/**
|
|
38
|
+
* Fired when an unauthenticated user clicks "Sign in to accept".
|
|
39
|
+
*
|
|
40
|
+
* The host application controls what "sign in" means — this
|
|
41
|
+
* callback typically triggers a redirect to the login page with
|
|
42
|
+
* a return URL back to the invite page.
|
|
43
|
+
*/
|
|
44
|
+
readonly onAuthRequired?: () => void;
|
|
45
|
+
/** Additional CSS class names for the root container. */
|
|
46
|
+
readonly className?: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Self-contained invite acceptance flow.
|
|
51
|
+
*
|
|
52
|
+
* Fetches the invitation preview by token (public endpoint, no auth
|
|
53
|
+
* required), displays the organization info and role being offered,
|
|
54
|
+
* and provides an accept button that redeems the invitation.
|
|
55
|
+
*
|
|
56
|
+
* Handles all states: loading, invalid (expired / revoked / fully
|
|
57
|
+
* redeemed), authentication required, redemption in flight,
|
|
58
|
+
* success, and error — with appropriate UX for each.
|
|
59
|
+
*
|
|
60
|
+
* The component is auth-agnostic: it delegates authentication
|
|
61
|
+
* decisions to the host application via `isAuthenticated` and
|
|
62
|
+
* `onAuthRequired` props. Platform builders who render this
|
|
63
|
+
* component only for authenticated users can ignore both props.
|
|
64
|
+
*
|
|
65
|
+
* All visual properties flow through `--stgm-*` design tokens.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```tsx
|
|
69
|
+
* <InvitationRedemption
|
|
70
|
+
* token={tokenFromUrl}
|
|
71
|
+
* onAccepted={(inv) => router.push("/dashboard")}
|
|
72
|
+
* />
|
|
73
|
+
*
|
|
74
|
+
* <InvitationRedemption
|
|
75
|
+
* token={tokenFromUrl}
|
|
76
|
+
* isAuthenticated={!!currentUser}
|
|
77
|
+
* onAccepted={(inv) => router.push(`/org/${inv.metadata?.org}`)}
|
|
78
|
+
* onAuthRequired={() => router.push(`/login?return=/invite/${token}`)}
|
|
79
|
+
* />
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
export function InvitationRedemption({
|
|
83
|
+
token,
|
|
84
|
+
isAuthenticated = true,
|
|
85
|
+
onAccepted,
|
|
86
|
+
onAuthRequired,
|
|
87
|
+
className,
|
|
88
|
+
}: InvitationRedemptionProps) {
|
|
89
|
+
const { preview, isLoading, error: fetchError, refetch } = useInvitationPreview(token);
|
|
90
|
+
const { redeem, isRedeeming, error: redeemError, clearError } = useRedeemInvitation();
|
|
91
|
+
const [accepted, setAccepted] = useState<Invitation | null>(null);
|
|
92
|
+
|
|
93
|
+
const handleAccept = useCallback(async () => {
|
|
94
|
+
clearError();
|
|
95
|
+
try {
|
|
96
|
+
const invitation = await redeem(token);
|
|
97
|
+
setAccepted(invitation);
|
|
98
|
+
onAccepted?.(invitation);
|
|
99
|
+
} catch {
|
|
100
|
+
// error state is managed by useRedeemInvitation
|
|
101
|
+
}
|
|
102
|
+
}, [token, redeem, clearError, onAccepted]);
|
|
103
|
+
|
|
104
|
+
// Loading state
|
|
105
|
+
if (isLoading) {
|
|
106
|
+
return (
|
|
107
|
+
<div
|
|
108
|
+
className={cn("mx-auto max-w-sm", className)}
|
|
109
|
+
aria-busy="true"
|
|
110
|
+
aria-label="Loading invitation"
|
|
111
|
+
>
|
|
112
|
+
<LoadingSkeleton />
|
|
113
|
+
</div>
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Fetch error
|
|
118
|
+
if (fetchError) {
|
|
119
|
+
return (
|
|
120
|
+
<div className={cn("mx-auto max-w-sm", className)}>
|
|
121
|
+
<ErrorCard
|
|
122
|
+
message={getUserMessage(fetchError)}
|
|
123
|
+
onRetry={refetch}
|
|
124
|
+
/>
|
|
125
|
+
</div>
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// No preview returned
|
|
130
|
+
if (!preview) {
|
|
131
|
+
return (
|
|
132
|
+
<div className={cn("mx-auto max-w-sm", className)}>
|
|
133
|
+
<ErrorCard message="This invitation could not be found." />
|
|
134
|
+
</div>
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Redemption success
|
|
139
|
+
if (accepted) {
|
|
140
|
+
const orgName = preview.organizationName || "the organization";
|
|
141
|
+
const roleName = iamRoleDisplayName(preview.role);
|
|
142
|
+
return (
|
|
143
|
+
<div className={cn("mx-auto max-w-sm", className)}>
|
|
144
|
+
<div className="rounded-lg border border-primary/30 bg-primary-subtle p-6 text-center">
|
|
145
|
+
<SuccessIcon />
|
|
146
|
+
<h2 className="mt-3 text-base font-semibold text-foreground">
|
|
147
|
+
You’ve joined {orgName}
|
|
148
|
+
</h2>
|
|
149
|
+
<p className="mt-1 text-sm text-muted-foreground">
|
|
150
|
+
You now have <span className="font-medium text-foreground">{roleName}</span> access.
|
|
151
|
+
</p>
|
|
152
|
+
</div>
|
|
153
|
+
</div>
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const orgName = preview.organizationName || "Unknown organization";
|
|
158
|
+
const orgLogo = preview.organizationLogoUrl;
|
|
159
|
+
const orgInitial = orgName.charAt(0).toUpperCase();
|
|
160
|
+
const roleName = iamRoleDisplayName(preview.role);
|
|
161
|
+
const expiresAt = preview.expiresAt ? timestampDate(preview.expiresAt) : null;
|
|
162
|
+
|
|
163
|
+
return (
|
|
164
|
+
<div className={cn("mx-auto max-w-sm", className)}>
|
|
165
|
+
<div className="rounded-lg border border-border bg-card p-6">
|
|
166
|
+
{/* Org identity */}
|
|
167
|
+
<div className="flex flex-col items-center text-center">
|
|
168
|
+
{orgLogo ? (
|
|
169
|
+
<img
|
|
170
|
+
src={orgLogo}
|
|
171
|
+
alt={`${orgName} logo`}
|
|
172
|
+
className="size-12 rounded-full object-cover"
|
|
173
|
+
/>
|
|
174
|
+
) : (
|
|
175
|
+
<div className="flex size-12 items-center justify-center rounded-full bg-muted text-lg font-semibold text-muted-foreground">
|
|
176
|
+
{orgInitial}
|
|
177
|
+
</div>
|
|
178
|
+
)}
|
|
179
|
+
|
|
180
|
+
<h2 className="mt-3 text-base font-semibold text-foreground">
|
|
181
|
+
Join {orgName}
|
|
182
|
+
</h2>
|
|
183
|
+
|
|
184
|
+
{preview.label && (
|
|
185
|
+
<p className="mt-1 text-sm text-muted-foreground">
|
|
186
|
+
{preview.label}
|
|
187
|
+
</p>
|
|
188
|
+
)}
|
|
189
|
+
</div>
|
|
190
|
+
|
|
191
|
+
{/* Role + expiry details */}
|
|
192
|
+
<div className="mt-4 flex items-center justify-center gap-3 text-xs text-muted-foreground">
|
|
193
|
+
<span className="inline-flex items-center gap-1">
|
|
194
|
+
<ShieldIcon />
|
|
195
|
+
{roleName} access
|
|
196
|
+
</span>
|
|
197
|
+
{expiresAt && (
|
|
198
|
+
<>
|
|
199
|
+
<Separator />
|
|
200
|
+
<span>{formatExpiry(expiresAt)}</span>
|
|
201
|
+
</>
|
|
202
|
+
)}
|
|
203
|
+
</div>
|
|
204
|
+
|
|
205
|
+
{/* Invalid state */}
|
|
206
|
+
{!preview.isValid && (
|
|
207
|
+
<InvalidNotice reason={preview.invalidReason} />
|
|
208
|
+
)}
|
|
209
|
+
|
|
210
|
+
{/* Action area */}
|
|
211
|
+
{preview.isValid && (
|
|
212
|
+
<div className="mt-5">
|
|
213
|
+
{isAuthenticated ? (
|
|
214
|
+
<>
|
|
215
|
+
<button
|
|
216
|
+
type="button"
|
|
217
|
+
onClick={handleAccept}
|
|
218
|
+
disabled={isRedeeming}
|
|
219
|
+
className={cn(
|
|
220
|
+
"w-full inline-flex items-center justify-center gap-1.5 rounded-md px-4 py-2 text-sm font-medium",
|
|
221
|
+
"bg-primary text-primary-foreground hover:bg-primary/90",
|
|
222
|
+
"disabled:pointer-events-none disabled:opacity-50",
|
|
223
|
+
"transition-colors",
|
|
224
|
+
)}
|
|
225
|
+
>
|
|
226
|
+
{isRedeeming && <SpinnerIcon />}
|
|
227
|
+
{isRedeeming ? "Accepting\u2026" : "Accept Invitation"}
|
|
228
|
+
</button>
|
|
229
|
+
{redeemError && (
|
|
230
|
+
<p className="mt-2 text-center text-[0.65rem] text-destructive" role="alert">
|
|
231
|
+
{getUserMessage(redeemError)}
|
|
232
|
+
</p>
|
|
233
|
+
)}
|
|
234
|
+
</>
|
|
235
|
+
) : (
|
|
236
|
+
<button
|
|
237
|
+
type="button"
|
|
238
|
+
onClick={onAuthRequired}
|
|
239
|
+
className={cn(
|
|
240
|
+
"w-full inline-flex items-center justify-center gap-1.5 rounded-md px-4 py-2 text-sm font-medium",
|
|
241
|
+
"bg-primary text-primary-foreground hover:bg-primary/90",
|
|
242
|
+
"transition-colors",
|
|
243
|
+
)}
|
|
244
|
+
>
|
|
245
|
+
Sign in to accept
|
|
246
|
+
</button>
|
|
247
|
+
)}
|
|
248
|
+
</div>
|
|
249
|
+
)}
|
|
250
|
+
</div>
|
|
251
|
+
</div>
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// ---------------------------------------------------------------------------
|
|
256
|
+
// InvalidNotice (internal)
|
|
257
|
+
// ---------------------------------------------------------------------------
|
|
258
|
+
|
|
259
|
+
function InvalidNotice({ reason }: { reason: string }) {
|
|
260
|
+
return (
|
|
261
|
+
<div className="mt-4 rounded-md bg-muted/50 px-3 py-2.5 text-center">
|
|
262
|
+
<WarningIcon />
|
|
263
|
+
<p className="mt-1 text-xs text-muted-foreground">
|
|
264
|
+
{reason || "This invitation is no longer valid."}
|
|
265
|
+
</p>
|
|
266
|
+
</div>
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// ---------------------------------------------------------------------------
|
|
271
|
+
// ErrorCard (internal)
|
|
272
|
+
// ---------------------------------------------------------------------------
|
|
273
|
+
|
|
274
|
+
function ErrorCard({
|
|
275
|
+
message,
|
|
276
|
+
onRetry,
|
|
277
|
+
}: {
|
|
278
|
+
message: string;
|
|
279
|
+
onRetry?: () => void;
|
|
280
|
+
}) {
|
|
281
|
+
return (
|
|
282
|
+
<div className="rounded-lg border border-destructive/30 bg-destructive/5 p-6 text-center">
|
|
283
|
+
<p className="text-sm text-destructive">{message}</p>
|
|
284
|
+
{onRetry && (
|
|
285
|
+
<button
|
|
286
|
+
type="button"
|
|
287
|
+
onClick={onRetry}
|
|
288
|
+
className={cn(
|
|
289
|
+
"mt-3 inline-flex items-center rounded-md px-3 py-1.5 text-xs font-medium",
|
|
290
|
+
"text-muted-foreground hover:text-foreground hover:bg-accent/50",
|
|
291
|
+
"transition-colors",
|
|
292
|
+
)}
|
|
293
|
+
>
|
|
294
|
+
Try again
|
|
295
|
+
</button>
|
|
296
|
+
)}
|
|
297
|
+
</div>
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// ---------------------------------------------------------------------------
|
|
302
|
+
// LoadingSkeleton (internal)
|
|
303
|
+
// ---------------------------------------------------------------------------
|
|
304
|
+
|
|
305
|
+
function LoadingSkeleton() {
|
|
306
|
+
return (
|
|
307
|
+
<div className="rounded-lg border border-border bg-card p-6 space-y-4">
|
|
308
|
+
<div className="flex flex-col items-center gap-3">
|
|
309
|
+
<div className="size-12 rounded-full bg-muted/40 animate-pulse" />
|
|
310
|
+
<div className="h-5 w-40 rounded bg-muted/40 animate-pulse" />
|
|
311
|
+
<div className="h-4 w-56 rounded bg-muted/40 animate-pulse" />
|
|
312
|
+
</div>
|
|
313
|
+
<div className="flex justify-center gap-3">
|
|
314
|
+
<div className="h-4 w-24 rounded bg-muted/40 animate-pulse" />
|
|
315
|
+
<div className="h-4 w-24 rounded bg-muted/40 animate-pulse" />
|
|
316
|
+
</div>
|
|
317
|
+
<div className="h-10 w-full rounded-md bg-muted/40 animate-pulse" />
|
|
318
|
+
</div>
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// ---------------------------------------------------------------------------
|
|
323
|
+
// Formatting helpers
|
|
324
|
+
// ---------------------------------------------------------------------------
|
|
325
|
+
|
|
326
|
+
function formatExpiry(date: Date): string {
|
|
327
|
+
const now = Date.now();
|
|
328
|
+
const diffMs = date.getTime() - now;
|
|
329
|
+
|
|
330
|
+
if (diffMs <= 0) return "Expired";
|
|
331
|
+
|
|
332
|
+
const days = Math.ceil(diffMs / 86_400_000);
|
|
333
|
+
if (days === 1) return "Expires tomorrow";
|
|
334
|
+
if (days <= 30) return `Expires in ${days} days`;
|
|
335
|
+
|
|
336
|
+
return `Expires ${date.toLocaleDateString(undefined, {
|
|
337
|
+
month: "short",
|
|
338
|
+
day: "numeric",
|
|
339
|
+
year: "numeric",
|
|
340
|
+
})}`;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// ---------------------------------------------------------------------------
|
|
344
|
+
// Separator (internal)
|
|
345
|
+
// ---------------------------------------------------------------------------
|
|
346
|
+
|
|
347
|
+
function Separator() {
|
|
348
|
+
return (
|
|
349
|
+
<span className="text-border" aria-hidden="true">
|
|
350
|
+
·
|
|
351
|
+
</span>
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// ---------------------------------------------------------------------------
|
|
356
|
+
// Icons
|
|
357
|
+
// ---------------------------------------------------------------------------
|
|
358
|
+
|
|
359
|
+
function ShieldIcon() {
|
|
360
|
+
return (
|
|
361
|
+
<svg
|
|
362
|
+
width="12"
|
|
363
|
+
height="12"
|
|
364
|
+
viewBox="0 0 16 16"
|
|
365
|
+
fill="none"
|
|
366
|
+
stroke="currentColor"
|
|
367
|
+
strokeWidth="1.5"
|
|
368
|
+
strokeLinecap="round"
|
|
369
|
+
strokeLinejoin="round"
|
|
370
|
+
aria-hidden="true"
|
|
371
|
+
className="shrink-0"
|
|
372
|
+
>
|
|
373
|
+
<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" />
|
|
374
|
+
</svg>
|
|
375
|
+
);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
function WarningIcon() {
|
|
379
|
+
return (
|
|
380
|
+
<svg
|
|
381
|
+
width="16"
|
|
382
|
+
height="16"
|
|
383
|
+
viewBox="0 0 16 16"
|
|
384
|
+
fill="none"
|
|
385
|
+
stroke="currentColor"
|
|
386
|
+
strokeWidth="1.5"
|
|
387
|
+
strokeLinecap="round"
|
|
388
|
+
strokeLinejoin="round"
|
|
389
|
+
aria-hidden="true"
|
|
390
|
+
className="mx-auto text-muted-foreground"
|
|
391
|
+
>
|
|
392
|
+
<circle cx="8" cy="8" r="6" />
|
|
393
|
+
<path d="M8 5v3.5M8 10.5v.5" />
|
|
394
|
+
</svg>
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
function SuccessIcon() {
|
|
399
|
+
return (
|
|
400
|
+
<svg
|
|
401
|
+
width="24"
|
|
402
|
+
height="24"
|
|
403
|
+
viewBox="0 0 24 24"
|
|
404
|
+
fill="none"
|
|
405
|
+
stroke="currentColor"
|
|
406
|
+
strokeWidth="2"
|
|
407
|
+
strokeLinecap="round"
|
|
408
|
+
strokeLinejoin="round"
|
|
409
|
+
aria-hidden="true"
|
|
410
|
+
className="mx-auto text-primary"
|
|
411
|
+
>
|
|
412
|
+
<circle cx="12" cy="12" r="10" />
|
|
413
|
+
<path d="M8 12l2.5 2.5L16 9" />
|
|
414
|
+
</svg>
|
|
415
|
+
);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
function SpinnerIcon() {
|
|
419
|
+
return (
|
|
420
|
+
<svg
|
|
421
|
+
width="14"
|
|
422
|
+
height="14"
|
|
423
|
+
viewBox="0 0 16 16"
|
|
424
|
+
fill="none"
|
|
425
|
+
stroke="currentColor"
|
|
426
|
+
strokeWidth="2"
|
|
427
|
+
strokeLinecap="round"
|
|
428
|
+
className="animate-spin"
|
|
429
|
+
aria-hidden="true"
|
|
430
|
+
>
|
|
431
|
+
<path d="M8 2a6 6 0 1 0 6 6" />
|
|
432
|
+
</svg>
|
|
433
|
+
);
|
|
434
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export { useOrgInvitations } from "./useOrgInvitations";
|
|
2
|
+
export type { UseOrgInvitationsReturn } from "./useOrgInvitations";
|
|
3
|
+
export { useCreateInvitation } from "./useCreateInvitation";
|
|
4
|
+
export type { UseCreateInvitationReturn } from "./useCreateInvitation";
|
|
5
|
+
export { useRevokeInvitation } from "./useRevokeInvitation";
|
|
6
|
+
export type { UseRevokeInvitationReturn } from "./useRevokeInvitation";
|
|
7
|
+
export { useInvitationPreview } from "./useInvitationPreview";
|
|
8
|
+
export type { UseInvitationPreviewReturn } from "./useInvitationPreview";
|
|
9
|
+
export { useRedeemInvitation } from "./useRedeemInvitation";
|
|
10
|
+
export type { UseRedeemInvitationReturn } from "./useRedeemInvitation";
|
|
11
|
+
export { InvitationCreatedAlert } from "./InvitationCreatedAlert";
|
|
12
|
+
export type { InvitationCreatedAlertProps } from "./InvitationCreatedAlert";
|
|
13
|
+
export { InvitationManager } from "./InvitationManager";
|
|
14
|
+
export type { InvitationManagerProps } from "./InvitationManager";
|
|
15
|
+
export { InvitationRedemption } from "./InvitationRedemption";
|
|
16
|
+
export type { InvitationRedemptionProps } from "./InvitationRedemption";
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useCallback, useState } from "react";
|
|
4
|
+
import type { InvitationInput } from "@stigmer/sdk";
|
|
5
|
+
import type { Invitation } from "@stigmer/protos/ai/stigmer/iam/invitation/v1/api_pb";
|
|
6
|
+
import { useStigmer } from "../hooks";
|
|
7
|
+
import { toError } from "../internal/toError";
|
|
8
|
+
|
|
9
|
+
/** Return value of {@link useCreateInvitation}. */
|
|
10
|
+
export interface UseCreateInvitationReturn {
|
|
11
|
+
/**
|
|
12
|
+
* Create an invitation link for an organization.
|
|
13
|
+
*
|
|
14
|
+
* Resolves with the server-created {@link Invitation} including the
|
|
15
|
+
* generated token in `status.token`. Callers must capture this token
|
|
16
|
+
* to construct the invite URL — it is always available via `get` and
|
|
17
|
+
* `listByOrg`, but surfacing it immediately after creation is the
|
|
18
|
+
* expected UX flow.
|
|
19
|
+
*/
|
|
20
|
+
readonly create: (input: InvitationInput) => Promise<Invitation>;
|
|
21
|
+
/** `true` while the create request is in flight. */
|
|
22
|
+
readonly isCreating: boolean;
|
|
23
|
+
/** Error from the last failed create, or `null` when healthy. */
|
|
24
|
+
readonly error: Error | null;
|
|
25
|
+
/** Reset `error` to `null`. */
|
|
26
|
+
readonly clearError: () => void;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Behavior hook that wraps `invitation.create()` with loading and
|
|
31
|
+
* error state.
|
|
32
|
+
*
|
|
33
|
+
* Creates an invitation resource. The caller provides an
|
|
34
|
+
* {@link InvitationInput} with `name`, `org`, `role`, `expiresAt`,
|
|
35
|
+
* and optionally `maxRedemptions` and `label`.
|
|
36
|
+
*
|
|
37
|
+
* The returned {@link Invitation} contains the server-generated token
|
|
38
|
+
* in `status?.token`. Use this to build the invite URL:
|
|
39
|
+
* `https://<host>/invite/<token>`.
|
|
40
|
+
*
|
|
41
|
+
* Creating an invitation requires `can_grant_access` on the
|
|
42
|
+
* organization — typically limited to admins and owners.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```tsx
|
|
46
|
+
* const { create, isCreating, error } = useCreateInvitation();
|
|
47
|
+
*
|
|
48
|
+
* const invitation = await create({
|
|
49
|
+
* name: "engineering-link",
|
|
50
|
+
* org: "acme",
|
|
51
|
+
* role: IamRole.VIEWER,
|
|
52
|
+
* expiresAt: new Date(Date.now() + 30 * 86_400_000),
|
|
53
|
+
* label: "Engineering team invite",
|
|
54
|
+
* });
|
|
55
|
+
* const inviteUrl = `${window.location.origin}/invite/${invitation.status?.token}`;
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export function useCreateInvitation(): UseCreateInvitationReturn {
|
|
59
|
+
const stigmer = useStigmer();
|
|
60
|
+
const [isCreating, setIsCreating] = useState(false);
|
|
61
|
+
const [error, setError] = useState<Error | null>(null);
|
|
62
|
+
|
|
63
|
+
const clearError = useCallback(() => setError(null), []);
|
|
64
|
+
|
|
65
|
+
const create = useCallback(
|
|
66
|
+
async (input: InvitationInput): Promise<Invitation> => {
|
|
67
|
+
setIsCreating(true);
|
|
68
|
+
setError(null);
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
return await stigmer.invitation.create(input);
|
|
72
|
+
} catch (err) {
|
|
73
|
+
setError(toError(err));
|
|
74
|
+
throw err;
|
|
75
|
+
} finally {
|
|
76
|
+
setIsCreating(false);
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
[stigmer],
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
return { create, isCreating, error, clearError };
|
|
83
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useCallback, useEffect, useState } from "react";
|
|
4
|
+
import { create } from "@bufbuild/protobuf";
|
|
5
|
+
import type { InvitationPreview } from "@stigmer/protos/ai/stigmer/iam/invitation/v1/io_pb";
|
|
6
|
+
import { InvitationTokenInputSchema } from "@stigmer/protos/ai/stigmer/iam/invitation/v1/io_pb";
|
|
7
|
+
import { useStigmer } from "../hooks";
|
|
8
|
+
import { toError } from "../internal/toError";
|
|
9
|
+
|
|
10
|
+
/** Return value of {@link useInvitationPreview}. */
|
|
11
|
+
export interface UseInvitationPreviewReturn {
|
|
12
|
+
/** The invitation preview, or `null` while loading or on error. */
|
|
13
|
+
readonly preview: InvitationPreview | null;
|
|
14
|
+
/** `true` while the initial fetch or a refetch is in flight. */
|
|
15
|
+
readonly isLoading: boolean;
|
|
16
|
+
/** Error from the last failed request, or `null` when healthy. */
|
|
17
|
+
readonly error: Error | null;
|
|
18
|
+
/** Discard cached data and re-fetch the preview from the server. */
|
|
19
|
+
readonly refetch: () => void;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Data hook that fetches an {@link InvitationPreview} by its
|
|
24
|
+
* shareable token.
|
|
25
|
+
*
|
|
26
|
+
* Pass `null` to skip fetching (stable no-op). When the `token`
|
|
27
|
+
* changes, the previous in-flight request is discarded and a fresh
|
|
28
|
+
* fetch begins.
|
|
29
|
+
*
|
|
30
|
+
* This hook calls the `getByToken` endpoint, which is **public** —
|
|
31
|
+
* it requires no authentication. The server returns a safe projection
|
|
32
|
+
* containing only the information needed to render the invite
|
|
33
|
+
* acceptance page: organization name/logo, the role being offered,
|
|
34
|
+
* expiry, and whether the invitation is still valid.
|
|
35
|
+
*
|
|
36
|
+
* Check `preview.isValid` before offering the redemption action.
|
|
37
|
+
* When `false`, `preview.invalidReason` contains a human-readable
|
|
38
|
+
* explanation (expired, revoked, or fully redeemed).
|
|
39
|
+
*
|
|
40
|
+
* **Note**: Although authentication is not required by the server,
|
|
41
|
+
* the hook still requires a `StigmerProvider` ancestor because it
|
|
42
|
+
* needs the transport configuration (API base URL) to make the
|
|
43
|
+
* request.
|
|
44
|
+
*
|
|
45
|
+
* @param token - The invitation token from the invite URL, or `null`
|
|
46
|
+
* to skip fetching.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```tsx
|
|
50
|
+
* const { preview, isLoading, error } = useInvitationPreview(token);
|
|
51
|
+
*
|
|
52
|
+
* if (isLoading) return <Spinner />;
|
|
53
|
+
* if (!preview) return <NotFound />;
|
|
54
|
+
* if (!preview.isValid) return <Expired reason={preview.invalidReason} />;
|
|
55
|
+
*
|
|
56
|
+
* return <p>Join {preview.organizationName} as {preview.role}</p>;
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
export function useInvitationPreview(
|
|
60
|
+
token: string | null,
|
|
61
|
+
): UseInvitationPreviewReturn {
|
|
62
|
+
const stigmer = useStigmer();
|
|
63
|
+
const [preview, setPreview] = useState<InvitationPreview | null>(null);
|
|
64
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
65
|
+
const [error, setError] = useState<Error | null>(null);
|
|
66
|
+
const [fetchKey, setFetchKey] = useState(0);
|
|
67
|
+
|
|
68
|
+
const refetch = useCallback(() => setFetchKey((k) => k + 1), []);
|
|
69
|
+
|
|
70
|
+
useEffect(() => {
|
|
71
|
+
if (!token) {
|
|
72
|
+
setPreview(null);
|
|
73
|
+
setIsLoading(false);
|
|
74
|
+
setError(null);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const cancelled = { current: false };
|
|
79
|
+
setIsLoading(true);
|
|
80
|
+
setError(null);
|
|
81
|
+
|
|
82
|
+
stigmer.invitation
|
|
83
|
+
.getByToken(create(InvitationTokenInputSchema, { token }))
|
|
84
|
+
.then(
|
|
85
|
+
(result) => {
|
|
86
|
+
if (cancelled.current) return;
|
|
87
|
+
setPreview(result);
|
|
88
|
+
setIsLoading(false);
|
|
89
|
+
},
|
|
90
|
+
(err) => {
|
|
91
|
+
if (cancelled.current) return;
|
|
92
|
+
setError(toError(err));
|
|
93
|
+
setIsLoading(false);
|
|
94
|
+
},
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
return () => {
|
|
98
|
+
cancelled.current = true;
|
|
99
|
+
};
|
|
100
|
+
}, [token, stigmer, fetchKey]);
|
|
101
|
+
|
|
102
|
+
return { preview, isLoading, error, refetch };
|
|
103
|
+
}
|