@adamjanicki/ui 1.0.6 → 1.0.7

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.
@@ -0,0 +1,26 @@
1
+ import React from "react";
2
+ type Props = {
3
+ /**
4
+ * Whether the layer is open or not
5
+ */
6
+ open: boolean;
7
+ /**
8
+ * Callback that fires when the user clicks outside the layer
9
+ */
10
+ onClose: () => void;
11
+ /**
12
+ * The child of the layer.
13
+ * IMPORTANT: the child must be able to accept a ref
14
+ */
15
+ children: React.ReactElement;
16
+ /**
17
+ * [Optional] Additional class name
18
+ */
19
+ backdropClassName?: string;
20
+ /**
21
+ * [Optional] Additional styles
22
+ */
23
+ backdropStyle?: React.CSSProperties;
24
+ };
25
+ declare const Modal: ({ open, onClose, children, backdropStyle, backdropClassName, }: Props) => JSX.Element | null;
26
+ export default Modal;
@@ -0,0 +1,35 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import React, { useEffect } from "react";
3
+ import { useFocusTrap, useScrollLock } from "../../hooks";
4
+ import { classNames } from "../../utils/util";
5
+ var Modal = function (_a) {
6
+ var open = _a.open, onClose = _a.onClose, children = _a.children, _b = _a.backdropStyle, backdropStyle = _b === void 0 ? {} : _b, backdropClassName = _a.backdropClassName;
7
+ var _c = useScrollLock(), lock = _c.lock, unlock = _c.unlock;
8
+ var focusRef = useFocusTrap(open);
9
+ useEffect(function () {
10
+ var handleEscape = function (event) {
11
+ if (event.key === "Escape") {
12
+ onClose();
13
+ }
14
+ };
15
+ document.addEventListener("keydown", handleEscape);
16
+ return function () {
17
+ document.removeEventListener("keydown", handleEscape);
18
+ };
19
+ }, [onClose]);
20
+ useEffect(function () {
21
+ if (open)
22
+ lock();
23
+ else
24
+ unlock();
25
+ }, [open, lock, unlock]);
26
+ return open ? (_jsx("div", { className: classNames("ajui-layer-backdrop", backdropClassName), style: backdropStyle, onClick: onClose, children: React.cloneElement(children, {
27
+ ref: focusRef,
28
+ onClick: function (e) {
29
+ var _a, _b;
30
+ e.stopPropagation();
31
+ (_b = (_a = children.props).onClick) === null || _b === void 0 ? void 0 : _b.call(_a, e);
32
+ },
33
+ }) })) : null;
34
+ };
35
+ export default Modal;
@@ -0,0 +1,2 @@
1
+ import Layer from "./Layer";
2
+ export default Layer;
@@ -0,0 +1,2 @@
1
+ import Layer from "./Layer";
2
+ export default Layer;
@@ -3,7 +3,7 @@ type Props = {
3
3
  /**
4
4
  * Whether the modal is open or not
5
5
  */
6
- isOpen: boolean;
6
+ open: boolean;
7
7
  /**
8
8
  * Callback that fires when the user clicks the close button or outside the modal
9
9
  */
@@ -21,5 +21,5 @@ type Props = {
21
21
  */
22
22
  style?: React.CSSProperties;
23
23
  };
24
- declare const Modal: ({ isOpen, onClose, children, className, style, }: Props) => JSX.Element | null;
24
+ declare const Modal: ({ open, onClose, children, className, style, }: Props) => JSX.Element | null;
25
25
  export default Modal;
@@ -1,36 +1,12 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { useEffect } from "react";
3
- import { useFocusTrap, useScrollLock } from "../../hooks";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
4
2
  import { IconButton } from "../Button";
5
3
  import { classNames } from "../../utils/util";
4
+ import Layer from "../Layer";
6
5
  var Modal = function (_a) {
7
- var isOpen = _a.isOpen, onClose = _a.onClose, children = _a.children, className = _a.className, style = _a.style;
8
- var _b = useScrollLock(), lock = _b.lock, unlock = _b.unlock;
9
- var focusRef = useFocusTrap(isOpen);
10
- useEffect(function () {
11
- var handleEscape = function (event) {
12
- if (event.key === "Escape") {
13
- onClose();
14
- }
15
- };
16
- document.addEventListener("keydown", handleEscape);
17
- return function () {
18
- document.removeEventListener("keydown", handleEscape);
19
- };
20
- }, [onClose]);
21
- useEffect(function () {
22
- if (isOpen) {
23
- lock();
24
- }
25
- else {
26
- unlock();
27
- }
28
- }, [isOpen, lock, unlock]);
29
- if (!isOpen)
30
- return null;
31
- return (_jsxs(_Fragment, { children: [_jsx("div", { className: "ajui-modal-backdrop", onClick: onClose }), _jsxs("div", { className: classNames("ajui-modal", className), role: "dialog", "aria-modal": "true", ref: focusRef, style: style, children: [_jsx("div", { style: {
32
- display: "flex",
33
- justifyContent: "flex-end",
34
- }, children: _jsx(IconButton, { name: "close", icon: "\u00D7", onClick: onClose, className: "ajui-modal-close" }) }), children, " "] })] }));
6
+ var open = _a.open, onClose = _a.onClose, children = _a.children, className = _a.className, style = _a.style;
7
+ return (_jsx(Layer, { onClose: onClose, open: open, children: _jsxs("div", { className: classNames("ajui-modal", className), role: "dialog", "aria-modal": "true", style: style, children: [_jsx("div", { style: {
8
+ display: "flex",
9
+ justifyContent: "flex-end",
10
+ }, children: _jsx(IconButton, { name: "close", icon: "\u00D7", onClick: onClose, className: "ajui-modal-close" }) }), children] }) }));
35
11
  };
36
12
  export default Modal;
@@ -11,14 +11,14 @@ type Props = React.DetailedHTMLProps<React.SelectHTMLAttributes<HTMLSelectElemen
11
11
  * @param option the option to get the value of
12
12
  * @returns the value of the option
13
13
  */
14
- getOptionValue: (option: string) => string;
14
+ getOptionValue?: (option: string) => string;
15
15
  /**
16
16
  * Mapper function to get the label of the option
17
17
  *
18
18
  * @param option the option to get the label of
19
19
  * @returns the label of the option
20
20
  */
21
- getOptionLabel: (option: string) => string;
21
+ getOptionLabel?: (option: string) => string;
22
22
  /**
23
23
  * [Optional] The corner style of the select element.
24
24
  * @default "rounded"
@@ -23,8 +23,9 @@ var __rest = (this && this.__rest) || function (s, e) {
23
23
  import { jsx as _jsx } from "react/jsx-runtime";
24
24
  import { forwardRef } from "react";
25
25
  import { classNames } from "../../utils/util";
26
+ var identity = function (x) { return x; };
26
27
  var Select = function (_a, ref) {
27
- var className = _a.className, options = _a.options, getOptionValue = _a.getOptionValue, getOptionLabel = _a.getOptionLabel, _b = _a.corners, corners = _b === void 0 ? "rounded" : _b, props = __rest(_a, ["className", "options", "getOptionValue", "getOptionLabel", "corners"]);
28
+ var className = _a.className, options = _a.options, _b = _a.getOptionValue, getOptionValue = _b === void 0 ? identity : _b, _c = _a.getOptionLabel, getOptionLabel = _c === void 0 ? identity : _c, _d = _a.corners, corners = _d === void 0 ? "rounded" : _d, props = __rest(_a, ["className", "options", "getOptionValue", "getOptionLabel", "corners"]);
28
29
  return (_jsx("select", __assign({}, props, { ref: ref, className: classNames("ajui-select-base corners--".concat(corners), className), children: options.map(function (option, index) { return (_jsx("option", { value: getOptionValue(option), children: getOptionLabel(option) }, index)); }) })));
29
30
  };
30
31
  export default forwardRef(Select);
package/index.d.ts CHANGED
@@ -10,4 +10,5 @@ export { default as Banner } from "./components/Banner";
10
10
  export { default as Select } from "./components/Select";
11
11
  export { default as ClickOutside } from "./components/ClickOutside";
12
12
  export { default as Modal } from "./components/Modal";
13
+ export { default as Layer } from "./components/Layer";
13
14
  export * from "./hooks";
package/index.js CHANGED
@@ -11,5 +11,6 @@ export { default as Banner } from "./components/Banner";
11
11
  export { default as Select } from "./components/Select";
12
12
  export { default as ClickOutside } from "./components/ClickOutside";
13
13
  export { default as Modal } from "./components/Modal";
14
+ export { default as Layer } from "./components/Layer";
14
15
  // Hooks
15
16
  export * from "./hooks";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adamjanicki/ui",
3
- "version": "1.0.6",
3
+ "version": "1.0.7",
4
4
  "description": "Basic UI components and hooks for React in TypeScript",
5
5
  "main": "./index.js",
6
6
  "types": "./index.d.ts",
package/style.css CHANGED
@@ -3,14 +3,16 @@
3
3
  /* General colors */
4
4
  --ajui-light-gray: #eee;
5
5
  --ajui-moon-gray: #ccc;
6
+ --ajui-dark-gray: #555;
6
7
  --ajui-darkest-gray: #333;
8
+ --ajui-obsidian: #121212;
7
9
  --ajui-focus-ring-color: #b2dbfa;
8
- --ajui-default-color: black;
10
+ --ajui-default-color: #111;
9
11
  --ajui-default-background: white;
10
12
  --ajui-default-border: var(--ajui-moon-gray);
11
13
  /* General values */
12
- --ajui-disabled-opacity: 0.4;
13
- --ajui-default-transition: 0.2s ease-in-out;
14
+ --ajui-disabled-opacity: 0.5;
15
+ --ajui-default-transition: 0.25s ease-in-out;
14
16
  --ajui-default-opacity-dim: 0.75;
15
17
  /* Corners */
16
18
  --ajui-sharp-radius: 0;
@@ -18,18 +20,18 @@
18
20
  --ajui-pill-radius: 9999px;
19
21
  --ajui-circle-radius: 50%;
20
22
  /* Buttons */
21
- --ajui-button-primary-background: var(--ajui-default-color);
22
- --ajui-button-primary-color: var(--ajui-default-background);
23
- --ajui-button-secondary-background: var(--ajui-default-background);
24
- --ajui-button-secondary-color: var(--ajui-default-color);
25
- --ajui-button-secondary-border: var(--ajui-default-border);
23
+ --ajui-button-primary-background: black;
24
+ --ajui-button-primary-color: white;
25
+ --ajui-button-secondary-background: white;
26
+ --ajui-button-secondary-color: #111;
27
+ --ajui-button-secondary-border: var(--ajui-moon-gray);
26
28
  --ajui-button-transparent-background: transparent;
27
29
  --ajui-button-secondary-border-hover: var(--ajui-darkest-gray);
28
30
  /* Input */
29
31
  --ajui-input-selection-color: var(--ajui-focus-ring-color);
30
32
  --ajui-input-border: var(--ajui-default-border);
31
33
  /* Select */
32
- --ajui-select-border: var(--ajui-default-border);
34
+ --ajui-select-border: var(--ajui-moon-gray);
33
35
  /* Content types */
34
36
  --ajui-success-background: #dff2e1;
35
37
  --ajui-success-color: #1b5e20;
@@ -51,13 +53,61 @@
51
53
  --ajui-static-color: #424242;
52
54
  --ajui-static-border: #bdbdbd;
53
55
  /* Modal */
54
- --ajui-modal-backdrop-background: rgba(0, 0, 0, 0.5);
56
+ --ajui-layer-backdrop-background: rgba(0, 0, 0, 0.5);
55
57
  /* Link */
56
58
  --ajui-link-color: #0070ff;
57
59
  }
58
60
 
61
+ [data-theme="dark"] {
62
+ /* General colors */
63
+ --ajui-focus-ring-color: #6699cc;
64
+ --ajui-default-color: white;
65
+ --ajui-default-background: var(--ajui-obsidian);
66
+ --ajui-default-border: var(--ajui-dark-gray);
67
+ /* Buttons */
68
+ --ajui-button-primary-background: white;
69
+ --ajui-button-primary-color: var(--ajui-obsidian);
70
+ --ajui-button-secondary-background: var(--ajui-obsidian);
71
+ --ajui-button-secondary-color: white;
72
+ --ajui-button-secondary-border: var(--ajui-dark-gray);
73
+ --ajui-button-transparent-background: transparent;
74
+ --ajui-button-secondary-border-hover: var(--ajui-moon-gray);
75
+ /* Input */
76
+ --ajui-input-selection-color: var(--ajui-focus-ring-color);
77
+ --ajui-input-border: var(--ajui-dark-gray);
78
+ /* Select */
79
+ --ajui-select-border: var(--ajui-dark-gray);
80
+ /* Content types */
81
+ --ajui-success-background: #2a5733;
82
+ --ajui-success-color: #d9efd8;
83
+ --ajui-success-border: #439e4a;
84
+
85
+ --ajui-warning-background: #736230;
86
+ --ajui-warning-color: #fff6d1;
87
+ --ajui-warning-border: #927a3b;
88
+
89
+ --ajui-error-background: #663232;
90
+ --ajui-error-color: #f9dadc;
91
+ --ajui-error-border: #8d2a2a;
92
+
93
+ --ajui-info-background: #335f72;
94
+ --ajui-info-color: #d4f1f5;
95
+ --ajui-info-border: #1d8ea4;
96
+
97
+ --ajui-static-background: #333333;
98
+ --ajui-static-color: #e5e5e5;
99
+ --ajui-static-border: #595959;
100
+ /* Modal */
101
+ --ajui-layer-backdrop-background: rgba(0, 0, 0, 0.8);
102
+ /* Link */
103
+ --ajui-link-color: #ffa500;
104
+ }
105
+
59
106
  a:not([disabled]):is(:focus-visible),
60
- button:not([disabled]):is(:focus-visible),
107
+ button:not([disabled]):is(:focus-visible) {
108
+ outline: 3px solid var(--ajui-link-color);
109
+ outline-offset: 0;
110
+ }
61
111
  .ajui-input-default:focus-within,
62
112
  .ajui-select-base:focus-within {
63
113
  outline: 3px solid var(--ajui-focus-ring-color);
@@ -108,7 +158,7 @@ button:not([disabled]):is(:focus-visible),
108
158
 
109
159
  /* Alert */
110
160
  .ajui-alert {
111
- padding: 0.75rem;
161
+ padding: 1rem;
112
162
  border-style: solid;
113
163
  border-width: 1px;
114
164
  font-weight: 400;
@@ -116,7 +166,7 @@ button:not([disabled]):is(:focus-visible),
116
166
 
117
167
  /* Badge */
118
168
  .ajui-badge {
119
- padding: 1px 5px;
169
+ padding: 0.125rem 0.375rem;
120
170
  border-style: solid;
121
171
  border-width: 1px;
122
172
  font-weight: 600;
@@ -151,7 +201,7 @@ a {
151
201
  }
152
202
 
153
203
  .ajui-button-default {
154
- padding: 0.5rem 0.75rem;
204
+ padding: 0.5rem 1rem;
155
205
  }
156
206
 
157
207
  .ajui-icon-button {
@@ -189,14 +239,14 @@ a {
189
239
  }
190
240
 
191
241
  @media (hover: hover) {
192
- .ajui-button--primary:not([disabled]):hover,
193
- .ajui-icon-button:not([disabled]):hover,
194
- .ajui-link-default:hover {
242
+ .ajui-button--primary:not([disabled]):is(:hover, :focus-within),
243
+ .ajui-icon-button:not([disabled]):is(:hover, :focus-within),
244
+ .ajui-link-default:is(:hover, :focus-within) {
195
245
  opacity: var(--ajui-default-opacity-dim);
196
246
  }
197
247
 
198
- .ajui-button--transparent:not([disabled]):hover,
199
- .ajui-button--secondary:not([disabled]):hover {
248
+ .ajui-button--transparent:not([disabled]):is(:hover, :focus-within),
249
+ .ajui-button--secondary:not([disabled]):is(:hover, :focus-within) {
200
250
  box-shadow: inset 0 0 0 1px var(--ajui-button-secondary-border-hover);
201
251
  }
202
252
  }
@@ -206,6 +256,7 @@ a {
206
256
  outline: 0px solid transparent;
207
257
  border: none;
208
258
  background-color: inherit;
259
+ color: inherit;
209
260
  padding: 0.75rem 0.5rem;
210
261
  font-size: 1rem;
211
262
  font-weight: 400;
@@ -234,6 +285,7 @@ a {
234
285
 
235
286
  /* Select */
236
287
  .ajui-select-base {
288
+ color: inherit;
237
289
  outline: 0px solid transparent;
238
290
  border: none;
239
291
  background-color: inherit;
@@ -251,27 +303,25 @@ a {
251
303
  }
252
304
 
253
305
  /* Modal */
254
- .ajui-modal-backdrop {
306
+ .ajui-layer-backdrop {
255
307
  position: fixed;
256
308
  top: 0;
257
309
  left: 0;
258
310
  width: 100vw;
259
311
  height: 100vh;
260
- background: var(--ajui-modal-backdrop-background);
261
312
  z-index: 10000;
313
+ background: var(--ajui-layer-backdrop-background);
314
+ display: flex;
315
+ justify-content: center;
316
+ align-items: center;
262
317
  }
263
318
 
264
319
  .ajui-modal {
265
- position: fixed;
266
- top: 50%;
267
- left: 50%;
268
- transform: translate(-50%, -50%);
269
320
  background: var(--ajui-default-background);
270
- z-index: 10001;
271
321
  box-shadow: inset 0 0 0 1px var(--ajui-default-border);
272
322
  border-radius: var(--ajui-rounded-radius);
273
- min-width: 50vw;
274
- max-width: 90vw;
323
+ min-width: 50%;
324
+ max-width: 90%;
275
325
  }
276
326
 
277
327
  .ajui-modal-close {