@rolder/kit 3.0.0-alpha.8 → 3.0.0-alpha.81
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/dist/ai/index.d.ts +2 -0
- package/dist/ai/index.js +2 -0
- package/dist/ai/ui/chat/Empty.d.ts +1 -0
- package/dist/ai/ui/chat/Empty.js +21 -0
- package/dist/ai/ui/chat/File.d.ts +3 -0
- package/dist/ai/ui/chat/File.js +43 -0
- package/dist/ai/ui/chat/FileIcon.d.ts +3 -0
- package/dist/ai/ui/chat/FileIcon.js +43 -0
- package/dist/ai/ui/chat/Loader.d.ts +2 -0
- package/dist/ai/ui/chat/Loader.js +13 -0
- package/dist/ai/ui/chat/Message.d.ts +3 -0
- package/dist/ai/ui/chat/Message.js +23 -0
- package/dist/ai/ui/chat/Messages.d.ts +2 -0
- package/dist/ai/ui/chat/Messages.js +27 -0
- package/dist/ai/ui/chat/Root.d.ts +49 -0
- package/dist/ai/ui/chat/Root.js +18 -0
- package/dist/ai/ui/chat/chatInput/File.d.ts +2 -0
- package/dist/ai/ui/chat/chatInput/File.js +71 -0
- package/dist/ai/ui/chat/chatInput/FileIcon.d.ts +3 -0
- package/dist/ai/ui/chat/chatInput/FileIcon.js +43 -0
- package/dist/ai/ui/chat/chatInput/Footer.d.ts +2 -0
- package/dist/ai/ui/chat/chatInput/Footer.js +8 -0
- package/dist/ai/ui/chat/chatInput/Root.d.ts +9 -0
- package/dist/ai/ui/chat/chatInput/Root.js +24 -0
- package/dist/ai/ui/chat/chatInput/Submit.d.ts +2 -0
- package/dist/ai/ui/chat/chatInput/Submit.js +23 -0
- package/dist/ai/ui/chat/chatInput/Textarea.d.ts +2 -0
- package/dist/ai/ui/chat/chatInput/Textarea.js +34 -0
- package/dist/ai/ui/chat/chatInput/index.d.ts +7 -0
- package/dist/ai/ui/chat/chatInput/index.js +13 -0
- package/dist/ai/ui/chat/chatInput/store/file.d.ts +8 -0
- package/dist/ai/ui/chat/chatInput/store/file.js +32 -0
- package/dist/ai/ui/chat/chatInput/store/fileErrorNotificaton.d.ts +2 -0
- package/dist/ai/ui/chat/chatInput/store/fileErrorNotificaton.js +21 -0
- package/dist/ai/ui/chat/chatInput/store/index.d.ts +2 -0
- package/dist/ai/ui/chat/chatInput/store/index.js +2 -0
- package/dist/ai/ui/chat/chatInput/store/input.d.ts +13 -0
- package/dist/ai/ui/chat/chatInput/store/input.js +81 -0
- package/dist/ai/ui/chat/chatInput/store/parseFile.d.ts +2 -0
- package/dist/ai/ui/chat/chatInput/store/parseFile.js +23 -0
- package/dist/ai/ui/chat/index.d.ts +13 -0
- package/dist/ai/ui/chat/index.js +15 -0
- package/dist/ai/ui/chat/store/index.d.ts +5 -0
- package/dist/ai/ui/chat/store/index.js +5 -0
- package/dist/ai/ui/chat/store/messageIds.d.ts +8 -0
- package/dist/ai/ui/chat/store/messageIds.js +41 -0
- package/dist/ai/ui/chat/store/messagesMap.d.ts +5 -0
- package/dist/ai/ui/chat/store/messagesMap.js +15 -0
- package/dist/ai/ui/chat/store/send.d.ts +14 -0
- package/dist/ai/ui/chat/store/send.js +16 -0
- package/dist/ai/ui/chat/store/states.d.ts +11 -0
- package/dist/ai/ui/chat/store/states.js +17 -0
- package/dist/ai/ui/chat/store/useInitChat.d.ts +3 -0
- package/dist/ai/ui/chat/store/useInitChat.js +40 -0
- package/dist/ai/ui/index.d.ts +1 -0
- package/dist/ai/ui/index.js +1 -0
- package/dist/ai/utils/convertFileUIPartBlobToDataURL.d.ts +5 -0
- package/dist/ai/utils/convertFileUIPartBlobToDataURL.js +21 -0
- package/dist/ai/utils/index.d.ts +2 -0
- package/dist/ai/utils/index.js +2 -0
- package/dist/ai/utils/parseAiMessagePart.d.ts +2 -0
- package/dist/ai/utils/parseAiMessagePart.js +12 -0
- package/dist/app/AppDefaults.d.ts +3 -0
- package/dist/app/AppDefaults.js +27 -0
- package/dist/app/DefaultApp.d.ts +6 -0
- package/dist/app/DefaultApp.js +43 -0
- package/dist/app/cookieColorSchemeManager.d.ts +6 -0
- package/dist/app/cookieColorSchemeManager.js +46 -0
- package/dist/app/defaultRequestMiddlewares.d.ts +4 -0
- package/dist/app/defaultRequestMiddlewares.js +24 -0
- package/dist/app/defaultTheme.d.ts +141 -0
- package/dist/app/defaultTheme.js +24 -0
- package/dist/app/index.d.ts +4 -0
- package/dist/app/index.js +4 -0
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.js +2 -0
- package/dist/hooks/useMutation.d.ts +4 -0
- package/dist/hooks/useMutation.js +8 -0
- package/dist/hooks/useMutationWithInvalidate.d.ts +4 -0
- package/dist/hooks/useMutationWithInvalidate.js +16 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/{src → dist}/styles.css +14 -29
- package/dist/tanstackFunctions/cookie/getCookie.d.ts +3 -0
- package/dist/tanstackFunctions/cookie/getCookie.js +8 -0
- package/dist/tanstackFunctions/cookie/index.d.ts +3 -0
- package/dist/tanstackFunctions/cookie/index.js +4 -0
- package/dist/tanstackFunctions/cookie/setCookie.d.ts +10 -0
- package/dist/tanstackFunctions/cookie/setCookie.js +19 -0
- package/dist/tanstackFunctions/cookie/setCookies.d.ts +14 -0
- package/dist/tanstackFunctions/cookie/setCookies.js +13 -0
- package/dist/tanstackFunctions/index.d.ts +3 -0
- package/dist/tanstackFunctions/index.js +3 -0
- package/dist/tanstackFunctions/s3/getS3Client.d.ts +2 -0
- package/dist/tanstackFunctions/s3/getS3Client.js +18 -0
- package/dist/tanstackFunctions/s3/getSignedFileUrlFn.d.ts +4 -0
- package/dist/tanstackFunctions/s3/getSignedFileUrlFn.js +21 -0
- package/dist/tanstackFunctions/s3/index.d.ts +2 -0
- package/dist/tanstackFunctions/s3/index.js +2 -0
- package/dist/tanstackFunctions/s3/uploadRequest.d.ts +3 -0
- package/dist/tanstackFunctions/s3/uploadRequest.js +21 -0
- package/dist/tanstackFunctions/surreal/connection.d.ts +9 -0
- package/dist/tanstackFunctions/surreal/connection.js +49 -0
- package/dist/tanstackFunctions/surreal/deafaultCrud.d.ts +2 -0
- package/dist/tanstackFunctions/surreal/deafaultCrud.js +18 -0
- package/dist/tanstackFunctions/surreal/deserialize.d.ts +17 -0
- package/dist/tanstackFunctions/surreal/deserialize.js +46 -0
- package/dist/tanstackFunctions/surreal/encryption.d.ts +6 -0
- package/dist/tanstackFunctions/surreal/encryption.js +30 -0
- package/dist/tanstackFunctions/surreal/index.d.ts +4 -0
- package/dist/tanstackFunctions/surreal/index.js +4 -0
- package/dist/ui/AnimatedChevron.d.ts +6 -0
- package/dist/ui/AnimatedChevron.js +13 -0
- package/dist/ui/JsonInput.d.ts +2 -0
- package/dist/ui/JsonInput.js +45 -0
- package/dist/ui/RouterLink.d.ts +16 -0
- package/dist/ui/RouterLink.js +36 -0
- package/dist/ui/editor/Content.d.ts +3 -0
- package/dist/ui/editor/Content.js +13 -0
- package/dist/ui/editor/Root.d.ts +8 -0
- package/dist/ui/editor/Root.js +55 -0
- package/dist/ui/editor/Toolbar.d.ts +5 -0
- package/dist/ui/editor/Toolbar.js +138 -0
- package/dist/ui/editor/index.d.ts +11 -0
- package/dist/ui/editor/index.js +10 -0
- package/dist/ui/editor/store.d.ts +6 -0
- package/dist/ui/editor/store.js +10 -0
- package/dist/ui/error/DefaultError.d.ts +2 -0
- package/dist/ui/error/DefaultError.js +62 -0
- package/dist/ui/error/DefaultNotFound.d.ts +1 -0
- package/dist/ui/error/DefaultNotFound.js +37 -0
- package/dist/ui/error/Forbidden.d.ts +1 -0
- package/dist/ui/error/Forbidden.js +32 -0
- package/dist/ui/error/defaultErrorNotification.d.ts +1 -0
- package/dist/ui/error/defaultErrorNotification.js +8 -0
- package/dist/ui/error/index.js +5 -0
- package/dist/ui/form/blurOnError.d.ts +4 -0
- package/dist/ui/form/blurOnError.js +11 -0
- package/dist/ui/form/buttons/CancelButton.d.ts +5 -0
- package/dist/ui/form/buttons/CancelButton.js +22 -0
- package/dist/ui/form/buttons/SubmitButton.d.ts +5 -0
- package/dist/ui/form/buttons/SubmitButton.js +22 -0
- package/dist/ui/form/buttons/SubscribeActionIcon.d.ts +4 -0
- package/dist/ui/form/buttons/SubscribeActionIcon.js +15 -0
- package/dist/ui/form/buttons/SubscribeButton.d.ts +5 -0
- package/dist/ui/form/buttons/SubscribeButton.js +16 -0
- package/dist/ui/form/buttons/index.js +4 -0
- package/dist/ui/form/context.d.ts +83 -0
- package/dist/ui/form/context.js +26 -0
- package/dist/ui/form/fields/JsonField.d.ts +2 -0
- package/dist/ui/form/fields/JsonField.js +13 -0
- package/dist/ui/form/fields/MultiSelectField.d.ts +2 -0
- package/dist/ui/form/fields/MultiSelectField.js +15 -0
- package/dist/ui/form/fields/NumberField.d.ts +2 -0
- package/dist/ui/form/fields/NumberField.js +15 -0
- package/dist/ui/form/fields/PassowrdField.d.ts +2 -0
- package/dist/ui/form/fields/PassowrdField.js +18 -0
- package/dist/ui/form/fields/SelectField.d.ts +2 -0
- package/dist/ui/form/fields/SelectField.js +15 -0
- package/dist/ui/form/fields/SwitchField.d.ts +2 -0
- package/dist/ui/form/fields/SwitchField.js +15 -0
- package/dist/ui/form/fields/TextField.d.ts +2 -0
- package/dist/ui/form/fields/TextField.js +15 -0
- package/dist/ui/form/fields/TextPassowrdField.d.ts +2 -0
- package/dist/ui/form/fields/TextPassowrdField.js +29 -0
- package/dist/ui/form/fields/TextareaField.d.ts +2 -0
- package/dist/ui/form/fields/TextareaField.js +15 -0
- package/dist/ui/form/fields/index.js +9 -0
- package/dist/ui/form/fieldsSchema.d.ts +12 -0
- package/dist/ui/form/fieldsSchema.js +13 -0
- package/dist/ui/form/index.js +4 -0
- package/dist/ui/hoverPaper/HoverPaper.d.ts +6 -0
- package/dist/ui/hoverPaper/HoverPaper.js +15 -0
- package/dist/ui/hoverPaper/index.js +3 -0
- package/dist/ui/hoverPaper/usePaperHover.d.ts +4 -0
- package/dist/ui/hoverPaper/usePaperHover.js +9 -0
- package/dist/ui/index.d.ts +9 -0
- package/dist/ui/index.js +9 -0
- package/dist/ui/saveInput/JsonInput.d.ts +6 -0
- package/dist/ui/saveInput/JsonInput.js +34 -0
- package/dist/ui/saveInput/NumberInput.d.ts +6 -0
- package/dist/ui/saveInput/NumberInput.js +27 -0
- package/dist/ui/saveInput/SaveInput.d.ts +36 -0
- package/dist/ui/saveInput/SaveInput.js +15 -0
- package/dist/ui/saveInput/Select.d.ts +6 -0
- package/dist/ui/saveInput/Select.js +27 -0
- package/dist/ui/saveInput/Switch.d.ts +6 -0
- package/dist/ui/saveInput/Switch.js +30 -0
- package/dist/ui/saveInput/TextInput.d.ts +6 -0
- package/dist/ui/saveInput/TextInput.js +26 -0
- package/dist/ui/saveInput/Textarea.d.ts +6 -0
- package/dist/ui/saveInput/Textarea.js +26 -0
- package/dist/ui/saveInput/index.js +2 -0
- package/dist/ui/scrollArea/Root.d.ts +7 -0
- package/dist/ui/scrollArea/Root.js +42 -0
- package/dist/ui/scrollArea/ScrollButton.d.ts +10 -0
- package/dist/ui/scrollArea/ScrollButton.js +30 -0
- package/dist/ui/scrollArea/index.d.ts +6 -0
- package/dist/ui/scrollArea/index.js +7 -0
- package/dist/ui/scrollArea/methods.d.ts +4 -0
- package/dist/ui/scrollArea/methods.js +32 -0
- package/dist/ui/scrollArea/store.d.ts +12 -0
- package/dist/ui/scrollArea/store.js +25 -0
- package/package.json +40 -28
- package/rslib.config.ts +0 -21
- package/src/ai/ui/conversation/ConversationContext.ts +0 -21
- package/src/ai/ui/conversation/ConversationProvider.tsx +0 -21
- package/src/ai/ui/conversation/Empty.tsx +0 -15
- package/src/ai/ui/conversation/File.tsx +0 -40
- package/src/ai/ui/conversation/FileIcon.tsx +0 -143
- package/src/ai/ui/conversation/Loader.tsx +0 -8
- package/src/ai/ui/conversation/Message.tsx +0 -34
- package/src/ai/ui/conversation/Root.tsx +0 -24
- package/src/ai/ui/conversation/index.ts +0 -16
- package/src/ai/ui/conversation/types.ts +0 -8
- package/src/ai/ui/conversation/useChatMessage.ts +0 -13
- package/src/ai/ui/promptInput/File.tsx +0 -98
- package/src/ai/ui/promptInput/FileIcon.tsx +0 -149
- package/src/ai/ui/promptInput/Footer.tsx +0 -5
- package/src/ai/ui/promptInput/PromptInputContext.ts +0 -24
- package/src/ai/ui/promptInput/PromptInputProvider.tsx +0 -54
- package/src/ai/ui/promptInput/Root.tsx +0 -29
- package/src/ai/ui/promptInput/Submit.tsx +0 -39
- package/src/ai/ui/promptInput/Textarea.tsx +0 -39
- package/src/ai/ui/promptInput/index.ts +0 -15
- package/src/ai/ui/promptInput/types.ts +0 -9
- package/src/ai/utils/convertFileUIPartBlobToDataURL.ts +0 -29
- package/src/ai/utils/parseAiMessagePart.ts +0 -19
- package/src/app/AppDefaults.tsx +0 -21
- package/src/app/DefaultApp.tsx +0 -50
- package/src/app/cookieColorSchemeManager.ts +0 -70
- package/src/app/defaultRequestMiddlewares.ts +0 -22
- package/src/app/defaultTheme.ts +0 -22
- package/src/functions/getCookie.ts +0 -36
- package/src/functions/setCookie.ts +0 -29
- package/src/functions/setCookies.ts +0 -24
- package/src/hooks/useMutation.ts +0 -14
- package/src/hooks/useMutationWithInvalidate.ts +0 -23
- package/src/index.ts +0 -66
- package/src/surreal/connection.ts +0 -72
- package/src/surreal/deafaultCrud.ts +0 -25
- package/src/surreal/deserialize.ts +0 -144
- package/src/surreal/encryption.ts +0 -51
- package/src/ui/AnimatedChevron.tsx +0 -32
- package/src/ui/JsonInput.tsx +0 -52
- package/src/ui/RouterLink.tsx +0 -78
- package/src/ui/editor/Content.tsx +0 -11
- package/src/ui/editor/Provider.tsx +0 -96
- package/src/ui/editor/Root.tsx +0 -25
- package/src/ui/editor/Toolbar.tsx +0 -92
- package/src/ui/editor/index.ts +0 -13
- package/src/ui/editor/types.ts +0 -7
- package/src/ui/error/DefaultError.tsx +0 -60
- package/src/ui/error/DefaultNotFound.tsx +0 -19
- package/src/ui/error/Forbidden.tsx +0 -18
- package/src/ui/error/defaultErrorNotification.ts +0 -9
- package/src/ui/form/blurOnError.ts +0 -21
- package/src/ui/form/buttons/CancelButton.tsx +0 -42
- package/src/ui/form/buttons/SubmitButton.tsx +0 -43
- package/src/ui/form/buttons/SubscribeActionIcon.tsx +0 -18
- package/src/ui/form/buttons/SubscribeButton.tsx +0 -17
- package/src/ui/form/context.ts +0 -45
- package/src/ui/form/fields/JsonField.tsx +0 -16
- package/src/ui/form/fields/MultiSelectField.tsx +0 -17
- package/src/ui/form/fields/NumberField.tsx +0 -17
- package/src/ui/form/fields/PassowrdField.tsx +0 -20
- package/src/ui/form/fields/SelectField.tsx +0 -17
- package/src/ui/form/fields/SwitchField.tsx +0 -17
- package/src/ui/form/fields/TextField.tsx +0 -17
- package/src/ui/form/fields/TextPassowrdField.tsx +0 -51
- package/src/ui/form/fields/TextareaField.tsx +0 -17
- package/src/ui/form/fieldsSchema.ts +0 -24
- package/src/ui/hoverPaper/HoverPaper.tsx +0 -17
- package/src/ui/hoverPaper/usePaperHover.ts +0 -9
- package/src/ui/saveInput/JsonInput.tsx +0 -40
- package/src/ui/saveInput/NumberInput.tsx +0 -40
- package/src/ui/saveInput/SaveInput.tsx +0 -15
- package/src/ui/saveInput/Select.tsx +0 -41
- package/src/ui/saveInput/Switch.tsx +0 -46
- package/src/ui/saveInput/TextInput.tsx +0 -40
- package/src/ui/saveInput/Textarea.tsx +0 -40
- package/src/ui/scrollArea/ARCH.md +0 -204
- package/src/ui/scrollArea/README.md +0 -369
- package/src/ui/scrollArea/ScrollArea.tsx +0 -93
- package/src/ui/scrollArea/ScrollAreaButton.tsx +0 -56
- package/src/ui/scrollArea/ScrollAreaContent.tsx +0 -36
- package/src/ui/scrollArea/context.tsx +0 -43
- package/src/ui/scrollArea/index.ts +0 -10
- package/src/ui/scrollArea/types.ts +0 -77
- package/src/ui/scrollArea/useScrollArea.ts +0 -227
- package/tsconfig.json +0 -14
- /package/{src/ui/error/index.ts → dist/ui/error/index.d.ts} +0 -0
- /package/{src/ui/form/buttons/index.ts → dist/ui/form/buttons/index.d.ts} +0 -0
- /package/{src/ui/form/fields/index.ts → dist/ui/form/fields/index.d.ts} +0 -0
- /package/{src/ui/form/index.ts → dist/ui/form/index.d.ts} +0 -0
- /package/{src/ui/hoverPaper/index.ts → dist/ui/hoverPaper/index.d.ts} +0 -0
- /package/{src/ui/saveInput/index.ts → dist/ui/saveInput/index.d.ts} +0 -0
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Loader,
|
|
3
|
-
TextInput as MantineTextInput,
|
|
4
|
-
type TextInputProps,
|
|
5
|
-
} from '@mantine/core';
|
|
6
|
-
import { useDebouncedCallback } from '@mantine/hooks';
|
|
7
|
-
import { useState } from 'react';
|
|
8
|
-
|
|
9
|
-
export const TextInput = ({
|
|
10
|
-
initialValue,
|
|
11
|
-
onChange,
|
|
12
|
-
debounce = 300,
|
|
13
|
-
...props
|
|
14
|
-
}: {
|
|
15
|
-
initialValue?: string;
|
|
16
|
-
onChange: (value: string) => Promise<void>;
|
|
17
|
-
debounce?: number;
|
|
18
|
-
} & Omit<TextInputProps, 'value' | 'onChange'>) => {
|
|
19
|
-
const [value, setValue] = useState(initialValue || '');
|
|
20
|
-
const [loading, setLoading] = useState(false);
|
|
21
|
-
|
|
22
|
-
const handleSave = useDebouncedCallback(async (content: string) => {
|
|
23
|
-
setLoading(true);
|
|
24
|
-
await onChange(content);
|
|
25
|
-
setLoading(false);
|
|
26
|
-
}, debounce);
|
|
27
|
-
|
|
28
|
-
return (
|
|
29
|
-
<MantineTextInput
|
|
30
|
-
value={value}
|
|
31
|
-
onChange={(e) => {
|
|
32
|
-
setValue(e.target.value);
|
|
33
|
-
handleSave(e.target.value);
|
|
34
|
-
}}
|
|
35
|
-
flex={props.w ? undefined : 1}
|
|
36
|
-
rightSection={loading ? <Loader size="sm" /> : undefined}
|
|
37
|
-
{...props}
|
|
38
|
-
/>
|
|
39
|
-
);
|
|
40
|
-
};
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Loader,
|
|
3
|
-
Textarea as MantineTextarea,
|
|
4
|
-
type TextareaProps,
|
|
5
|
-
} from '@mantine/core';
|
|
6
|
-
import { useDebouncedCallback } from '@mantine/hooks';
|
|
7
|
-
import { useState } from 'react';
|
|
8
|
-
|
|
9
|
-
export const Textarea = ({
|
|
10
|
-
initialValue,
|
|
11
|
-
onChange,
|
|
12
|
-
debounce = 300,
|
|
13
|
-
...props
|
|
14
|
-
}: {
|
|
15
|
-
initialValue: string;
|
|
16
|
-
onChange: (value: string) => Promise<void>;
|
|
17
|
-
debounce?: number;
|
|
18
|
-
} & Omit<TextareaProps, 'value' | 'onChange'>) => {
|
|
19
|
-
const [value, setValue] = useState(initialValue);
|
|
20
|
-
const [loading, setLoading] = useState(false);
|
|
21
|
-
|
|
22
|
-
const handleSave = useDebouncedCallback(async (content: string) => {
|
|
23
|
-
setLoading(true);
|
|
24
|
-
await onChange(content);
|
|
25
|
-
setLoading(false);
|
|
26
|
-
}, debounce);
|
|
27
|
-
|
|
28
|
-
return (
|
|
29
|
-
<MantineTextarea
|
|
30
|
-
value={value}
|
|
31
|
-
onChange={(e) => {
|
|
32
|
-
setValue(e.target.value);
|
|
33
|
-
handleSave(e.target.value);
|
|
34
|
-
}}
|
|
35
|
-
flex={props.w ? undefined : 1}
|
|
36
|
-
rightSection={loading ? <Loader size="sm" /> : undefined}
|
|
37
|
-
{...props}
|
|
38
|
-
/>
|
|
39
|
-
);
|
|
40
|
-
};
|
|
@@ -1,204 +0,0 @@
|
|
|
1
|
-
# ScrollArea Component - Техническое задание
|
|
2
|
-
|
|
3
|
-
Компонент расширенной области прокрутки с автоматическим скроллом и интеллектуальным управлением позиционированием на базе Mantine Scrollarea.
|
|
4
|
-
|
|
5
|
-
## Архитектура компонента
|
|
6
|
-
|
|
7
|
-
### Составная структура
|
|
8
|
-
|
|
9
|
-
- `ScrollArea` - корневой контейнер с провайдером контекста
|
|
10
|
-
- `ScrollArea.ScrollButton` - опциональная адаптивная кнопка управления прокруткой
|
|
11
|
-
- `ScrollArea.Provider` - контекст для передачи состояния между компонентами
|
|
12
|
-
- `ScrollArea.Content` - внутренний приватный компонент (не экспортируется)
|
|
13
|
-
|
|
14
|
-
## Интерфейсы и типы
|
|
15
|
-
|
|
16
|
-
### Основные пропсы ScrollArea
|
|
17
|
-
|
|
18
|
-
```typescript
|
|
19
|
-
interface ScrollAreaProps extends Omit<MantineScrollAreaProps, "children"> {
|
|
20
|
-
autoScroll?: boolean; // Включение автоскролла (по умолчанию false)
|
|
21
|
-
scrollToBottomOnInit?: boolean; // Прокрутить к концу при инициализации (по умолчанию false)
|
|
22
|
-
animated?: boolean; // Анимированная прокрутка (по умолчанию true)
|
|
23
|
-
nearThreshold?: number; // Отступ для near-зон в пикселях (по умолчанию 100)
|
|
24
|
-
children: ReactNode;
|
|
25
|
-
}
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
### Публичный API (useScrollArea)
|
|
29
|
-
|
|
30
|
-
```typescript
|
|
31
|
-
interface ScrollAreaHook {
|
|
32
|
-
// Индикаторы позиции
|
|
33
|
-
isAtTop: boolean; // Точно в начале (scrollTop === 0)
|
|
34
|
-
isNearTop: boolean; // В пределах nearThreshold от начала
|
|
35
|
-
isAtBottom: boolean; // Точно в конце (scrollTop + clientHeight >= scrollHeight)
|
|
36
|
-
isNearBottom: boolean; // В пределах nearThreshold от конца
|
|
37
|
-
isAboveCenter: boolean; // Выше центральной точки области прокрутки
|
|
38
|
-
hasScrollableContent: boolean; // Есть контент требующий прокрутки
|
|
39
|
-
|
|
40
|
-
// Методы управления
|
|
41
|
-
scrollToTop: (animated?: boolean) => void;
|
|
42
|
-
scrollToBottom: (animated?: boolean) => void;
|
|
43
|
-
|
|
44
|
-
// Доступ к viewport элементу
|
|
45
|
-
viewportRef: React.RefObject<HTMLDivElement | null>;
|
|
46
|
-
}
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
### Внутреннее состояние (useScrollAreaState)
|
|
50
|
-
|
|
51
|
-
```typescript
|
|
52
|
-
interface ScrollAreaState extends ScrollAreaHook {
|
|
53
|
-
_callbackRef: (node: HTMLDivElement | null) => void; // для подключения к Mantine
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
interface ScrollAreaContextValue extends ScrollAreaState {
|
|
57
|
-
mantineProps: Omit<MantineScrollAreaProps, "children">; // пропсы Mantine
|
|
58
|
-
}
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
## Логика отслеживания позиции
|
|
62
|
-
|
|
63
|
-
### Расчет состояний позиции
|
|
64
|
-
|
|
65
|
-
- Отслеживание через событие `scroll` на viewport элементе
|
|
66
|
-
- Дебаунсинг через `useDebouncedCallback` (16ms для 60fps)
|
|
67
|
-
- Расчет всех индикаторов позиции на основе `scrollTop`, `clientHeight`, `scrollHeight`
|
|
68
|
-
- Использование `nearThreshold` для определения `isNearTop` и `isNearBottom`
|
|
69
|
-
|
|
70
|
-
### Отслеживание изменений контента
|
|
71
|
-
|
|
72
|
-
- `useResizeObserver` от Mantine для отслеживания изменений размера
|
|
73
|
-
- `MutationObserver` для детекции изменений DOM
|
|
74
|
-
- `useMergedRef` для объединения refs (scrollAreaRef + resizeRef)
|
|
75
|
-
- Перерасчет состояний при изменении размеров
|
|
76
|
-
|
|
77
|
-
## Автоскролл логика
|
|
78
|
-
|
|
79
|
-
### Прокрутка при инициализации (scrollToBottomOnInit)
|
|
80
|
-
|
|
81
|
-
**Условия активации:**
|
|
82
|
-
|
|
83
|
-
- `scrollToBottomOnInit === true` (независимо от autoScroll)
|
|
84
|
-
- `hasScrollableContent === true`
|
|
85
|
-
|
|
86
|
-
**Поведение:**
|
|
87
|
-
|
|
88
|
-
- Выполняется при первом рендере с прокручиваемым контентом
|
|
89
|
-
- Использует анимацию (если `animated !== false`)
|
|
90
|
-
- Прокручивает к концу области
|
|
91
|
-
|
|
92
|
-
### Автоскролл при добавлении контента
|
|
93
|
-
|
|
94
|
-
**Условия активации:**
|
|
95
|
-
|
|
96
|
-
1. `autoScroll === true`
|
|
97
|
-
2. `isAtBottom === true` (точное позиционирование, НЕ near!)
|
|
98
|
-
3. `!isUserInteracting` (нет активного взаимодействия)
|
|
99
|
-
|
|
100
|
-
**Поведение:**
|
|
101
|
-
|
|
102
|
-
- Выполняется мгновенно (instant, без анимации)
|
|
103
|
-
- Сохраняет позицию в конце при добавлении нового контента
|
|
104
|
-
|
|
105
|
-
### Блокировка автоскролла
|
|
106
|
-
|
|
107
|
-
**Детекция пользовательского взаимодействия:**
|
|
108
|
-
|
|
109
|
-
- События: `wheel`, `touchstart`, `touchmove`, `mousedown` на области прокрутки
|
|
110
|
-
- Установка флага `isUserInteracting = true`
|
|
111
|
-
- Автоматический сброс через таймаут (например, 150ms после последнего события)
|
|
112
|
-
|
|
113
|
-
## Методы управления прокруткой
|
|
114
|
-
|
|
115
|
-
### scrollToTop(animated?: boolean)
|
|
116
|
-
|
|
117
|
-
- Прокрутка к началу области
|
|
118
|
-
- Использует параметр `animated` или дефолтное значение из пропсов
|
|
119
|
-
- Реализация через `element.scrollTo()` с `behavior: 'smooth'` или прямое управление `scrollTop`
|
|
120
|
-
|
|
121
|
-
### scrollToBottom(animated?: boolean)
|
|
122
|
-
|
|
123
|
-
- Прокрутка к концу области
|
|
124
|
-
- Использует параметр `animated` или дефолтное значение из пропсов
|
|
125
|
-
- Реализация через `element.scrollTo()` с `behavior: 'smooth'` или прямое управление `scrollTop`
|
|
126
|
-
|
|
127
|
-
## ScrollArea.ScrollButton
|
|
128
|
-
|
|
129
|
-
### Адаптивное поведение
|
|
130
|
-
|
|
131
|
-
**Логика отображения:**
|
|
132
|
-
|
|
133
|
-
- Показывается только при `hasScrollableContent === true`
|
|
134
|
-
- Скрывается при отсутствии прокручиваемого контента
|
|
135
|
-
|
|
136
|
-
**Логика направления:**
|
|
137
|
-
|
|
138
|
-
- `isAboveCenter === true` → стрелка вниз, действие `scrollToBottom()`
|
|
139
|
-
- `isAboveCenter === false` → стрелка вверх, действие `scrollToTop()`
|
|
140
|
-
|
|
141
|
-
### Пропсы ScrollButton
|
|
142
|
-
|
|
143
|
-
```typescript
|
|
144
|
-
interface ScrollButtonProps {
|
|
145
|
-
className?: string;
|
|
146
|
-
upIcon?: ReactNode; // Иконка для прокрутки вверх
|
|
147
|
-
downIcon?: ReactNode; // Иконка для прокрутки вниз
|
|
148
|
-
}
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
## Производительность и оптимизация
|
|
152
|
-
|
|
153
|
-
### Дебаунсинг событий
|
|
154
|
-
|
|
155
|
-
- `useDebouncedCallback` от Mantine для обработчика `scroll`
|
|
156
|
-
- Задержка: 16ms (60fps)
|
|
157
|
-
|
|
158
|
-
### Объединение refs
|
|
159
|
-
|
|
160
|
-
- `useMergedRef` от Mantine для объединения scrollAreaRef и resizeRef
|
|
161
|
-
- Один callback ref для подключения к Mantine ScrollArea
|
|
162
|
-
|
|
163
|
-
### Управление подписками
|
|
164
|
-
|
|
165
|
-
- Правильная очистка обработчиков событий в useEffect cleanup
|
|
166
|
-
- Корректное управление ResizeObserver и MutationObserver через Mantine хуки
|
|
167
|
-
|
|
168
|
-
## Интеграция с Mantine
|
|
169
|
-
|
|
170
|
-
### Стилизация
|
|
171
|
-
|
|
172
|
-
- Полная совместимость с системой стилизации Mantine
|
|
173
|
-
- Передача всех Mantine ScrollArea пропсов через корневой ScrollArea компонент
|
|
174
|
-
- Поддержка кастомизации через className и стили
|
|
175
|
-
- Прямой доступ к viewport через `viewportRef` из `useScrollArea()`
|
|
176
|
-
|
|
177
|
-
### Пропсы Content (приватный компонент)
|
|
178
|
-
|
|
179
|
-
```typescript
|
|
180
|
-
interface ScrollAreaContentProps {
|
|
181
|
-
children: ReactNode;
|
|
182
|
-
}
|
|
183
|
-
```
|
|
184
|
-
|
|
185
|
-
**Примечание:** ScrollArea.Content не экспортируется и используется только внутри компонента.
|
|
186
|
-
|
|
187
|
-
## Требования к реализации
|
|
188
|
-
|
|
189
|
-
### Обязательные зависимости
|
|
190
|
-
|
|
191
|
-
- React 18+
|
|
192
|
-
- Mantine Scrollarea компонент
|
|
193
|
-
- React Context для состояния
|
|
194
|
-
|
|
195
|
-
### Хуки
|
|
196
|
-
|
|
197
|
-
- `useScrollArea` - публичный хук для разработчиков (фильтрует внутренние детали)
|
|
198
|
-
- `useScrollAreaState` - внутренний хук с полным состоянием
|
|
199
|
-
- Разделение ответственности: публичный API vs внутренняя логика
|
|
200
|
-
|
|
201
|
-
### Типизация
|
|
202
|
-
|
|
203
|
-
- Полная TypeScript типизация всех интерфейсов
|
|
204
|
-
- Экспорт типов для использования потребителями
|
|
@@ -1,369 +0,0 @@
|
|
|
1
|
-
# ScrollArea Component
|
|
2
|
-
|
|
3
|
-
Расширенная область прокрутки с автоматическим скроллом и интеллектуальным управлением позиционированием на базе Mantine ScrollArea.
|
|
4
|
-
|
|
5
|
-
## Установка
|
|
6
|
-
|
|
7
|
-
Компонент уже включен в kit компонентов:
|
|
8
|
-
|
|
9
|
-
```tsx
|
|
10
|
-
import { ScrollArea, useScrollArea } from "@/components/kit";
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
## Базовое использование
|
|
14
|
-
|
|
15
|
-
### Простая прокручиваемая область
|
|
16
|
-
|
|
17
|
-
```tsx
|
|
18
|
-
import { ScrollArea } from "@/components/kit";
|
|
19
|
-
|
|
20
|
-
function BasicExample() {
|
|
21
|
-
return (
|
|
22
|
-
<ScrollArea h={300}>
|
|
23
|
-
<div>
|
|
24
|
-
{Array.from({ length: 50 }, (_, i) => (
|
|
25
|
-
<div key={i} style={{ padding: "10px" }}>
|
|
26
|
-
Элемент {i + 1}
|
|
27
|
-
</div>
|
|
28
|
-
))}
|
|
29
|
-
</div>
|
|
30
|
-
</ScrollArea>
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
### Чат с автоскроллом
|
|
36
|
-
|
|
37
|
-
```tsx
|
|
38
|
-
import { ScrollArea } from "@/components/kit";
|
|
39
|
-
|
|
40
|
-
function ChatMessages({ messages }) {
|
|
41
|
-
return (
|
|
42
|
-
<ScrollArea
|
|
43
|
-
autoScroll
|
|
44
|
-
scrollToBottomOnInit
|
|
45
|
-
animated
|
|
46
|
-
nearThreshold={100}
|
|
47
|
-
h={400}
|
|
48
|
-
>
|
|
49
|
-
{messages.map((msg) => (
|
|
50
|
-
<div
|
|
51
|
-
key={msg.id}
|
|
52
|
-
style={{ padding: "8px", borderBottom: "1px solid #eee" }}
|
|
53
|
-
>
|
|
54
|
-
<strong>{msg.author}:</strong> {msg.text}
|
|
55
|
-
</div>
|
|
56
|
-
))}
|
|
57
|
-
|
|
58
|
-
<ScrollArea.ScrollButton className="absolute bottom-4 right-4 z-10" />
|
|
59
|
-
</ScrollArea>
|
|
60
|
-
);
|
|
61
|
-
}
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
## API
|
|
65
|
-
|
|
66
|
-
### Важно понимать:
|
|
67
|
-
|
|
68
|
-
- **ScrollArea** автоматически оборачивает `children` в `ScrollArea.Content`
|
|
69
|
-
- **ScrollArea.Content** нужен только когда требуется ref на прокручиваемую область
|
|
70
|
-
- **ScrollArea.ScrollButton** работает везде внутри ScrollArea через контекст
|
|
71
|
-
|
|
72
|
-
### ScrollArea Props
|
|
73
|
-
|
|
74
|
-
Наследует все пропсы от Mantine ScrollArea плюс дополнительные:
|
|
75
|
-
|
|
76
|
-
| Prop | Type | Default | Описание |
|
|
77
|
-
| ---------------------- | ------------------ | ------- | ----------------------------------------------- |
|
|
78
|
-
| `autoScroll` | `boolean` | `false` | Включение автоскролла при добавлении контента |
|
|
79
|
-
| `scrollToBottomOnInit` | `boolean` | `false` | Прокрутить к концу при инициализации компонента |
|
|
80
|
-
| `animated` | `boolean` | `true` | Анимированная прокрутка |
|
|
81
|
-
| `nearThreshold` | `number` | `100` | Отступ для near-зон в пикселях |
|
|
82
|
-
| `h` | `string \| number` | - | Высота области прокрутки |
|
|
83
|
-
| `scrollbarSize` | `number` | - | Размер полосы прокрутки |
|
|
84
|
-
| `type` | `string` | - | Тип поведения полос прокрутки |
|
|
85
|
-
| `...mantineProps` | - | - | Все остальные пропсы Mantine ScrollArea |
|
|
86
|
-
|
|
87
|
-
### Доступ к viewport элементу
|
|
88
|
-
|
|
89
|
-
Используйте `useScrollArea` для получения ref на прокручиваемую область:
|
|
90
|
-
|
|
91
|
-
```tsx
|
|
92
|
-
function MyComponent() {
|
|
93
|
-
const { viewportRef } = useScrollArea();
|
|
94
|
-
|
|
95
|
-
const scrollToElement = () => {
|
|
96
|
-
const target = viewportRef.current?.querySelector("[data-target]");
|
|
97
|
-
target?.scrollIntoView();
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
const getScrollPosition = () => {
|
|
101
|
-
console.log("Scroll top:", viewportRef.current?.scrollTop);
|
|
102
|
-
console.log("Scroll height:", viewportRef.current?.scrollHeight);
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
return (
|
|
106
|
-
<ScrollArea h={400}>
|
|
107
|
-
<div data-target>Элемент для прокрутки</div>
|
|
108
|
-
<button onClick={scrollToElement}>Прокрутить к элементу</button>
|
|
109
|
-
<button onClick={getScrollPosition}>Получить позицию</button>
|
|
110
|
-
</ScrollArea>
|
|
111
|
-
);
|
|
112
|
-
}
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
### ScrollArea.ScrollButton Props
|
|
116
|
-
|
|
117
|
-
✅ **Работает везде внутри ScrollArea** - использует контекст, не требует Content.
|
|
118
|
-
|
|
119
|
-
| Prop | Type | Default | Описание |
|
|
120
|
-
| ----------- | ----------- | --------------------- | -------------------------- |
|
|
121
|
-
| `className` | `string` | - | CSS классы |
|
|
122
|
-
| `upIcon` | `ReactNode` | `<IconChevronUp />` | Иконка для прокрутки вверх |
|
|
123
|
-
| `downIcon` | `ReactNode` | `<IconChevronDown />` | Иконка для прокрутки вниз |
|
|
124
|
-
|
|
125
|
-
#### Примеры размещения:
|
|
126
|
-
|
|
127
|
-
```tsx
|
|
128
|
-
// В любом месте внутри ScrollArea
|
|
129
|
-
<ScrollArea h={400}>
|
|
130
|
-
{content}
|
|
131
|
-
<ScrollArea.ScrollButton className="absolute bottom-4 right-4" />
|
|
132
|
-
</ScrollArea>
|
|
133
|
-
|
|
134
|
-
// Даже вложенно
|
|
135
|
-
<ScrollArea h={400}>
|
|
136
|
-
<div className="relative">
|
|
137
|
-
{content}
|
|
138
|
-
<ScrollArea.ScrollButton />
|
|
139
|
-
</div>
|
|
140
|
-
</ScrollArea>
|
|
141
|
-
|
|
142
|
-
// Или в начале
|
|
143
|
-
<ScrollArea h={400}>
|
|
144
|
-
<ScrollArea.ScrollButton className="mb-4" />
|
|
145
|
-
{content}
|
|
146
|
-
</ScrollArea>
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
## Контекст
|
|
150
|
-
|
|
151
|
-
### useScrollArea
|
|
152
|
-
|
|
153
|
-
Хук для доступа к состоянию и методам ScrollArea:
|
|
154
|
-
|
|
155
|
-
```tsx
|
|
156
|
-
import { ScrollArea, useScrollArea } from "@/components/kit";
|
|
157
|
-
|
|
158
|
-
function CustomControls() {
|
|
159
|
-
const {
|
|
160
|
-
isAtTop,
|
|
161
|
-
isNearTop,
|
|
162
|
-
isAtBottom,
|
|
163
|
-
isNearBottom,
|
|
164
|
-
isAboveCenter,
|
|
165
|
-
hasScrollableContent,
|
|
166
|
-
scrollToTop,
|
|
167
|
-
scrollToBottom,
|
|
168
|
-
viewportRef,
|
|
169
|
-
} = useScrollArea();
|
|
170
|
-
|
|
171
|
-
return (
|
|
172
|
-
<div>
|
|
173
|
-
<button onClick={() => scrollToTop()} disabled={isAtTop}>
|
|
174
|
-
В начало
|
|
175
|
-
</button>
|
|
176
|
-
|
|
177
|
-
<button onClick={() => scrollToBottom()} disabled={isAtBottom}>
|
|
178
|
-
В конец
|
|
179
|
-
</button>
|
|
180
|
-
|
|
181
|
-
{hasScrollableContent && (
|
|
182
|
-
<span>{isAboveCenter ? "Верхняя половина" : "Нижняя половина"}</span>
|
|
183
|
-
)}
|
|
184
|
-
</div>
|
|
185
|
-
);
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
function App() {
|
|
189
|
-
return (
|
|
190
|
-
<ScrollArea>
|
|
191
|
-
{/* контент */}
|
|
192
|
-
<CustomControls />
|
|
193
|
-
</ScrollArea>
|
|
194
|
-
);
|
|
195
|
-
}
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
### Состояния позиции
|
|
199
|
-
|
|
200
|
-
- `isAtTop`: точно в начале (scrollTop === 0)
|
|
201
|
-
- `isNearTop`: в пределах nearThreshold от начала
|
|
202
|
-
- `isAtBottom`: точно в конце
|
|
203
|
-
- `isNearBottom`: в пределах nearThreshold от конца
|
|
204
|
-
- `isAboveCenter`: выше центральной точки
|
|
205
|
-
- `hasScrollableContent`: есть контент для прокрутки
|
|
206
|
-
|
|
207
|
-
### Методы управления
|
|
208
|
-
|
|
209
|
-
- `scrollToTop(animated?: boolean)`: прокрутить к началу
|
|
210
|
-
- `scrollToBottom(animated?: boolean)`: прокрутить к концу
|
|
211
|
-
- `viewportRef`: React RefObject на viewport элемент для прямого доступа
|
|
212
|
-
|
|
213
|
-
## Логика автоскролла
|
|
214
|
-
|
|
215
|
-
### Автоскролл при инициализации
|
|
216
|
-
|
|
217
|
-
Выполняется когда:
|
|
218
|
-
|
|
219
|
-
- `autoScroll === true`
|
|
220
|
-
- `scrollToBottomOnInit === true`
|
|
221
|
-
- Есть прокручиваемый контент
|
|
222
|
-
|
|
223
|
-
### Автоскролл при добавлении контента
|
|
224
|
-
|
|
225
|
-
Выполняется когда:
|
|
226
|
-
|
|
227
|
-
- `autoScroll === true`
|
|
228
|
-
- `isAtBottom === true` (точное позиционирование!)
|
|
229
|
-
- Нет активного взаимодействия пользователя
|
|
230
|
-
|
|
231
|
-
## Примеры использования
|
|
232
|
-
|
|
233
|
-
### Логи в реальном времени
|
|
234
|
-
|
|
235
|
-
```tsx
|
|
236
|
-
function LogViewer({ logs }) {
|
|
237
|
-
return (
|
|
238
|
-
<ScrollArea
|
|
239
|
-
autoScroll
|
|
240
|
-
h={500}
|
|
241
|
-
style={{ fontFamily: "monospace", fontSize: "12px" }}
|
|
242
|
-
>
|
|
243
|
-
{logs.map((log, index) => (
|
|
244
|
-
<div key={index} style={{ padding: "2px 8px" }}>
|
|
245
|
-
<span style={{ color: "#666" }}>{log.timestamp}</span>
|
|
246
|
-
<span
|
|
247
|
-
style={{
|
|
248
|
-
color:
|
|
249
|
-
log.level === "error"
|
|
250
|
-
? "red"
|
|
251
|
-
: log.level === "warn"
|
|
252
|
-
? "orange"
|
|
253
|
-
: "inherit",
|
|
254
|
-
}}
|
|
255
|
-
>
|
|
256
|
-
{log.message}
|
|
257
|
-
</span>
|
|
258
|
-
</div>
|
|
259
|
-
))}
|
|
260
|
-
</ScrollArea>
|
|
261
|
-
);
|
|
262
|
-
}
|
|
263
|
-
```
|
|
264
|
-
|
|
265
|
-
### Список с кастомными контролами
|
|
266
|
-
|
|
267
|
-
```tsx
|
|
268
|
-
function ItemsList({ items }) {
|
|
269
|
-
return (
|
|
270
|
-
<ScrollArea nearThreshold={50} h={400}>
|
|
271
|
-
{items.map((item) => (
|
|
272
|
-
<div
|
|
273
|
-
key={item.id}
|
|
274
|
-
style={{ padding: "12px", borderBottom: "1px solid #eee" }}
|
|
275
|
-
>
|
|
276
|
-
{item.name}
|
|
277
|
-
</div>
|
|
278
|
-
))}
|
|
279
|
-
|
|
280
|
-
<div style={{ position: "absolute", top: "10px", right: "10px" }}>
|
|
281
|
-
<CustomScrollControls />
|
|
282
|
-
</div>
|
|
283
|
-
</ScrollArea>
|
|
284
|
-
);
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
function CustomScrollControls() {
|
|
288
|
-
const { scrollToTop, scrollToBottom, hasScrollableContent } = useScrollArea();
|
|
289
|
-
|
|
290
|
-
if (!hasScrollableContent) return null;
|
|
291
|
-
|
|
292
|
-
return (
|
|
293
|
-
<div style={{ display: "flex", gap: "8px" }}>
|
|
294
|
-
<button onClick={() => scrollToTop()}>↑</button>
|
|
295
|
-
<button onClick={() => scrollToBottom()}>↓</button>
|
|
296
|
-
</div>
|
|
297
|
-
);
|
|
298
|
-
}
|
|
299
|
-
```
|
|
300
|
-
|
|
301
|
-
### Комбинация с другими компонентами
|
|
302
|
-
|
|
303
|
-
```tsx
|
|
304
|
-
import { ScrollArea } from "@/components/kit";
|
|
305
|
-
import { Button, Text, Badge } from "@mantine/core";
|
|
306
|
-
|
|
307
|
-
function NotificationCenter({ notifications }) {
|
|
308
|
-
return (
|
|
309
|
-
<ScrollArea autoScroll maxH={300} p="md">
|
|
310
|
-
{notifications.length === 0 ? (
|
|
311
|
-
<Text c="dimmed" ta="center" py="xl">
|
|
312
|
-
Нет уведомлений
|
|
313
|
-
</Text>
|
|
314
|
-
) : (
|
|
315
|
-
notifications.map((notification) => (
|
|
316
|
-
<div key={notification.id} style={{ marginBottom: "12px" }}>
|
|
317
|
-
<div
|
|
318
|
-
style={{
|
|
319
|
-
display: "flex",
|
|
320
|
-
justifyContent: "space-between",
|
|
321
|
-
alignItems: "center",
|
|
322
|
-
}}
|
|
323
|
-
>
|
|
324
|
-
<Text size="sm" fw={500}>
|
|
325
|
-
{notification.title}
|
|
326
|
-
</Text>
|
|
327
|
-
<Badge
|
|
328
|
-
size="xs"
|
|
329
|
-
color={notification.priority === "high" ? "red" : "blue"}
|
|
330
|
-
>
|
|
331
|
-
{notification.priority}
|
|
332
|
-
</Badge>
|
|
333
|
-
</div>
|
|
334
|
-
<Text size="xs" c="dimmed" mt={4}>
|
|
335
|
-
{notification.message}
|
|
336
|
-
</Text>
|
|
337
|
-
</div>
|
|
338
|
-
))
|
|
339
|
-
)}
|
|
340
|
-
</ScrollArea>
|
|
341
|
-
);
|
|
342
|
-
}
|
|
343
|
-
```
|
|
344
|
-
|
|
345
|
-
## Стилизация
|
|
346
|
-
|
|
347
|
-
Компонент полностью совместим с системой стилизации Mantine. Вы можете передавать все стандартные Mantine пропсы через `ScrollArea.Content`:
|
|
348
|
-
|
|
349
|
-
```tsx
|
|
350
|
-
<ScrollArea
|
|
351
|
-
h={400}
|
|
352
|
-
p="md"
|
|
353
|
-
style={{ backgroundColor: "#f8f9fa" }}
|
|
354
|
-
scrollbarSize={6}
|
|
355
|
-
scrollHideDelay={1500}
|
|
356
|
-
type="hover"
|
|
357
|
-
>
|
|
358
|
-
{/* контент */}
|
|
359
|
-
</ScrollArea>
|
|
360
|
-
```
|
|
361
|
-
|
|
362
|
-
## Производительность
|
|
363
|
-
|
|
364
|
-
Компонент оптимизирован для производительности:
|
|
365
|
-
|
|
366
|
-
- Дебаунсинг событий скролла (16ms для 60fps)
|
|
367
|
-
- Оптимальное отслеживание изменений размера через ResizeObserver
|
|
368
|
-
- Минимальные ререндеры благодаря правильной мемоизации
|
|
369
|
-
- Автоматическая очистка event listeners и таймеров
|