@brandup/ui-kit 1.0.40 → 1.0.42
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/package.json +2 -1
- package/source/common.less +44 -1
- package/source/index.ts +7 -0
- package/source/modal.less +13 -4
- package/source/modal.ts +28 -3
- package/source/typings/svg.d.ts +4 -0
- package/svg/x.svg +1 -0
- package/vars.less +6 -0
package/package.json
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
},
|
|
26
26
|
"type": "module",
|
|
27
27
|
"license": "Apache-2.0",
|
|
28
|
-
"version": "1.0.
|
|
28
|
+
"version": "1.0.42",
|
|
29
29
|
"main": "source/index.ts",
|
|
30
30
|
"types": "source/index.ts",
|
|
31
31
|
"dependencies": {
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
"files": [
|
|
35
35
|
"source",
|
|
36
36
|
"build",
|
|
37
|
+
"svg",
|
|
37
38
|
"vars.less",
|
|
38
39
|
"README.md"
|
|
39
40
|
]
|
package/source/common.less
CHANGED
|
@@ -46,6 +46,11 @@
|
|
|
46
46
|
--popup-border-color: @popup-border-color;
|
|
47
47
|
--popup-border-radius: @popup-border-radius;
|
|
48
48
|
--popup-box-shadow: @popup-box-shadow;
|
|
49
|
+
|
|
50
|
+
// scrollable
|
|
51
|
+
--scrollbar-size: @scrollbar-size;
|
|
52
|
+
--scrollbar-thumb: @scrollbar-thumb;
|
|
53
|
+
--scrollbar-thumb-radius: @scrollbar-thumb-radius;
|
|
49
54
|
}
|
|
50
55
|
|
|
51
56
|
// Body styles
|
|
@@ -146,4 +151,42 @@ svg {
|
|
|
146
151
|
& ~ .ui-popup {
|
|
147
152
|
visibility: visible;
|
|
148
153
|
}
|
|
149
|
-
}
|
|
154
|
+
}
|
|
155
|
+
// Scrollable styles
|
|
156
|
+
|
|
157
|
+
// Прокручиваемая область с оформленной полосой: везде в ките она выглядит одинаково,
|
|
158
|
+
// а размер и цвет при надобности переопределяются переменными на самом элементе.
|
|
159
|
+
//
|
|
160
|
+
// Полоса рисуется по краю коробки, поэтому у элемента со скруглением её лучше уводить внутрь —
|
|
161
|
+
// на вложенный прокручиваемый элемент, иначе угол выглядит срезанным.
|
|
162
|
+
.ui-scrollable {
|
|
163
|
+
&::-webkit-scrollbar {
|
|
164
|
+
width: var(--scrollbar-size);
|
|
165
|
+
height: var(--scrollbar-size);
|
|
166
|
+
background: none;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
&::-webkit-scrollbar-track {
|
|
170
|
+
background-color: transparent;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
&::-webkit-scrollbar-thumb {
|
|
174
|
+
background-color: var(--scrollbar-thumb);
|
|
175
|
+
border-radius: var(--scrollbar-thumb-radius);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// кнопки-стрелки по концам полосы: полоса и так узкая, а нажимать их всё равно некому
|
|
179
|
+
&::-webkit-scrollbar-button {
|
|
180
|
+
display: none;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Стандартные свойства — только там, где своей полосы не нарисовать (Firefox). В Blink они
|
|
185
|
+
// отменяют всё оформление выше и возвращают системную полосу: тоньше заданной и со стрелками.
|
|
186
|
+
// Размером Firefox не управляется, у него лишь thin/auto.
|
|
187
|
+
@supports not selector(::-webkit-scrollbar) {
|
|
188
|
+
.ui-scrollable {
|
|
189
|
+
scrollbar-width: thin;
|
|
190
|
+
scrollbar-color: var(--scrollbar-thumb) transparent;
|
|
191
|
+
}
|
|
192
|
+
}
|
package/source/index.ts
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { UiKitMiddleware } from "./middleware";
|
|
2
2
|
export * from "./popup";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Прокручиваемая область с оформленной полосой (см. `.ui-scrollable` в common.less).
|
|
6
|
+
* Размер и цвет переопределяются переменными `--scrollbar-*` на самом элементе.
|
|
7
|
+
*/
|
|
8
|
+
export const SCROLLABLE_CLASS = "ui-scrollable";
|
|
9
|
+
|
|
3
10
|
export { default as Modal, MODAL_CLASS, MODAL_OPENED_CLASS, MODAL_CLOSE_COMMAND, type ModalOptions } from "./modal";
|
|
4
11
|
export { IS_TOUCH_DEVICE } from "./utils/compatibility";
|
|
5
12
|
import "./styles.less";
|
package/source/modal.less
CHANGED
|
@@ -56,14 +56,17 @@
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
& .modal-title {
|
|
59
|
-
font-size: var(--
|
|
60
|
-
font-weight: var(--
|
|
59
|
+
font-size: var(--h4-font-size);
|
|
60
|
+
font-weight: var(--h4-font-weight);
|
|
61
61
|
line-height: var(--h-line-height);
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
& .modal-close {
|
|
65
65
|
flex: 0 0 auto;
|
|
66
66
|
margin-left: auto; // без заголовка крестик всё равно справа
|
|
67
|
+
display: flex;
|
|
68
|
+
align-items: center;
|
|
69
|
+
justify-content: center;
|
|
67
70
|
width: 28px;
|
|
68
71
|
height: 28px;
|
|
69
72
|
padding: 0;
|
|
@@ -71,9 +74,15 @@
|
|
|
71
74
|
border-radius: 50%;
|
|
72
75
|
background: transparent;
|
|
73
76
|
color: inherit;
|
|
74
|
-
font-size: 22px;
|
|
75
|
-
line-height: 1;
|
|
76
77
|
cursor: pointer;
|
|
78
|
+
// Размер значка — общий, но переопределён на месте: крестик вспомогательный, и в полный
|
|
79
|
+
// размер он забивает кнопку. Размеры берёт общее правило для svg, повторять их незачем.
|
|
80
|
+
--svg-size: 12px;
|
|
81
|
+
|
|
82
|
+
& svg {
|
|
83
|
+
fill: currentColor; // крестик следует за цветом окна, а не за общей заливкой значков
|
|
84
|
+
pointer-events: none; // цель клика — сама кнопка, иначе команда искалась бы от svg
|
|
85
|
+
}
|
|
77
86
|
|
|
78
87
|
&:hover {
|
|
79
88
|
background-color: rgba(0, 0, 0, 0.06);
|
package/source/modal.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import "./modal.less"; // стили окна
|
|
2
2
|
|
|
3
3
|
import { DOM, UIElement } from "@brandup/ui";
|
|
4
|
+
import closeIcon from "../svg/x.svg";
|
|
4
5
|
|
|
5
6
|
export const MODAL_CLASS = "ui-modal";
|
|
6
7
|
export const MODAL_OPENED_CLASS = "ui-modal-opened"; // на <body>, чтобы страница не прокручивалась
|
|
@@ -28,6 +29,7 @@ export interface ModalOptions {
|
|
|
28
29
|
export default abstract class Modal extends UIElement {
|
|
29
30
|
private readonly __body: HTMLElement;
|
|
30
31
|
private readonly __onKeyDown: (e: KeyboardEvent) => void;
|
|
32
|
+
private readonly __closeHandlers: Array<() => void> = [];
|
|
31
33
|
private __closed = false;
|
|
32
34
|
private __disposed = false;
|
|
33
35
|
|
|
@@ -47,15 +49,15 @@ export default abstract class Modal extends UIElement {
|
|
|
47
49
|
"div",
|
|
48
50
|
options.closeOnBackdrop === false
|
|
49
51
|
? { class: "modal-backdrop" }
|
|
50
|
-
: { class: "modal-backdrop",
|
|
52
|
+
: { class: "modal-backdrop", command: MODAL_CLOSE_COMMAND }
|
|
51
53
|
),
|
|
52
54
|
DOM.tag("div", { class: "modal-window", role: "dialog", "aria-modal": "true" }, [
|
|
53
55
|
DOM.tag("div", { class: "modal-header" }, [
|
|
54
56
|
options.title ? DOM.tag("div", { class: "modal-title" }, options.title) : null,
|
|
55
57
|
DOM.tag(
|
|
56
58
|
"button",
|
|
57
|
-
{ type: "button", class: "modal-close", title: "Закрыть",
|
|
58
|
-
|
|
59
|
+
{ type: "button", class: "modal-close", title: "Закрыть", command: MODAL_CLOSE_COMMAND },
|
|
60
|
+
closeIcon
|
|
59
61
|
),
|
|
60
62
|
]),
|
|
61
63
|
body,
|
|
@@ -85,6 +87,18 @@ export default abstract class Modal extends UIElement {
|
|
|
85
87
|
// по умолчанию ничего
|
|
86
88
|
}
|
|
87
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Подписка на закрытие окна: вызывается ровно один раз, чем бы оно ни кончилось — крестиком,
|
|
92
|
+
* Esc, подложкой, применением или удалением элемента из DOM. Нужна тому, кто придержал что-то
|
|
93
|
+
* на время работы окна и обязан отпустить это в любом исходе.
|
|
94
|
+
*
|
|
95
|
+
* Подписка на уже закрытое окно срабатывает сразу: иначе придержанное не отпустил бы никто.
|
|
96
|
+
*/
|
|
97
|
+
onClosed(handler: () => void): void {
|
|
98
|
+
if (this.__disposed) handler();
|
|
99
|
+
else this.__closeHandlers.push(handler);
|
|
100
|
+
}
|
|
101
|
+
|
|
88
102
|
protected get body(): HTMLElement {
|
|
89
103
|
return this.__body;
|
|
90
104
|
}
|
|
@@ -109,6 +123,17 @@ export default abstract class Modal extends UIElement {
|
|
|
109
123
|
|
|
110
124
|
this.element?.remove();
|
|
111
125
|
|
|
126
|
+
// После того как окна не стало: подписчик обычно возвращает себе фокус и каретку.
|
|
127
|
+
// Ошибка одного не должна лишать остальных их уборки и рвать разрушение окна.
|
|
128
|
+
const handlers = this.__closeHandlers.splice(0);
|
|
129
|
+
for (const handler of handlers) {
|
|
130
|
+
try {
|
|
131
|
+
handler();
|
|
132
|
+
} catch (error) {
|
|
133
|
+
console.error("Modal: обработчик закрытия завершился ошибкой.", error);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
112
137
|
super.destroy();
|
|
113
138
|
}
|
|
114
139
|
}
|
package/svg/x.svg
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30"><path d="M 7 4 C 6.744125 4 6.4879687 4.0974687 6.2929688 4.2929688 L 4.2929688 6.2929688 C 3.9019687 6.6839688 3.9019687 7.3170313 4.2929688 7.7070312 L 11.585938 15 L 4.2929688 22.292969 C 3.9019687 22.683969 3.9019687 23.317031 4.2929688 23.707031 L 6.2929688 25.707031 C 6.6839688 26.098031 7.3170313 26.098031 7.7070312 25.707031 L 15 18.414062 L 22.292969 25.707031 C 22.682969 26.098031 23.317031 26.098031 23.707031 25.707031 L 25.707031 23.707031 C 26.098031 23.316031 26.098031 22.682969 25.707031 22.292969 L 18.414062 15 L 25.707031 7.7070312 C 26.098031 7.3170312 26.098031 6.6829688 25.707031 6.2929688 L 23.707031 4.2929688 C 23.316031 3.9019687 22.682969 3.9019687 22.292969 4.2929688 L 15 11.585938 L 7.7070312 4.2929688 C 7.5115312 4.0974687 7.255875 4 7 4 z"/></svg>
|
package/vars.less
CHANGED
|
@@ -46,6 +46,12 @@
|
|
|
46
46
|
@popup-border-radius: 5px;
|
|
47
47
|
@popup-box-shadow: 0px 4px 8px 2px rgba(0, 0, 0, 0.12);
|
|
48
48
|
|
|
49
|
+
// scrollable
|
|
50
|
+
|
|
51
|
+
@scrollbar-size: 6px;
|
|
52
|
+
@scrollbar-thumb: #8696a0;
|
|
53
|
+
@scrollbar-thumb-radius: 3px;
|
|
54
|
+
|
|
49
55
|
// inputs
|
|
50
56
|
|
|
51
57
|
@placeholder-font-weight: inherit;
|