@koslibs/components 1.3.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/dist/components/Button/button.js +1 -0
  3. package/dist/components/Input/index.d.ts +2 -0
  4. package/dist/components/Input/index.js +1 -0
  5. package/dist/components/Input/index.module.js +25 -0
  6. package/dist/components/Input/index_module.css +312 -0
  7. package/dist/components/Input/input.d.ts +29 -0
  8. package/dist/components/Input/input.js +179 -0
  9. package/dist/components/Input/types.d.ts +115 -0
  10. package/dist/components/Input/types.js +0 -0
  11. package/dist/components/Input/vars.css +32 -0
  12. package/dist/components/Modal/colors.module.js +5 -0
  13. package/dist/components/Modal/colors_module.css +10 -0
  14. package/dist/components/Modal/components/content/index.d.ts +15 -0
  15. package/dist/components/Modal/components/content/index.js +19 -0
  16. package/dist/components/Modal/components/content/index.module.js +5 -0
  17. package/dist/components/Modal/components/content/index_module.css +12 -0
  18. package/dist/components/Modal/components/controls/index.d.ts +56 -0
  19. package/dist/components/Modal/components/controls/index.js +24 -0
  20. package/dist/components/Modal/components/controls/index.module.js +19 -0
  21. package/dist/components/Modal/components/controls/index_module.css +52 -0
  22. package/dist/components/Modal/components/footer/index.d.ts +15 -0
  23. package/dist/components/Modal/components/footer/index.js +19 -0
  24. package/dist/components/Modal/components/footer/index.module.js +5 -0
  25. package/dist/components/Modal/components/footer/index_module.css +9 -0
  26. package/dist/components/Modal/components/header/index.d.ts +43 -0
  27. package/dist/components/Modal/components/header/index.js +54 -0
  28. package/dist/components/Modal/components/header/index.module.js +8 -0
  29. package/dist/components/Modal/components/header/index_module.css +31 -0
  30. package/dist/components/Modal/components/modal-surface/index.d.ts +4 -0
  31. package/dist/components/Modal/components/modal-surface/index.js +81 -0
  32. package/dist/components/Modal/context.d.ts +6 -0
  33. package/dist/components/Modal/context.js +3 -0
  34. package/dist/components/Modal/index.d.ts +10 -0
  35. package/dist/components/Modal/index.js +5 -0
  36. package/dist/components/Modal/index.module.js +15 -0
  37. package/dist/components/Modal/index_module.css +46 -0
  38. package/dist/components/Modal/modal.d.ts +10 -0
  39. package/dist/components/Modal/modal.js +13 -0
  40. package/dist/components/Modal/types.d.ts +41 -0
  41. package/dist/components/Modal/types.js +0 -0
  42. package/dist/components/Modal/utils/lock-scroll.d.ts +1 -0
  43. package/dist/components/Modal/utils/lock-scroll.js +31 -0
  44. package/dist/components/Modal/vars.css +9 -0
  45. package/dist/components/Popover/popover.js +9 -7
  46. package/dist/components/Portal/index.d.ts +2 -0
  47. package/dist/components/Portal/index.js +1 -0
  48. package/dist/components/Portal/portal.d.ts +2 -0
  49. package/dist/components/Portal/portal.js +19 -0
  50. package/dist/components/Portal/types.d.ts +18 -0
  51. package/dist/components/Portal/types.js +0 -0
  52. package/dist/hooks/use-data-test-id.d.ts +5 -0
  53. package/dist/hooks/use-data-test-id.js +7 -0
  54. package/dist/index.d.ts +6 -0
  55. package/dist/index.js +3 -0
  56. package/package.json +2 -2
@@ -0,0 +1,115 @@
1
+ import type { ChangeEvent, CSSProperties, InputHTMLAttributes, MouseEvent, ReactNode } from 'react';
2
+ export type InputProps = Omit<InputHTMLAttributes<HTMLInputElement>, 'size' | 'value' | 'defaultValue' | 'maxLength' | 'onChange' | 'children'> & {
3
+ /**
4
+ * Значение управляемого поля.
5
+ */
6
+ value?: string;
7
+ /**
8
+ * Начальное значение неуправляемого поля.
9
+ */
10
+ defaultValue?: string;
11
+ /**
12
+ * Максимальная длина ввода. Передаётся в нативный maxLength.
13
+ * Длина считается в кодовых единицах UTF-16, как в HTML input.
14
+ */
15
+ maxLength?: number;
16
+ /**
17
+ * Показывает текущую длину и maxLength, например 13/64.
18
+ * Работает только при заданном неотрицательном целом maxLength.
19
+ * При inner расположен внутри поля, при outer — рядом с внешним label.
20
+ * @default false
21
+ */
22
+ showValueLength?: boolean;
23
+ /**
24
+ * Вид поля: белый primary или светлый secondary.
25
+ * @default 'primary'
26
+ */
27
+ view?: 'primary' | 'secondary';
28
+ /**
29
+ * Высота поля в пикселях без внешнего label и сообщения.
30
+ * @default 40
31
+ */
32
+ size?: 40 | 48 | 56 | 64 | 72;
33
+ /**
34
+ * Растягивает компонент на ширину контейнера.
35
+ * @default false
36
+ */
37
+ block?: boolean;
38
+ /**
39
+ * Название поля. Связывается с input через htmlFor и id.
40
+ */
41
+ label?: ReactNode;
42
+ /**
43
+ * Положение label: снаружи или внутри поля.
44
+ * Внутренний label поднимается при фокусе или заполнении поля.
45
+ * @default 'outer'
46
+ */
47
+ labelView?: 'outer' | 'inner';
48
+ /**
49
+ * Подсказка под полем. При наличии сообщения об ошибке заменяется им.
50
+ */
51
+ hint?: ReactNode;
52
+ /**
53
+ * Сообщение об ошибке или true для состояния ошибки без сообщения.
54
+ * Сообщение заменяет hint; без hint отображается только состояние ошибки.
55
+ */
56
+ error?: ReactNode | boolean;
57
+ /**
58
+ * Аддон слева от значения, например иконка поиска.
59
+ */
60
+ leftAddon?: ReactNode;
61
+ /**
62
+ * Аддон справа от значения, например единица измерения или кнопка.
63
+ */
64
+ rightAddon?: ReactNode;
65
+ /**
66
+ * Показывает кнопку очистки заполненного поля. Скрыта в disabled и readOnly.
67
+ * @default false
68
+ */
69
+ clear?: boolean;
70
+ /**
71
+ * Доступное имя кнопки очистки.
72
+ * @default 'Очистить поле'
73
+ */
74
+ clearLabel?: string;
75
+ /**
76
+ * Обработчик ввода с нативным событием React и текущим значением.
77
+ */
78
+ onChange?: (event: ChangeEvent<HTMLInputElement>, payload: {
79
+ value: string;
80
+ }) => void;
81
+ /**
82
+ * Обработчик очистки. Не вызывает onChange.
83
+ * Для управляемого поля обновите value в этом обработчике.
84
+ */
85
+ onClear?: (event: MouseEvent<HTMLButtonElement>) => void;
86
+ /**
87
+ * Класс обёртки компонента.
88
+ */
89
+ className?: string;
90
+ /**
91
+ * Стили обёртки компонента, включая ширину и CSS-переменные.
92
+ */
93
+ style?: CSSProperties;
94
+ /**
95
+ * Класс визуального поля с аддонами.
96
+ */
97
+ fieldClassName?: string;
98
+ /**
99
+ * Класс нативного input.
100
+ */
101
+ inputClassName?: string;
102
+ /**
103
+ * Класс label.
104
+ */
105
+ labelClassName?: string;
106
+ /**
107
+ * Класс подсказки или сообщения об ошибке.
108
+ */
109
+ messageClassName?: string;
110
+ /**
111
+ * Идентификатор нативного input. Части получают суффиксы -form-control,
112
+ * -field, -label, -hint, -error, -left-addon, -right-addon, -clear и -counter.
113
+ */
114
+ dataTestId?: string;
115
+ };
File without changes
@@ -0,0 +1,32 @@
1
+ :root {
2
+ --input-primary-background-color: #fff;
3
+ --input-secondary-background-color: #f5f3ec;
4
+ --input-color: #1c1a18;
5
+ --input-placeholder-color: #736554;
6
+ --input-label-color: #736554;
7
+ --input-hint-color: #736554;
8
+ --input-icon-color: #736554;
9
+ --input-border-color: transparent;
10
+ --input-hover-border-color: #c8beaa;
11
+ --input-focus-border-color: #d95300;
12
+ --input-error-border-color: #ef5350;
13
+ --input-error-message-color: #b42318;
14
+ --input-disabled-background-color: #cfd1cb;
15
+ --input-disabled-color: #858981;
16
+ --input-read-only-border-color: #c8beaa;
17
+ --input-border-radius: 8px;
18
+ --input-gap: 8px;
19
+ --input-icon-size: 16px;
20
+ --input-width: 320px;
21
+ --input-font-size-40: 13px;
22
+ --input-font-size-48: 13px;
23
+ --input-font-size-56: 14px;
24
+ --input-font-size-64: 14px;
25
+ --input-font-size-72: 16px;
26
+ --input-padding-40: 12px;
27
+ --input-padding-48: 12px;
28
+ --input-padding-56: 16px;
29
+ --input-padding-64: 16px;
30
+ --input-padding-72: 20px;
31
+ }
32
+
@@ -0,0 +1,5 @@
1
+ import "./colors_module.css";
2
+ const colors_module = {
3
+ component: "component-NzhSoV"
4
+ };
5
+ export default colors_module;
@@ -0,0 +1,10 @@
1
+ .component-NzhSoV {
2
+ background-color: var(--modal-background-color);
3
+ color: var(--modal-color);
4
+
5
+ &::backdrop {
6
+ background-color: var(--modal-backdrop-color);
7
+ backdrop-filter: blur(var(--modal-backdrop-blur));
8
+ }
9
+ }
10
+
@@ -0,0 +1,15 @@
1
+ import { type HTMLAttributes } from 'react';
2
+ export type ContentProps = HTMLAttributes<HTMLDivElement> & {
3
+ /**
4
+ * Базовый идентификатор для автоматизированных тестов с суффиксом -content.
5
+ * По умолчанию наследуется от ближайшего Modal; явно заданный имеет приоритет.
6
+ */
7
+ dataTestId?: string;
8
+ };
9
+ export declare const Content: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLDivElement> & {
10
+ /**
11
+ * Базовый идентификатор для автоматизированных тестов с суффиксом -content.
12
+ * По умолчанию наследуется от ближайшего Modal; явно заданный имеет приоритет.
13
+ */
14
+ dataTestId?: string;
15
+ } & import("react").RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,19 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import classnames from "classnames";
3
+ import { forwardRef, useContext } from "react";
4
+ import { useDataTestId } from "../../../../hooks/use-data-test-id.js";
5
+ import { ModalContext } from "../../context.js";
6
+ import index_module from "./index.module.js";
7
+ const Content = /*#__PURE__*/ forwardRef(({ children, className, dataTestId, ...restProps }, ref)=>{
8
+ const { dataTestId: modalDataTestId } = useContext(ModalContext);
9
+ const getDataTestId = useDataTestId(dataTestId ?? modalDataTestId);
10
+ return /*#__PURE__*/ jsx("div", {
11
+ ...restProps,
12
+ ref: ref,
13
+ className: classnames(index_module.component, className),
14
+ "data-test-id": getDataTestId('content'),
15
+ children: children
16
+ });
17
+ });
18
+ Content.displayName = 'ModalContent';
19
+ export { Content };
@@ -0,0 +1,5 @@
1
+ import "./index_module.css";
2
+ const index_module = {
3
+ component: "component-Xoedpj"
4
+ };
5
+ export default index_module;
@@ -0,0 +1,12 @@
1
+ .component-Xoedpj {
2
+ gap: var(--size-24, 24px);
3
+ min-height: 0;
4
+ padding: var(--modal-padding);
5
+ overscroll-behavior: contain;
6
+ overflow-wrap: anywhere;
7
+ flex-direction: column;
8
+ flex: auto;
9
+ display: flex;
10
+ overflow: auto;
11
+ }
12
+
@@ -0,0 +1,56 @@
1
+ import { type HTMLAttributes, type ReactNode } from 'react';
2
+ import React from 'react';
3
+ export type ControlsProps = HTMLAttributes<HTMLDivElement> & {
4
+ /**
5
+ * Основное действие, отображается после дополнительного.
6
+ */
7
+ primary?: ReactNode;
8
+ /**
9
+ * Дополнительное действие.
10
+ */
11
+ secondary?: ReactNode;
12
+ /**
13
+ * Выравнивание действий.
14
+ * В строковых раскладках block-кнопки делят свободную ширину поровну.
15
+ * В column кнопки занимают всю ширину и располагаются друг под другом.
16
+ * @default 'end'
17
+ */
18
+ layout?: 'start' | 'end' | 'center' | 'space-between' | 'column';
19
+ /**
20
+ * Расстояние между действиями.
21
+ * @default 12
22
+ */
23
+ gap?: 8 | 12 | 16 | 24;
24
+ /**
25
+ * Базовый идентификатор для автоматизированных тестов с суффиксом -controls.
26
+ * По умолчанию наследуется от ближайшего Modal; явно заданный имеет приоритет.
27
+ */
28
+ dataTestId?: string;
29
+ };
30
+ export declare const Controls: React.ForwardRefExoticComponent<HTMLAttributes<HTMLDivElement> & {
31
+ /**
32
+ * Основное действие, отображается после дополнительного.
33
+ */
34
+ primary?: ReactNode;
35
+ /**
36
+ * Дополнительное действие.
37
+ */
38
+ secondary?: ReactNode;
39
+ /**
40
+ * Выравнивание действий.
41
+ * В строковых раскладках block-кнопки делят свободную ширину поровну.
42
+ * В column кнопки занимают всю ширину и располагаются друг под другом.
43
+ * @default 'end'
44
+ */
45
+ layout?: "start" | "end" | "center" | "space-between" | "column";
46
+ /**
47
+ * Расстояние между действиями.
48
+ * @default 12
49
+ */
50
+ gap?: 8 | 12 | 16 | 24;
51
+ /**
52
+ * Базовый идентификатор для автоматизированных тестов с суффиксом -controls.
53
+ * По умолчанию наследуется от ближайшего Modal; явно заданный имеет приоритет.
54
+ */
55
+ dataTestId?: string;
56
+ } & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,24 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import classnames from "classnames";
3
+ import react, { forwardRef, useContext } from "react";
4
+ import { useDataTestId } from "../../../../hooks/use-data-test-id.js";
5
+ import { ModalContext } from "../../context.js";
6
+ import index_module from "./index.module.js";
7
+ const Controls = /*#__PURE__*/ forwardRef(({ primary, secondary, layout = 'end', gap = 12, className, children, dataTestId, ...restProps }, ref)=>{
8
+ const { dataTestId: modalDataTestId } = useContext(ModalContext);
9
+ const getDataTestId = useDataTestId(dataTestId ?? modalDataTestId);
10
+ return /*#__PURE__*/ jsx("div", {
11
+ ...restProps,
12
+ ref: ref,
13
+ className: classnames(index_module.component, index_module[layout], index_module[`gap-${gap}`], className),
14
+ "data-test-id": getDataTestId('controls'),
15
+ children: children ?? /*#__PURE__*/ jsxs(react.Fragment, {
16
+ children: [
17
+ secondary,
18
+ primary
19
+ ]
20
+ })
21
+ });
22
+ });
23
+ Controls.displayName = 'ModalControls';
24
+ export { Controls };
@@ -0,0 +1,19 @@
1
+ import "./index_module.css";
2
+ const index_module = {
3
+ component: "component-IPNCFT",
4
+ column: "column-dBeQXP",
5
+ start: "start-ouHlcU",
6
+ end: "end-TYAvEX",
7
+ center: "center-I4ALjs",
8
+ "space-between": "space-between-OxpVhA",
9
+ spaceBetween: "space-between-OxpVhA",
10
+ "gap-8": "gap-8-xwhlts",
11
+ gap8: "gap-8-xwhlts",
12
+ "gap-12": "gap-12-IFyQQK",
13
+ gap12: "gap-12-IFyQQK",
14
+ "gap-16": "gap-16-iZpxeN",
15
+ gap16: "gap-16-iZpxeN",
16
+ "gap-24": "gap-24-eEhuId",
17
+ gap24: "gap-24-eEhuId"
18
+ };
19
+ export default index_module;
@@ -0,0 +1,52 @@
1
+ .component-IPNCFT {
2
+ flex-wrap: wrap;
3
+ align-items: center;
4
+ width: 100%;
5
+ display: flex;
6
+ }
7
+
8
+ .component-IPNCFT:not(.column-dBeQXP) > button[data-block="true"] {
9
+ flex: 1 1 0;
10
+ }
11
+
12
+ .start-ouHlcU {
13
+ justify-content: flex-start;
14
+ }
15
+
16
+ .end-TYAvEX {
17
+ justify-content: flex-end;
18
+ }
19
+
20
+ .center-I4ALjs {
21
+ justify-content: center;
22
+ }
23
+
24
+ .space-between-OxpVhA {
25
+ justify-content: space-between;
26
+ }
27
+
28
+ .column-dBeQXP {
29
+ flex-direction: column;
30
+ align-items: stretch;
31
+ }
32
+
33
+ .column-dBeQXP > button {
34
+ width: 100%;
35
+ }
36
+
37
+ .gap-8-xwhlts {
38
+ gap: var(--size-8, 8px);
39
+ }
40
+
41
+ .gap-12-IFyQQK {
42
+ gap: var(--size-12, 12px);
43
+ }
44
+
45
+ .gap-16-iZpxeN {
46
+ gap: var(--size-16, 16px);
47
+ }
48
+
49
+ .gap-24-eEhuId {
50
+ gap: var(--size-24, 24px);
51
+ }
52
+
@@ -0,0 +1,15 @@
1
+ import { type HTMLAttributes } from 'react';
2
+ export type FooterProps = HTMLAttributes<HTMLDivElement> & {
3
+ /**
4
+ * Базовый идентификатор для автоматизированных тестов с суффиксом -footer.
5
+ * По умолчанию наследуется от ближайшего Modal; явно заданный имеет приоритет.
6
+ */
7
+ dataTestId?: string;
8
+ };
9
+ export declare const Footer: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLDivElement> & {
10
+ /**
11
+ * Базовый идентификатор для автоматизированных тестов с суффиксом -footer.
12
+ * По умолчанию наследуется от ближайшего Modal; явно заданный имеет приоритет.
13
+ */
14
+ dataTestId?: string;
15
+ } & import("react").RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,19 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import classnames from "classnames";
3
+ import { forwardRef, useContext } from "react";
4
+ import { useDataTestId } from "../../../../hooks/use-data-test-id.js";
5
+ import { ModalContext } from "../../context.js";
6
+ import index_module from "./index.module.js";
7
+ const Footer = /*#__PURE__*/ forwardRef(({ children, className, dataTestId, ...restProps }, ref)=>{
8
+ const { dataTestId: modalDataTestId } = useContext(ModalContext);
9
+ const getDataTestId = useDataTestId(dataTestId ?? modalDataTestId);
10
+ return /*#__PURE__*/ jsx("div", {
11
+ ...restProps,
12
+ ref: ref,
13
+ className: classnames(index_module.component, className),
14
+ "data-test-id": getDataTestId('footer'),
15
+ children: children
16
+ });
17
+ });
18
+ Footer.displayName = 'ModalFooter';
19
+ export { Footer };
@@ -0,0 +1,5 @@
1
+ import "./index_module.css";
2
+ const index_module = {
3
+ component: "component-ZDJl0C"
4
+ };
5
+ export default index_module;
@@ -0,0 +1,9 @@
1
+ .component-ZDJl0C {
2
+ justify-content: flex-end;
3
+ align-items: center;
4
+ gap: var(--size-12, 12px);
5
+ padding: 0 var(--modal-padding) var(--modal-padding);
6
+ flex-shrink: 0;
7
+ display: flex;
8
+ }
9
+
@@ -0,0 +1,43 @@
1
+ import { type HTMLAttributes } from 'react';
2
+ export type HeaderProps = Omit<HTMLAttributes<HTMLDivElement>, 'title' | 'onClose' | 'children'> & {
3
+ /**
4
+ * Заголовок окна.
5
+ */
6
+ title?: string;
7
+ /**
8
+ * Описание под заголовком.
9
+ */
10
+ subtitle?: string;
11
+ /**
12
+ * Показывать кнопку закрытия.
13
+ * Кнопка вызывает onClose ближайшего Modal.
14
+ * @default true
15
+ */
16
+ hasCloser?: boolean;
17
+ /**
18
+ * Базовый идентификатор для автоматизированных тестов с суффиксом -header.
19
+ * По умолчанию наследуется от ближайшего Modal; явно заданный имеет приоритет.
20
+ */
21
+ dataTestId?: string;
22
+ };
23
+ export declare const Header: import("react").ForwardRefExoticComponent<Omit<HTMLAttributes<HTMLDivElement>, "title" | "children" | "onClose"> & {
24
+ /**
25
+ * Заголовок окна.
26
+ */
27
+ title?: string;
28
+ /**
29
+ * Описание под заголовком.
30
+ */
31
+ subtitle?: string;
32
+ /**
33
+ * Показывать кнопку закрытия.
34
+ * Кнопка вызывает onClose ближайшего Modal.
35
+ * @default true
36
+ */
37
+ hasCloser?: boolean;
38
+ /**
39
+ * Базовый идентификатор для автоматизированных тестов с суффиксом -header.
40
+ * По умолчанию наследуется от ближайшего Modal; явно заданный имеет приоритет.
41
+ */
42
+ dataTestId?: string;
43
+ } & import("react").RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,54 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { CrossHeavyMIcon } from "@koslibs/icons/CrossHeavyMIcon";
3
+ import classnames from "classnames";
4
+ import { forwardRef, useContext } from "react";
5
+ import { useDataTestId } from "../../../../hooks/use-data-test-id.js";
6
+ import { Button } from "../../../Button/index.js";
7
+ import { TypographyText } from "../../../Typography/index.js";
8
+ import { ModalContext } from "../../context.js";
9
+ import index_module from "./index.module.js";
10
+ const Header = /*#__PURE__*/ forwardRef(({ title, subtitle, hasCloser = true, className, dataTestId, ...restProps }, ref)=>{
11
+ const { onClose, dataTestId: modalDataTestId } = useContext(ModalContext);
12
+ const getDataTestId = useDataTestId(dataTestId ?? modalDataTestId);
13
+ const handleClick = ()=>{
14
+ onClose?.();
15
+ };
16
+ return /*#__PURE__*/ jsxs("div", {
17
+ ...restProps,
18
+ ref: ref,
19
+ className: classnames(index_module.component, className),
20
+ "data-test-id": getDataTestId('header'),
21
+ children: [
22
+ /*#__PURE__*/ jsxs("div", {
23
+ className: index_module.content,
24
+ children: [
25
+ Boolean(title) && /*#__PURE__*/ jsx(TypographyText, {
26
+ size: 20,
27
+ weight: "semibold",
28
+ children: title
29
+ }),
30
+ Boolean(subtitle) && /*#__PURE__*/ jsx(TypographyText, {
31
+ size: 14,
32
+ color: "secondary",
33
+ children: subtitle
34
+ })
35
+ ]
36
+ }),
37
+ hasCloser && /*#__PURE__*/ jsx(Button, {
38
+ size: 32,
39
+ view: "transparent",
40
+ className: index_module.closer,
41
+ labelClassName: index_module.closerLabel,
42
+ "aria-label": "Закрыть окно",
43
+ onClick: handleClick,
44
+ children: /*#__PURE__*/ jsx(CrossHeavyMIcon, {
45
+ width: 18,
46
+ height: 18,
47
+ "aria-hidden": "true"
48
+ })
49
+ })
50
+ ]
51
+ });
52
+ });
53
+ Header.displayName = 'ModalHeader';
54
+ export { Header };
@@ -0,0 +1,8 @@
1
+ import "./index_module.css";
2
+ const index_module = {
3
+ component: "component-sqEuYd",
4
+ content: "content-cnwKDB",
5
+ closer: "closer-odHjP5",
6
+ closerLabel: "closerLabel-r61y3R"
7
+ };
8
+ export default index_module;
@@ -0,0 +1,31 @@
1
+ .component-sqEuYd {
2
+ justify-content: space-between;
3
+ align-items: flex-start;
4
+ gap: var(--size-24, 24px);
5
+ padding: var(--modal-padding) var(--modal-padding) 0;
6
+ flex-shrink: 0;
7
+ display: flex;
8
+ }
9
+
10
+ .content-cnwKDB {
11
+ gap: var(--size-4, 4px);
12
+ overflow-wrap: anywhere;
13
+ flex-direction: column;
14
+ flex: 1;
15
+ min-width: 0;
16
+ display: flex;
17
+ }
18
+
19
+ .component-sqEuYd > .closer-odHjP5 {
20
+ flex-shrink: 0;
21
+ width: 48px;
22
+ min-width: 48px;
23
+ padding: 0;
24
+ }
25
+
26
+ .closerLabel-r61y3R {
27
+ justify-content: center;
28
+ align-items: center;
29
+ display: flex;
30
+ }
31
+
@@ -0,0 +1,4 @@
1
+ import type { ModalProps } from '../../types.js';
2
+ type SurfaceProps = Omit<ModalProps, 'open' | 'getPortalContainer'>;
3
+ export declare const ModalSurface: import("react").ForwardRefExoticComponent<SurfaceProps & import("react").RefAttributes<HTMLDialogElement>>;
4
+ export {};
@@ -0,0 +1,81 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import classnames from "classnames";
3
+ import { forwardRef, useCallback, useLayoutEffect, useMemo, useRef } from "react";
4
+ import { ModalContext } from "../../context.js";
5
+ import { lockScroll } from "../../utils/lock-scroll.js";
6
+ import colors_module from "../../colors.module.js";
7
+ import index_module from "../../index.module.js";
8
+ const ModalSurface = /*#__PURE__*/ forwardRef(({ onClose, size = 720, escapeKeyDown = true, backdropClick = true, lockScroll: shouldLockScroll = true, className, dataTestId, children, onPointerDown, onClick, ...restProps }, ref)=>{
9
+ const dialogRef = useRef(null);
10
+ const backdropPointerDown = useRef(false);
11
+ const mounted = useRef(false);
12
+ const contextValue = useMemo(()=>({
13
+ onClose,
14
+ dataTestId
15
+ }), [
16
+ onClose,
17
+ dataTestId
18
+ ]);
19
+ const mergedRef = useCallback((element)=>{
20
+ dialogRef.current = element;
21
+ if ('function' == typeof ref) ref(element);
22
+ else if (ref) ref.current = element;
23
+ }, [
24
+ ref
25
+ ]);
26
+ useLayoutEffect(()=>{
27
+ const dialog = dialogRef.current;
28
+ if (!dialog) return;
29
+ mounted.current = true;
30
+ if (!dialog.open) dialog.showModal();
31
+ return ()=>{
32
+ mounted.current = false;
33
+ dialog.close();
34
+ };
35
+ }, []);
36
+ useLayoutEffect(()=>{
37
+ const dialog = dialogRef.current;
38
+ if (dialog && shouldLockScroll) return lockScroll(dialog.ownerDocument);
39
+ }, [
40
+ shouldLockScroll
41
+ ]);
42
+ const isBackdrop = (event)=>{
43
+ const bounds = event.currentTarget.getBoundingClientRect();
44
+ return event.target === event.currentTarget && (event.clientX < bounds.left || event.clientX > bounds.right || event.clientY < bounds.top || event.clientY > bounds.bottom);
45
+ };
46
+ const handleCancel = (event)=>{
47
+ event.stopPropagation();
48
+ event.preventDefault();
49
+ if (escapeKeyDown) onClose?.();
50
+ };
51
+ const handleClose = (event)=>{
52
+ event.stopPropagation();
53
+ if (mounted.current && !event.currentTarget.open) onClose?.();
54
+ };
55
+ const handlePointerDown = (event)=>{
56
+ onPointerDown?.(event);
57
+ backdropPointerDown.current = !event.defaultPrevented && isBackdrop(event);
58
+ };
59
+ const handleClick = (event)=>{
60
+ onClick?.(event);
61
+ const close = backdropPointerDown.current && isBackdrop(event);
62
+ backdropPointerDown.current = false;
63
+ if (backdropClick && close && !event.defaultPrevented) onClose?.();
64
+ };
65
+ return /*#__PURE__*/ jsx("dialog", {
66
+ ...restProps,
67
+ ref: mergedRef,
68
+ className: classnames(index_module.component, colors_module.component, index_module[`size-${size}`], className),
69
+ "data-test-id": dataTestId,
70
+ onCancel: handleCancel,
71
+ onClose: handleClose,
72
+ onPointerDown: handlePointerDown,
73
+ onClick: handleClick,
74
+ children: /*#__PURE__*/ jsx(ModalContext.Provider, {
75
+ value: contextValue,
76
+ children: children
77
+ })
78
+ });
79
+ });
80
+ ModalSurface.displayName = 'ModalSurface';
81
+ export { ModalSurface };