@brandup/ui-kit 1.0.1 → 1.0.2
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 +31 -2
- package/package.json +1 -1
- package/source/common.less +34 -0
- package/source/index.ts +3 -6
- package/source/middleware.ts +23 -0
- package/source/popup.ts +79 -0
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ npm i @brandup/ui-kit@latest
|
|
|
10
10
|
|
|
11
11
|
Add `@brandup/ui-kit` middleware to your application.
|
|
12
12
|
|
|
13
|
-
```
|
|
13
|
+
```TypeScript
|
|
14
14
|
import { ApplicationBuilder } from "@brandup/ui-app";
|
|
15
15
|
import { uiKitMiddlewareFactory } from "@brandup/ui-kit";
|
|
16
16
|
|
|
@@ -105,4 +105,33 @@ Styles for:
|
|
|
105
105
|
- input[type=text]
|
|
106
106
|
- textarea
|
|
107
107
|
|
|
108
|
-
See [inputs.less](source/inputs.less) file.
|
|
108
|
+
See [inputs.less](source/inputs.less) file.
|
|
109
|
+
|
|
110
|
+
### Popups
|
|
111
|
+
|
|
112
|
+
Popups work with class `ui-popup`.
|
|
113
|
+
|
|
114
|
+
```HTML
|
|
115
|
+
<button data-command="ui-popup-toggle">Menu1</button>
|
|
116
|
+
<div class="ui-popup"></div>
|
|
117
|
+
|
|
118
|
+
<button id="menu2">Menu2</button>
|
|
119
|
+
<div id="popup2" class="ui-popup"></div>
|
|
120
|
+
|
|
121
|
+
<button>Menu3</button>
|
|
122
|
+
<div id="popup2" class="ui-popup"></div>
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Open popup by popup and initiator element:
|
|
126
|
+
|
|
127
|
+
```TypeScript
|
|
128
|
+
PopupManager.open(DOM.getById("popup2"), { initiator: DOM.getById("menu2") });
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Open popup by only popup element:
|
|
132
|
+
|
|
133
|
+
```TypeScript
|
|
134
|
+
PopupManager.open(DOM.getById("popup3"));
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
If the initiator is specified, then when the popup is opened again, it will be closed.
|
package/package.json
CHANGED
package/source/common.less
CHANGED
|
@@ -31,6 +31,15 @@
|
|
|
31
31
|
--svg-height: var(--svg-size);
|
|
32
32
|
--svg-fill: var(--text-color);
|
|
33
33
|
--svg-stroke: var(--text-color);
|
|
34
|
+
|
|
35
|
+
// popup
|
|
36
|
+
|
|
37
|
+
--popup-fill: var(--main-background);
|
|
38
|
+
--popup-border-style: solid;
|
|
39
|
+
--popup-border-width: 1px;
|
|
40
|
+
--popup-border-color: #aaa;
|
|
41
|
+
--popup-border-radius: 5px;
|
|
42
|
+
--popup-box-shadow: 0px 4px 8px 2px rgba(0, 0, 0, 0.12);
|
|
34
43
|
}
|
|
35
44
|
|
|
36
45
|
// Body styles
|
|
@@ -105,4 +114,29 @@ svg {
|
|
|
105
114
|
padding-left: var(--content-padding-lr);
|
|
106
115
|
padding-right: var(--content-padding-lr);
|
|
107
116
|
box-sizing: border-box;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Popup styles
|
|
120
|
+
|
|
121
|
+
.ui-popup {
|
|
122
|
+
position: absolute;
|
|
123
|
+
box-sizing: border-box;
|
|
124
|
+
z-index: 1000;
|
|
125
|
+
background: var(--popup-fill);
|
|
126
|
+
border-style: var(--popup-border-style);
|
|
127
|
+
border-color: var(--popup-border-color);
|
|
128
|
+
border-width: var(--popup-border-width);
|
|
129
|
+
border-radius: var(--popup-border-radius);
|
|
130
|
+
box-shadow: var(--popup-box-shadow);
|
|
131
|
+
visibility: collapse;
|
|
132
|
+
|
|
133
|
+
&.opened {
|
|
134
|
+
visibility: visible;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.ui-popup-expanded {
|
|
139
|
+
& ~ .ui-popup {
|
|
140
|
+
visibility: visible;
|
|
141
|
+
}
|
|
108
142
|
}
|
package/source/index.ts
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { UiKitMiddleware } from "./middleware";
|
|
2
|
+
export * from "./popup"
|
|
2
3
|
import "./styles.less";
|
|
3
4
|
|
|
4
|
-
export const uiKitMiddlewareFactory = ()
|
|
5
|
-
return {
|
|
6
|
-
name: "uikit"
|
|
7
|
-
};
|
|
8
|
-
};
|
|
5
|
+
export const uiKitMiddlewareFactory = () => new UiKitMiddleware();
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Middleware, MiddlewareNext, NavigateContext, StartContext } from "@brandup/ui-app";
|
|
2
|
+
import { PopupManager, POPUP_COMMAND, POPUP_CLASS } from "./popup";
|
|
3
|
+
|
|
4
|
+
export class UiKitMiddleware implements Middleware {
|
|
5
|
+
name = "uikit";
|
|
6
|
+
|
|
7
|
+
start(context: StartContext, next: MiddlewareNext) {
|
|
8
|
+
context.app.registerCommand(POPUP_COMMAND, context => {
|
|
9
|
+
if (!context.target.nextElementSibling?.classList.contains(POPUP_CLASS))
|
|
10
|
+
throw new Error('Not found popup elem.');
|
|
11
|
+
|
|
12
|
+
PopupManager.open(context.target.nextElementSibling as HTMLElement, { initiator: context.target });
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
return next();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
navigate(_context: NavigateContext, next: MiddlewareNext) {
|
|
19
|
+
PopupManager.close(); // закрываем открытое контекстное меню при навигации
|
|
20
|
+
|
|
21
|
+
return next();
|
|
22
|
+
}
|
|
23
|
+
}
|
package/source/popup.ts
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
export const POPUP_CLASS = "ui-popup";
|
|
2
|
+
export const POPUP_EXPANDED_CLASS = "ui-popup-expanded";
|
|
3
|
+
export const POPUP_COMMAND = "ui-popup-toggle";
|
|
4
|
+
|
|
5
|
+
type CurrentPopup = {
|
|
6
|
+
initiator?: HTMLElement,
|
|
7
|
+
popup: HTMLElement,
|
|
8
|
+
closeCallback?: () => void
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
var current: CurrentPopup | null = null;
|
|
12
|
+
|
|
13
|
+
const closePopupEventHandler = (e: MouseEvent) => {
|
|
14
|
+
const target = e.target as HTMLElement;
|
|
15
|
+
if (target.closest(`.${POPUP_CLASS}`))
|
|
16
|
+
return; // если клик внутри popup, то делать ничего не нужно
|
|
17
|
+
|
|
18
|
+
close();
|
|
19
|
+
|
|
20
|
+
const clickedMenuItem = target.closest(`.${POPUP_EXPANDED_CLASS}`);
|
|
21
|
+
if (clickedMenuItem || target == current?.initiator) {
|
|
22
|
+
// если клик по тому же элементу, который открыл контекстное меню, то останавливаем обработку клика, чтобы оно не отрылось заново
|
|
23
|
+
|
|
24
|
+
e.preventDefault();
|
|
25
|
+
e.stopImmediatePropagation();
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const close = () => {
|
|
30
|
+
if (current) {
|
|
31
|
+
if (current.closeCallback)
|
|
32
|
+
current.closeCallback();
|
|
33
|
+
|
|
34
|
+
current.initiator?.classList.remove(POPUP_EXPANDED_CLASS); // закрываем последнее открытое контекстное меню
|
|
35
|
+
current.popup.classList.remove("opened");
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
document.body.removeEventListener("click", closePopupEventHandler);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const open = (popupElem: HTMLElement, options?: PopupOptions) => {
|
|
42
|
+
let newPopup: CurrentPopup = {
|
|
43
|
+
popup: popupElem,
|
|
44
|
+
initiator: options?.initiator
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
newPopup.closeCallback = options?.onClose;
|
|
48
|
+
|
|
49
|
+
if (newPopup.popup.classList.toggle("opened")) {
|
|
50
|
+
// это новый popup, открываем его
|
|
51
|
+
|
|
52
|
+
newPopup.initiator?.classList.add(POPUP_EXPANDED_CLASS);
|
|
53
|
+
|
|
54
|
+
document.body.addEventListener("click", closePopupEventHandler);
|
|
55
|
+
|
|
56
|
+
current = newPopup;
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
// данный popup уже открыт, закрываем его
|
|
60
|
+
close();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export const PopupManager: IPopupManager = {
|
|
65
|
+
open,
|
|
66
|
+
close,
|
|
67
|
+
isOpened: () => !!current
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
interface IPopupManager {
|
|
71
|
+
open: (popupElem: HTMLElement, options?: PopupOptions) => void;
|
|
72
|
+
close: () => void;
|
|
73
|
+
isOpened: () => boolean;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
interface PopupOptions {
|
|
77
|
+
initiator?: HTMLElement;
|
|
78
|
+
onClose?: () => void
|
|
79
|
+
}
|