@brandup/ui-kit 1.0.1 → 1.0.3

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 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
 
@@ -101,8 +101,40 @@ See [common.less](source/common.less) file.
101
101
  ### Input styles
102
102
 
103
103
  Styles for:
104
- - reset for input, textarea, button
105
- - input[type=text]
106
- - textarea
107
104
 
108
- See [inputs.less](source/inputs.less) file.
105
+ - reset for input, textarea, button
106
+ - input[type=text]
107
+ - input[type=checkbox]
108
+ - textarea
109
+ - select
110
+
111
+ See [inputs.less](source/inputs.less) file.
112
+
113
+ ### Popups
114
+
115
+ Popups work with class `ui-popup`.
116
+
117
+ ```HTML
118
+ <button data-command="ui-popup-toggle">Menu1</button>
119
+ <div class="ui-popup"></div>
120
+
121
+ <button id="menu2">Menu2</button>
122
+ <div id="popup2" class="ui-popup"></div>
123
+
124
+ <button>Menu3</button>
125
+ <div id="popup2" class="ui-popup"></div>
126
+ ```
127
+
128
+ Open popup by popup and initiator element:
129
+
130
+ ```TypeScript
131
+ PopupManager.open(DOM.getById("popup2"), { initiator: DOM.getById("menu2") });
132
+ ```
133
+
134
+ Open popup by only popup element:
135
+
136
+ ```TypeScript
137
+ PopupManager.open(DOM.getById("popup3"));
138
+ ```
139
+
140
+ If the initiator is specified, then when the popup is opened again, it will be closed.
package/package.json CHANGED
@@ -22,7 +22,7 @@
22
22
  },
23
23
  "type": "module",
24
24
  "license": "Apache-2.0",
25
- "version": "1.0.1",
25
+ "version": "1.0.3",
26
26
  "main": "source/index.ts",
27
27
  "types": "source/index.ts",
28
28
  "dependencies": {
@@ -30,7 +30,16 @@
30
30
  --svg-width: var(--svg-size);
31
31
  --svg-height: var(--svg-size);
32
32
  --svg-fill: var(--text-color);
33
- --svg-stroke: var(--text-color);
33
+ --svg-stroke: none;
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 { Middleware } from "@brandup/ui-app";
1
+ import { UiKitMiddleware } from "./middleware";
2
+ export * from "./popup"
2
3
  import "./styles.less";
3
4
 
4
- export const uiKitMiddlewareFactory = (): Middleware => {
5
- return {
6
- name: "uikit"
7
- };
8
- };
5
+ export const uiKitMiddlewareFactory = () => new UiKitMiddleware();
@@ -40,22 +40,30 @@
40
40
  --invalid--input-border-color: red;
41
41
  --invalid--input-fill: var(--input-fill);
42
42
  --invalid--input-color: var(--input-color);
43
+
44
+ // toggler
45
+ --toggler-height: 30px;
46
+ --toggler-padding: 3px;
47
+ --toggler-round-fill: var(--hover--input-border-color); // цвет круглешка
43
48
  }
44
49
 
45
50
  input,
46
51
  textarea,
47
- button {
48
- appearance: none;
52
+ button,
53
+ select {
49
54
  font-family: inherit;
50
- font-size: unset;
55
+ font-size: var(--input-font-size);
56
+ font-weight: var(--input-font-weidth);
57
+ font-style: var(--input-font-style);
58
+ color: var(--input-color);
51
59
  line-height: unset;
52
- color: unset;
53
60
  box-sizing: border-box;
54
61
  padding: 0;
55
62
  margin: 0;
56
63
  }
57
64
 
58
- input[type=text], textarea {
65
+ input[type=text], textarea, select {
66
+ appearance: none;
59
67
  outline: none;
60
68
  border-style: var(--input-border-type);
61
69
  border-width: var(--input-border-width);
@@ -67,11 +75,6 @@ input[type=text], textarea {
67
75
  padding-left: var(--input-padding-lr);
68
76
  padding-right: var(--input-padding-lr);
69
77
 
70
- font-size: var(--input-font-size);
71
- font-weight: var(--input-font-weidth);
72
- font-style: var(--input-font-style);
73
- color: var(--input-color);
74
-
75
78
  &::placeholder {
76
79
  font-weight: var(--placeholder-font-weidth);
77
80
  font-style: var(--placeholder-font-style);
@@ -101,7 +104,80 @@ input[type=text], textarea {
101
104
  }
102
105
  }
103
106
 
107
+ select {
108
+ appearance: auto;
109
+ }
110
+
104
111
  textarea {
105
112
  padding-top: calc(1em / 2);
106
113
  padding-bottom: calc(1em / 2);
114
+ }
115
+
116
+ input[type=checkbox] {
117
+ appearance: none;
118
+ position: relative;
119
+ cursor: pointer;
120
+
121
+ background-color: var(--input-fill);
122
+ border-style: var(--input-border-type);
123
+ border-width: var(--input-border-width);
124
+ border-color: var(--input-border-color);
125
+ border-radius: calc(var(--toggler-height) / 2);
126
+
127
+ height: var(--toggler-height);
128
+ width: calc(var(--toggler-height) * 2);
129
+
130
+ --round-size: calc(var(--toggler-height) - var(--toggler-padding) * 2 - var(--input-border-width) * 2);
131
+
132
+ &:after {
133
+ content: '';
134
+ position: absolute;
135
+ background-color: var(--toggler-round-fill);
136
+ width: var(--round-size);
137
+ height: var(--round-size);
138
+ border-radius: 50%;
139
+ left: var(--toggler-padding);
140
+ margin-top: auto;
141
+ margin-bottom: auto;
142
+ top: 0;
143
+ bottom: 0;
144
+ }
145
+
146
+ &:hover, &:focus {
147
+ border-color: var(--hover--input-border-color);
148
+ background: var(--hover--input-fill);
149
+ color: var(--hover--input-color);
150
+ }
151
+
152
+ &[readonly] {
153
+ pointer-events: none;
154
+ }
155
+
156
+ &:checked {
157
+ background-color: var(--toggler-round-fill);
158
+
159
+ &:after {
160
+ background-color: var(--input-fill);
161
+ right: var(--toggler-padding);
162
+ left: auto;
163
+ }
164
+ }
165
+
166
+ &:disabled {
167
+ border-color: var(--disabled--input-border-color);
168
+ background: var(--disabled--input-fill);
169
+ color: var(--disabled--input-color);
170
+ cursor: default;
171
+
172
+ &:after {
173
+ background-color: var(--toggler-round-fill);
174
+ opacity: 0.4;
175
+ }
176
+ }
177
+
178
+ &:user-invalid {
179
+ border-color: var(--invalid--input-border-color);
180
+ background: var(--invalid--input-fill);
181
+ color: var(--invalid--input-color);
182
+ }
107
183
  }
@@ -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
+ }
@@ -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
+ }