@ploykit/ui 0.1.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +183 -23
- package/dist/AppProviders.d.ts +15 -0
- package/dist/AppProviders.js +15 -0
- package/dist/components/ConfirmDialog.js +8 -2
- package/dist/components/CronInput.js +2 -2
- package/dist/components/DataTable.d.ts +12 -3
- package/dist/components/DataTable.js +7 -3
- package/dist/components/ErrorBoundary.js +1 -1
- package/dist/components/ImpersonationBanner.js +1 -1
- package/dist/components/NotificationBell.js +5 -5
- package/dist/components/OnboardingChecklist.js +3 -3
- package/dist/components/Page.js +1 -1
- package/dist/components/ReauthDialog.d.ts +15 -0
- package/dist/components/ReauthDialog.js +42 -0
- package/dist/components/SecretModal.d.ts +8 -1
- package/dist/components/SecretModal.js +6 -3
- package/dist/components/SettingsCard.js +2 -2
- package/dist/components/SiteBannerLayer.js +1 -1
- package/dist/components/StatusBadge.d.ts +4 -0
- package/dist/components/StatusBadge.js +7 -0
- package/dist/components/UserMenu.js +2 -2
- package/dist/components/WorkspaceSwitcher.js +4 -4
- package/dist/components/ui/alert-dialog.d.ts +2 -2
- package/dist/components/ui/alert-dialog.js +10 -9
- package/dist/components/ui/avatar.js +3 -2
- package/dist/components/ui/badge.d.ts +7 -0
- package/dist/components/ui/badge.js +33 -0
- package/dist/components/ui/breadcrumb.js +7 -7
- package/dist/components/ui/button.d.ts +8 -0
- package/dist/components/ui/button.js +34 -0
- package/dist/components/ui/card.d.ts +2 -4
- package/dist/components/ui/card.js +7 -7
- package/dist/components/ui/checkbox.js +3 -2
- package/dist/components/ui/dialog.d.ts +22 -14
- package/dist/components/ui/dialog.js +40 -25
- package/dist/components/ui/dropdown-menu.js +50 -0
- package/dist/components/ui/empty.d.ts +7 -9
- package/dist/components/ui/empty.js +6 -9
- package/dist/components/ui/field.js +10 -9
- package/dist/components/ui/input.d.ts +3 -0
- package/dist/components/ui/input.js +7 -0
- package/dist/components/ui/popover.js +3 -2
- package/dist/components/ui/progress.js +2 -1
- package/dist/components/ui/select.d.ts +20 -1
- package/dist/components/ui/select.js +28 -7
- package/dist/components/ui/separator.js +1 -0
- package/dist/components/ui/sheet.d.ts +9 -1
- package/dist/components/ui/sheet.js +11 -4
- package/dist/components/ui/sidebar.d.ts +2 -2
- package/dist/components/ui/sidebar.js +25 -34
- package/dist/components/ui/skeleton.d.ts +1 -2
- package/dist/components/ui/switch.js +1 -1
- package/dist/components/ui/tabs.js +3 -3
- package/dist/components/ui/textarea.d.ts +9 -0
- package/dist/components/ui/textarea.js +12 -0
- package/dist/components/ui/tooltip.js +1 -1
- package/dist/index.d.ts +10 -40
- package/dist/index.js +10 -26
- package/dist/layouts/AppShell.d.ts +1 -1
- package/dist/layouts/AppShell.js +23 -1
- package/dist/layouts/SettingsShell.d.ts +1 -1
- package/dist/layouts/SettingsShell.js +3 -3
- package/dist/pages/LandingPage.js +1 -1
- package/dist/pages/LoginPage.js +7 -7
- package/dist/pages/account/NotificationPreferencesPage.js +2 -2
- package/dist/pages/account/ProfileSettingsPage.js +7 -7
- package/dist/pages/account/SecuritySettingsPage.js +8 -8
- package/dist/pages/account/TokensPage.js +4 -4
- package/dist/pages/admin/AdminSettingsPage.js +5 -5
- package/dist/pages/admin/AdminShell.js +2 -2
- package/dist/pages/admin/AuditPage.js +3 -3
- package/dist/pages/admin/OrdersPage.js +4 -3
- package/dist/pages/admin/OverviewPage.js +4 -4
- package/dist/pages/admin/SSOPage.js +3 -3
- package/dist/pages/admin/UserDetailPage.js +6 -5
- package/dist/pages/admin/UsersPage.js +7 -6
- package/dist/pages/admin/WebhookDeliveriesPage.js +4 -3
- package/dist/pages/admin/WorkspaceDetailPage.js +5 -5
- package/dist/pages/admin/WorkspacesPage.js +4 -4
- package/dist/pages/admin/shared.js +1 -1
- package/dist/pages/auth/ForgotPasswordPage.js +3 -3
- package/dist/pages/auth/InviteAcceptPage.js +4 -4
- package/dist/pages/auth/RegisterPage.js +6 -6
- package/dist/pages/auth/ResetPasswordPage.js +4 -4
- package/dist/pages/auth/VerifyEmailPage.js +4 -4
- package/dist/pages/workspace/BillingPage.js +8 -7
- package/dist/pages/workspace/BillingSuccessPage.js +3 -3
- package/dist/pages/workspace/MembersPage.js +7 -6
- package/dist/pages/workspace/RolePermissionsPage.d.ts +3 -0
- package/dist/pages/workspace/RolePermissionsPage.js +118 -0
- package/dist/pages/workspace/SchedulesPage.js +5 -5
- package/dist/pages/workspace/UsagePage.d.ts +1 -1
- package/dist/pages/workspace/UsagePage.js +2 -2
- package/dist/pages/workspace/WebhooksPage.js +9 -9
- package/dist/pages/workspace/WorkspaceAuditPage.js +3 -3
- package/dist/pages/workspace/WorkspaceGeneralPage.js +7 -7
- package/package.json +9 -5
- package/dist/components/ui/Badge.d.ts +0 -13
- package/dist/components/ui/Badge.js +0 -21
- package/dist/components/ui/Button.d.ts +0 -10
- package/dist/components/ui/Button.js +0 -33
- package/dist/components/ui/Input.d.ts +0 -3
- package/dist/components/ui/Input.js +0 -10
- package/dist/components/ui/menu.js +0 -50
- package/dist/hooks/useApi.d.ts +0 -10
- package/dist/hooks/useApi.js +0 -11
- package/dist/hooks/useAudit.d.ts +0 -39
- package/dist/hooks/useAudit.js +0 -55
- package/dist/hooks/useAuth.d.ts +0 -1
- package/dist/hooks/useAuth.js +0 -4
- package/dist/hooks/useBilling.d.ts +0 -44
- package/dist/hooks/useBilling.js +0 -64
- package/dist/hooks/useLogin.d.ts +0 -10
- package/dist/hooks/useLogin.js +0 -39
- package/dist/hooks/useMembers.d.ts +0 -125
- package/dist/hooks/useMembers.js +0 -127
- package/dist/hooks/useNotificationPrefs.d.ts +0 -20
- package/dist/hooks/useNotificationPrefs.js +0 -42
- package/dist/hooks/usePasswordReset.d.ts +0 -5
- package/dist/hooks/usePasswordReset.js +0 -12
- package/dist/hooks/useSEO.d.ts +0 -6
- package/dist/hooks/useSEO.js +0 -14
- package/dist/hooks/useSessions.d.ts +0 -20
- package/dist/hooks/useSessions.js +0 -38
- package/dist/hooks/useSiteConfig.d.ts +0 -12
- package/dist/hooks/useSiteConfig.js +0 -11
- package/dist/hooks/useTokens.d.ts +0 -36
- package/dist/hooks/useTokens.js +0 -35
- package/dist/hooks/useUsage.d.ts +0 -20
- package/dist/hooks/useUsage.js +0 -21
- package/dist/hooks/useWorkspace.d.ts +0 -26
- package/dist/hooks/useWorkspace.js +0 -32
- package/dist/hooks/useZodForm.d.ts +0 -6
- package/dist/hooks/useZodForm.js +0 -6
- package/dist/hooks/ws.d.ts +0 -4
- package/dist/hooks/ws.js +0 -21
- package/dist/lib/perm.d.ts +0 -2
- package/dist/lib/perm.js +0 -7
- package/dist/lib/ws-query-bridge.d.ts +0 -7
- package/dist/lib/ws-query-bridge.js +0 -35
- package/dist/provider/PloykitProvider.d.ts +0 -50
- package/dist/provider/PloykitProvider.js +0 -240
- package/dist/realtime.d.ts +0 -3
- package/dist/realtime.js +0 -11
- /package/dist/components/ui/{menu.d.ts → dropdown-menu.d.ts} +0 -0
|
@@ -10,11 +10,12 @@ import { PageEmpty, PageError, PageHeader } from '../../components/Page';
|
|
|
10
10
|
import { ImpactConfirmation } from '../../components/SecretModal';
|
|
11
11
|
import { SettingsCard } from '../../components/SettingsCard';
|
|
12
12
|
import { toast } from '../../components/toast';
|
|
13
|
-
import { Badge
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
13
|
+
import { Badge } from '../../components/ui/badge';
|
|
14
|
+
import { StatusBadge } from '../../components/StatusBadge';
|
|
15
|
+
import { Button } from '../../components/ui/button';
|
|
16
|
+
import { Input } from '../../components/ui/input';
|
|
17
|
+
import { useApi, ApiError } from '@ploykit/hooks';
|
|
18
|
+
import { useAuth } from '@ploykit/hooks';
|
|
18
19
|
import { apiErrorMessage } from '../../lib/api-error';
|
|
19
20
|
import { formatDate, formatDateTime, shortID } from '../../lib/utils';
|
|
20
21
|
import { adminError } from './shared';
|
|
@@ -8,13 +8,14 @@ import { DataTable } from '../../components/DataTable';
|
|
|
8
8
|
import { PageEmpty, PageError, PageHeader } from '../../components/Page';
|
|
9
9
|
import { ImpactConfirmation } from '../../components/SecretModal';
|
|
10
10
|
import { toast } from '../../components/toast';
|
|
11
|
-
import { Badge
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
11
|
+
import { Badge } from '../../components/ui/badge';
|
|
12
|
+
import { StatusBadge } from '../../components/StatusBadge';
|
|
13
|
+
import { Button } from '../../components/ui/button';
|
|
14
|
+
import { Input } from '../../components/ui/input';
|
|
15
|
+
import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, } from '../../components/ui/dropdown-menu';
|
|
15
16
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '../../components/ui/select';
|
|
16
|
-
import { useApi } from '
|
|
17
|
-
import { useAuth } from '
|
|
17
|
+
import { useApi } from '@ploykit/hooks';
|
|
18
|
+
import { useAuth } from '@ploykit/hooks';
|
|
18
19
|
import { formatDate, formatDateTime } from '../../lib/utils';
|
|
19
20
|
import { ADMIN_PAGE_SIZE, adminError, adminListQuery, } from './shared';
|
|
20
21
|
const STATUS_OPTIONS = [
|
|
@@ -5,10 +5,11 @@ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
|
|
5
5
|
import { DataTable } from '../../components/DataTable';
|
|
6
6
|
import { PageEmpty, PageError, PageHeader } from '../../components/Page';
|
|
7
7
|
import { toast } from '../../components/toast';
|
|
8
|
-
import { Badge
|
|
9
|
-
import {
|
|
8
|
+
import { Badge } from '../../components/ui/badge';
|
|
9
|
+
import { StatusBadge } from '../../components/StatusBadge';
|
|
10
|
+
import { Button } from '../../components/ui/button';
|
|
10
11
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '../../components/ui/select';
|
|
11
|
-
import { useApi } from '
|
|
12
|
+
import { useApi } from '@ploykit/hooks';
|
|
12
13
|
import { formatDateTime, shortID, statusLabel } from '../../lib/utils';
|
|
13
14
|
import { ADMIN_PAGE_SIZE, adminError, adminListQuery, } from './shared';
|
|
14
15
|
const DELIVERY_STATUSES = ['pending', 'delivered', 'dead'];
|
|
@@ -10,12 +10,12 @@ import { PageEmpty, PageError, PageHeader } from '../../components/Page';
|
|
|
10
10
|
import { ImpactConfirmation } from '../../components/SecretModal';
|
|
11
11
|
import { SettingsCard } from '../../components/SettingsCard';
|
|
12
12
|
import { toast } from '../../components/toast';
|
|
13
|
-
import { Badge } from '../../components/ui/
|
|
14
|
-
import { Button } from '../../components/ui/
|
|
15
|
-
import { Input } from '../../components/ui/
|
|
13
|
+
import { Badge } from '../../components/ui/badge';
|
|
14
|
+
import { Button } from '../../components/ui/button';
|
|
15
|
+
import { Input } from '../../components/ui/input';
|
|
16
16
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '../../components/ui/select';
|
|
17
|
-
import { useApi } from '
|
|
18
|
-
import { useAuth } from '
|
|
17
|
+
import { useApi } from '@ploykit/hooks';
|
|
18
|
+
import { useAuth } from '@ploykit/hooks';
|
|
19
19
|
import { apiErrorMessage } from '../../lib/api-error';
|
|
20
20
|
import { formatDate, formatDateTime, shortID } from '../../lib/utils';
|
|
21
21
|
import { adminError } from './shared';
|
|
@@ -5,11 +5,11 @@ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
|
|
5
5
|
import { DataTable } from '../../components/DataTable';
|
|
6
6
|
import { PageEmpty, PageError, PageHeader } from '../../components/Page';
|
|
7
7
|
import { toast } from '../../components/toast';
|
|
8
|
-
import { Badge } from '../../components/ui/
|
|
9
|
-
import { Button } from '../../components/ui/
|
|
10
|
-
import { Input } from '../../components/ui/
|
|
8
|
+
import { Badge } from '../../components/ui/badge';
|
|
9
|
+
import { Button } from '../../components/ui/button';
|
|
10
|
+
import { Input } from '../../components/ui/input';
|
|
11
11
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '../../components/ui/select';
|
|
12
|
-
import { useApi } from '
|
|
12
|
+
import { useApi } from '@ploykit/hooks';
|
|
13
13
|
import { formatDate } from '../../lib/utils';
|
|
14
14
|
import { ADMIN_PAGE_SIZE, adminError, adminListQuery, } from './shared';
|
|
15
15
|
const FALLBACK_PLAN_CODES = ['free'];
|
|
@@ -2,9 +2,9 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
2
2
|
import { useState } from 'react';
|
|
3
3
|
import { AuthShell } from '../../layouts/AuthShell';
|
|
4
4
|
import { FormField } from '../../components/FormField';
|
|
5
|
-
import { Button } from '../../components/ui/
|
|
6
|
-
import { Input } from '../../components/ui/
|
|
7
|
-
import { usePasswordReset } from '
|
|
5
|
+
import { Button } from '../../components/ui/button';
|
|
6
|
+
import { Input } from '../../components/ui/input';
|
|
7
|
+
import { usePasswordReset } from '@ploykit/hooks';
|
|
8
8
|
export function ForgotPasswordPage({ title = '找回密码', sentHint = '如果该邮箱存在,重置链接已发送,请查收邮箱。', backPath = '/login', }) {
|
|
9
9
|
const { requestReset } = usePasswordReset();
|
|
10
10
|
const [email, setEmail] = useState('');
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useNavigate } from 'react-router';
|
|
3
3
|
import { Check, X } from 'lucide-react';
|
|
4
|
-
import { Button } from '../../components/ui/
|
|
5
|
-
import { Badge } from '../../components/ui/
|
|
4
|
+
import { Button } from '../../components/ui/button';
|
|
5
|
+
import { Badge } from '../../components/ui/badge';
|
|
6
6
|
import { PageLoading, PageEmpty } from '../../components/Page';
|
|
7
7
|
import { toast } from '../../components/toast';
|
|
8
|
-
import { useMyInvitations } from '
|
|
8
|
+
import { useMyInvitations } from '@ploykit/hooks';
|
|
9
9
|
import { formatDateTime } from '../../lib/utils';
|
|
10
10
|
import { apiErrorMessage } from '../../lib/api-error';
|
|
11
11
|
const ROLE_LABEL = { owner: '所有者', admin: '管理员', member: '成员' };
|
|
@@ -36,5 +36,5 @@ export function InviteAcceptPage({ onAccepted, onDeclined } = {}) {
|
|
|
36
36
|
toast.error(apiErrorMessage(e, '操作失败'));
|
|
37
37
|
}
|
|
38
38
|
};
|
|
39
|
-
return (_jsx("div", { className: "flex min-h-svh w-full items-center justify-center bg-muted/40 p-6 md:p-10", children: _jsxs("div", { className: "w-full max-w-md rounded-xl border bg-card p-6 shadow-sm", children: [_jsx("h1", { className: "text-xl font-bold", children: "\u6211\u7684\u9080\u8BF7" }), _jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: "\u63A5\u53D7\u540E\u4F60\u5C06\u52A0\u5165\u5BF9\u5E94\u5DE5\u4F5C\u533A\u3002" }), _jsx("div", { className: "mt-4", children: loading ? (_jsx(PageLoading, { label: "\u52A0\u8F7D\u9080\u8BF7\u2026" })) : error ? (_jsxs("div", { className: "py-6 text-center text-sm text-
|
|
39
|
+
return (_jsx("div", { className: "flex min-h-svh w-full items-center justify-center bg-muted/40 p-6 md:p-10", children: _jsxs("div", { className: "w-full max-w-md rounded-xl border bg-card p-6 shadow-sm", children: [_jsx("h1", { className: "text-xl font-bold", children: "\u6211\u7684\u9080\u8BF7" }), _jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: "\u63A5\u53D7\u540E\u4F60\u5C06\u52A0\u5165\u5BF9\u5E94\u5DE5\u4F5C\u533A\u3002" }), _jsx("div", { className: "mt-4", children: loading ? (_jsx(PageLoading, { label: "\u52A0\u8F7D\u9080\u8BF7\u2026" })) : error ? (_jsxs("div", { className: "py-6 text-center text-sm text-destructive", children: [apiErrorMessage(error, '邀请加载失败'), _jsx("div", { className: "mt-3", children: _jsx(Button, { size: "sm", variant: "outline", onClick: () => refetch(), children: "\u91CD\u8BD5" }) })] })) : pending.length === 0 ? (_jsx(PageEmpty, { label: "\u6682\u65E0\u5F85\u5904\u7406\u7684\u9080\u8BF7", hint: "\u6536\u5230\u65B0\u9080\u8BF7\u65F6\u4F1A\u51FA\u73B0\u5728\u8FD9\u91CC" })) : (_jsx("ul", { className: "divide-y", children: pending.map((inv) => (_jsxs("li", { className: "flex items-center justify-between gap-3 py-3", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "truncate text-sm font-medium", children: inv.workspace_name || inv.workspace_slug || '工作区' }), _jsxs("p", { className: "mt-0.5 flex items-center gap-2 text-xs text-muted-foreground", children: [_jsx(Badge, { variant: "secondary", children: ROLE_LABEL[inv.role] ?? inv.role }), _jsxs("span", { children: [formatDateTime(inv.expires_at), " \u8FC7\u671F"] })] })] }), _jsxs("div", { className: "flex shrink-0 gap-1.5", children: [_jsxs(Button, { size: "sm", variant: "outline", disabled: decline.isPending, onClick: () => onDecline(inv.id, inv.workspace_name), children: [_jsx(X, {}), " \u62D2\u7EDD"] }), _jsxs(Button, { size: "sm", disabled: accept.isPending, onClick: () => onAccept(inv.id, inv.workspace_name), children: [_jsx(Check, {}), " \u63A5\u53D7"] })] })] }, inv.id))) })) })] }) }));
|
|
40
40
|
}
|
|
@@ -3,13 +3,13 @@ import { useState } from 'react';
|
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
import { AuthShell } from '../../layouts/AuthShell';
|
|
5
5
|
import { FormField } from '../../components/FormField';
|
|
6
|
-
import { Button } from '../../components/ui/
|
|
7
|
-
import { Input } from '../../components/ui/
|
|
6
|
+
import { Button } from '../../components/ui/button';
|
|
7
|
+
import { Input } from '../../components/ui/input';
|
|
8
8
|
import { FieldDescription, FieldSeparator } from '../../components/ui/field';
|
|
9
|
-
import { useApi } from '
|
|
10
|
-
import { useAuth } from '
|
|
11
|
-
import { useSiteConfig } from '
|
|
12
|
-
import { useZodForm } from '
|
|
9
|
+
import { useApi } from '@ploykit/hooks';
|
|
10
|
+
import { useAuth } from '@ploykit/hooks';
|
|
11
|
+
import { useSiteConfig } from '@ploykit/hooks';
|
|
12
|
+
import { useZodForm } from '@ploykit/hooks';
|
|
13
13
|
import { apiErrorMessage } from '../../lib/api-error';
|
|
14
14
|
import { toast } from '../../components/toast';
|
|
15
15
|
function passwordKinds(pw) {
|
|
@@ -2,9 +2,9 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
2
2
|
import { useEffect, useState } from 'react';
|
|
3
3
|
import { AuthShell } from '../../layouts/AuthShell';
|
|
4
4
|
import { FormField } from '../../components/FormField';
|
|
5
|
-
import { Button } from '../../components/ui/
|
|
6
|
-
import { Input } from '../../components/ui/
|
|
7
|
-
import { usePasswordReset } from '
|
|
5
|
+
import { Button } from '../../components/ui/button';
|
|
6
|
+
import { Input } from '../../components/ui/input';
|
|
7
|
+
import { usePasswordReset } from '@ploykit/hooks';
|
|
8
8
|
import { passwordSchema } from './RegisterPage';
|
|
9
9
|
const REDIRECT_DELAY_MS = 3000;
|
|
10
10
|
export function ResetPasswordPage({ onDone }) {
|
|
@@ -67,5 +67,5 @@ export function ResetPasswordPage({ onDone }) {
|
|
|
67
67
|
setLoading(false);
|
|
68
68
|
}
|
|
69
69
|
};
|
|
70
|
-
return (_jsx(AuthShell, { children: _jsxs("form", { onSubmit: handleSubmit, className: "space-y-4", children: [_jsx("div", { className: "space-y-1 text-center", children: _jsx("h1", { className: "text-2xl font-bold tracking-tight", children: "\u8BBE\u7F6E\u65B0\u5BC6\u7801" }) }), done ? (_jsxs("div", { className: "space-y-2 text-center", "data-testid": "reset-done", children: [_jsx("p", { className: "text-sm text-
|
|
70
|
+
return (_jsx(AuthShell, { children: _jsxs("form", { onSubmit: handleSubmit, className: "space-y-4", children: [_jsx("div", { className: "space-y-1 text-center", children: _jsx("h1", { className: "text-2xl font-bold tracking-tight", children: "\u8BBE\u7F6E\u65B0\u5BC6\u7801" }) }), done ? (_jsxs("div", { className: "space-y-2 text-center", "data-testid": "reset-done", children: [_jsx("p", { className: "text-sm text-(--success)", children: "\u5BC6\u7801\u5DF2\u91CD\u7F6E\uFF0C\u5168\u90E8\u65E7\u4F1A\u8BDD\u5DF2\u5931\u6548\u3002" }), _jsx("p", { className: "text-sm text-muted-foreground", children: countdown > 0 ? `${countdown} 秒后跳转登录页…` : '正在跳转…' })] })) : params === null ? (_jsx("p", { className: "text-center text-sm text-muted-foreground", children: "\u6B63\u5728\u6253\u5F00\u94FE\u63A5\u2026" })) : !email || !token ? (_jsx("p", { className: "text-center text-sm text-destructive", "data-testid": "reset-invalid", children: "\u94FE\u63A5\u65E0\u6548\uFF1A\u7F3A\u5C11\u90AE\u7BB1\u6216\u4EE4\u724C\u53C2\u6570\uFF0C\u8BF7\u4ECE\u90AE\u4EF6\u4E2D\u7684\u94FE\u63A5\u8FDB\u5165\u3002" })) : (_jsxs(_Fragment, { children: [_jsxs("p", { className: "text-sm text-muted-foreground", children: ["\u6B63\u5728\u4E3A ", email, " \u8BBE\u7F6E\u65B0\u5BC6\u7801"] }), _jsx(FormField, { label: "\u65B0\u5BC6\u7801", htmlFor: "reset-new", children: _jsx(Input, { id: "reset-new", type: "password", value: password, onChange: (e) => setPassword(e.target.value), placeholder: "\u81F3\u5C11 10 \u4F4D\uFF0C\u542B\u4E09\u7C7B\u5B57\u7B26", autoComplete: "new-password", required: true }) }), _jsx(FormField, { label: "\u786E\u8BA4\u65B0\u5BC6\u7801", error: confirmError ?? undefined, htmlFor: "reset-confirm", children: _jsx(Input, { id: "reset-confirm", type: "password", value: confirm, onChange: (e) => setConfirm(e.target.value), placeholder: "\u518D\u8F93\u5165\u4E00\u6B21", autoComplete: "new-password", "aria-invalid": confirmError ? true : undefined, required: true }) }), serverError && (_jsx("p", { role: "alert", className: "text-sm text-destructive", children: serverError })), _jsx(Button, { type: "submit", className: "w-full", disabled: loading || !password || !confirm, children: loading ? '提交中…' : '重置密码' })] }))] }) }));
|
|
71
71
|
}
|
|
@@ -2,8 +2,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { useEffect, useRef, useState } from 'react';
|
|
3
3
|
import { api } from '@ploykit/client';
|
|
4
4
|
import { AuthShell } from '../../layouts/AuthShell';
|
|
5
|
-
import { buttonVariants } from '../../components/ui/
|
|
6
|
-
import { Empty, EmptyHeader, EmptyMedia, EmptyTitle, EmptyDescription,
|
|
5
|
+
import { buttonVariants } from '../../components/ui/button';
|
|
6
|
+
import { Empty, EmptyHeader, EmptyMedia, EmptyTitle, EmptyDescription, EmptyContent, } from '../../components/ui/empty';
|
|
7
7
|
import { MailCheck, LoaderCircle, CircleX } from 'lucide-react';
|
|
8
8
|
export function VerifyEmailPage() {
|
|
9
9
|
const [state, setState] = useState('verifying');
|
|
@@ -37,9 +37,9 @@ export function VerifyEmailPage() {
|
|
|
37
37
|
setMessage(err instanceof Error ? err.message : '验证失败,链接可能已失效');
|
|
38
38
|
});
|
|
39
39
|
}, []);
|
|
40
|
-
return (_jsx(AuthShell, { children: _jsxs(Empty, { className: "border-none p-0", children: [_jsxs(EmptyHeader, { children: [_jsxs(EmptyMedia, { variant: "icon", "data-testid": "verify-state", children: [state === 'ok' && _jsx(MailCheck, { className: "text-
|
|
40
|
+
return (_jsx(AuthShell, { children: _jsxs(Empty, { className: "border-none p-0", children: [_jsxs(EmptyHeader, { children: [_jsxs(EmptyMedia, { variant: "icon", "data-testid": "verify-state", children: [state === 'ok' && _jsx(MailCheck, { className: "text-(--success)", "aria-hidden": "true" }), state === 'verifying' && _jsx(LoaderCircle, { className: "animate-spin", "aria-hidden": "true" }), state === 'failed' && _jsx(CircleX, { className: "text-destructive", "aria-hidden": "true" })] }), _jsx(EmptyTitle, { children: state === 'ok' ? '邮箱验证成功' : state === 'failed' ? '验证失败' : '正在验证…' }), _jsx(EmptyDescription, { children: state === 'ok'
|
|
41
41
|
? '感谢确认,现在可以正常登录了。'
|
|
42
42
|
: state === 'failed'
|
|
43
43
|
? (message ?? '验证失败')
|
|
44
|
-
: '请稍候,正在校验邮件链接…' })] }), _jsx(
|
|
44
|
+
: '请稍候,正在校验邮件链接…' })] }), _jsx(EmptyContent, { children: _jsx("a", { href: "/login", className: buttonVariants({ variant: 'outline' }), children: "\u8FD4\u56DE\u767B\u5F55" }) })] }) }));
|
|
45
45
|
}
|
|
@@ -7,14 +7,15 @@ import { DataTable } from '../../components/DataTable';
|
|
|
7
7
|
import { SettingsCard } from '../../components/SettingsCard';
|
|
8
8
|
import { useConfirm } from '../../components/ConfirmDialog';
|
|
9
9
|
import { toast } from '../../components/toast';
|
|
10
|
-
import { Button } from '../../components/ui/
|
|
11
|
-
import { Badge
|
|
10
|
+
import { Button } from '../../components/ui/button';
|
|
11
|
+
import { Badge } from '../../components/ui/badge';
|
|
12
|
+
import { StatusBadge } from '../../components/StatusBadge';
|
|
12
13
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../../components/ui/select';
|
|
13
|
-
import { useApi } from '
|
|
14
|
-
import { useBilling } from '
|
|
15
|
-
import { useSiteConfig } from '
|
|
16
|
-
import { useWorkspace } from '
|
|
17
|
-
import { queryKeys, } from '
|
|
14
|
+
import { useApi } from '@ploykit/hooks';
|
|
15
|
+
import { useBilling } from '@ploykit/hooks';
|
|
16
|
+
import { useSiteConfig } from '@ploykit/hooks';
|
|
17
|
+
import { useWorkspace } from '@ploykit/hooks';
|
|
18
|
+
import { queryKeys, } from '@ploykit/hooks';
|
|
18
19
|
import { formatDateTime, cn } from '../../lib/utils';
|
|
19
20
|
import { apiErrorMessage } from '../../lib/api-error';
|
|
20
21
|
const INTERVAL_LABEL = { monthly: '按月', yearly: '按年' };
|
|
@@ -4,9 +4,9 @@ import { useNavigate } from 'react-router';
|
|
|
4
4
|
import { useQuery, useQueryClient } from '@tanstack/react-query';
|
|
5
5
|
import { Skeleton } from '../../components/ui/skeleton';
|
|
6
6
|
import { toast } from '../../components/toast';
|
|
7
|
-
import { useApi } from '
|
|
8
|
-
import { useWorkspace } from '
|
|
9
|
-
import { queryKeys } from '
|
|
7
|
+
import { useApi } from '@ploykit/hooks';
|
|
8
|
+
import { useWorkspace } from '@ploykit/hooks';
|
|
9
|
+
import { queryKeys } from '@ploykit/hooks';
|
|
10
10
|
const POLL_MS = 5_000;
|
|
11
11
|
const MAX_TRIES = 12;
|
|
12
12
|
function toBaseline(sub) {
|
|
@@ -9,17 +9,18 @@ import { FormField } from '../../components/FormField';
|
|
|
9
9
|
import { SecretModal, ImpactConfirmation } from '../../components/SecretModal';
|
|
10
10
|
import { useConfirm } from '../../components/ConfirmDialog';
|
|
11
11
|
import { toast } from '../../components/toast';
|
|
12
|
-
import { Button } from '../../components/ui/
|
|
13
|
-
import { Input } from '../../components/ui/
|
|
14
|
-
import { Badge
|
|
12
|
+
import { Button } from '../../components/ui/button';
|
|
13
|
+
import { Input } from '../../components/ui/input';
|
|
14
|
+
import { Badge } from '../../components/ui/badge';
|
|
15
|
+
import { StatusBadge } from '../../components/StatusBadge';
|
|
15
16
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from '../../components/ui/tabs';
|
|
16
17
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '../../components/ui/select';
|
|
17
18
|
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, } from '../../components/ui/dialog';
|
|
18
|
-
import { useZodForm } from '
|
|
19
|
-
import { useMembers, useMemberMutations, ASSIGNABLE_ROLES, LIST_PAGE_SIZE, } from '
|
|
19
|
+
import { useZodForm } from '@ploykit/hooks';
|
|
20
|
+
import { useMembers, useMemberMutations, ASSIGNABLE_ROLES, LIST_PAGE_SIZE, } from '@ploykit/hooks';
|
|
20
21
|
import { formatDateTime } from '../../lib/utils';
|
|
21
22
|
import { apiErrorMessage } from '../../lib/api-error';
|
|
22
|
-
import { roleSatisfies } from '
|
|
23
|
+
import { roleSatisfies } from '@ploykit/hooks';
|
|
23
24
|
const inviteSchema = z.object({
|
|
24
25
|
email: z.string().min(1, '请输入邮箱').email('邮箱格式不正确'),
|
|
25
26
|
role: z.enum(['admin', 'member']),
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useMemo, useState } from 'react';
|
|
3
|
+
import { RotateCcw, Save } from 'lucide-react';
|
|
4
|
+
import { PageHeader, PageLoading, PageError, } from '../../components/Page';
|
|
5
|
+
import { SettingsCard } from '../../components/SettingsCard';
|
|
6
|
+
import { ReauthDialog } from '../../components/ReauthDialog';
|
|
7
|
+
import { useConfirm } from '../../components/ConfirmDialog';
|
|
8
|
+
import { toast } from '../../components/toast';
|
|
9
|
+
import { Button } from '../../components/ui/button';
|
|
10
|
+
import { Badge } from '../../components/ui/badge';
|
|
11
|
+
import { Checkbox } from '../../components/ui/checkbox';
|
|
12
|
+
import { useRoleConfig } from '@ploykit/hooks';
|
|
13
|
+
import { isApiError } from '@ploykit/client';
|
|
14
|
+
import { apiErrorMessage } from '../../lib/api-error';
|
|
15
|
+
const ROLE_LABEL = { owner: '所有者', admin: '管理员', member: '成员' };
|
|
16
|
+
const DOMAIN_LABEL = {
|
|
17
|
+
workspace: '工作区',
|
|
18
|
+
members: '成员',
|
|
19
|
+
invites: '邀请',
|
|
20
|
+
roles: '角色权限',
|
|
21
|
+
billing: '计费',
|
|
22
|
+
webhooks: 'Webhooks',
|
|
23
|
+
notifications: '通知',
|
|
24
|
+
audit: '审计',
|
|
25
|
+
usage: '用量',
|
|
26
|
+
};
|
|
27
|
+
function domainOf(perm) {
|
|
28
|
+
const i = perm.indexOf(':');
|
|
29
|
+
return i > 0 ? perm.slice(0, i) : perm;
|
|
30
|
+
}
|
|
31
|
+
/** catalog 权限按域分组,保持目录的字典序。 */
|
|
32
|
+
function groupByDomain(catalog) {
|
|
33
|
+
const groups = new Map();
|
|
34
|
+
for (const p of catalog) {
|
|
35
|
+
const d = domainOf(p);
|
|
36
|
+
const arr = groups.get(d) ?? [];
|
|
37
|
+
arr.push(p);
|
|
38
|
+
groups.set(d, arr);
|
|
39
|
+
}
|
|
40
|
+
return [...groups.entries()].map(([domain, perms]) => ({ domain, perms }));
|
|
41
|
+
}
|
|
42
|
+
function isReauth(err) {
|
|
43
|
+
return isApiError(err, 'E_REAUTH_REQUIRED');
|
|
44
|
+
}
|
|
45
|
+
export function RolePermissionsPage(_props = {}) {
|
|
46
|
+
const { roles, catalog, loading, error, setPerms, resetPerms } = useRoleConfig();
|
|
47
|
+
const confirm = useConfirm();
|
|
48
|
+
const [drafts, setDrafts] = useState({});
|
|
49
|
+
const [reauthOpen, setReauthOpen] = useState(false);
|
|
50
|
+
const [pendingRetry, setPendingRetry] = useState(null);
|
|
51
|
+
// 数据到达(或写后失效重取)时以服务端有效集重建草稿
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
const next = {};
|
|
54
|
+
for (const r of roles)
|
|
55
|
+
next[r.role] = { perms: [...r.perms], dirty: false };
|
|
56
|
+
setDrafts(next);
|
|
57
|
+
}, [roles]);
|
|
58
|
+
const groups = useMemo(() => groupByDomain(catalog), [catalog]);
|
|
59
|
+
const toggle = (role, perm, on) => {
|
|
60
|
+
setDrafts((d) => {
|
|
61
|
+
const cur = d[role];
|
|
62
|
+
if (!cur)
|
|
63
|
+
return d;
|
|
64
|
+
const perms = on ? [...cur.perms, perm].sort() : cur.perms.filter((p) => p !== perm);
|
|
65
|
+
const server = roles.find((r) => r.role === role)?.perms ?? [];
|
|
66
|
+
const dirty = perms.join('\u0000') !== server.join('\u0000');
|
|
67
|
+
return { ...d, [role]: { perms, dirty } };
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
const save = async (role) => {
|
|
71
|
+
const draft = drafts[role];
|
|
72
|
+
if (!draft)
|
|
73
|
+
return;
|
|
74
|
+
try {
|
|
75
|
+
await setPerms.mutateAsync({ role, perms: draft.perms });
|
|
76
|
+
toast.success(`已更新${ROLE_LABEL[role] ?? role}权限`);
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
if (isReauth(err)) {
|
|
80
|
+
setPendingRetry(() => () => setPerms.mutateAsync({ role, perms: draft.perms }));
|
|
81
|
+
setReauthOpen(true);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
toast.error(apiErrorMessage(err));
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
const reset = async (role) => {
|
|
88
|
+
const ok = await confirm({
|
|
89
|
+
title: `恢复${ROLE_LABEL[role] ?? role}默认权限?`,
|
|
90
|
+
description: '自定义权限集将被清除,该角色回到内置默认权限。',
|
|
91
|
+
confirmText: '恢复默认',
|
|
92
|
+
});
|
|
93
|
+
if (!ok)
|
|
94
|
+
return;
|
|
95
|
+
try {
|
|
96
|
+
await resetPerms.mutateAsync(role);
|
|
97
|
+
toast.success(`已恢复${ROLE_LABEL[role] ?? role}默认权限`);
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
if (isReauth(err)) {
|
|
101
|
+
setPendingRetry(() => () => resetPerms.mutateAsync(role));
|
|
102
|
+
setReauthOpen(true);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
toast.error(apiErrorMessage(err));
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
if (loading)
|
|
109
|
+
return _jsx(PageLoading, { label: "\u52A0\u8F7D\u89D2\u8272\u6743\u9650\u2026" });
|
|
110
|
+
if (error)
|
|
111
|
+
return _jsx(PageError, { message: apiErrorMessage(error) });
|
|
112
|
+
return (_jsxs("div", { className: "mx-auto w-full max-w-4xl p-6", children: [_jsx(PageHeader, { title: "\u89D2\u8272\u6743\u9650", description: "\u81EA\u5B9A\u4E49\u5404\u89D2\u8272\u80FD\u505A\u4EC0\u4E48\u3002\u6240\u6709\u8005\u59CB\u7EC8\u62E5\u6709\u5168\u90E8\u6743\u9650\uFF1B\u81EA\u5B9A\u4E49\u96C6\u4E3A\u6574\u4F53\u66FF\u6362\uFF08\u975E\u7D2F\u52A0\uFF09\uFF0C\u672A\u77E5\u6743\u9650\u4F1A\u88AB\u670D\u52A1\u7AEF\u62D2\u7EDD\u3002" }), roles.map((r) => {
|
|
113
|
+
const draft = drafts[r.role];
|
|
114
|
+
return (_jsx(SettingsCard, { title: _jsxs(_Fragment, { children: [ROLE_LABEL[r.role] ?? r.role, r.overridden && _jsx(Badge, { variant: "secondary", children: "\u5DF2\u81EA\u5B9A\u4E49" })] }), description: r.overridden
|
|
115
|
+
? '当前为自定义权限集(覆盖默认)'
|
|
116
|
+
: '当前为内置默认权限集', cta: _jsxs("div", { className: "flex gap-2", children: [r.overridden && (_jsxs(Button, { variant: "outline", size: "sm", onClick: () => void reset(r.role), children: [_jsx(RotateCcw, { className: "size-4" }), "\u6062\u590D\u9ED8\u8BA4"] })), _jsxs(Button, { size: "sm", disabled: !draft?.dirty, onClick: () => void save(r.role), children: [_jsx(Save, { className: "size-4" }), "\u4FDD\u5B58\u4FEE\u6539"] })] }), children: _jsx("div", { className: "grid gap-4 sm:grid-cols-2", children: groups.map(({ domain, perms }) => (_jsxs("div", { className: "space-y-2", children: [_jsx("p", { className: "text-sm font-medium text-muted-foreground", children: DOMAIN_LABEL[domain] ?? domain }), _jsx("div", { className: "space-y-1.5", children: perms.map((perm) => (_jsxs("label", { className: "flex items-center gap-2 text-sm", children: [_jsx(Checkbox, { checked: draft?.perms.includes(perm) ?? false, onCheckedChange: (v) => toggle(r.role, perm, v === true) }), _jsx("span", { className: "font-mono text-xs", children: perm })] }, perm))) })] }, domain))) }) }, r.role));
|
|
117
|
+
}), _jsx(ReauthDialog, { open: reauthOpen, retry: pendingRetry, onClose: () => { setReauthOpen(false); setPendingRetry(null); } })] }));
|
|
118
|
+
}
|
|
@@ -8,13 +8,13 @@ import { DataTable } from '../../components/DataTable';
|
|
|
8
8
|
import { FormField } from '../../components/FormField';
|
|
9
9
|
import { CronInput, describeCron } from '../../components/CronInput';
|
|
10
10
|
import { toast } from '../../components/toast';
|
|
11
|
-
import { Button } from '../../components/ui/
|
|
12
|
-
import { Input } from '../../components/ui/
|
|
11
|
+
import { Button } from '../../components/ui/button';
|
|
12
|
+
import { Input } from '../../components/ui/input';
|
|
13
13
|
import { Switch } from '../../components/ui/switch';
|
|
14
14
|
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, } from '../../components/ui/dialog';
|
|
15
|
-
import { useApi } from '
|
|
16
|
-
import { useWorkspace } from '
|
|
17
|
-
import { useZodForm } from '
|
|
15
|
+
import { useApi } from '@ploykit/hooks';
|
|
16
|
+
import { useWorkspace } from '@ploykit/hooks';
|
|
17
|
+
import { useZodForm } from '@ploykit/hooks';
|
|
18
18
|
import { useConfirm } from '../../components/ConfirmDialog';
|
|
19
19
|
import { browserTzLabel, formatDateTimeTz } from '../../lib/utils';
|
|
20
20
|
import { apiErrorMessage } from '../../lib/api-error';
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { Link } from 'react-router';
|
|
3
3
|
import { PageHeader, PageLoading, PageError, PageEmpty } from '../../components/Page';
|
|
4
|
-
import { Badge } from '../../components/ui/
|
|
4
|
+
import { Badge } from '../../components/ui/badge';
|
|
5
5
|
import { Card, CardHeader, CardTitle, CardAction, CardContent } from '../../components/ui/card';
|
|
6
6
|
import { Progress, ProgressLabel, ProgressValue, } from '../../components/ui/progress';
|
|
7
7
|
import { DataTable } from '../../components/DataTable';
|
|
8
|
-
import { useUsage } from '
|
|
8
|
+
import { useUsage } from '@ploykit/hooks';
|
|
9
9
|
import { apiErrorMessage } from '../../lib/api-error';
|
|
10
10
|
const NEAR_FULL_PCT = 80;
|
|
11
11
|
const DIM_LABEL = {
|
|
@@ -9,21 +9,21 @@ import { FormField } from '../../components/FormField';
|
|
|
9
9
|
import { SecretModal } from '../../components/SecretModal';
|
|
10
10
|
import { useConfirm } from '../../components/ConfirmDialog';
|
|
11
11
|
import { toast } from '../../components/toast';
|
|
12
|
-
import { Button } from '../../components/ui/
|
|
13
|
-
import { Input } from '../../components/ui/
|
|
14
|
-
import { StatusBadge } from '../../components/
|
|
12
|
+
import { Button } from '../../components/ui/button';
|
|
13
|
+
import { Input } from '../../components/ui/input';
|
|
14
|
+
import { StatusBadge } from '../../components/StatusBadge';
|
|
15
15
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from '../../components/ui/tabs';
|
|
16
16
|
import { Switch } from '../../components/ui/switch';
|
|
17
17
|
import { Checkbox } from '../../components/ui/checkbox';
|
|
18
18
|
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, } from '../../components/ui/dialog';
|
|
19
|
-
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from '../../components/ui/menu';
|
|
20
|
-
import { useApi } from '
|
|
21
|
-
import { useWorkspace } from '
|
|
22
|
-
import { useZodForm } from '
|
|
23
|
-
import { queryKeys } from '
|
|
19
|
+
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from '../../components/ui/dropdown-menu';
|
|
20
|
+
import { useApi } from '@ploykit/hooks';
|
|
21
|
+
import { useWorkspace } from '@ploykit/hooks';
|
|
22
|
+
import { useZodForm } from '@ploykit/hooks';
|
|
23
|
+
import { queryKeys } from '@ploykit/hooks';
|
|
24
24
|
import { formatDateTime } from '../../lib/utils';
|
|
25
25
|
import { apiErrorMessage } from '../../lib/api-error';
|
|
26
|
-
import { roleSatisfies } from '
|
|
26
|
+
import { roleSatisfies } from '@ploykit/hooks';
|
|
27
27
|
const createSchema = z.object({
|
|
28
28
|
url: z
|
|
29
29
|
.string()
|
|
@@ -4,10 +4,10 @@ import { useSearchParams } from 'react-router';
|
|
|
4
4
|
import { Download, Search } from 'lucide-react';
|
|
5
5
|
import { PageHeader, PageLoading, PageError, PageEmpty } from '../../components/Page';
|
|
6
6
|
import { DataTable } from '../../components/DataTable';
|
|
7
|
-
import { Button } from '../../components/ui/
|
|
8
|
-
import { Input } from '../../components/ui/
|
|
7
|
+
import { Button } from '../../components/ui/button';
|
|
8
|
+
import { Input } from '../../components/ui/input';
|
|
9
9
|
import { toast } from '../../components/toast';
|
|
10
|
-
import { useAudit, exportAuditCsv, } from '
|
|
10
|
+
import { useAudit, exportAuditCsv, } from '@ploykit/hooks';
|
|
11
11
|
import { formatDateTime } from '../../lib/utils';
|
|
12
12
|
import { apiErrorMessage } from '../../lib/api-error';
|
|
13
13
|
const PAGE_SIZE = 20;
|
|
@@ -9,14 +9,14 @@ import { FormField } from '../../components/FormField';
|
|
|
9
9
|
import { ImpactConfirmation } from '../../components/SecretModal';
|
|
10
10
|
import { useConfirm } from '../../components/ConfirmDialog';
|
|
11
11
|
import { toast } from '../../components/toast';
|
|
12
|
-
import { Button } from '../../components/ui/
|
|
13
|
-
import { Input } from '../../components/ui/
|
|
14
|
-
import { useApi } from '
|
|
15
|
-
import { useWorkspace } from '
|
|
16
|
-
import { useZodForm } from '
|
|
17
|
-
import { queryKeys } from '
|
|
12
|
+
import { Button } from '../../components/ui/button';
|
|
13
|
+
import { Input } from '../../components/ui/input';
|
|
14
|
+
import { useApi } from '@ploykit/hooks';
|
|
15
|
+
import { useWorkspace } from '@ploykit/hooks';
|
|
16
|
+
import { useZodForm } from '@ploykit/hooks';
|
|
17
|
+
import { queryKeys } from '@ploykit/hooks';
|
|
18
18
|
import { apiErrorMessage } from '../../lib/api-error';
|
|
19
|
-
import { roleSatisfies } from '
|
|
19
|
+
import { roleSatisfies } from '@ploykit/hooks';
|
|
20
20
|
const renameSchema = z.object({
|
|
21
21
|
name: z.string().trim().min(1, '请输入工作区名称').max(64, '名称最多 64 字符'),
|
|
22
22
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ploykit/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -10,6 +10,11 @@
|
|
|
10
10
|
"types": "./dist/index.d.ts",
|
|
11
11
|
"default": "./dist/index.js"
|
|
12
12
|
},
|
|
13
|
+
"./components/ui/*": {
|
|
14
|
+
"development": "./src/components/ui/*.tsx",
|
|
15
|
+
"types": "./dist/components/ui/*.d.ts",
|
|
16
|
+
"default": "./dist/components/ui/*.js"
|
|
17
|
+
},
|
|
13
18
|
"./package.json": "./package.json"
|
|
14
19
|
},
|
|
15
20
|
"files": [
|
|
@@ -24,13 +29,12 @@
|
|
|
24
29
|
},
|
|
25
30
|
"dependencies": {
|
|
26
31
|
"@base-ui/react": "^1.8.0",
|
|
27
|
-
"@
|
|
28
|
-
"@ploykit/
|
|
29
|
-
"@ploykit/runtime": "^0.1.0",
|
|
32
|
+
"@ploykit/client": "^0.4.0",
|
|
33
|
+
"@ploykit/hooks": "^0.4.0",
|
|
30
34
|
"class-variance-authority": "^0.7.1",
|
|
31
35
|
"clsx": "^2.1.1",
|
|
36
|
+
"cn": "^0.4.0",
|
|
32
37
|
"lucide-react": "^1.52.0",
|
|
33
|
-
"react-hook-form": "^7.0.0",
|
|
34
38
|
"sonner": "^2.0.8",
|
|
35
39
|
"tailwind-merge": "^3.7.0",
|
|
36
40
|
"zod": "^4.0.0"
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { type VariantProps } from 'class-variance-authority';
|
|
3
|
-
declare const badgeVariants: (props?: ({
|
|
4
|
-
variant?: "default" | "destructive" | "outline" | "secondary" | null | undefined;
|
|
5
|
-
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
6
|
-
export interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement>, VariantProps<typeof badgeVariants> {
|
|
7
|
-
}
|
|
8
|
-
declare function Badge({ className, variant, ...props }: BadgeProps): React.JSX.Element;
|
|
9
|
-
export declare function StatusBadge({ status, className }: {
|
|
10
|
-
status: string;
|
|
11
|
-
className?: string;
|
|
12
|
-
}): React.JSX.Element;
|
|
13
|
-
export { Badge, badgeVariants };
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { cva } from 'class-variance-authority';
|
|
3
|
-
import { cn, statusTone, statusLabel, STATUS_TONE_CLASS } from '../../lib/utils';
|
|
4
|
-
const badgeVariants = cva('inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors whitespace-nowrap', {
|
|
5
|
-
variants: {
|
|
6
|
-
variant: {
|
|
7
|
-
default: 'border-transparent bg-primary text-primary-foreground',
|
|
8
|
-
secondary: 'border-transparent bg-secondary text-secondary-foreground',
|
|
9
|
-
destructive: 'border-transparent bg-destructive text-destructive-foreground',
|
|
10
|
-
outline: 'text-foreground',
|
|
11
|
-
},
|
|
12
|
-
},
|
|
13
|
-
defaultVariants: { variant: 'default' },
|
|
14
|
-
});
|
|
15
|
-
function Badge({ className, variant, ...props }) {
|
|
16
|
-
return _jsx("span", { className: cn(badgeVariants({ variant }), className), ...props });
|
|
17
|
-
}
|
|
18
|
-
export function StatusBadge({ status, className }) {
|
|
19
|
-
return (_jsx("span", { className: cn('inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-medium whitespace-nowrap', STATUS_TONE_CLASS[statusTone(status)], className), children: statusLabel(status) }));
|
|
20
|
-
}
|
|
21
|
-
export { Badge, badgeVariants };
|