uibee 1.4.0 → 1.4.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 +36 -2
- package/dist/globals.css +40 -3
- package/dist/src/components/toast/toaster.d.ts +2 -2
- package/dist/src/components/toast/toaster.js +28 -14
- package/dist/src/utils/LogoConsoleOutput/LogoConsoleOutput.d.ts +1 -0
- package/dist/src/utils/LogoConsoleOutput/LogoConsoleOutput.js +44 -0
- package/dist/src/utils/cookies/cookies.d.ts +4 -0
- package/dist/src/utils/cookies/cookies.js +28 -0
- package/dist/src/utils/index.d.ts +2 -0
- package/dist/src/utils/index.js +2 -0
- package/index.d.ts +5 -0
- package/package.json +1 -1
- package/src/components/toast/toaster.tsx +37 -17
- package/src/types/components.d.ts +7 -4
- package/src/utils/LogoConsoleOutput/LogoConsoleOutput.ts +61 -0
- package/src/utils/cookies/cookies.ts +38 -0
- package/src/utils/index.ts +2 -0
- package/tsconfig.json +5 -2
package/Readme.md
CHANGED
|
@@ -1,4 +1,38 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
|
|
2
|
+
# Uibee
|
|
3
3
|
|
|
4
4
|
This package includes shared components, functions and hooks for reuse across Login projects.
|
|
5
|
+
|
|
6
|
+
## Installation
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
# Clone the repository
|
|
10
|
+
git clone git@github.com:Login-Linjeforening-for-IT/uibee.git
|
|
11
|
+
cd uibee
|
|
12
|
+
|
|
13
|
+
# Install dependencies
|
|
14
|
+
npm install
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# Start the development server
|
|
21
|
+
npm run build
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Folder Structure
|
|
25
|
+
```
|
|
26
|
+
.
|
|
27
|
+
├── src/
|
|
28
|
+
│ ├── components/ # Reusable NextJS components
|
|
29
|
+
│ ├── hooks/ # Custom React hooks
|
|
30
|
+
│ ├── scripts/ # Build and utility scripts
|
|
31
|
+
│ ├── types/ # TypeScript type definitions
|
|
32
|
+
│ ├── utils/ # Utility functions
|
|
33
|
+
│ └── globals.css # Global styles
|
|
34
|
+
├── images/ # Project images and SVGs
|
|
35
|
+
├── package.json # Project metadata and scripts
|
|
36
|
+
├── tailwind.config.ts # Tailwind CSS configuration
|
|
37
|
+
├── tsconfig.json # TypeScript configuration
|
|
38
|
+
```
|
package/dist/globals.css
CHANGED
|
@@ -7,6 +7,10 @@
|
|
|
7
7
|
"Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
|
8
8
|
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
|
|
9
9
|
"Courier New", monospace;
|
|
10
|
+
--color-red-300: oklch(80.8% 0.114 19.571);
|
|
11
|
+
--color-yellow-300: oklch(90.5% 0.182 98.111);
|
|
12
|
+
--color-green-300: oklch(87.1% 0.15 154.449);
|
|
13
|
+
--color-blue-300: oklch(80.9% 0.105 251.813);
|
|
10
14
|
--spacing: 0.25rem;
|
|
11
15
|
--container-xs: 20rem;
|
|
12
16
|
--container-sm: 24rem;
|
|
@@ -185,9 +189,6 @@
|
|
|
185
189
|
}
|
|
186
190
|
}
|
|
187
191
|
@layer utilities {
|
|
188
|
-
.absolute {
|
|
189
|
-
position: absolute;
|
|
190
|
-
}
|
|
191
192
|
.fixed {
|
|
192
193
|
position: fixed;
|
|
193
194
|
}
|
|
@@ -209,6 +210,12 @@
|
|
|
209
210
|
.mb-2 {
|
|
210
211
|
margin-bottom: calc(var(--spacing) * 2);
|
|
211
212
|
}
|
|
213
|
+
.line-clamp-3 {
|
|
214
|
+
overflow: hidden;
|
|
215
|
+
display: -webkit-box;
|
|
216
|
+
-webkit-box-orient: vertical;
|
|
217
|
+
-webkit-line-clamp: 3;
|
|
218
|
+
}
|
|
212
219
|
.flex {
|
|
213
220
|
display: flex;
|
|
214
221
|
}
|
|
@@ -326,6 +333,12 @@
|
|
|
326
333
|
.py-12 {
|
|
327
334
|
padding-block: calc(var(--spacing) * 12);
|
|
328
335
|
}
|
|
336
|
+
.pr-1 {
|
|
337
|
+
padding-right: calc(var(--spacing) * 1);
|
|
338
|
+
}
|
|
339
|
+
.pb-1 {
|
|
340
|
+
padding-bottom: calc(var(--spacing) * 1);
|
|
341
|
+
}
|
|
329
342
|
.text-center {
|
|
330
343
|
text-align: center;
|
|
331
344
|
}
|
|
@@ -357,6 +370,18 @@
|
|
|
357
370
|
--tw-tracking: var(--tracking-tight);
|
|
358
371
|
letter-spacing: var(--tracking-tight);
|
|
359
372
|
}
|
|
373
|
+
.text-blue-300\/70 {
|
|
374
|
+
color: color-mix(in srgb, oklch(80.9% 0.105 251.813) 70%, transparent);
|
|
375
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
376
|
+
color: color-mix(in oklab, var(--color-blue-300) 70%, transparent);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
.text-green-300\/70 {
|
|
380
|
+
color: color-mix(in srgb, oklch(87.1% 0.15 154.449) 70%, transparent);
|
|
381
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
382
|
+
color: color-mix(in oklab, var(--color-green-300) 70%, transparent);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
360
385
|
.text-login {
|
|
361
386
|
color: var(--color-login);
|
|
362
387
|
}
|
|
@@ -366,6 +391,18 @@
|
|
|
366
391
|
.text-login-100 {
|
|
367
392
|
color: var(--color-login-100);
|
|
368
393
|
}
|
|
394
|
+
.text-red-300\/70 {
|
|
395
|
+
color: color-mix(in srgb, oklch(80.8% 0.114 19.571) 70%, transparent);
|
|
396
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
397
|
+
color: color-mix(in oklab, var(--color-red-300) 70%, transparent);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
.text-yellow-300\/70 {
|
|
401
|
+
color: color-mix(in srgb, oklch(90.5% 0.182 98.111) 70%, transparent);
|
|
402
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
403
|
+
color: color-mix(in oklab, var(--color-yellow-300) 70%, transparent);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
369
406
|
.transition-all {
|
|
370
407
|
transition-property: all;
|
|
371
408
|
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare function addToast(
|
|
1
|
+
import { ToastType } from 'uibee/components';
|
|
2
|
+
export declare function addToast(type: ToastType, title: string, description?: string): void;
|
|
3
3
|
export default function Toaster(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -3,19 +3,21 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { CircleAlert, CircleCheck, CircleX, Info } from 'lucide-react';
|
|
4
4
|
import { useEffect, useState, useRef } from 'react';
|
|
5
5
|
const observers = [];
|
|
6
|
-
export function addToast(
|
|
7
|
-
observers.forEach((observer) => observer({
|
|
6
|
+
export function addToast(type, title, description = '') {
|
|
7
|
+
observers.forEach((observer) => observer({ title, description, type }));
|
|
8
8
|
}
|
|
9
9
|
export default function Toaster() {
|
|
10
10
|
const [toasts, setToasts] = useState([]);
|
|
11
11
|
const timers = useRef({});
|
|
12
12
|
const [isHovered, setIsHovered] = useState(false);
|
|
13
13
|
const pauseTimes = useRef({});
|
|
14
|
+
const mainToastRef = useRef(null);
|
|
15
|
+
const [mainToastPosition, setMainToastPosition] = useState(null);
|
|
14
16
|
useEffect(() => {
|
|
15
|
-
const listener = ({
|
|
17
|
+
const listener = ({ type, title, description }) => {
|
|
16
18
|
const id = Date.now();
|
|
17
19
|
setToasts(prev => {
|
|
18
|
-
const newToasts = prev.concat({ id,
|
|
20
|
+
const newToasts = prev.concat({ id, type, title, description, remaining: 3000, created: Date.now() }).slice(-3);
|
|
19
21
|
return newToasts;
|
|
20
22
|
});
|
|
21
23
|
};
|
|
@@ -51,25 +53,37 @@ export default function Toaster() {
|
|
|
51
53
|
});
|
|
52
54
|
}
|
|
53
55
|
}, [isHovered, toasts]);
|
|
56
|
+
// Track main toast position for stacking
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
if (mainToastRef.current && toasts.length > 0) {
|
|
59
|
+
const rect = mainToastRef.current.getBoundingClientRect();
|
|
60
|
+
setMainToastPosition({
|
|
61
|
+
top: rect.top,
|
|
62
|
+
right: window.innerWidth - rect.right
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}, [toasts, isHovered]);
|
|
54
66
|
const bgClasses = ['bg-login-600', 'bg-login-700', 'bg-login-800'];
|
|
55
|
-
return (_jsx("div", { className: `fixed bottom-4 right-4 z-50 flex ${isHovered ? 'flex-col-reverse items-end gap-2' : 'flex-col items-end'}`, onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), children: toasts.slice().reverse().map((toast, idx) => (_jsxs("div", { className: 'p-2 rounded-lg text-login-50 animate-fade-in-down transition-all w-sm flex items-center gap-2 ' +
|
|
56
|
-
(bgClasses[idx] || bgClasses[2]), style: isHovered ? {} : {
|
|
57
|
-
|
|
58
|
-
|
|
67
|
+
return (_jsx("div", { className: `fixed bottom-4 right-4 z-50 flex ${isHovered ? 'flex-col-reverse items-end gap-2' : 'flex-col items-end'}`, onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), children: toasts.slice().reverse().map((toast, idx) => (_jsxs("div", { ref: idx === 0 ? mainToastRef : null, className: 'p-2 rounded-lg text-login-50 animate-fade-in-down transition-all w-sm flex items-center gap-2 ' +
|
|
68
|
+
(bgClasses[idx] || bgClasses[2]), style: isHovered ? {} : idx === 0 ? {
|
|
69
|
+
zIndex: 100,
|
|
70
|
+
} : {
|
|
71
|
+
position: 'fixed',
|
|
72
|
+
top: mainToastPosition ? `${mainToastPosition.top - idx * 8}px` : 'auto',
|
|
59
73
|
zIndex: 100 - idx,
|
|
60
|
-
bottom: `${idx * 8}px`,
|
|
61
74
|
transform: `scale(${1 - idx * 0.05})`,
|
|
62
|
-
}, children: [_jsx("span", { className: 'flex-shrink-0 w-10 h-10 flex items-center justify-center', children: _jsx(ToastIcon, { type: toast.type }) }), _jsx("span", { children: toast.
|
|
75
|
+
}, children: [_jsx("span", { className: 'flex-shrink-0 w-10 h-10 flex items-center justify-center', children: _jsx(ToastIcon, { type: toast.type }) }), _jsxs("div", { className: 'pr-1 pb-1', children: [_jsx("span", { className: 'font-bold', children: toast.title }), (idx === 0 || isHovered) &&
|
|
76
|
+
_jsx("span", { className: 'text-sm line-clamp-3', children: toast.description })] })] }, `${toast.id}-${idx}`))) }));
|
|
63
77
|
}
|
|
64
78
|
function ToastIcon({ type }) {
|
|
65
79
|
switch (type) {
|
|
66
80
|
case 'success':
|
|
67
|
-
return _jsx(CircleCheck, {});
|
|
81
|
+
return _jsx(CircleCheck, { className: 'text-green-300/70' });
|
|
68
82
|
case 'warning':
|
|
69
|
-
return _jsx(CircleAlert, {});
|
|
83
|
+
return _jsx(CircleAlert, { className: 'text-yellow-300/70' });
|
|
70
84
|
case 'error':
|
|
71
|
-
return _jsx(CircleX, {});
|
|
85
|
+
return _jsx(CircleX, { className: 'text-red-300/70' });
|
|
72
86
|
case 'info':
|
|
73
|
-
return _jsx(Info, {});
|
|
87
|
+
return _jsx(Info, { className: 'text-blue-300/70' });
|
|
74
88
|
}
|
|
75
89
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function LogoConsoleOutput(): void;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export function LogoConsoleOutput() {
|
|
2
|
+
const chromeStr = '%c███████╗ ███████╗\n' +
|
|
3
|
+
'██╔════╝ ╚════██║\n' +
|
|
4
|
+
'██║%c ██╗ ██████╗ ██████╗ ██╗███╗ ██╗ %c██║\n' +
|
|
5
|
+
'╚═╝%c ██║ ██╔═══██╗██╔════╝ ██║████╗ ██║ %c╚═╝%c\n' +
|
|
6
|
+
' ██║ ██║ ██║██║ ███╗██║██╔██╗ ██║\n' +
|
|
7
|
+
' ██║ ██║ ██║██║ ██║██║██║╚██╗██║\n' +
|
|
8
|
+
'%c██╗%c ██████╗╚██████╔╝╚██████╔╝██║██║ ╚████║ %c██╗\n' +
|
|
9
|
+
'██║%c ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝╚═╝ ╚═══╝ %c██║\n' +
|
|
10
|
+
'███████╗%c %c███████║\n' +
|
|
11
|
+
'╚══════╝ ╚══════╝%c\n\n' +
|
|
12
|
+
' - Laget av TekKom med 🍕 og ❤️';
|
|
13
|
+
const safariStr = '\n' +
|
|
14
|
+
'%c███████╗\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t ███████╗\n' +
|
|
15
|
+
'██╔═════╝\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t╚════██║\n' +
|
|
16
|
+
'██║%c ██╗\t\t\t\t ██████╗\t \t ╔██████╗\t ██╗ \t ███╗ \t\t ██╗%c\t ██║\n' +
|
|
17
|
+
' ╚═╝%c \t██║\t\t\t ██╔════██╗\t ██╔════╝\t ██║ \t ████╗\t ██║%c\t ╚═╝%c\n' +
|
|
18
|
+
' \t\t██║\t\t\t ██║\t\t\t ██║\t ██║\t ███╗ ██║\t\t ██╔██╗ ██║\n' +
|
|
19
|
+
' \t\t██║\t\t\t ██║\t\t\t ██║\t ██║\t\t ██║ ██║\t\t ██║╚██╗ ██║\n' +
|
|
20
|
+
'%c██╗%c ██████╗\t╚██████╝\t\t ╚██████╝\t ██║ ██║\t\t ╚███║ \t %c██╗\n' +
|
|
21
|
+
'██║%c\t ╚═════╝\t\t ╚════╝\t\t\t\t╚═════╝\t\t ╚═╝\t\t ╚═╝\t\t ╚═══╝\t\t %c██║\n' +
|
|
22
|
+
'███████╗%c\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t %c███████║\n' +
|
|
23
|
+
' ╚══════╝\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t╚══════╝%c\n\n' +
|
|
24
|
+
'\t\t\t\t\t\t\t\t\t\t\t\t\t- Laget av TekKom med 🍕 og ❤️';
|
|
25
|
+
let str = '';
|
|
26
|
+
if (navigator.userAgent.indexOf('Chrome') != -1) {
|
|
27
|
+
str = chromeStr;
|
|
28
|
+
}
|
|
29
|
+
else if (navigator.userAgent.indexOf('Firefox') != -1) {
|
|
30
|
+
str = chromeStr;
|
|
31
|
+
}
|
|
32
|
+
else if (navigator.userAgent.indexOf('Safari') != -1) {
|
|
33
|
+
str = safariStr;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
return (console.log('Login - Linjeforeningen for IT'));
|
|
37
|
+
}
|
|
38
|
+
// each string is the CSS to apply for each consecutive %c
|
|
39
|
+
console.log(str,
|
|
40
|
+
// applies orange color
|
|
41
|
+
'color: #fd8738',
|
|
42
|
+
// clears the style for every non orange part
|
|
43
|
+
'', 'color: #fd8738', '', 'color: #fd8738', '', 'color: #fd8738', '', 'color: #fd8738', '', 'color: #fd8738', '', 'color: #fd8738', '');
|
|
44
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function getCookie(name: string): string | null;
|
|
2
|
+
export declare function setCookie(name: string, value: string, days?: number): void;
|
|
3
|
+
export declare function removeCookies(...cookies: string[]): void;
|
|
4
|
+
export declare function removeCookie(name: string): void;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export function getCookie(name) {
|
|
2
|
+
const matches = document.cookie.match(new RegExp('(?:^|; )' + name.replace(/([.$?*|{}()[\]/\\+^])/g, '\\$1') + '=([^;]*)'));
|
|
3
|
+
return matches ? decodeURIComponent(matches[1]) : null;
|
|
4
|
+
}
|
|
5
|
+
export function setCookie(name, value, days) {
|
|
6
|
+
let expires = '';
|
|
7
|
+
if (!value) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
if (days) {
|
|
11
|
+
const date = new Date();
|
|
12
|
+
date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);
|
|
13
|
+
expires = `expires=${date.toUTCString()};`;
|
|
14
|
+
}
|
|
15
|
+
document.cookie =
|
|
16
|
+
`${name}=${encodeURIComponent(value)}; ` +
|
|
17
|
+
`${expires} path=/; SameSite=Lax`;
|
|
18
|
+
}
|
|
19
|
+
export function removeCookies(...cookies) {
|
|
20
|
+
for (const cookie of cookies) {
|
|
21
|
+
removeCookie(cookie);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export function removeCookie(name) {
|
|
25
|
+
document.cookie =
|
|
26
|
+
`${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; ` +
|
|
27
|
+
'path=/; SameSite=Lax';
|
|
28
|
+
}
|
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
export { default as alertSlowQuery } from './sql/alertSlowQuery';
|
|
2
2
|
export { default as discordAlert } from './discord/discordAlert';
|
|
3
|
+
export { getCookie, setCookie, removeCookie } from './cookies/cookies';
|
|
4
|
+
export { LogoConsoleOutput } from './LogoConsoleOutput/LogoConsoleOutput';
|
package/dist/src/utils/index.js
CHANGED
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
export { default as alertSlowQuery } from './sql/alertSlowQuery';
|
|
2
2
|
export { default as discordAlert } from './discord/discordAlert';
|
|
3
|
+
export { getCookie, setCookie, removeCookie } from './cookies/cookies';
|
|
4
|
+
export { LogoConsoleOutput } from './LogoConsoleOutput/LogoConsoleOutput';
|
package/index.d.ts
ADDED
package/package.json
CHANGED
|
@@ -2,26 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
import { CircleAlert, CircleCheck, CircleX, Info } from 'lucide-react'
|
|
4
4
|
import { useEffect, useState, useRef } from 'react'
|
|
5
|
-
import { ToastProps, ToastObserverProps } from 'uibee/components'
|
|
5
|
+
import { ToastProps, ToastType, ToastObserverProps } from 'uibee/components'
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
const observers: ToastObserverProps[] = []
|
|
9
9
|
|
|
10
|
-
export function addToast(
|
|
11
|
-
observers.forEach((observer) => observer({
|
|
10
|
+
export function addToast(type: ToastType, title: string, description: string = '') {
|
|
11
|
+
observers.forEach((observer) => observer({ title, description, type }))
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
export default function Toaster() {
|
|
15
|
-
const [toasts, setToasts] = useState<Array<ToastProps & {
|
|
15
|
+
const [toasts, setToasts] = useState<Array<ToastProps & { remaining: number; created: number }>>([])
|
|
16
16
|
const timers = useRef<{ [id: number]: NodeJS.Timeout }>({})
|
|
17
17
|
const [isHovered, setIsHovered] = useState(false)
|
|
18
18
|
const pauseTimes = useRef<{ [id: number]: number }>({})
|
|
19
|
+
const mainToastRef = useRef<HTMLDivElement>(null)
|
|
20
|
+
const [mainToastPosition, setMainToastPosition] = useState<{ top: number; right: number } | null>(null)
|
|
19
21
|
|
|
20
22
|
useEffect(() => {
|
|
21
|
-
const listener: ToastObserverProps = ({
|
|
23
|
+
const listener: ToastObserverProps = ({ type, title, description }) => {
|
|
22
24
|
const id = Date.now()
|
|
23
25
|
setToasts(prev => {
|
|
24
|
-
const newToasts = prev.concat({ id,
|
|
26
|
+
const newToasts = prev.concat({ id, type, title, description, remaining: 3000, created: Date.now() }).slice(-3)
|
|
25
27
|
return newToasts
|
|
26
28
|
})
|
|
27
29
|
}
|
|
@@ -57,6 +59,17 @@ export default function Toaster() {
|
|
|
57
59
|
}
|
|
58
60
|
}, [isHovered, toasts])
|
|
59
61
|
|
|
62
|
+
// Track main toast position for stacking
|
|
63
|
+
useEffect(() => {
|
|
64
|
+
if (mainToastRef.current && toasts.length > 0) {
|
|
65
|
+
const rect = mainToastRef.current.getBoundingClientRect()
|
|
66
|
+
setMainToastPosition({
|
|
67
|
+
top: rect.top,
|
|
68
|
+
right: window.innerWidth - rect.right
|
|
69
|
+
})
|
|
70
|
+
}
|
|
71
|
+
}, [toasts, isHovered])
|
|
72
|
+
|
|
60
73
|
const bgClasses = ['bg-login-600', 'bg-login-700', 'bg-login-800']
|
|
61
74
|
return (
|
|
62
75
|
<div
|
|
@@ -66,38 +79,45 @@ export default function Toaster() {
|
|
|
66
79
|
>
|
|
67
80
|
{toasts.slice().reverse().map((toast, idx) => (
|
|
68
81
|
<div
|
|
69
|
-
key={toast.id}
|
|
82
|
+
key={`${toast.id}-${idx}`}
|
|
83
|
+
ref={idx === 0 ? mainToastRef : null}
|
|
70
84
|
className={
|
|
71
85
|
'p-2 rounded-lg text-login-50 animate-fade-in-down transition-all w-sm flex items-center gap-2 ' +
|
|
72
86
|
(bgClasses[idx] || bgClasses[2])
|
|
73
87
|
}
|
|
74
|
-
style={isHovered ? {} : {
|
|
75
|
-
|
|
76
|
-
|
|
88
|
+
style={isHovered ? {} : idx === 0 ? {
|
|
89
|
+
zIndex: 100,
|
|
90
|
+
} : {
|
|
91
|
+
position: 'fixed',
|
|
92
|
+
top: mainToastPosition ? `${mainToastPosition.top - idx * 8}px` : 'auto',
|
|
77
93
|
zIndex: 100 - idx,
|
|
78
|
-
bottom: `${idx * 8}px`,
|
|
79
94
|
transform: `scale(${1 - idx * 0.05})`,
|
|
80
95
|
}}
|
|
81
96
|
>
|
|
82
97
|
<span className='flex-shrink-0 w-10 h-10 flex items-center justify-center'>
|
|
83
98
|
<ToastIcon type={toast.type} />
|
|
84
99
|
</span>
|
|
85
|
-
<
|
|
100
|
+
<div className='pr-1 pb-1'>
|
|
101
|
+
<span className='font-bold'>{toast.title}</span>
|
|
102
|
+
{(idx === 0 || isHovered) &&
|
|
103
|
+
<span className='text-sm line-clamp-3'>{toast.description}</span>
|
|
104
|
+
}
|
|
105
|
+
</div>
|
|
86
106
|
</div>
|
|
87
107
|
))}
|
|
88
108
|
</div>
|
|
89
109
|
)
|
|
90
110
|
}
|
|
91
111
|
|
|
92
|
-
function ToastIcon({ type }: { type?:
|
|
112
|
+
function ToastIcon({ type }: { type?: ToastType }) {
|
|
93
113
|
switch (type) {
|
|
94
114
|
case 'success':
|
|
95
|
-
return <CircleCheck />
|
|
115
|
+
return <CircleCheck className='text-green-300/70' />
|
|
96
116
|
case 'warning':
|
|
97
|
-
return <CircleAlert />
|
|
117
|
+
return <CircleAlert className='text-yellow-300/70' />
|
|
98
118
|
case 'error':
|
|
99
|
-
return <CircleX />
|
|
119
|
+
return <CircleX className='text-red-300/70' />
|
|
100
120
|
case 'info':
|
|
101
|
-
return <Info />
|
|
121
|
+
return <Info className='text-blue-300/70' />
|
|
102
122
|
}
|
|
103
123
|
}
|
|
@@ -9,15 +9,18 @@ declare module 'uibee/components' {
|
|
|
9
9
|
handleSubmit?: (formData: FormData) => void
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
export type ToastType = 'success' | 'error' | 'info' | 'warning'
|
|
12
13
|
export interface ToastProps {
|
|
13
14
|
id: number
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
type: ToastType
|
|
16
|
+
title: string
|
|
17
|
+
description?: string
|
|
16
18
|
}
|
|
17
19
|
|
|
18
20
|
export interface ToastEventProps {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
type: ToastType
|
|
22
|
+
title: string
|
|
23
|
+
description?: string
|
|
21
24
|
}
|
|
22
25
|
|
|
23
26
|
export interface ToastObserverProps {
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export function LogoConsoleOutput() {
|
|
2
|
+
|
|
3
|
+
const chromeStr =
|
|
4
|
+
'%c███████╗ ███████╗\n' +
|
|
5
|
+
'██╔════╝ ╚════██║\n' +
|
|
6
|
+
'██║%c ██╗ ██████╗ ██████╗ ██╗███╗ ██╗ %c██║\n' +
|
|
7
|
+
'╚═╝%c ██║ ██╔═══██╗██╔════╝ ██║████╗ ██║ %c╚═╝%c\n' +
|
|
8
|
+
' ██║ ██║ ██║██║ ███╗██║██╔██╗ ██║\n' +
|
|
9
|
+
' ██║ ██║ ██║██║ ██║██║██║╚██╗██║\n' +
|
|
10
|
+
'%c██╗%c ██████╗╚██████╔╝╚██████╔╝██║██║ ╚████║ %c██╗\n' +
|
|
11
|
+
'██║%c ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝╚═╝ ╚═══╝ %c██║\n' +
|
|
12
|
+
'███████╗%c %c███████║\n' +
|
|
13
|
+
'╚══════╝ ╚══════╝%c\n\n' +
|
|
14
|
+
' - Laget av TekKom med 🍕 og ❤️'
|
|
15
|
+
|
|
16
|
+
const safariStr =
|
|
17
|
+
'\n' +
|
|
18
|
+
'%c███████╗\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t ███████╗\n' +
|
|
19
|
+
'██╔═════╝\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t╚════██║\n' +
|
|
20
|
+
'██║%c ██╗\t\t\t\t ██████╗\t \t ╔██████╗\t ██╗ \t ███╗ \t\t ██╗%c\t ██║\n' +
|
|
21
|
+
' ╚═╝%c \t██║\t\t\t ██╔════██╗\t ██╔════╝\t ██║ \t ████╗\t ██║%c\t ╚═╝%c\n' +
|
|
22
|
+
' \t\t██║\t\t\t ██║\t\t\t ██║\t ██║\t ███╗ ██║\t\t ██╔██╗ ██║\n' +
|
|
23
|
+
' \t\t██║\t\t\t ██║\t\t\t ██║\t ██║\t\t ██║ ██║\t\t ██║╚██╗ ██║\n' +
|
|
24
|
+
'%c██╗%c ██████╗\t╚██████╝\t\t ╚██████╝\t ██║ ██║\t\t ╚███║ \t %c██╗\n' +
|
|
25
|
+
'██║%c\t ╚═════╝\t\t ╚════╝\t\t\t\t╚═════╝\t\t ╚═╝\t\t ╚═╝\t\t ╚═══╝\t\t %c██║\n' +
|
|
26
|
+
'███████╗%c\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t %c███████║\n' +
|
|
27
|
+
' ╚══════╝\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t╚══════╝%c\n\n' +
|
|
28
|
+
'\t\t\t\t\t\t\t\t\t\t\t\t\t- Laget av TekKom med 🍕 og ❤️'
|
|
29
|
+
|
|
30
|
+
let str = ''
|
|
31
|
+
|
|
32
|
+
if(navigator.userAgent.indexOf('Chrome') != -1) {
|
|
33
|
+
str = chromeStr
|
|
34
|
+
} else if (navigator.userAgent.indexOf('Firefox') != -1) {
|
|
35
|
+
str = chromeStr
|
|
36
|
+
} else if (navigator.userAgent.indexOf('Safari') != -1) {
|
|
37
|
+
str = safariStr
|
|
38
|
+
} else {
|
|
39
|
+
return (console.log('Login - Linjeforeningen for IT'))
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// each string is the CSS to apply for each consecutive %c
|
|
43
|
+
console.log(str,
|
|
44
|
+
// applies orange color
|
|
45
|
+
'color: #fd8738',
|
|
46
|
+
// clears the style for every non orange part
|
|
47
|
+
'',
|
|
48
|
+
'color: #fd8738',
|
|
49
|
+
'',
|
|
50
|
+
'color: #fd8738',
|
|
51
|
+
'',
|
|
52
|
+
'color: #fd8738',
|
|
53
|
+
'',
|
|
54
|
+
'color: #fd8738',
|
|
55
|
+
'',
|
|
56
|
+
'color: #fd8738',
|
|
57
|
+
'',
|
|
58
|
+
'color: #fd8738',
|
|
59
|
+
''
|
|
60
|
+
)
|
|
61
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export function getCookie(name: string): string | null {
|
|
2
|
+
const matches = document.cookie.match(
|
|
3
|
+
new RegExp(
|
|
4
|
+
'(?:^|; )' + name.replace(/([.$?*|{}()[\]/\\+^])/g, '\\$1') + '=([^;]*)'
|
|
5
|
+
)
|
|
6
|
+
)
|
|
7
|
+
return matches ? decodeURIComponent(matches[1]) : null
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function setCookie(name: string, value: string, days?: number) {
|
|
11
|
+
let expires = ''
|
|
12
|
+
|
|
13
|
+
if (!value) {
|
|
14
|
+
return
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (days) {
|
|
18
|
+
const date = new Date()
|
|
19
|
+
date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000)
|
|
20
|
+
expires = `expires=${date.toUTCString()};`
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
document.cookie =
|
|
24
|
+
`${name}=${encodeURIComponent(value)}; ` +
|
|
25
|
+
`${expires} path=/; SameSite=Lax`
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function removeCookies(...cookies: string[]) {
|
|
29
|
+
for (const cookie of cookies) {
|
|
30
|
+
removeCookie(cookie)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function removeCookie(name: string) {
|
|
35
|
+
document.cookie =
|
|
36
|
+
`${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; ` +
|
|
37
|
+
'path=/; SameSite=Lax'
|
|
38
|
+
}
|
package/src/utils/index.ts
CHANGED
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
export { default as alertSlowQuery } from './sql/alertSlowQuery'
|
|
2
2
|
export { default as discordAlert } from './discord/discordAlert'
|
|
3
|
+
export { getCookie, setCookie, removeCookie } from './cookies/cookies'
|
|
4
|
+
export { LogoConsoleOutput } from './LogoConsoleOutput/LogoConsoleOutput'
|
package/tsconfig.json
CHANGED
|
@@ -14,11 +14,14 @@
|
|
|
14
14
|
"jsx": "react-jsx",
|
|
15
15
|
"resolveJsonModule": true,
|
|
16
16
|
"paths": {
|
|
17
|
-
"@images/*": [
|
|
17
|
+
"@images/*": [
|
|
18
|
+
"images/*"
|
|
19
|
+
]
|
|
18
20
|
}
|
|
19
21
|
},
|
|
20
22
|
"include": [
|
|
21
23
|
"src",
|
|
22
|
-
"tailwind.config.ts"
|
|
24
|
+
"tailwind.config.ts",
|
|
25
|
+
"index.d.ts"
|
|
23
26
|
]
|
|
24
27
|
}
|