@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.
Files changed (145) hide show
  1. package/README.md +183 -23
  2. package/dist/AppProviders.d.ts +15 -0
  3. package/dist/AppProviders.js +15 -0
  4. package/dist/components/ConfirmDialog.js +8 -2
  5. package/dist/components/CronInput.js +2 -2
  6. package/dist/components/DataTable.d.ts +12 -3
  7. package/dist/components/DataTable.js +7 -3
  8. package/dist/components/ErrorBoundary.js +1 -1
  9. package/dist/components/ImpersonationBanner.js +1 -1
  10. package/dist/components/NotificationBell.js +5 -5
  11. package/dist/components/OnboardingChecklist.js +3 -3
  12. package/dist/components/Page.js +1 -1
  13. package/dist/components/ReauthDialog.d.ts +15 -0
  14. package/dist/components/ReauthDialog.js +42 -0
  15. package/dist/components/SecretModal.d.ts +8 -1
  16. package/dist/components/SecretModal.js +6 -3
  17. package/dist/components/SettingsCard.js +2 -2
  18. package/dist/components/SiteBannerLayer.js +1 -1
  19. package/dist/components/StatusBadge.d.ts +4 -0
  20. package/dist/components/StatusBadge.js +7 -0
  21. package/dist/components/UserMenu.js +2 -2
  22. package/dist/components/WorkspaceSwitcher.js +4 -4
  23. package/dist/components/ui/alert-dialog.d.ts +2 -2
  24. package/dist/components/ui/alert-dialog.js +10 -9
  25. package/dist/components/ui/avatar.js +3 -2
  26. package/dist/components/ui/badge.d.ts +7 -0
  27. package/dist/components/ui/badge.js +33 -0
  28. package/dist/components/ui/breadcrumb.js +7 -7
  29. package/dist/components/ui/button.d.ts +8 -0
  30. package/dist/components/ui/button.js +34 -0
  31. package/dist/components/ui/card.d.ts +2 -4
  32. package/dist/components/ui/card.js +7 -7
  33. package/dist/components/ui/checkbox.js +3 -2
  34. package/dist/components/ui/dialog.d.ts +22 -14
  35. package/dist/components/ui/dialog.js +40 -25
  36. package/dist/components/ui/dropdown-menu.js +50 -0
  37. package/dist/components/ui/empty.d.ts +7 -9
  38. package/dist/components/ui/empty.js +6 -9
  39. package/dist/components/ui/field.js +10 -9
  40. package/dist/components/ui/input.d.ts +3 -0
  41. package/dist/components/ui/input.js +7 -0
  42. package/dist/components/ui/popover.js +3 -2
  43. package/dist/components/ui/progress.js +2 -1
  44. package/dist/components/ui/select.d.ts +20 -1
  45. package/dist/components/ui/select.js +28 -7
  46. package/dist/components/ui/separator.js +1 -0
  47. package/dist/components/ui/sheet.d.ts +9 -1
  48. package/dist/components/ui/sheet.js +11 -4
  49. package/dist/components/ui/sidebar.d.ts +2 -2
  50. package/dist/components/ui/sidebar.js +25 -34
  51. package/dist/components/ui/skeleton.d.ts +1 -2
  52. package/dist/components/ui/switch.js +1 -1
  53. package/dist/components/ui/tabs.js +3 -3
  54. package/dist/components/ui/textarea.d.ts +9 -0
  55. package/dist/components/ui/textarea.js +12 -0
  56. package/dist/components/ui/tooltip.js +1 -1
  57. package/dist/index.d.ts +10 -40
  58. package/dist/index.js +10 -26
  59. package/dist/layouts/AppShell.d.ts +1 -1
  60. package/dist/layouts/AppShell.js +23 -1
  61. package/dist/layouts/SettingsShell.d.ts +1 -1
  62. package/dist/layouts/SettingsShell.js +3 -3
  63. package/dist/pages/LandingPage.js +1 -1
  64. package/dist/pages/LoginPage.js +7 -7
  65. package/dist/pages/account/NotificationPreferencesPage.js +2 -2
  66. package/dist/pages/account/ProfileSettingsPage.js +7 -7
  67. package/dist/pages/account/SecuritySettingsPage.js +8 -8
  68. package/dist/pages/account/TokensPage.js +4 -4
  69. package/dist/pages/admin/AdminSettingsPage.js +5 -5
  70. package/dist/pages/admin/AdminShell.js +2 -2
  71. package/dist/pages/admin/AuditPage.js +3 -3
  72. package/dist/pages/admin/OrdersPage.js +4 -3
  73. package/dist/pages/admin/OverviewPage.js +4 -4
  74. package/dist/pages/admin/SSOPage.js +3 -3
  75. package/dist/pages/admin/UserDetailPage.js +6 -5
  76. package/dist/pages/admin/UsersPage.js +7 -6
  77. package/dist/pages/admin/WebhookDeliveriesPage.js +4 -3
  78. package/dist/pages/admin/WorkspaceDetailPage.js +5 -5
  79. package/dist/pages/admin/WorkspacesPage.js +4 -4
  80. package/dist/pages/admin/shared.js +1 -1
  81. package/dist/pages/auth/ForgotPasswordPage.js +3 -3
  82. package/dist/pages/auth/InviteAcceptPage.js +4 -4
  83. package/dist/pages/auth/RegisterPage.js +6 -6
  84. package/dist/pages/auth/ResetPasswordPage.js +4 -4
  85. package/dist/pages/auth/VerifyEmailPage.js +4 -4
  86. package/dist/pages/workspace/BillingPage.js +8 -7
  87. package/dist/pages/workspace/BillingSuccessPage.js +3 -3
  88. package/dist/pages/workspace/MembersPage.js +7 -6
  89. package/dist/pages/workspace/RolePermissionsPage.d.ts +3 -0
  90. package/dist/pages/workspace/RolePermissionsPage.js +118 -0
  91. package/dist/pages/workspace/SchedulesPage.js +5 -5
  92. package/dist/pages/workspace/UsagePage.d.ts +1 -1
  93. package/dist/pages/workspace/UsagePage.js +2 -2
  94. package/dist/pages/workspace/WebhooksPage.js +9 -9
  95. package/dist/pages/workspace/WorkspaceAuditPage.js +3 -3
  96. package/dist/pages/workspace/WorkspaceGeneralPage.js +7 -7
  97. package/package.json +9 -5
  98. package/dist/components/ui/Badge.d.ts +0 -13
  99. package/dist/components/ui/Badge.js +0 -21
  100. package/dist/components/ui/Button.d.ts +0 -10
  101. package/dist/components/ui/Button.js +0 -33
  102. package/dist/components/ui/Input.d.ts +0 -3
  103. package/dist/components/ui/Input.js +0 -10
  104. package/dist/components/ui/menu.js +0 -50
  105. package/dist/hooks/useApi.d.ts +0 -10
  106. package/dist/hooks/useApi.js +0 -11
  107. package/dist/hooks/useAudit.d.ts +0 -39
  108. package/dist/hooks/useAudit.js +0 -55
  109. package/dist/hooks/useAuth.d.ts +0 -1
  110. package/dist/hooks/useAuth.js +0 -4
  111. package/dist/hooks/useBilling.d.ts +0 -44
  112. package/dist/hooks/useBilling.js +0 -64
  113. package/dist/hooks/useLogin.d.ts +0 -10
  114. package/dist/hooks/useLogin.js +0 -39
  115. package/dist/hooks/useMembers.d.ts +0 -125
  116. package/dist/hooks/useMembers.js +0 -127
  117. package/dist/hooks/useNotificationPrefs.d.ts +0 -20
  118. package/dist/hooks/useNotificationPrefs.js +0 -42
  119. package/dist/hooks/usePasswordReset.d.ts +0 -5
  120. package/dist/hooks/usePasswordReset.js +0 -12
  121. package/dist/hooks/useSEO.d.ts +0 -6
  122. package/dist/hooks/useSEO.js +0 -14
  123. package/dist/hooks/useSessions.d.ts +0 -20
  124. package/dist/hooks/useSessions.js +0 -38
  125. package/dist/hooks/useSiteConfig.d.ts +0 -12
  126. package/dist/hooks/useSiteConfig.js +0 -11
  127. package/dist/hooks/useTokens.d.ts +0 -36
  128. package/dist/hooks/useTokens.js +0 -35
  129. package/dist/hooks/useUsage.d.ts +0 -20
  130. package/dist/hooks/useUsage.js +0 -21
  131. package/dist/hooks/useWorkspace.d.ts +0 -26
  132. package/dist/hooks/useWorkspace.js +0 -32
  133. package/dist/hooks/useZodForm.d.ts +0 -6
  134. package/dist/hooks/useZodForm.js +0 -6
  135. package/dist/hooks/ws.d.ts +0 -4
  136. package/dist/hooks/ws.js +0 -21
  137. package/dist/lib/perm.d.ts +0 -2
  138. package/dist/lib/perm.js +0 -7
  139. package/dist/lib/ws-query-bridge.d.ts +0 -7
  140. package/dist/lib/ws-query-bridge.js +0 -35
  141. package/dist/provider/PloykitProvider.d.ts +0 -50
  142. package/dist/provider/PloykitProvider.js +0 -240
  143. package/dist/realtime.d.ts +0 -3
  144. package/dist/realtime.js +0 -11
  145. /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, StatusBadge } from '../../components/ui/Badge';
14
- import { Button } from '../../components/ui/Button';
15
- import { Input } from '../../components/ui/Input';
16
- import { useApi, ApiError } from '../../hooks/useApi';
17
- import { useAuth } from '../../hooks/useAuth';
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, StatusBadge } from '../../components/ui/Badge';
12
- import { Button } from '../../components/ui/Button';
13
- import { Input } from '../../components/ui/Input';
14
- import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, } from '../../components/ui/menu';
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 '../../hooks/useApi';
17
- import { useAuth } from '../../hooks/useAuth';
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, StatusBadge } from '../../components/ui/Badge';
9
- import { Button } from '../../components/ui/Button';
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 '../../hooks/useApi';
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/Badge';
14
- import { Button } from '../../components/ui/Button';
15
- import { Input } from '../../components/ui/Input';
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 '../../hooks/useApi';
18
- import { useAuth } from '../../hooks/useAuth';
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/Badge';
9
- import { Button } from '../../components/ui/Button';
10
- import { Input } from '../../components/ui/Input';
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 '../../hooks/useApi';
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'];
@@ -1,4 +1,4 @@
1
- import { ApiError } from '../../hooks/useApi';
1
+ import { ApiError } from '@ploykit/hooks';
2
2
  import { apiErrorMessage } from '../../lib/api-error';
3
3
  export const ADMIN_PAGE_SIZE = 20;
4
4
  export function adminError(err, fallback) {
@@ -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/Button';
6
- import { Input } from '../../components/ui/Input';
7
- import { usePasswordReset } from '../../hooks/usePasswordReset';
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/Button';
5
- import { Badge } from '../../components/ui/Badge';
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 '../../hooks/useMembers';
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-red-600", 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))) })) })] }) }));
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/Button';
7
- import { Input } from '../../components/ui/Input';
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 '../../hooks/useApi';
10
- import { useAuth } from '../../hooks/useAuth';
11
- import { useSiteConfig } from '../../hooks/useSiteConfig';
12
- import { useZodForm } from '../../hooks/useZodForm';
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/Button';
6
- import { Input } from '../../components/ui/Input';
7
- import { usePasswordReset } from '../../hooks/usePasswordReset';
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-emerald-600", 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 ? '提交中…' : '重置密码' })] }))] }) }));
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/Button';
6
- import { Empty, EmptyHeader, EmptyMedia, EmptyTitle, EmptyDescription, EmptyFooter, } from '../../components/ui/empty';
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-emerald-600", "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'
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(EmptyFooter, { children: _jsx("a", { href: "/login", className: buttonVariants({ variant: 'outline' }), children: "\u8FD4\u56DE\u767B\u5F55" }) })] }) }));
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/Button';
11
- import { Badge, StatusBadge } from '../../components/ui/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 '../../hooks/useApi';
14
- import { useBilling } from '../../hooks/useBilling';
15
- import { useSiteConfig } from '../../hooks/useSiteConfig';
16
- import { useWorkspace } from '../../hooks/useWorkspace';
17
- import { queryKeys, } from '../../provider/PloykitProvider';
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 '../../hooks/useApi';
8
- import { useWorkspace } from '../../hooks/useWorkspace';
9
- import { queryKeys } from '../../provider/PloykitProvider';
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/Button';
13
- import { Input } from '../../components/ui/Input';
14
- import { Badge, StatusBadge } from '../../components/ui/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 '../../hooks/useZodForm';
19
- import { useMembers, useMemberMutations, ASSIGNABLE_ROLES, LIST_PAGE_SIZE, } from '../../hooks/useMembers';
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 '../../lib/perm';
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,3 @@
1
+ export interface RolePermissionsPageProps {
2
+ }
3
+ export declare function RolePermissionsPage(_props?: RolePermissionsPageProps): import("react").JSX.Element;
@@ -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/Button';
12
- import { Input } from '../../components/ui/Input';
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 '../../hooks/useApi';
16
- import { useWorkspace } from '../../hooks/useWorkspace';
17
- import { useZodForm } from '../../hooks/useZodForm';
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,4 +1,4 @@
1
- import { type PKUsageItem } from '../../hooks/useUsage';
1
+ import { type PKUsageItem } from '@ploykit/hooks';
2
2
  interface ReservationDetail {
3
3
  id: string;
4
4
  amount: number;
@@ -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/Badge';
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 '../../hooks/useUsage';
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/Button';
13
- import { Input } from '../../components/ui/Input';
14
- import { StatusBadge } from '../../components/ui/Badge';
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 '../../hooks/useApi';
21
- import { useWorkspace } from '../../hooks/useWorkspace';
22
- import { useZodForm } from '../../hooks/useZodForm';
23
- import { queryKeys } from '../../provider/PloykitProvider';
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 '../../lib/perm';
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/Button';
8
- import { Input } from '../../components/ui/Input';
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 '../../hooks/useAudit';
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/Button';
13
- import { Input } from '../../components/ui/Input';
14
- import { useApi } from '../../hooks/useApi';
15
- import { useWorkspace } from '../../hooks/useWorkspace';
16
- import { useZodForm } from '../../hooks/useZodForm';
17
- import { queryKeys } from '../../provider/PloykitProvider';
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 '../../lib/perm';
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.1.1",
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
- "@hookform/resolvers": "^5.9.1",
28
- "@ploykit/client": "^0.2.0",
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 };