@lark-apaas/client-toolkit 0.1.0-alpha.1 → 0.1.0-alpha.log.10
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 +1 -1
- package/lib/apis/hooks/useTheme.d.ts +1 -0
- package/lib/apis/hooks/useTheme.js +1 -0
- package/lib/components/AppContainer/LogInterceptor.js +3 -0
- package/lib/components/AppContainer/PageHoc.js +3 -0
- package/lib/components/AppContainer/index.js +4 -0
- package/lib/components/AppContainer/utils/childApi.js +13 -1
- package/lib/components/ErrorRender/index.js +28 -18
- package/lib/components/User/UserDisplay.d.ts +1 -1
- package/lib/components/User/UserDisplay.js +101 -25
- package/lib/components/User/UserProfile/UserProfile.css +1 -1
- package/lib/components/User/UserProfile/UserProfileContainer.d.ts +1 -1
- package/lib/components/User/UserProfile/UserProfileSkeleton.d.ts +0 -1
- package/lib/components/User/UserProfile/UserProfileSkeleton.js +21 -29
- package/lib/components/User/UserProfile/UserProfileUI.d.ts +1 -2
- package/lib/components/User/UserProfile/UserProfileUI.js +106 -92
- package/lib/components/User/UserSelect.d.ts +1 -1
- package/lib/components/User/UserSelect.js +17 -143
- package/lib/components/User/UserSelectUI/ActionButtons.d.ts +11 -0
- package/lib/components/User/UserSelectUI/ActionButtons.js +44 -0
- package/lib/components/User/UserSelectUI/Dropdown.d.ts +12 -0
- package/lib/components/User/UserSelectUI/Dropdown.js +66 -0
- package/lib/components/User/UserSelectUI/MultipleSelectionTags.d.ts +14 -0
- package/lib/components/User/UserSelectUI/MultipleSelectionTags.js +48 -0
- package/lib/components/User/UserSelectUI/SingleSelectionPreview.d.ts +9 -0
- package/lib/components/User/UserSelectUI/SingleSelectionPreview.js +37 -0
- package/lib/components/User/UserSelectUI/Spinner.d.ts +2 -0
- package/lib/components/User/UserSelectUI/Spinner.js +13 -0
- package/lib/components/User/UserSelectUI/UserSelectUI.d.ts +5 -0
- package/lib/components/User/UserSelectUI/UserSelectUI.js +230 -0
- package/lib/components/User/UserSelectUI/index.d.ts +2 -0
- package/lib/components/User/UserSelectUI/index.js +2 -0
- package/lib/components/User/UserSelectUI/types.d.ts +14 -0
- package/lib/components/User/UserSelectUI/types.js +0 -0
- package/lib/components/User/UserWithAvatar.js +38 -21
- package/lib/components/index.d.ts +2 -5
- package/lib/components/index.js +2 -3
- package/lib/components/ui/avatar.d.ts +6 -0
- package/lib/components/ui/avatar.js +27 -0
- package/lib/components/ui/badge.d.ts +9 -0
- package/lib/components/ui/badge.js +29 -0
- package/lib/components/ui/button.d.ts +10 -0
- package/lib/components/ui/button.js +42 -0
- package/lib/components/ui/input.d.ts +3 -0
- package/lib/components/ui/input.js +12 -0
- package/lib/components/ui/overflow-tooltip-text.d.ts +8 -0
- package/lib/components/ui/overflow-tooltip-text.js +66 -0
- package/lib/components/ui/popover.d.ts +7 -0
- package/lib/components/ui/popover.js +35 -0
- package/lib/components/ui/skeleton.d.ts +7 -0
- package/lib/components/ui/skeleton.js +10 -0
- package/lib/components/ui/tooltip.d.ts +7 -0
- package/lib/components/ui/tooltip.js +24 -0
- package/lib/integrations/getAppInfo.js +11 -1
- package/lib/logger/__tests__/batch-logger.test.d.ts +1 -0
- package/lib/logger/__tests__/batch-logger.test.js +367 -0
- package/lib/logger/batch-logger.d.ts +77 -0
- package/lib/logger/batch-logger.js +131 -0
- package/lib/override.css +0 -16
- package/lib/types/iframe-events.d.ts +1 -0
- package/lib/types/index.d.ts +0 -29
- package/lib/utils/axiosConfig.d.ts +5 -0
- package/lib/utils/axiosConfig.js +60 -0
- package/package.json +10 -4
- package/lib/apis/components/SidebarNav.d.ts +0 -1
- package/lib/apis/components/SidebarNav.js +0 -2
- package/lib/components/SidebarNav/DrawerNav.d.ts +0 -3
- package/lib/components/SidebarNav/DrawerNav.js +0 -64
- package/lib/components/SidebarNav/DropdownNav.d.ts +0 -3
- package/lib/components/SidebarNav/DropdownNav.js +0 -40
- package/lib/components/SidebarNav/Sidebar.d.ts +0 -3
- package/lib/components/SidebarNav/Sidebar.js +0 -33
- package/lib/components/SidebarNav/index.d.ts +0 -5
- package/lib/components/SidebarNav/index.js +0 -61
- package/lib/components/User/UserSelect.css +0 -11
- package/lib/components/common/LogoInfo.d.ts +0 -5
- package/lib/components/common/LogoInfo.js +0 -30
- package/lib/components/common/NavItem.d.ts +0 -20
- package/lib/components/common/NavItem.js +0 -112
- package/lib/components/common/NavMenu.d.ts +0 -9
- package/lib/components/common/NavMenu.js +0 -50
- package/lib/components/common/UserAvatarLayout.d.ts +0 -4
- package/lib/components/common/UserAvatarLayout.js +0 -41
- package/lib/components/common/UserAvatarMenu.d.ts +0 -4
- package/lib/components/common/UserAvatarMenu.js +0 -58
- package/lib/components/common/index.d.ts +0 -9
- 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,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,
|
|
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
|
|
6
|
-
small:
|
|
7
|
-
medium:
|
|
8
|
-
large:
|
|
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-
|
|
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__*/
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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(
|
|
32
|
-
|
|
33
|
-
|
|
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';
|
package/lib/components/index.js
CHANGED
|
@@ -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,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 };
|