@lark-apaas/client-toolkit 1.0.4 → 1.0.6

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 (80) hide show
  1. package/lib/apis/hooks/useTheme.d.ts +1 -0
  2. package/lib/apis/hooks/useTheme.js +1 -0
  3. package/lib/components/AppContainer/LogInterceptor.js +27 -5
  4. package/lib/components/AppContainer/index.js +2 -0
  5. package/lib/components/User/UserDisplay.d.ts +1 -1
  6. package/lib/components/User/UserDisplay.js +101 -25
  7. package/lib/components/User/UserProfile/UserProfile.css +1 -1
  8. package/lib/components/User/UserProfile/UserProfileContainer.d.ts +1 -1
  9. package/lib/components/User/UserProfile/UserProfileSkeleton.d.ts +0 -1
  10. package/lib/components/User/UserProfile/UserProfileSkeleton.js +21 -29
  11. package/lib/components/User/UserProfile/UserProfileUI.d.ts +1 -2
  12. package/lib/components/User/UserProfile/UserProfileUI.js +106 -92
  13. package/lib/components/User/UserSelect.d.ts +1 -1
  14. package/lib/components/User/UserSelect.js +17 -143
  15. package/lib/components/User/UserSelectUI/ActionButtons.d.ts +11 -0
  16. package/lib/components/User/UserSelectUI/ActionButtons.js +44 -0
  17. package/lib/components/User/UserSelectUI/Dropdown.d.ts +12 -0
  18. package/lib/components/User/UserSelectUI/Dropdown.js +66 -0
  19. package/lib/components/User/UserSelectUI/MultipleSelectionTags.d.ts +14 -0
  20. package/lib/components/User/UserSelectUI/MultipleSelectionTags.js +48 -0
  21. package/lib/components/User/UserSelectUI/SingleSelectionPreview.d.ts +9 -0
  22. package/lib/components/User/UserSelectUI/SingleSelectionPreview.js +37 -0
  23. package/lib/components/User/UserSelectUI/Spinner.d.ts +2 -0
  24. package/lib/components/User/UserSelectUI/Spinner.js +13 -0
  25. package/lib/components/User/UserSelectUI/UserSelectUI.d.ts +5 -0
  26. package/lib/components/User/UserSelectUI/UserSelectUI.js +230 -0
  27. package/lib/components/User/UserSelectUI/index.d.ts +2 -0
  28. package/lib/components/User/UserSelectUI/index.js +2 -0
  29. package/lib/components/User/UserSelectUI/types.d.ts +14 -0
  30. package/lib/components/User/UserSelectUI/types.js +0 -0
  31. package/lib/components/User/UserWithAvatar.js +38 -21
  32. package/lib/components/index.d.ts +2 -5
  33. package/lib/components/index.js +2 -3
  34. package/lib/components/ui/avatar.d.ts +6 -0
  35. package/lib/components/ui/avatar.js +27 -0
  36. package/lib/components/ui/badge.d.ts +9 -0
  37. package/lib/components/ui/badge.js +29 -0
  38. package/lib/components/ui/button.d.ts +10 -0
  39. package/lib/components/ui/button.js +42 -0
  40. package/lib/components/ui/input.d.ts +3 -0
  41. package/lib/components/ui/input.js +12 -0
  42. package/lib/components/ui/overflow-tooltip-text.d.ts +8 -0
  43. package/lib/components/ui/overflow-tooltip-text.js +66 -0
  44. package/lib/components/ui/popover.d.ts +7 -0
  45. package/lib/components/ui/popover.js +35 -0
  46. package/lib/components/ui/skeleton.d.ts +7 -0
  47. package/lib/components/ui/skeleton.js +10 -0
  48. package/lib/components/ui/tooltip.d.ts +7 -0
  49. package/lib/components/ui/tooltip.js +24 -0
  50. package/lib/integrations/getAppInfo.js +14 -2
  51. package/lib/logger/__tests__/batch-logger.test.d.ts +1 -0
  52. package/lib/logger/__tests__/batch-logger.test.js +367 -0
  53. package/lib/logger/batch-logger.d.ts +78 -0
  54. package/lib/logger/batch-logger.js +134 -0
  55. package/lib/override.css +0 -16
  56. package/lib/types/index.d.ts +0 -29
  57. package/package.json +7 -1
  58. package/lib/apis/components/SidebarNav.d.ts +0 -1
  59. package/lib/apis/components/SidebarNav.js +0 -2
  60. package/lib/components/SidebarNav/DrawerNav.d.ts +0 -3
  61. package/lib/components/SidebarNav/DrawerNav.js +0 -64
  62. package/lib/components/SidebarNav/DropdownNav.d.ts +0 -3
  63. package/lib/components/SidebarNav/DropdownNav.js +0 -40
  64. package/lib/components/SidebarNav/Sidebar.d.ts +0 -3
  65. package/lib/components/SidebarNav/Sidebar.js +0 -33
  66. package/lib/components/SidebarNav/index.d.ts +0 -5
  67. package/lib/components/SidebarNav/index.js +0 -61
  68. package/lib/components/User/UserSelect.css +0 -11
  69. package/lib/components/common/LogoInfo.d.ts +0 -5
  70. package/lib/components/common/LogoInfo.js +0 -30
  71. package/lib/components/common/NavItem.d.ts +0 -20
  72. package/lib/components/common/NavItem.js +0 -112
  73. package/lib/components/common/NavMenu.d.ts +0 -9
  74. package/lib/components/common/NavMenu.js +0 -50
  75. package/lib/components/common/UserAvatarLayout.d.ts +0 -4
  76. package/lib/components/common/UserAvatarLayout.js +0 -41
  77. package/lib/components/common/UserAvatarMenu.d.ts +0 -4
  78. package/lib/components/common/UserAvatarMenu.js +0 -58
  79. package/lib/components/common/index.d.ts +0 -9
  80. package/lib/components/common/index.js +0 -10
@@ -0,0 +1,230 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useMemo, useRef, useState } from "react";
3
+ import { debounce } from "lodash";
4
+ import { clsxWithTw } from "../../../utils/utils.js";
5
+ import { Input } from "../../ui/input.js";
6
+ import { MultipleSelectionTags } from "./MultipleSelectionTags.js";
7
+ import { SingleSelectionPreview } from "./SingleSelectionPreview.js";
8
+ import { ActionButtons } from "./ActionButtons.js";
9
+ import { Dropdown } from "./Dropdown.js";
10
+ const UserSelectUI = ({ mode = 'single', value, onChange, placeholder = '请选择用户', disabled = false, allowClear = true, onSearch, loading = false, options = [] })=>{
11
+ const [isOpen, setIsOpen] = useState(false);
12
+ const [searchText, setSearchText] = useState('');
13
+ const [searchResults, setSearchResults] = useState([]);
14
+ const [fetching, setFetching] = useState(false);
15
+ const fetchRef = useRef(0);
16
+ const inputRef = useRef(null);
17
+ const isUserSearchingRef = useRef(false);
18
+ const onSearchRef = useRef(onSearch);
19
+ const optionsRef = useRef(options);
20
+ const dropdownInteractionRef = useRef(false);
21
+ const debouncedSearchRef = useRef();
22
+ const triggerRef = useRef(null);
23
+ const inputContainerRef = useRef(null);
24
+ const actionButtonsRef = useRef(null);
25
+ useEffect(()=>{
26
+ onSearchRef.current = onSearch;
27
+ }, [
28
+ onSearch
29
+ ]);
30
+ useEffect(()=>{
31
+ optionsRef.current = options;
32
+ }, [
33
+ options
34
+ ]);
35
+ const selectedUsers = useMemo(()=>{
36
+ if (!value) return [];
37
+ return Array.isArray(value) ? value : [
38
+ value
39
+ ];
40
+ }, [
41
+ value
42
+ ]);
43
+ useEffect(()=>{
44
+ const debounced = debounce(async (searchValue)=>{
45
+ const latestOnSearch = onSearchRef.current;
46
+ const latestOptions = optionsRef.current;
47
+ if (!latestOnSearch) {
48
+ const filtered = latestOptions.filter((user)=>user.name.toLowerCase().includes(searchValue.toLowerCase()));
49
+ setSearchResults(filtered);
50
+ return;
51
+ }
52
+ fetchRef.current += 1;
53
+ const fetchId = fetchRef.current;
54
+ setFetching(true);
55
+ try {
56
+ const results = await latestOnSearch(searchValue);
57
+ if (fetchId === fetchRef.current) setSearchResults(results);
58
+ } catch (error) {
59
+ console.error('Search failed:', error);
60
+ if (fetchId === fetchRef.current) setSearchResults([]);
61
+ } finally{
62
+ if (fetchId === fetchRef.current) setFetching(false);
63
+ }
64
+ }, 500);
65
+ debouncedSearchRef.current = debounced;
66
+ return ()=>{
67
+ debounced.cancel();
68
+ };
69
+ }, []);
70
+ const handleSearch = (value)=>{
71
+ setSearchText(value);
72
+ isUserSearchingRef.current = true;
73
+ if (!isOpen) setIsOpen(true);
74
+ debouncedSearchRef.current?.(value);
75
+ };
76
+ const handleInputFocus = ()=>{
77
+ setIsOpen(true);
78
+ };
79
+ const handleInputBlur = ()=>{
80
+ setTimeout(()=>{
81
+ if ('multiple' === mode && dropdownInteractionRef.current) {
82
+ dropdownInteractionRef.current = false;
83
+ inputRef.current?.focus();
84
+ return;
85
+ }
86
+ dropdownInteractionRef.current = false;
87
+ const inputElement = inputRef.current;
88
+ if (!inputElement || 'undefined' == typeof document) return void setIsOpen(false);
89
+ const activeElement = document.activeElement;
90
+ if (activeElement !== inputElement) setIsOpen(false);
91
+ }, 150);
92
+ };
93
+ const handleSelect = (user)=>{
94
+ if (!onChange) return;
95
+ if ('single' === mode) {
96
+ onChange(user);
97
+ setIsOpen(false);
98
+ setSearchText('');
99
+ isUserSearchingRef.current = false;
100
+ inputRef.current?.blur();
101
+ } else {
102
+ const isAlreadySelected = selectedUsers.some((u)=>u.user_id === user.user_id);
103
+ if (isAlreadySelected) {
104
+ const newValue = selectedUsers.filter((u)=>u.user_id !== user.user_id);
105
+ onChange(newValue);
106
+ } else onChange([
107
+ ...selectedUsers,
108
+ user
109
+ ]);
110
+ isUserSearchingRef.current = false;
111
+ setSearchText('');
112
+ setTimeout(()=>{
113
+ inputRef.current?.focus();
114
+ }, 0);
115
+ }
116
+ };
117
+ const handleRemove = (userId, e)=>{
118
+ e.stopPropagation();
119
+ if (!onChange) return;
120
+ if ('single' === mode) onChange(void 0);
121
+ else {
122
+ const newValue = selectedUsers.filter((u)=>u.user_id !== userId);
123
+ onChange(newValue);
124
+ }
125
+ };
126
+ const handleClear = (e)=>{
127
+ e.stopPropagation();
128
+ if (!onChange) return;
129
+ onChange('single' === mode ? void 0 : []);
130
+ setSearchText('');
131
+ setIsOpen(false);
132
+ };
133
+ const isSelected = (userId)=>selectedUsers.some((u)=>u.user_id === userId);
134
+ const hasSelection = selectedUsers.length > 0;
135
+ const singleSelectedUser = 'single' === mode && hasSelection ? selectedUsers[0] : void 0;
136
+ const showSingleSelection = !!singleSelectedUser && 0 === searchText.length;
137
+ const canClear = allowClear && hasSelection && !disabled;
138
+ const inputPlaceholder = hasSelection ? '' : placeholder;
139
+ const focusInputAtStart = ()=>{
140
+ const input = inputRef.current;
141
+ if (!input) return;
142
+ try {
143
+ input.setSelectionRange(0, 0);
144
+ } catch {}
145
+ };
146
+ const toggleDropdown = ()=>{
147
+ if (disabled) return;
148
+ setIsOpen((prev)=>{
149
+ const next = !prev;
150
+ if (!prev && !disabled) inputRef.current?.focus();
151
+ return next;
152
+ });
153
+ };
154
+ const handleTriggerMouseDown = (event)=>{
155
+ if (disabled) return;
156
+ const target = event.target;
157
+ if (target.closest('[data-select-interactive="true"]')) return;
158
+ if (inputRef.current && (target === inputRef.current || inputRef.current.contains(target))) return;
159
+ event.preventDefault();
160
+ inputRef.current?.focus();
161
+ if ('single' === mode) if ('undefined' != typeof window) window.requestAnimationFrame(()=>focusInputAtStart());
162
+ else focusInputAtStart();
163
+ };
164
+ return /*#__PURE__*/ jsxs("div", {
165
+ className: "relative w-full",
166
+ children: [
167
+ /*#__PURE__*/ jsxs("div", {
168
+ ref: triggerRef,
169
+ className: clsxWithTw('group relative flex w-full flex-wrap items-center gap-2 rounded-md border bg-background text-sm transition-colors', disabled ? 'cursor-not-allowed opacity-50' : '', isOpen ? 'border-primary' : 'border-border'),
170
+ onMouseDown: handleTriggerMouseDown,
171
+ children: [
172
+ /*#__PURE__*/ jsxs("div", {
173
+ className: clsxWithTw('flex-1 flex flex-wrap items-center gap-1 gap-y-0', 'multiple' === mode && hasSelection ? 'pl-1' : 'py-0'),
174
+ children: [
175
+ hasSelection && 'multiple' === mode && /*#__PURE__*/ jsx(MultipleSelectionTags, {
176
+ displayUsers: selectedUsers,
177
+ allUsers: selectedUsers,
178
+ hiddenCount: 0,
179
+ onRemove: handleRemove
180
+ }),
181
+ showSingleSelection && singleSelectedUser && /*#__PURE__*/ jsx(SingleSelectionPreview, {
182
+ user: singleSelectedUser,
183
+ canClear: canClear,
184
+ isOpen: isOpen
185
+ }),
186
+ /*#__PURE__*/ jsx("div", {
187
+ ref: inputContainerRef,
188
+ className: clsxWithTw('relative min-w-[120px] flex-grow', 'multiple' === mode && hasSelection ? 'mr-1' : ''),
189
+ children: /*#__PURE__*/ jsx(Input, {
190
+ ref: inputRef,
191
+ value: searchText,
192
+ onChange: (e)=>handleSearch(e.target.value),
193
+ onFocus: handleInputFocus,
194
+ onBlur: handleInputBlur,
195
+ placeholder: inputPlaceholder,
196
+ disabled: disabled,
197
+ className: clsxWithTw('relative z-[1] h-8 border-0 !bg-transparent text-[14px] shadow-none focus-visible:ring-0 focus-visible:ring-offset-0', 'multiple' === mode && hasSelection ? 'px-0' : 'pl-3 pr-2')
198
+ })
199
+ })
200
+ ]
201
+ }),
202
+ /*#__PURE__*/ jsx(ActionButtons, {
203
+ ref: actionButtonsRef,
204
+ loading: loading,
205
+ canClear: canClear,
206
+ isOpen: isOpen,
207
+ disabled: disabled,
208
+ onClear: handleClear,
209
+ onToggle: toggleDropdown
210
+ })
211
+ ]
212
+ }),
213
+ /*#__PURE__*/ jsx(Dropdown, {
214
+ isOpen: isOpen,
215
+ fetching: fetching,
216
+ searchResults: searchResults,
217
+ onSelect: handleSelect,
218
+ isSelected: isSelected,
219
+ onOptionMouseDown: ()=>{
220
+ if ('multiple' === mode) dropdownInteractionRef.current = true;
221
+ }
222
+ }),
223
+ isOpen && /*#__PURE__*/ jsx("div", {
224
+ className: "fixed inset-0 z-40",
225
+ onClick: ()=>setIsOpen(false)
226
+ })
227
+ ]
228
+ });
229
+ };
230
+ export { UserSelectUI };
@@ -0,0 +1,2 @@
1
+ export { UserSelectUI } from './UserSelectUI';
2
+ export type { UserSelectProps, UserSelectValue } from './types';
@@ -0,0 +1,2 @@
1
+ import { UserSelectUI } from "./UserSelectUI.js";
2
+ export { UserSelectUI };
@@ -0,0 +1,14 @@
1
+ import type { IUserProfile } from '../../../apis/udt-types';
2
+ export type UserSelectValue = IUserProfile | IUserProfile[];
3
+ export interface UserSelectProps {
4
+ value?: UserSelectValue;
5
+ onChange?: (value: UserSelectValue) => void;
6
+ defaultValue?: UserSelectValue;
7
+ mode?: 'single' | 'multiple';
8
+ placeholder?: string;
9
+ disabled?: boolean;
10
+ allowClear?: boolean;
11
+ onSearch?: (searchText: string) => Promise<IUserProfile[]>;
12
+ loading?: boolean;
13
+ options?: IUserProfile[];
14
+ }
File without changes
@@ -1,11 +1,22 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import "react";
3
- import { Avatar, Typography } from "antd";
3
+ import { Avatar, AvatarFallback, AvatarImage } from "../ui/avatar.js";
4
+ import { OverflowTooltipText } from "../ui/overflow-tooltip-text.js";
4
5
  import { clsxWithTw } from "../../utils/utils.js";
5
- const avatarSizeMap = {
6
- small: 16,
7
- medium: 20,
8
- large: 24
6
+ const avatarDimensionClassMap = {
7
+ small: 'h-4 w-4',
8
+ medium: 'h-5 w-5',
9
+ large: 'h-6 w-6'
10
+ };
11
+ const avatarFallbackTextClassMap = {
12
+ small: 'text-[10px]',
13
+ medium: 'text-[12px]',
14
+ large: 'text-[14px]'
15
+ };
16
+ const sizeClassMap = {
17
+ small: 'py-0.5 pl-0.5 pr-1.5 max-w-[148px]',
18
+ medium: 'py-0.5 pl-0.5 pr-2 max-w-[172px]',
19
+ large: 'py-1 pl-1 pr-2.5 max-w-[196px]'
9
20
  };
10
21
  const textVariantMap = {
11
22
  small: 'text-[12px] leading-[16px]',
@@ -14,26 +25,32 @@ const textVariantMap = {
14
25
  };
15
26
  function UserWithAvatar({ data, size = 'medium', mode = 'tag', className }) {
16
27
  const { avatar, name } = data;
17
- const displayName = name || '无效人员';
28
+ const displayName = name?.trim() || '无效人员';
29
+ const formatSize = [
30
+ 'small',
31
+ 'medium',
32
+ 'large'
33
+ ].includes(size) ? size : 'medium';
18
34
  return /*#__PURE__*/ jsxs("div", {
19
- className: clsxWithTw('flex items-center gap-1 rounded-full', {
20
- 'bg-[rgba(31,35,41,0.1)]': 'tag' === mode,
21
- 'py-0.5 pl-0.5 pr-1.5 max-w-[148px]': 'small' === size,
22
- 'py-0.5 pl-0.5 pr-2 max-w-[172px]': 'medium' === size,
23
- 'py-1 pl-1 pr-2.5 max-w-[196px]': 'large' === size
35
+ className: clsxWithTw('flex min-w-0 items-center gap-1 rounded-full', sizeClassMap[formatSize], {
36
+ 'bg-muted': 'tag' === mode
24
37
  }, className),
25
38
  children: [
26
- /*#__PURE__*/ jsx(Avatar, {
27
- src: avatar,
28
- size: avatarSizeMap[size],
29
- className: "shrink-0 border-0"
39
+ /*#__PURE__*/ jsxs(Avatar, {
40
+ className: clsxWithTw(avatarDimensionClassMap[formatSize]),
41
+ children: [
42
+ /*#__PURE__*/ jsx(AvatarImage, {
43
+ src: avatar,
44
+ alt: displayName
45
+ }),
46
+ /*#__PURE__*/ jsx(AvatarFallback, {
47
+ className: clsxWithTw('text-foreground leading-none', avatarFallbackTextClassMap[formatSize])
48
+ })
49
+ ]
30
50
  }),
31
- /*#__PURE__*/ jsx(Typography.Text, {
32
- ellipsis: {
33
- tooltip: displayName
34
- },
35
- className: textVariantMap[size],
36
- children: displayName
51
+ /*#__PURE__*/ jsx(OverflowTooltipText, {
52
+ text: displayName,
53
+ className: clsxWithTw('text-card-foreground', textVariantMap[formatSize])
37
54
  })
38
55
  ]
39
56
  });
@@ -1,8 +1,5 @@
1
- export * from './SidebarNav';
2
- export * from './User';
3
- export * from './SidebarNav';
4
- export * from './User';
5
- export * from './theme';
6
1
  export * from './AppContainer';
7
2
  export * from './ErrorRender';
8
3
  export * from './NotFoundRender';
4
+ export * from './theme';
5
+ export * from './User';
@@ -1,6 +1,5 @@
1
- export * from "./SidebarNav/index.js";
2
- export * from "./User/index.js";
3
- export * from "./theme/index.js";
4
1
  export * from "./AppContainer/index.js";
5
2
  export * from "./ErrorRender/index.js";
6
3
  export * from "./NotFoundRender/index.js";
4
+ export * from "./theme/index.js";
5
+ export * from "./User/index.js";
@@ -0,0 +1,6 @@
1
+ import * as React from "react";
2
+ import * as AvatarPrimitive from "@radix-ui/react-avatar";
3
+ declare function Avatar({ className, ...props }: React.ComponentProps<typeof AvatarPrimitive.Root>): React.JSX.Element;
4
+ declare function AvatarImage({ className, ...props }: React.ComponentProps<typeof AvatarPrimitive.Image>): React.JSX.Element;
5
+ declare function AvatarFallback({ className, ...props }: React.ComponentProps<typeof AvatarPrimitive.Fallback>): React.JSX.Element;
6
+ export { Avatar, AvatarImage, AvatarFallback };
@@ -0,0 +1,27 @@
1
+ "use client"
2
+ import { jsx } from "react/jsx-runtime";
3
+ import "react";
4
+ import { Fallback, Image, Root } from "@radix-ui/react-avatar";
5
+ import { clsxWithTw } from "../../utils/utils.js";
6
+ function Avatar({ className, ...props }) {
7
+ return /*#__PURE__*/ jsx(Root, {
8
+ "data-slot": "avatar",
9
+ className: clsxWithTw("relative flex size-8 shrink-0 overflow-hidden rounded-full", className),
10
+ ...props
11
+ });
12
+ }
13
+ function AvatarImage({ className, ...props }) {
14
+ return /*#__PURE__*/ jsx(Image, {
15
+ "data-slot": "avatar-image",
16
+ className: clsxWithTw("aspect-square size-full", className),
17
+ ...props
18
+ });
19
+ }
20
+ function AvatarFallback({ className, ...props }) {
21
+ return /*#__PURE__*/ jsx(Fallback, {
22
+ "data-slot": "avatar-fallback",
23
+ className: clsxWithTw("bg-muted flex size-full items-center justify-center rounded-full", className),
24
+ ...props
25
+ });
26
+ }
27
+ export { Avatar, AvatarFallback, AvatarImage };
@@ -0,0 +1,9 @@
1
+ import * as React from "react";
2
+ import { type VariantProps } from "class-variance-authority";
3
+ declare const badgeVariants: (props?: {
4
+ variant?: "default" | "secondary" | "destructive" | "outline";
5
+ } & import("class-variance-authority/dist/types").ClassProp) => string;
6
+ declare function Badge({ className, variant, asChild, ...props }: React.ComponentProps<"span"> & VariantProps<typeof badgeVariants> & {
7
+ asChild?: boolean;
8
+ }): React.JSX.Element;
9
+ export { Badge, badgeVariants };
@@ -0,0 +1,29 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import "react";
3
+ import { Slot } from "@radix-ui/react-slot";
4
+ import { cva } from "class-variance-authority";
5
+ import { clsxWithTw } from "../../utils/utils.js";
6
+ const badgeVariants = cva("inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden", {
7
+ variants: {
8
+ variant: {
9
+ default: "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
10
+ secondary: "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
11
+ destructive: "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
12
+ outline: "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground"
13
+ }
14
+ },
15
+ defaultVariants: {
16
+ variant: "default"
17
+ }
18
+ });
19
+ function Badge({ className, variant, asChild = false, ...props }) {
20
+ const Comp = asChild ? Slot : "span";
21
+ return /*#__PURE__*/ jsx(Comp, {
22
+ "data-slot": "badge",
23
+ className: clsxWithTw(badgeVariants({
24
+ variant
25
+ }), className),
26
+ ...props
27
+ });
28
+ }
29
+ export { Badge, badgeVariants };
@@ -0,0 +1,10 @@
1
+ import * as React from "react";
2
+ import { type VariantProps } from "class-variance-authority";
3
+ declare const buttonVariants: (props?: {
4
+ variant?: "default" | "link" | "secondary" | "destructive" | "outline" | "ghost";
5
+ size?: "default" | "icon" | "sm" | "lg" | "icon-sm" | "icon-lg";
6
+ } & import("class-variance-authority/dist/types").ClassProp) => string;
7
+ declare function Button({ className, variant, size, asChild, ...props }: React.ComponentProps<"button"> & VariantProps<typeof buttonVariants> & {
8
+ asChild?: boolean;
9
+ }): React.JSX.Element;
10
+ export { Button, buttonVariants };
@@ -0,0 +1,42 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import "react";
3
+ import { Slot } from "@radix-ui/react-slot";
4
+ import { cva } from "class-variance-authority";
5
+ import { clsxWithTw } from "../../utils/utils.js";
6
+ const buttonVariants = cva("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", {
7
+ variants: {
8
+ variant: {
9
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
10
+ destructive: "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
11
+ outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
12
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
13
+ ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
14
+ link: "text-primary underline-offset-4 hover:underline"
15
+ },
16
+ size: {
17
+ default: "h-9 px-4 py-2 has-[>svg]:px-3",
18
+ sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
19
+ lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
20
+ icon: "size-9",
21
+ "icon-sm": "size-8",
22
+ "icon-lg": "size-10"
23
+ }
24
+ },
25
+ defaultVariants: {
26
+ variant: "default",
27
+ size: "default"
28
+ }
29
+ });
30
+ function Button({ className, variant, size, asChild = false, ...props }) {
31
+ const Comp = asChild ? Slot : "button";
32
+ return /*#__PURE__*/ jsx(Comp, {
33
+ "data-slot": "button",
34
+ className: clsxWithTw(buttonVariants({
35
+ variant,
36
+ size,
37
+ className
38
+ })),
39
+ ...props
40
+ });
41
+ }
42
+ export { Button, buttonVariants };
@@ -0,0 +1,3 @@
1
+ import * as React from "react";
2
+ declare const Input: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "ref"> & React.RefAttributes<HTMLInputElement>>;
3
+ export { Input };
@@ -0,0 +1,12 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { forwardRef } from "react";
3
+ import { clsxWithTw } from "../../utils/utils.js";
4
+ const Input = /*#__PURE__*/ forwardRef(({ className, type, ...props }, ref)=>/*#__PURE__*/ jsx("input", {
5
+ ref: ref,
6
+ type: type,
7
+ "data-slot": "input",
8
+ className: clsxWithTw("file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]", "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", className),
9
+ ...props
10
+ }));
11
+ Input.displayName = "Input";
12
+ export { Input };
@@ -0,0 +1,8 @@
1
+ import * as React from 'react';
2
+ export interface OverflowTooltipTextProps extends React.HTMLAttributes<HTMLSpanElement> {
3
+ text: string;
4
+ }
5
+ /**
6
+ * Displays truncated inline text and shows a tooltip with the full content when overflowed.
7
+ */
8
+ export declare function OverflowTooltipText({ text, className, ...props }: OverflowTooltipTextProps): React.JSX.Element;
@@ -0,0 +1,66 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { useCallback, useEffect, useLayoutEffect, useRef, useState } from "react";
3
+ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "./tooltip.js";
4
+ import { clsxWithTw } from "../../utils/utils.js";
5
+ function OverflowTooltipText({ text, className, ...props }) {
6
+ const textRef = useRef(null);
7
+ const [isOverflowing, setIsOverflowing] = useState(false);
8
+ const checkOverflow = useCallback(()=>{
9
+ const el = textRef.current;
10
+ if (!el) return;
11
+ setIsOverflowing(el.scrollWidth > el.clientWidth + 1);
12
+ }, []);
13
+ useLayoutEffect(()=>{
14
+ checkOverflow();
15
+ }, [
16
+ checkOverflow
17
+ ]);
18
+ useEffect(()=>{
19
+ const el = textRef.current;
20
+ if (!el) return;
21
+ const observer = new ResizeObserver(()=>{
22
+ checkOverflow();
23
+ });
24
+ observer.observe(el);
25
+ return ()=>{
26
+ observer.disconnect();
27
+ };
28
+ }, [
29
+ checkOverflow
30
+ ]);
31
+ useEffect(()=>{
32
+ const handleResize = ()=>{
33
+ checkOverflow();
34
+ };
35
+ window.addEventListener('resize', handleResize);
36
+ return ()=>{
37
+ window.removeEventListener('resize', handleResize);
38
+ };
39
+ }, [
40
+ checkOverflow
41
+ ]);
42
+ const textNode = /*#__PURE__*/ jsx("span", {
43
+ ref: textRef,
44
+ className: clsxWithTw('inline-block truncate', className),
45
+ ...props,
46
+ children: text
47
+ });
48
+ if (!isOverflowing) return textNode;
49
+ return /*#__PURE__*/ jsx(TooltipProvider, {
50
+ children: /*#__PURE__*/ jsxs(Tooltip, {
51
+ delayDuration: 80,
52
+ children: [
53
+ /*#__PURE__*/ jsx(TooltipTrigger, {
54
+ asChild: true,
55
+ children: textNode
56
+ }),
57
+ /*#__PURE__*/ jsx(TooltipContent, {
58
+ sideOffset: 4,
59
+ className: "bg-[rgb(31,35,41)] text-white ring-0",
60
+ children: text
61
+ })
62
+ ]
63
+ })
64
+ });
65
+ }
66
+ export { OverflowTooltipText };
@@ -0,0 +1,7 @@
1
+ import * as React from "react";
2
+ import * as PopoverPrimitive from "@radix-ui/react-popover";
3
+ declare function Popover({ ...props }: React.ComponentProps<typeof PopoverPrimitive.Root>): React.JSX.Element;
4
+ declare function PopoverTrigger({ ...props }: React.ComponentProps<typeof PopoverPrimitive.Trigger>): React.JSX.Element;
5
+ declare function PopoverContent({ className, align, sideOffset, ...props }: React.ComponentProps<typeof PopoverPrimitive.Content>): React.JSX.Element;
6
+ declare function PopoverAnchor({ ...props }: React.ComponentProps<typeof PopoverPrimitive.Anchor>): React.JSX.Element;
7
+ export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor };
@@ -0,0 +1,35 @@
1
+ "use client"
2
+ import { jsx } from "react/jsx-runtime";
3
+ import "react";
4
+ import { Anchor, Content, Portal, Root, Trigger } from "@radix-ui/react-popover";
5
+ import { clsxWithTw } from "../../utils/utils.js";
6
+ function Popover({ ...props }) {
7
+ return /*#__PURE__*/ jsx(Root, {
8
+ "data-slot": "popover",
9
+ ...props
10
+ });
11
+ }
12
+ function PopoverTrigger({ ...props }) {
13
+ return /*#__PURE__*/ jsx(Trigger, {
14
+ "data-slot": "popover-trigger",
15
+ ...props
16
+ });
17
+ }
18
+ function PopoverContent({ className, align = "center", sideOffset = 4, ...props }) {
19
+ return /*#__PURE__*/ jsx(Portal, {
20
+ children: /*#__PURE__*/ jsx(Content, {
21
+ "data-slot": "popover-content",
22
+ align: align,
23
+ sideOffset: sideOffset,
24
+ className: clsxWithTw("bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 origin-(--radix-popover-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden", className),
25
+ ...props
26
+ })
27
+ });
28
+ }
29
+ function PopoverAnchor({ ...props }) {
30
+ return /*#__PURE__*/ jsx(Anchor, {
31
+ "data-slot": "popover-anchor",
32
+ ...props
33
+ });
34
+ }
35
+ export { Popover, PopoverAnchor, PopoverContent, PopoverTrigger };
@@ -0,0 +1,7 @@
1
+ import * as React from 'react';
2
+ export type SkeletonProps = React.HTMLAttributes<HTMLDivElement>;
3
+ /**
4
+ * Minimal shadcn/ui-compatible Skeleton primitive.
5
+ * Mirrors the upstream API so that downstream components can swap in seamlessly.
6
+ */
7
+ export declare const Skeleton: React.ForwardRefExoticComponent<SkeletonProps & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,10 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { forwardRef } from "react";
3
+ import { clsxWithTw } from "../../utils/utils.js";
4
+ const Skeleton = /*#__PURE__*/ forwardRef(({ className, ...props }, ref)=>/*#__PURE__*/ jsx("div", {
5
+ ref: ref,
6
+ className: clsxWithTw('animate-pulse rounded-md bg-accent', className),
7
+ ...props
8
+ }));
9
+ Skeleton.displayName = 'Skeleton';
10
+ export { Skeleton };
@@ -0,0 +1,7 @@
1
+ import * as React from 'react';
2
+ import * as TooltipPrimitive from '@radix-ui/react-tooltip';
3
+ declare const TooltipProvider: React.FC<TooltipPrimitive.TooltipProviderProps>;
4
+ declare const Tooltip: React.FC<TooltipPrimitive.TooltipProps>;
5
+ declare const TooltipTrigger: React.ForwardRefExoticComponent<TooltipPrimitive.TooltipTriggerProps & React.RefAttributes<HTMLButtonElement>>;
6
+ declare const TooltipContent: React.ForwardRefExoticComponent<Omit<TooltipPrimitive.TooltipContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
7
+ export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };