typescript-overlay-essentials 1.3.0 → 1.3.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/dist/ConfirmationBox.d.ts +23 -0
- package/dist/ConfirmationBox.js +90 -0
- package/dist/Dropdown.d.ts +21 -0
- package/dist/Dropdown.js +141 -0
- package/dist/InfoOverlay.d.ts +17 -0
- package/dist/InfoOverlay.js +57 -0
- package/dist/InfoOverlayWithInput.d.ts +22 -0
- package/dist/InfoOverlayWithInput.js +84 -0
- package/dist/InputFilter.d.ts +1 -0
- package/dist/InputFilter.js +36 -0
- package/dist/LoadingOverlay.d.ts +13 -0
- package/dist/LoadingOverlay.js +36 -0
- package/dist/MultipleChoiceOverlay.d.ts +22 -0
- package/dist/MultipleChoiceOverlay.js +94 -0
- package/dist/MultipleRadioOverlay.d.ts +22 -0
- package/dist/MultipleRadioOverlay.js +84 -0
- package/dist/Toast.d.ts +6 -0
- package/dist/Toast.js +23 -0
- package/dist/ToggleSwitch.d.ts +11 -0
- package/dist/ToggleSwitch.js +27 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +10 -0
- package/package.json +3 -2
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { CSSProperties } from 'react';
|
|
3
|
+
import './ConfirmationBox.css';
|
|
4
|
+
export interface ConfirmationBoxState {
|
|
5
|
+
headline?: string | undefined;
|
|
6
|
+
message?: string | undefined;
|
|
7
|
+
message1?: string | undefined;
|
|
8
|
+
message2?: string | undefined;
|
|
9
|
+
cancelButtonText?: string | undefined;
|
|
10
|
+
proceedButtonText?: string | undefined;
|
|
11
|
+
handlerOk?: ((args?: unknown) => void) | undefined;
|
|
12
|
+
handlerCancel?: ((args?: unknown) => void) | undefined;
|
|
13
|
+
handlerArgs?: unknown;
|
|
14
|
+
addCloseButton?: boolean | undefined;
|
|
15
|
+
activateConfirm?: boolean | undefined;
|
|
16
|
+
proceedButtonStyle?: CSSProperties | undefined;
|
|
17
|
+
cancelButtonStyle?: CSSProperties | undefined;
|
|
18
|
+
}
|
|
19
|
+
export declare const defaultConfirmationState: ConfirmationBoxState;
|
|
20
|
+
export declare function ConfirmationBox({ state, setState }: {
|
|
21
|
+
state: ConfirmationBoxState;
|
|
22
|
+
setState: (state: ConfirmationBoxState) => void;
|
|
23
|
+
}): React.ReactElement;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState, useRef } from 'react';
|
|
3
|
+
import './ConfirmationBox.css';
|
|
4
|
+
// Der standard ComfirmationBox Status, der zur Initialisierung genutzt werden kann
|
|
5
|
+
export const defaultConfirmationState = {
|
|
6
|
+
headline: undefined,
|
|
7
|
+
message: undefined,
|
|
8
|
+
message1: undefined,
|
|
9
|
+
message2: undefined,
|
|
10
|
+
cancelButtonText: undefined,
|
|
11
|
+
proceedButtonText: undefined,
|
|
12
|
+
handlerOk: undefined,
|
|
13
|
+
handlerCancel: undefined,
|
|
14
|
+
handlerArgs: undefined,
|
|
15
|
+
addCloseButton: false,
|
|
16
|
+
activateConfirm: undefined,
|
|
17
|
+
proceedButtonStyle: undefined,
|
|
18
|
+
cancelButtonStyle: undefined,
|
|
19
|
+
};
|
|
20
|
+
// Wobei alle Attribute grundsätzlich optional sind:
|
|
21
|
+
// - headline: Eine fett hinterlegte Überschrift (optional)
|
|
22
|
+
// - message1: ist die angezeigte Nachricht
|
|
23
|
+
// - message2: ist optional und wird fett hinterlegt (z.B. ein wichtiger Hinweis oder ähnliches)
|
|
24
|
+
// - message: ist optional und wird nur angezeigt, wenn message1 nicht gesetzt ist (damit message oder message1 genutzt werden kann)
|
|
25
|
+
// - cancelButtonText: ist der Text der auf dem Cancel Button stehen soll (ohne Angabe wird "Abbrechen" verwendet)
|
|
26
|
+
// - proceedButtonText: ist der Text der auf dem Proceed Button stehen soll (ohne Angabe wird "OK" verwendet)
|
|
27
|
+
// - handlerOk: ist die Funktion die bei Bestätigung der Box ausgeführt wird (nutzt handlerargs, erwartet also nur 1 Argument!)
|
|
28
|
+
// - handlerCancel: ist die Funktion die bei Ablehnung der Box ausgeführt wird (nutzt handlerargs, erwartet also nur 1 Argument!)
|
|
29
|
+
// - addCloseButton: boolscher Wert, der angibt, ob ein x oben rechts als close-Button verfügbar sein soll (bricht die Aktion ohne handler ab, standardmäßig false)
|
|
30
|
+
// - handlerArgs: kann im handler als weitere Argumente genutzt werden
|
|
31
|
+
// - activateConfirm: ist ein Boolean, der angibt ob die ConfirmationBox angezeigt werden soll oder nicht (wenn false, wird direkt handlerOk aufgerufen) (Standardmäßig true wenn nicht anders angegeben)
|
|
32
|
+
// - proceedButtonStyle: ist der Style des Bestätigungsbuttons (Standardmäßig unverändert)
|
|
33
|
+
// - cancelButtonStyle: ist der Style des Abbrechenbuttons (Standardmäßig unverändert)
|
|
34
|
+
export function ConfirmationBox({ state, setState }) {
|
|
35
|
+
var _a, _b, _c;
|
|
36
|
+
// Wird verwendet um die Confirmation Boxen ein- und auszublenden
|
|
37
|
+
const [showConfirm, setShowConfirm] = useState(false);
|
|
38
|
+
// Damit der Fokus auf die Confirmation Box gesetzt wird, wenn sie geöffnet wird
|
|
39
|
+
// Und man sie mit Enter bestätigen kann
|
|
40
|
+
const overlayRef = useRef(null);
|
|
41
|
+
// Sobald der State von außen aktualisiert wird triggert diese Funktion
|
|
42
|
+
// Die setzt showConfirm auf true (oder ruft die übergebene Funktion auf wenn confirmationBoxen disabled sind)
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
var _a;
|
|
45
|
+
if (state === null || state === void 0 ? void 0 : state.handlerOk) {
|
|
46
|
+
if ((_a = state.activateConfirm) !== null && _a !== void 0 ? _a : true) {
|
|
47
|
+
setShowConfirm(true);
|
|
48
|
+
setTimeout(() => { var _a; (_a = document.getElementById("confirmButton")) === null || _a === void 0 ? void 0 : _a.focus(); }, 1);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
// Wenn activateConfirm explizit false ist, dann wird die übergebene Funktion direkt ausgeführt ohne ConfirmationBox
|
|
52
|
+
if (typeof state.handlerOk === 'function')
|
|
53
|
+
state.handlerOk(state.handlerArgs);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
setTimeout(() => {
|
|
57
|
+
var _a;
|
|
58
|
+
(_a = overlayRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
59
|
+
}, 0);
|
|
60
|
+
}, [state]);
|
|
61
|
+
const handleAction = (handler) => {
|
|
62
|
+
setShowConfirm(false);
|
|
63
|
+
const tempState = {
|
|
64
|
+
handler: handler,
|
|
65
|
+
handlerArgs: state.handlerArgs
|
|
66
|
+
};
|
|
67
|
+
setState(defaultConfirmationState);
|
|
68
|
+
if (typeof tempState.handler === 'function')
|
|
69
|
+
tempState.handler(tempState.handlerArgs);
|
|
70
|
+
};
|
|
71
|
+
return showConfirm ?
|
|
72
|
+
_jsx("div", { className: "confirmation-overlay", tabIndex: 0, ref: overlayRef, children: _jsxs("div", { className: "confirmation-box", children: [state.addCloseButton ?
|
|
73
|
+
_jsx("span", { className: "closeButton", children: _jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", tabIndex: 0, className: "close-icon", onClick: () => handleAction(undefined), onKeyDown: (e) => {
|
|
74
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
75
|
+
e.preventDefault(); // Verhindert Scroll bei Space
|
|
76
|
+
handleAction(undefined);
|
|
77
|
+
}
|
|
78
|
+
}, role: "button", "aria-label": "Dialog schlie\u00DFen", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), _jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })] }) }) :
|
|
79
|
+
_jsx(_Fragment, {}), (state === null || state === void 0 ? void 0 : state.headline) !== undefined ? _jsx("p", { className: "headline", style: { whiteSpace: "pre-line", wordBreak: "break-word" }, children: _jsx("strong", { children: state === null || state === void 0 ? void 0 : state.headline }) }) : _jsx(_Fragment, {}), _jsx("p", { style: { whiteSpace: "pre-line", wordBreak: "break-word" }, children: (_b = (_a = state.message1) !== null && _a !== void 0 ? _a : state.message) !== null && _b !== void 0 ? _b : "" }), _jsx("p", { style: { whiteSpace: "pre-line", wordBreak: "break-word" }, children: _jsx("strong", { children: (_c = state.message2) !== null && _c !== void 0 ? _c : "" }) }), _jsxs("div", { className: "confirmation-buttons", children: [_jsx("button", { onClick: () => handleAction(state.handlerCancel), onKeyDown: (e) => {
|
|
80
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
81
|
+
e.preventDefault(); // Verhindert Scroll bei Space
|
|
82
|
+
handleAction(state.handlerCancel);
|
|
83
|
+
}
|
|
84
|
+
}, className: "px-4 py-2 bg-gray-300 rounded", style: (state === null || state === void 0 ? void 0 : state.cancelButtonStyle) !== undefined ? state.cancelButtonStyle : {}, children: state.cancelButtonText ? state.cancelButtonText : "Abbrechen" }), _jsx("button", { onClick: () => handleAction(state.handlerOk), id: "confirmButton", onKeyDown: (e) => {
|
|
85
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
86
|
+
e.preventDefault(); // Verhindert Scroll bei Space
|
|
87
|
+
handleAction(state.handlerOk);
|
|
88
|
+
}
|
|
89
|
+
}, className: "px-4 py-2 bg-blue-600 text-white rounded", style: (state === null || state === void 0 ? void 0 : state.proceedButtonStyle) !== undefined ? state.proceedButtonStyle : {}, children: state.proceedButtonText ? state.proceedButtonText : "OK" })] })] }) }) : _jsx(_Fragment, {});
|
|
90
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import './Dropdown.css';
|
|
3
|
+
export interface DropdownOption<T = string> {
|
|
4
|
+
value: T;
|
|
5
|
+
label: string;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
indent?: number;
|
|
8
|
+
}
|
|
9
|
+
export declare function Dropdown<T = string>({ selections, value, onChange, maxMenuHeight, menuPlacement, width, placeHolder, defaultValue, isMulti, cardColorVariant, ignoreDarkMode, ...rest }: {
|
|
10
|
+
selections: DropdownOption<T>[];
|
|
11
|
+
value: T | T[];
|
|
12
|
+
onChange: (value: T | T[] | undefined) => void;
|
|
13
|
+
maxMenuHeight?: number;
|
|
14
|
+
menuPlacement?: "top" | "bottom";
|
|
15
|
+
width?: React.CSSProperties["width"];
|
|
16
|
+
placeHolder?: string;
|
|
17
|
+
defaultValue?: DropdownOption<T> | DropdownOption<T>[];
|
|
18
|
+
isMulti?: boolean;
|
|
19
|
+
cardColorVariant?: boolean;
|
|
20
|
+
ignoreDarkMode?: boolean;
|
|
21
|
+
}): React.ReactElement;
|
package/dist/Dropdown.js
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useRef, useEffect, useState } from 'react';
|
|
3
|
+
import Select from 'react-select';
|
|
4
|
+
import './Dropdown.css';
|
|
5
|
+
// Wobei alle Attribute außer dem value und dem label optional sind:
|
|
6
|
+
// - value: Der Wert, der bei Auswahl gesetzt werden soll
|
|
7
|
+
// -> Dabei kann es sich um komplexe Objekte handeln, diese müssen dann ein Attribut id haben, mithilfe derer sie verglichen werden!
|
|
8
|
+
// - label: Der String, der in der Auswahl angezeigt werden soll
|
|
9
|
+
// - disabled: Kann auf true gesetzt werden, wenn diese Option nicht zur Auswahl verfügbar sein soll
|
|
10
|
+
// - indent: Eine Zahl größer 0, kann angegeben werden, wenn die Option mit so vielen Strichen eingerückt werden soll (nur im Auswahlmenü)
|
|
11
|
+
// Attribute vom Dropdown:
|
|
12
|
+
// - selections: Das Array mit den Optionen die zur Auswahl stehen sollen
|
|
13
|
+
// - value: Der Wert, der ausgewählt angezeigt werden soll (useState)
|
|
14
|
+
// - onChange: Die Funktion die bei Änderung ausgeführt werden soll.
|
|
15
|
+
// Standardmäßig könnte z.B. {(value) => {value ? setValue(value) : setValue("")}} genutzt werden, wenn es sich bei value um einen String handelt
|
|
16
|
+
// - maxMenuHeight: Maximale Menühöhe in Pixeln (Optional)
|
|
17
|
+
// - menuPlacement: Ob das Menü oben oder unten platziert sein soll (Optional, Standard: Auto)
|
|
18
|
+
// - width: Breite des Menüs als CSS Property (Optional)
|
|
19
|
+
// - placeHolder: Der Platzhalter der angezeigt wird, wenn noch nichts ausgewählt ist (Optional) (Wird auch nur angezeigt, wenn value noch keinen validen Wert hat)
|
|
20
|
+
// - defaultValue: Die Auswahl die von Anfang an ausgewählt ist (Optional) (sollten mehrere Werte übergeben werden, wird "isMulti" automatisch gesetzt)
|
|
21
|
+
// - isMulti: Ob mehrere Optionen gleichzeitig ausgewählt werden können (Optional)
|
|
22
|
+
// - Daraufhin MUSS value ein Array sein und falls defaultValue angegeben ist, MUSS das auch ein Array sein
|
|
23
|
+
// - cardColorVariant: Wenn auf true gesetzt, wird eine leicht andere Farbvariante gewählt
|
|
24
|
+
// - ignoreDarkMode: Wenn auf true gesetzt wird der DarkMode ignoriert, der sonst standardmäßig angewendet wird
|
|
25
|
+
// - ...rest (Optional): sorgt dafür, dass alle weiteren angegebenen Attribute (z.B. aria-label) direkt an React-Select weitergegeben werden
|
|
26
|
+
export function Dropdown({ selections, value, onChange, maxMenuHeight, menuPlacement, width, placeHolder, defaultValue, isMulti = false, cardColorVariant = false, ignoreDarkMode = false, ...rest }) {
|
|
27
|
+
const initializedRef = useRef(false);
|
|
28
|
+
const options = selections.map(({ value, label, disabled, indent }) => ({ value: value, label: label, isDisabled: disabled !== null && disabled !== void 0 ? disabled : false, indent }));
|
|
29
|
+
if (!initializedRef.current && Array.isArray(value) && value.length === 0 && Array.isArray(defaultValue) && defaultValue.length > 0) {
|
|
30
|
+
value = options.filter(opt => defaultValue.map(({ value }) => (value)).includes(opt.value)).map(opt => opt.value);
|
|
31
|
+
}
|
|
32
|
+
function usePrefersDarkMode() {
|
|
33
|
+
const [isDarkMode, setIsDarkMode] = useState(window.matchMedia('(prefers-color-scheme: dark)').matches);
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
|
36
|
+
const handler = (event) => setIsDarkMode(event.matches);
|
|
37
|
+
// EventListener hinzufügen
|
|
38
|
+
mediaQuery.addEventListener('change', handler);
|
|
39
|
+
// Aufräumen
|
|
40
|
+
return () => mediaQuery.removeEventListener('change', handler);
|
|
41
|
+
}, []);
|
|
42
|
+
return isDarkMode;
|
|
43
|
+
}
|
|
44
|
+
const isDarkModeRaw = usePrefersDarkMode();
|
|
45
|
+
const isDarkMode = ignoreDarkMode ? false : isDarkModeRaw;
|
|
46
|
+
function hasId(value) {
|
|
47
|
+
return typeof value === "object" && value !== null && "id" in value;
|
|
48
|
+
}
|
|
49
|
+
return isMulti || Array.isArray(defaultValue) ? (_jsx(Select, { className: "custom-select", isMulti: true, placeholder: placeHolder !== null && placeHolder !== void 0 ? placeHolder : "", options: options, value: options.length > 0 && hasId(options[0].value) ? // Wenn die values der Optionen ids haben, handelt es sich um komplexe Objekte, die zur Auswahl stehen und müssen dahingehend verglichen werden
|
|
50
|
+
options.filter(opt => (hasId(opt.value) && value.find(val => hasId(val) && hasId(opt.value) && val.id === opt.value.id))) // Dann alle Optionen, die in den values per id vorkommen
|
|
51
|
+
: options.filter(opt => (value.includes(opt.value))) // Ansonsten einfach alle Optionen, die in den values vorkommen
|
|
52
|
+
, onChange: (selectedOption) => { initializedRef.current = true; onChange(selectedOption.map((opt) => opt.value)); }, maxMenuHeight: maxMenuHeight !== null && maxMenuHeight !== void 0 ? maxMenuHeight : 280, menuPlacement: menuPlacement !== null && menuPlacement !== void 0 ? menuPlacement : "auto", menuPosition: "fixed", classNamePrefix: "dropdown", defaultValue: options.filter(opt => defaultValue.map(({ value }) => (value)).includes(opt.value)), formatOptionLabel: ({ label, indent }, { context }) => {
|
|
53
|
+
if (context === 'menu') {
|
|
54
|
+
// Alle mit indent angegebenen Werte im Dropdown-Menü einrücken
|
|
55
|
+
return indent && indent > 0 ? '-'.repeat(indent) + '\u00A0' + label : label;
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
// Im ausgewählten Zustand: normal
|
|
59
|
+
return label;
|
|
60
|
+
}
|
|
61
|
+
}, styles: {
|
|
62
|
+
container: (provided) => ({
|
|
63
|
+
...provided,
|
|
64
|
+
backgroundColor: isDarkMode ? (cardColorVariant ? 'var(--FastSchwarz, black)' : 'black') : cardColorVariant ? 'var(--FastWeiß, white)' : 'white',
|
|
65
|
+
color: isDarkMode ? 'white' : 'black',
|
|
66
|
+
...(width ? { width } : {})
|
|
67
|
+
}),
|
|
68
|
+
control: () => ({
|
|
69
|
+
display: 'flex',
|
|
70
|
+
...(width ? { width } : {})
|
|
71
|
+
}),
|
|
72
|
+
menu: (provided) => ({
|
|
73
|
+
...provided,
|
|
74
|
+
borderRadius: '8px', // runde Ecken für das Dropdown
|
|
75
|
+
overflow: 'hidden',
|
|
76
|
+
backgroundColor: isDarkMode ? (cardColorVariant ? 'var(--FastSchwarz, black)' : 'black') : cardColorVariant ? 'var(--FastWeiß, white)' : 'white',
|
|
77
|
+
color: isDarkMode ? 'white' : 'black',
|
|
78
|
+
...(width ? { width } : {})
|
|
79
|
+
}),
|
|
80
|
+
menuList: (provided) => ({
|
|
81
|
+
...provided,
|
|
82
|
+
overflowY: "auto",
|
|
83
|
+
padding: 0,
|
|
84
|
+
backgroundColor: isDarkMode ? (cardColorVariant ? 'var(--FastSchwarz, black)' : 'black') : cardColorVariant ? 'var(--FastWeiß, white)' : 'white',
|
|
85
|
+
color: isDarkMode ? 'white' : 'black',
|
|
86
|
+
}),
|
|
87
|
+
option: (provided, state) => ({
|
|
88
|
+
...provided,
|
|
89
|
+
backgroundColor: state.isFocused ? 'var(--DunkelAkzent, red)' : state.isSelected ? 'var(--MittelAkzent, blue)' :
|
|
90
|
+
isDarkMode ? (cardColorVariant ? 'var(--FastSchwarz, black)' : 'black') : cardColorVariant ? 'var(--FastWeiß, white)' : 'white',
|
|
91
|
+
color: state.isFocused ? 'white' : state.isSelected ? 'var(--FastSchwarz, black)' :
|
|
92
|
+
isDarkMode ? (cardColorVariant ? 'white' : 'white') : cardColorVariant ? 'black' : 'var(--FastSchwarz, black)',
|
|
93
|
+
cursor: 'pointer',
|
|
94
|
+
}),
|
|
95
|
+
}, ...rest })) : (_jsx(Select, { className: "custom-select", isMulti: false, placeholder: placeHolder !== null && placeHolder !== void 0 ? placeHolder : "", options: options, value: options.length > 0 && hasId(options[0].value) ? // Wenn die values der Optionen ids haben, handelt es sich um komplexe Objekte, die zur Auswahl stehen und müssen dahingehend verglichen werden
|
|
96
|
+
options.find(opt => hasId(opt.value) && hasId(value) && opt.value.id === value.id) // Die eine Option mit der passenden id finden
|
|
97
|
+
: options.find(opt => opt.value === value), onChange: (selectedOption) => { var _a; return onChange((_a = selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.value) !== null && _a !== void 0 ? _a : undefined); }, maxMenuHeight: maxMenuHeight !== null && maxMenuHeight !== void 0 ? maxMenuHeight : 280, menuPlacement: menuPlacement !== null && menuPlacement !== void 0 ? menuPlacement : "auto", menuPosition: "fixed", classNamePrefix: "dropdown", defaultValue: defaultValue, formatOptionLabel: ({ label, indent }, { context }) => {
|
|
98
|
+
if (context === 'menu') {
|
|
99
|
+
// Alle mit indent angegebenen Werte im Dropdown-Menü einrücken
|
|
100
|
+
return indent && indent > 0 ? '-'.repeat(indent) + '\u00A0' + label : label;
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
// Im ausgewählten Zustand: normal
|
|
104
|
+
return label;
|
|
105
|
+
}
|
|
106
|
+
}, styles: {
|
|
107
|
+
container: (provided) => ({
|
|
108
|
+
...provided,
|
|
109
|
+
backgroundColor: isDarkMode ? (cardColorVariant ? 'var(--FastSchwarz, black)' : 'black') : cardColorVariant ? 'var(--FastWeiß, white)' : 'white',
|
|
110
|
+
color: isDarkMode ? 'white' : 'black',
|
|
111
|
+
...(width ? { width } : {})
|
|
112
|
+
}),
|
|
113
|
+
control: () => ({
|
|
114
|
+
display: 'flex',
|
|
115
|
+
...(width ? { width } : {})
|
|
116
|
+
}),
|
|
117
|
+
menu: (provided) => ({
|
|
118
|
+
...provided,
|
|
119
|
+
borderRadius: '8px', // runde Ecken für das Dropdown
|
|
120
|
+
overflow: 'hidden',
|
|
121
|
+
backgroundColor: isDarkMode ? (cardColorVariant ? 'var(--FastSchwarz, black)' : 'black') : cardColorVariant ? 'var(--FastWeiß, white)' : 'white',
|
|
122
|
+
color: isDarkMode ? 'white' : 'black',
|
|
123
|
+
...(width ? { width } : {})
|
|
124
|
+
}),
|
|
125
|
+
menuList: (provided) => ({
|
|
126
|
+
...provided,
|
|
127
|
+
overflowY: "auto",
|
|
128
|
+
padding: 0,
|
|
129
|
+
backgroundColor: isDarkMode ? (cardColorVariant ? 'var(--FastSchwarz, black)' : 'black') : cardColorVariant ? 'var(--FastWeiß, white)' : 'white',
|
|
130
|
+
color: isDarkMode ? 'white' : 'black',
|
|
131
|
+
}),
|
|
132
|
+
option: (provided, state) => ({
|
|
133
|
+
...provided,
|
|
134
|
+
backgroundColor: state.isFocused ? 'var(--DunkelAkzent, red)' : state.isSelected ? 'var(--MittelAkzent, blue)' :
|
|
135
|
+
isDarkMode ? (cardColorVariant ? 'var(--FastSchwarz, black)' : 'black') : cardColorVariant ? 'var(--FastWeiß, white)' : 'white',
|
|
136
|
+
color: state.isFocused ? 'white' : state.isSelected ? 'var(--FastSchwarz, black)' :
|
|
137
|
+
isDarkMode ? (cardColorVariant ? 'white' : 'white') : cardColorVariant ? 'black' : 'var(--FastSchwarz, black)',
|
|
138
|
+
cursor: 'pointer',
|
|
139
|
+
}),
|
|
140
|
+
}, ...rest }));
|
|
141
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { CSSProperties } from 'react';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import './InfoOverlay.css';
|
|
4
|
+
export interface InfoOverlayState {
|
|
5
|
+
headline?: string | undefined;
|
|
6
|
+
message?: string | undefined;
|
|
7
|
+
proceedButtonText?: string | undefined;
|
|
8
|
+
handler?: ((args?: unknown) => void) | undefined;
|
|
9
|
+
handlerArgs?: unknown;
|
|
10
|
+
addCloseButton?: boolean | undefined;
|
|
11
|
+
style?: CSSProperties | undefined;
|
|
12
|
+
}
|
|
13
|
+
export declare const defaultInfoOverlayState: InfoOverlayState;
|
|
14
|
+
export declare function InfoOverlay({ state, setState }: {
|
|
15
|
+
state: InfoOverlayState;
|
|
16
|
+
setState: (state: InfoOverlayState) => void;
|
|
17
|
+
}): React.ReactElement;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
|
+
import './InfoOverlay.css';
|
|
4
|
+
// Der standard InfoOverlay Status, der zur Initialisierung genutzt werden kann
|
|
5
|
+
export const defaultInfoOverlayState = {
|
|
6
|
+
headline: undefined,
|
|
7
|
+
message: undefined,
|
|
8
|
+
proceedButtonText: undefined,
|
|
9
|
+
handler: undefined,
|
|
10
|
+
handlerArgs: undefined,
|
|
11
|
+
addCloseButton: false,
|
|
12
|
+
style: undefined,
|
|
13
|
+
};
|
|
14
|
+
// Wobei alle Attribute grundsätzlich optional sind:
|
|
15
|
+
// - headline: ist die Überschrift und wird fett hinterlegt
|
|
16
|
+
// - message: ist die angezeigte Nachricht
|
|
17
|
+
// - proceedButtonText: ist der Text der auf dem Procceed Button stehen soll (ohne Angabe wird "OK" verwendet)
|
|
18
|
+
// - handler: Funktion, die optional beim Bestätigen ausgeführt werden kann (Struktur: handler(args))
|
|
19
|
+
// - handlerArgs: kann im handler als Argumente genutzt werden
|
|
20
|
+
// - addCloseButton: boolscher Wert, der angibt, ob ein x oben rechts als close-Button verfügbar sein soll (bricht die Aktion ohne handler ab, standardmäßig false)
|
|
21
|
+
// - style: ist der Style der Information-Box (Standardmäßig unverändert)
|
|
22
|
+
export function InfoOverlay({ state, setState }) {
|
|
23
|
+
// Wird verwendet um das Infoverlay ein- und auszublenden
|
|
24
|
+
const [showOverlay, setShowOverlay] = useState(false);
|
|
25
|
+
// Sobald der State von außen aktualisiert wird triggert diese Funktion
|
|
26
|
+
// Die setzt showOverlay auf true
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
if ((state === null || state === void 0 ? void 0 : state.message) !== undefined || (state === null || state === void 0 ? void 0 : state.headline) !== undefined) {
|
|
29
|
+
setShowOverlay(true);
|
|
30
|
+
setTimeout(() => { var _a; (_a = document.getElementById("infoButton")) === null || _a === void 0 ? void 0 : _a.focus(); }, 5);
|
|
31
|
+
}
|
|
32
|
+
}, [state]);
|
|
33
|
+
const handleAction = () => {
|
|
34
|
+
setShowOverlay(false);
|
|
35
|
+
const tempState = {
|
|
36
|
+
handler: state.handler,
|
|
37
|
+
handlerArgs: state.handlerArgs
|
|
38
|
+
};
|
|
39
|
+
setState(defaultInfoOverlayState);
|
|
40
|
+
if (typeof tempState.handler === 'function')
|
|
41
|
+
tempState.handler(tempState.handlerArgs);
|
|
42
|
+
};
|
|
43
|
+
return showOverlay ?
|
|
44
|
+
_jsx("div", { className: "information-overlay", tabIndex: 0, children: _jsxs("div", { className: "information-box", style: (state === null || state === void 0 ? void 0 : state.style) !== undefined ? state.style : {}, children: [state.addCloseButton ?
|
|
45
|
+
_jsx("span", { className: "closeButton", children: _jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", tabIndex: 0, className: "close-icon", onClick: () => setShowOverlay(false), onKeyDown: (e) => {
|
|
46
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
47
|
+
e.preventDefault(); // Verhindert Scroll bei Space
|
|
48
|
+
setShowOverlay(false);
|
|
49
|
+
}
|
|
50
|
+
}, role: "button", "aria-label": "Dialog schlie\u00DFen", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), _jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })] }) }) :
|
|
51
|
+
_jsx(_Fragment, {}), _jsx("p", { className: "headline", tabIndex: 0, style: { whiteSpace: "pre-line" }, children: _jsx("strong", { children: (state === null || state === void 0 ? void 0 : state.headline) !== undefined ? state.headline : "" }) }), _jsx("p", { tabIndex: 0, style: { whiteSpace: "pre-line", wordBreak: "break-word" }, children: (state === null || state === void 0 ? void 0 : state.message) !== undefined ? state.message : "" }), _jsx("div", { className: "information-buttons", children: _jsx("button", { onClick: () => handleAction(), onKeyDown: (e) => {
|
|
52
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
53
|
+
e.preventDefault(); // Verhindert Scroll bei Space
|
|
54
|
+
handleAction();
|
|
55
|
+
}
|
|
56
|
+
}, className: "px-4 py-2 bg-blue-600 text-white rounded", id: "infoButton", children: (state === null || state === void 0 ? void 0 : state.proceedButtonText) !== undefined ? state.proceedButtonText : "OK" }) })] }) }) : _jsx(_Fragment, {});
|
|
57
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { CSSProperties } from 'react';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import './InfoOverlayWithInput.css';
|
|
4
|
+
export interface InfoOverlayWithInputState {
|
|
5
|
+
headline?: string | undefined;
|
|
6
|
+
message?: string | undefined;
|
|
7
|
+
preInput?: string | undefined;
|
|
8
|
+
placeholder?: string | undefined;
|
|
9
|
+
cancelButtonText?: string | undefined;
|
|
10
|
+
proceedButtonText?: string | undefined;
|
|
11
|
+
handlerOk?: ((userInput: string, args?: unknown) => void) | undefined;
|
|
12
|
+
handlerCancel?: ((args?: unknown) => void) | undefined;
|
|
13
|
+
handlerArgs?: unknown;
|
|
14
|
+
addCloseButton?: boolean | undefined;
|
|
15
|
+
proceedButtonStyle?: CSSProperties | undefined;
|
|
16
|
+
cancelButtonStyle?: CSSProperties | undefined;
|
|
17
|
+
}
|
|
18
|
+
export declare const defaultInfoOverlayWithInputState: InfoOverlayWithInputState;
|
|
19
|
+
export declare function InfoOverlayWithInput({ state, setState }: {
|
|
20
|
+
state: InfoOverlayWithInputState;
|
|
21
|
+
setState: (state: InfoOverlayWithInputState) => void;
|
|
22
|
+
}): React.ReactElement;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
|
+
import './InfoOverlayWithInput.css';
|
|
4
|
+
// Um das InfoOverlayWithInput zu nutzen, muss der State die folgende Struktur haben:
|
|
5
|
+
export const defaultInfoOverlayWithInputState = {
|
|
6
|
+
headline: undefined,
|
|
7
|
+
message: undefined,
|
|
8
|
+
preInput: undefined,
|
|
9
|
+
placeholder: undefined,
|
|
10
|
+
cancelButtonText: undefined,
|
|
11
|
+
proceedButtonText: undefined,
|
|
12
|
+
handlerOk: undefined,
|
|
13
|
+
handlerCancel: undefined,
|
|
14
|
+
handlerArgs: undefined,
|
|
15
|
+
addCloseButton: false,
|
|
16
|
+
proceedButtonStyle: undefined,
|
|
17
|
+
cancelButtonStyle: undefined,
|
|
18
|
+
};
|
|
19
|
+
// Wobei alle Attribute grundsätzlich optional sind:
|
|
20
|
+
// - headline: ist die Überschrift und wird fett hinterlegt
|
|
21
|
+
// - message: ist die angezeigte Nachricht
|
|
22
|
+
// - preInput: Beinhaltet den Text der schon vorher im Inputfield stehen soll (ohne Angabe wird nichts angezeigt)
|
|
23
|
+
// - placeholder: Was bei leerem Inputfield als Platzhalter angezeigt wird (ohne Angabe wird nichts angezeigt)
|
|
24
|
+
// - cancelButtonText: ist der Text der auf dem Cancel Button stehen soll (ohne Angabe wird "Abbrechen" verwendet)
|
|
25
|
+
// - proceedButtonText: ist der Text der auf dem Proceed Button stehen soll (ohne Angabe wird "OK" verwendet)
|
|
26
|
+
// - handlerOk: ist die Funktion die bei Bestätigung des Inputs ausgeführt wird (Struktur: handlerOk(userInput, handlerArgs)
|
|
27
|
+
// - handlerCancel: ist die Funktion die bei Ablehnung des Inputs ausgeführt wird (Struktur: handlerCancel(handlerArgs)
|
|
28
|
+
// - handlerArgs: kann im handler als Argumente genutzt werden
|
|
29
|
+
// - addCloseButton: boolscher Wert, der angibt, ob ein x oben rechts als close-Button verfügbar sein soll (bricht die Aktion ohne handler ab, standardmäßig false)
|
|
30
|
+
// - proceedButtonStyle: ist der Style des Bestätigungsbuttons (Standardmäßig unverändert)
|
|
31
|
+
// - cancelButtonStyle: ist der Style des Abbrechenbuttons (Standardmäßig unverändert)
|
|
32
|
+
// Output: Der Input vom User wird am Ende an den handlerOk übergeben (oder bei handlerCancel ignoriert)!
|
|
33
|
+
// Somit wird der handler so aufgerufen: handlerOk(UserInput, handlerArgs) oder handlerCancel(handlerArgs)
|
|
34
|
+
export function InfoOverlayWithInput({ state, setState }) {
|
|
35
|
+
// Wird verwendet um das Infoverlay ein- und auszublenden
|
|
36
|
+
const [showOverlay, setShowOverlay] = useState(false);
|
|
37
|
+
// Wird verwendet um den Inhalt des InputFields aktuell zu halten
|
|
38
|
+
const [input, setInput] = useState("");
|
|
39
|
+
// Sobald der State von außen aktualisiert wird triggert diese Funktion
|
|
40
|
+
// Die setzt showOverlay auf true
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
if ((state === null || state === void 0 ? void 0 : state.message) != null || (state === null || state === void 0 ? void 0 : state.headline) != null) {
|
|
43
|
+
setInput((state === null || state === void 0 ? void 0 : state.preInput) != null ? state.preInput : "");
|
|
44
|
+
setShowOverlay(true);
|
|
45
|
+
setTimeout(() => { var _a; (_a = document.getElementById("information-inputfield")) === null || _a === void 0 ? void 0 : _a.focus(); }, 1);
|
|
46
|
+
}
|
|
47
|
+
}, [state]);
|
|
48
|
+
// Sorgt dafür, dass die Eingabe beim tippen aktualisiert wird
|
|
49
|
+
const handleInputChange = (event) => {
|
|
50
|
+
setInput(event.target.value);
|
|
51
|
+
};
|
|
52
|
+
// Sorgt dafür, dass auch bei Enter bestätigt wird
|
|
53
|
+
const handleInputKeyDown = (event) => {
|
|
54
|
+
if (event.key === "Enter") {
|
|
55
|
+
handleAction(state.handlerOk, true);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
const handleAction = (handler, useInput) => {
|
|
59
|
+
setShowOverlay(false);
|
|
60
|
+
var tempState = {
|
|
61
|
+
handler: handler,
|
|
62
|
+
handlerArgs: state.handlerArgs
|
|
63
|
+
};
|
|
64
|
+
setState(defaultInfoOverlayWithInputState);
|
|
65
|
+
if (typeof tempState.handler === 'function' && useInput)
|
|
66
|
+
tempState.handler(input, tempState.handlerArgs);
|
|
67
|
+
else if (typeof tempState.handler === 'function')
|
|
68
|
+
tempState.handler(tempState.handlerArgs);
|
|
69
|
+
};
|
|
70
|
+
return showOverlay ?
|
|
71
|
+
_jsx("div", { className: "information-overlay-with-input", children: _jsxs("div", { className: "information-box-with-input", children: [state.addCloseButton ?
|
|
72
|
+
_jsx("span", { className: "closeButton", children: _jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", tabIndex: 0, className: "close-icon", onClick: () => handleAction(undefined, false), onKeyDown: (e) => {
|
|
73
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
74
|
+
e.preventDefault(); // Verhindert Scroll bei Space
|
|
75
|
+
handleAction(undefined, false);
|
|
76
|
+
}
|
|
77
|
+
}, role: "button", "aria-label": "Dialog schlie\u00DFen", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), _jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })] }) }) :
|
|
78
|
+
_jsx(_Fragment, {}), _jsx("p", { className: "headline", style: { whiteSpace: "pre-line", wordBreak: "break-word" }, children: _jsx("strong", { children: (state === null || state === void 0 ? void 0 : state.headline) != null ? state.headline : "" }) }), _jsx("p", { style: { whiteSpace: "pre-line", wordBreak: "break-word" }, children: (state === null || state === void 0 ? void 0 : state.message) != null ? state.message : "" }), _jsx("div", { className: "information-input", children: _jsx("input", { id: "information-inputfield", placeholder: (state === null || state === void 0 ? void 0 : state.placeholder) != null ? state.placeholder : "", pattern: "^[A-Za-z0-9_-~]+$", required: true, type: "text", className: "form-control", value: input, onChange: handleInputChange, onKeyDown: handleInputKeyDown, tabIndex: 0 }) }), _jsxs("div", { className: "information-buttons", children: [_jsx("button", { onClick: () => handleAction(state.handlerCancel, false), className: "px-4 py-2 bg-gray-300 rounded", style: (state === null || state === void 0 ? void 0 : state.cancelButtonStyle) != null ? state.cancelButtonStyle : {}, tabIndex: 0, onKeyDown: (e) => {
|
|
79
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
80
|
+
e.preventDefault(); // Verhindert Scroll bei Space
|
|
81
|
+
handleAction(state.handlerCancel, false);
|
|
82
|
+
}
|
|
83
|
+
}, children: (state === null || state === void 0 ? void 0 : state.cancelButtonText) != null ? state.cancelButtonText : "Abbrechen" }), _jsx("button", { onClick: () => handleAction(state.handlerOk, true), className: "px-4 py-2 bg-blue-600 text-white rounded", style: (state === null || state === void 0 ? void 0 : state.proceedButtonStyle) != null ? state.proceedButtonStyle : {}, tabIndex: 0, children: (state === null || state === void 0 ? void 0 : state.proceedButtonText) != null ? state.proceedButtonText : "OK" })] })] }) }) : _jsx(_Fragment, {});
|
|
84
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function setInputFilter(textbox: HTMLElement | undefined, inputFilter: (value: string) => boolean, errMsg: string): void;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Restricts input for the given textbox to the given inputFilter function.
|
|
2
|
+
export function setInputFilter(textbox, inputFilter, errMsg) {
|
|
3
|
+
["input", "keydown", "keyup", "mousedown", "mouseup", "select", "contextmenu", "drop", "focusout"].forEach(function (event) {
|
|
4
|
+
if (textbox) {
|
|
5
|
+
textbox.addEventListener(event, function (e) {
|
|
6
|
+
var _a, _b, _c, _d;
|
|
7
|
+
const target = e.currentTarget;
|
|
8
|
+
if (inputFilter(target.value)) {
|
|
9
|
+
// Accepted value.
|
|
10
|
+
if (["keydown", "mousedown", "focusout"].indexOf(e.type) >= 0) {
|
|
11
|
+
target.classList.remove("input-error");
|
|
12
|
+
target.setCustomValidity("");
|
|
13
|
+
}
|
|
14
|
+
target.dataset.oldValue = target.value;
|
|
15
|
+
target.dataset.oldSelectionStart = (_b = (_a = target.selectionStart) === null || _a === void 0 ? void 0 : _a.toString()) !== null && _b !== void 0 ? _b : "";
|
|
16
|
+
target.dataset.oldSelectionEnd = (_d = (_c = target.selectionEnd) === null || _c === void 0 ? void 0 : _c.toString()) !== null && _d !== void 0 ? _d : "";
|
|
17
|
+
}
|
|
18
|
+
else if (target.dataset.oldValue !== undefined) {
|
|
19
|
+
// Rejected value: restore the previous one.
|
|
20
|
+
target.classList.add("input-error");
|
|
21
|
+
target.setCustomValidity(errMsg);
|
|
22
|
+
target.reportValidity();
|
|
23
|
+
target.setAttribute("aria-invalid", "true");
|
|
24
|
+
target.value = target.dataset.oldValue;
|
|
25
|
+
const start = target.dataset.oldSelectionStart ? parseInt(target.dataset.oldSelectionStart) : 0;
|
|
26
|
+
const end = target.dataset.oldSelectionEnd ? parseInt(target.dataset.oldSelectionEnd) : start;
|
|
27
|
+
target.setSelectionRange(start, end);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
// Rejected value: nothing to restore.
|
|
31
|
+
target.value = "";
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ReactElement } from 'react';
|
|
2
|
+
import './LoadingOverlay.css';
|
|
3
|
+
export interface LoadingOverlayState {
|
|
4
|
+
isActive?: boolean;
|
|
5
|
+
message?: string | undefined;
|
|
6
|
+
color?: string | undefined;
|
|
7
|
+
showSuccess?: boolean | undefined;
|
|
8
|
+
}
|
|
9
|
+
export declare const defaultLoadingOverlayState: LoadingOverlayState;
|
|
10
|
+
export declare function LoadingOverlay({ state, setState }: {
|
|
11
|
+
state: LoadingOverlayState;
|
|
12
|
+
setState: (state: LoadingOverlayState) => void;
|
|
13
|
+
}): ReactElement;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
|
+
import './LoadingOverlay.css';
|
|
4
|
+
// Der standard LoadingOverlay Status, der zur Initialisierung genutzt werden kann
|
|
5
|
+
export const defaultLoadingOverlayState = {
|
|
6
|
+
isActive: false,
|
|
7
|
+
message: undefined,
|
|
8
|
+
color: undefined,
|
|
9
|
+
showSuccess: undefined,
|
|
10
|
+
};
|
|
11
|
+
// Wobei alle Attribute grundsätzlich optional sind:
|
|
12
|
+
// - isActive: gibt an ob das Overlay gerade aktiv sein soll oder nicht
|
|
13
|
+
// - message: ist die angezeigte Nachricht
|
|
14
|
+
// - color: ist dir Farbe des Loading icons (ohne Angabe HSD rot)
|
|
15
|
+
// - showSuccess: zeigt bei "true" ein grünes Häkchen an und bei "false" ein rot hinterlegtes X. Bei "undefined" wird die normale Ladeanimation gezeigt.
|
|
16
|
+
export function LoadingOverlay({ state, setState }) {
|
|
17
|
+
var _a, _b, _c;
|
|
18
|
+
// Wird verwendet um das LoadingOverlay ein- und auszublenden
|
|
19
|
+
const [showOverlay, setShowOverlay] = useState(false);
|
|
20
|
+
// Sobald der State von außen aktualisiert wird triggert diese Funktion
|
|
21
|
+
// Die setzt showOverlay auf true
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
if (state === null || state === void 0 ? void 0 : state.isActive) {
|
|
24
|
+
setShowOverlay(true);
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
setState(defaultLoadingOverlayState);
|
|
28
|
+
setShowOverlay(false);
|
|
29
|
+
}
|
|
30
|
+
}, [state, setState]);
|
|
31
|
+
return showOverlay ? (_jsx("div", { className: "loading-overlay", children: _jsxs("div", { className: "loading-box", children: [_jsx("div", { className: "spinner " + (state.showSuccess === undefined ? "is-loading" : (state.showSuccess ? "is-success" : "is-error")), style: {
|
|
32
|
+
"--spinner-color": (_a = state.color) !== null && _a !== void 0 ? _a : "#e60028",
|
|
33
|
+
"--success-bg": (_b = state.color) !== null && _b !== void 0 ? _b : "#42ab34",
|
|
34
|
+
"--error-bg": (_c = state.color) !== null && _c !== void 0 ? _c : "#e60028",
|
|
35
|
+
} }), state.message && _jsx("p", { className: "loading-message", children: state.message })] }) })) : _jsx(_Fragment, {});
|
|
36
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { CSSProperties } from 'react';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import './MultipleChoiceOverlay.css';
|
|
4
|
+
export interface MultipleChoiceOverlayState {
|
|
5
|
+
headline?: string | undefined;
|
|
6
|
+
message?: string | undefined;
|
|
7
|
+
choices: string[] | [];
|
|
8
|
+
preInput?: string[] | undefined;
|
|
9
|
+
cancelButtonText?: string | undefined;
|
|
10
|
+
proceedButtonText?: string | undefined;
|
|
11
|
+
handlerOk?: ((userInput: string[], args?: unknown) => void) | undefined;
|
|
12
|
+
handlerCancel?: ((args?: unknown) => void) | undefined;
|
|
13
|
+
handlerArgs?: unknown;
|
|
14
|
+
addCloseButton?: boolean | undefined;
|
|
15
|
+
proceedButtonStyle?: CSSProperties | undefined;
|
|
16
|
+
cancelButtonStyle?: CSSProperties | undefined;
|
|
17
|
+
}
|
|
18
|
+
export declare const defaultMultipleChoiceState: MultipleChoiceOverlayState;
|
|
19
|
+
export declare function MultipleChoiceOverlay({ state, setState }: {
|
|
20
|
+
state: MultipleChoiceOverlayState;
|
|
21
|
+
setState: (state: MultipleChoiceOverlayState) => void;
|
|
22
|
+
}): React.ReactElement;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
|
+
import './MultipleChoiceOverlay.css';
|
|
4
|
+
// Der standard MultipleChoiceOverlay Status, der zur Initialisierung genutzt werden kann
|
|
5
|
+
export const defaultMultipleChoiceState = {
|
|
6
|
+
headline: undefined,
|
|
7
|
+
message: undefined,
|
|
8
|
+
choices: [],
|
|
9
|
+
preInput: undefined,
|
|
10
|
+
cancelButtonText: undefined,
|
|
11
|
+
proceedButtonText: undefined,
|
|
12
|
+
handlerOk: undefined,
|
|
13
|
+
handlerCancel: undefined,
|
|
14
|
+
handlerArgs: undefined,
|
|
15
|
+
addCloseButton: false,
|
|
16
|
+
proceedButtonStyle: undefined,
|
|
17
|
+
cancelButtonStyle: undefined,
|
|
18
|
+
};
|
|
19
|
+
// Wobei alle Attribute grundsätzlich optional sind:
|
|
20
|
+
// - headline: ist die Überschrift und wird fett hinterlegt
|
|
21
|
+
// - message: ist die angezeigte Nachricht
|
|
22
|
+
// - choices: Ein String-Array mit den Optionen die ausgewählt werden können (ohne Angabe gibt es keine Auswahl)
|
|
23
|
+
// - preInput: Ein String-Array: Die Einträge sind stadardmäßig ausgewählt alle anderen nicht ausgewählt
|
|
24
|
+
// - cancelButtonText: ist der Text der auf dem Cancel Button stehen soll (ohne Angabe wird "Abbrechen" verwendet)
|
|
25
|
+
// - proceedButtonText: ist der Text der auf dem Proceed Button stehen soll (ohne Angabe wird "OK" verwendet)
|
|
26
|
+
// - handlerOk: ist die Funktion die bei Bestätigung des Inputs ausgeführt wird (Struktur: handlerOk(userInput, handlerArgs)
|
|
27
|
+
// - handlerCancel: ist die Funktion die bei Ablehnung des Inputs ausgeführt wird (Struktur: handlerCancel(handlerArgs)
|
|
28
|
+
// - handlerArgs: kann im handler als Argumente genutzt werden
|
|
29
|
+
// - addCloseButton: boolscher Wert, der angibt, ob ein x oben rechts als close-Button verfügbar sein soll (bricht die Aktion ohne handler ab, standardmäßig false)
|
|
30
|
+
// - proceedButtonStyle: ist der Style des Bestätigungsbuttons (Standardmäßig unverändert)
|
|
31
|
+
// - cancelButtonStyle: ist der Style des Abbrechenbuttons (Standardmäßig unverändert)
|
|
32
|
+
// Output: Der Input vom User wird am Ende an den handlerOk übergeben (oder bei handlerCancel ignoriert)!
|
|
33
|
+
// Somit wird der handler so aufgerufen: handlerOk(UserInput, handlerArgs) oder handlerCancel(handlerArgs)
|
|
34
|
+
export function MultipleChoiceOverlay({ state, setState }) {
|
|
35
|
+
// Wird verwendet um das Infoverlay ein- und auszublenden
|
|
36
|
+
const [showOverlay, setShowOverlay] = useState(false);
|
|
37
|
+
// Wird verwendet um die ausgewählten Choices aktuell zu halten
|
|
38
|
+
const [input, setInput] = useState([]);
|
|
39
|
+
// Sobald der State von außen aktualisiert wird triggert diese Funktion
|
|
40
|
+
// Die setzt showOverlay auf true
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
if ((state === null || state === void 0 ? void 0 : state.message) != null || (state === null || state === void 0 ? void 0 : state.headline) != null) {
|
|
43
|
+
setInput((state === null || state === void 0 ? void 0 : state.preInput) != null ? state.preInput : []);
|
|
44
|
+
setShowOverlay(true);
|
|
45
|
+
setTimeout(() => { var _a; (_a = document.getElementById("confirmButton")) === null || _a === void 0 ? void 0 : _a.focus(); }, 1);
|
|
46
|
+
}
|
|
47
|
+
}, [state]);
|
|
48
|
+
// Toggled die Auswahl eines Choices
|
|
49
|
+
// Setzt dafür den aktuellen Input auf den neuen Input + Choice
|
|
50
|
+
const toggle = (choice) => {
|
|
51
|
+
if (input.includes(choice)) {
|
|
52
|
+
setInput(input.filter(item => item !== choice)); // Entfernt den Choice wenn er schon ausgewählt ist
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
setInput([...input, choice]); // Fügt den Choice hinzu wenn er noch nicht ausgewählt ist
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
const handleAction = (handler, useInput) => {
|
|
59
|
+
setShowOverlay(false);
|
|
60
|
+
var tempState = {
|
|
61
|
+
handler: handler,
|
|
62
|
+
handlerArgs: state.handlerArgs
|
|
63
|
+
};
|
|
64
|
+
setState(defaultMultipleChoiceState);
|
|
65
|
+
if (typeof tempState.handler === 'function' && useInput)
|
|
66
|
+
tempState.handler(input, tempState.handlerArgs);
|
|
67
|
+
else if (typeof tempState.handler === 'function')
|
|
68
|
+
tempState.handler(tempState.handlerArgs);
|
|
69
|
+
};
|
|
70
|
+
return showOverlay ?
|
|
71
|
+
_jsx("div", { className: "multiplechoice-overlay", children: _jsxs("div", { className: "multiplechoice-box", children: [state.addCloseButton ?
|
|
72
|
+
_jsx("span", { className: "closeButton", children: _jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", tabIndex: 0, className: "close-icon", onClick: () => handleAction(undefined, false), onKeyDown: (e) => {
|
|
73
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
74
|
+
e.preventDefault(); // Verhindert Scroll bei Space
|
|
75
|
+
handleAction(undefined, false);
|
|
76
|
+
}
|
|
77
|
+
}, role: "button", "aria-label": "Dialog schlie\u00DFen", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), _jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })] }) }) :
|
|
78
|
+
_jsx(_Fragment, {}), _jsx("p", { className: "headline", id: "theHeadline", tabIndex: 0, style: { whiteSpace: "pre-line", wordBreak: "break-word" }, children: _jsx("strong", { children: (state === null || state === void 0 ? void 0 : state.headline) != null ? state.headline : "" }) }), _jsx("p", { tabIndex: 0, style: { whiteSpace: "pre-line", wordBreak: "break-word" }, children: (state === null || state === void 0 ? void 0 : state.message) != null ? state.message : "" }), _jsx("div", { className: "choices-input", children: _jsx("div", { className: "choices-container", children: state === null || state === void 0 ? void 0 : state.choices.map(choice => (_jsxs("label", { className: "choice-label", children: [_jsx("input", { type: "checkbox", checked: input.includes(choice), onChange: () => toggle(choice), tabIndex: 0, onKeyDown: (e) => {
|
|
79
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
80
|
+
e.preventDefault(); // Verhindert Scroll bei Space
|
|
81
|
+
toggle(choice);
|
|
82
|
+
}
|
|
83
|
+
} }), choice] }, choice))) }) }), _jsxs("div", { className: "information-buttons", children: [_jsx("button", { onClick: () => handleAction(state.handlerCancel, false), onKeyDown: (event) => {
|
|
84
|
+
if (event.key === "Enter" || event.key === ' ') {
|
|
85
|
+
event.preventDefault(); // Verhindert Scroll bei Space
|
|
86
|
+
handleAction(state.handlerCancel, false);
|
|
87
|
+
}
|
|
88
|
+
}, className: "px-4 py-2 bg-gray-300 rounded", style: (state === null || state === void 0 ? void 0 : state.cancelButtonStyle) != null ? state.cancelButtonStyle : {}, children: (state === null || state === void 0 ? void 0 : state.cancelButtonText) != null ? state.cancelButtonText : "Abbrechen" }), _jsx("button", { onClick: () => handleAction(state.handlerOk, true), id: "confirmButton", onKeyDown: (event) => {
|
|
89
|
+
if (event.key === "Enter" || event.key === ' ') {
|
|
90
|
+
event.preventDefault(); // Verhindert Scroll bei Space
|
|
91
|
+
handleAction(state.handlerOk, true);
|
|
92
|
+
}
|
|
93
|
+
}, className: "px-4 py-2 bg-blue-600 text-white rounded", style: (state === null || state === void 0 ? void 0 : state.proceedButtonStyle) != null ? state.proceedButtonStyle : {}, children: (state === null || state === void 0 ? void 0 : state.proceedButtonText) != null ? state.proceedButtonText : "OK" })] })] }) }) : _jsx(_Fragment, {});
|
|
94
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { CSSProperties } from 'react';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import './MultipleRadioOverlay.css';
|
|
4
|
+
export interface MultipleRadioOverlayState {
|
|
5
|
+
headline?: string | undefined;
|
|
6
|
+
message?: string | undefined;
|
|
7
|
+
choices: string[] | [];
|
|
8
|
+
preInput?: string | undefined;
|
|
9
|
+
cancelButtonText?: string | undefined;
|
|
10
|
+
proceedButtonText?: string | undefined;
|
|
11
|
+
handlerOk?: ((userInput: string, args?: unknown) => void) | undefined;
|
|
12
|
+
handlerCancel?: ((args?: unknown) => void) | undefined;
|
|
13
|
+
handlerArgs?: unknown;
|
|
14
|
+
addCloseButton?: boolean | undefined;
|
|
15
|
+
proceedButtonStyle?: CSSProperties | undefined;
|
|
16
|
+
cancelButtonStyle?: CSSProperties | undefined;
|
|
17
|
+
}
|
|
18
|
+
export declare const defaultMultipleRadioState: MultipleRadioOverlayState;
|
|
19
|
+
export declare function MultipleRadioOverlay({ state, setState }: {
|
|
20
|
+
state: MultipleRadioOverlayState;
|
|
21
|
+
setState: (state: MultipleRadioOverlayState) => void;
|
|
22
|
+
}): React.ReactElement;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
|
+
import './MultipleRadioOverlay.css';
|
|
4
|
+
// Um das MultipleRadioOverlay zu nutzen, muss der State die folgende Struktur haben:
|
|
5
|
+
export const defaultMultipleRadioState = {
|
|
6
|
+
headline: undefined,
|
|
7
|
+
message: undefined,
|
|
8
|
+
choices: [],
|
|
9
|
+
preInput: undefined,
|
|
10
|
+
cancelButtonText: undefined,
|
|
11
|
+
proceedButtonText: undefined,
|
|
12
|
+
handlerOk: undefined,
|
|
13
|
+
handlerCancel: undefined,
|
|
14
|
+
handlerArgs: undefined,
|
|
15
|
+
addCloseButton: false,
|
|
16
|
+
proceedButtonStyle: undefined,
|
|
17
|
+
cancelButtonStyle: undefined,
|
|
18
|
+
};
|
|
19
|
+
// Wobei alle Attribute grundsätzlich optional sind:
|
|
20
|
+
// - headline: ist die Überschrift und wird fett hinterlegt
|
|
21
|
+
// - message: ist die angezeigte Nachricht
|
|
22
|
+
// - choices: Ein String-Array mit den Optionen die ausgewählt werden können (ohne Angabe gibt es keine Auswahl)
|
|
23
|
+
// - preInput: Ein String: Dieser Eintrag ist stadardmäßig ausgewählt
|
|
24
|
+
// - cancelButtonText: ist der Text der auf dem Cancel Button stehen soll (ohne Angabe wird "Abbrechen" verwendet)
|
|
25
|
+
// - proceedButtonText: ist der Text der auf dem Proceed Button stehen soll (ohne Angabe wird "OK" verwendet)
|
|
26
|
+
// - handlerOk: ist die Funktion die bei Bestätigung des Inputs ausgeführt wird (Struktur: handlerOk(userInput, handlerArgs)
|
|
27
|
+
// - handlerCancel: ist die Funktion die bei Ablehnung des Inputs ausgeführt wird (Struktur: handlerCancel(handlerArgs)
|
|
28
|
+
// - handlerArgs: kann im handler als Argumente genutzt werden
|
|
29
|
+
// - addCloseButton: boolscher Wert, der angibt, ob ein x oben rechts als close-Button verfügbar sein soll (bricht die Aktion ohne handler ab, standardmäßig false)
|
|
30
|
+
// - proceedButtonStyle: ist der Style des Bestätigungsbuttons (Standardmäßig unverändert)
|
|
31
|
+
// - cancelButtonStyle: ist der Style des Abbrechenbuttons (Standardmäßig unverändert)
|
|
32
|
+
// Output: Der Input vom User wird am Ende an den handlerOk übergeben (oder bei handlerCancel ignoriert)!
|
|
33
|
+
// Somit wird der handler so aufgerufen: handlerOk(UserInput, handlerArgs) oder handlerCancel(handlerArgs)
|
|
34
|
+
export function MultipleRadioOverlay({ state, setState }) {
|
|
35
|
+
// Wird verwendet um das Infoverlay ein- und auszublenden
|
|
36
|
+
const [showOverlay, setShowOverlay] = useState(false);
|
|
37
|
+
// Wird verwendet um die ausgewählte Wahl aktuell zu halten
|
|
38
|
+
const [input, setInput] = useState("");
|
|
39
|
+
// Sobald der State von außen aktualisiert wird triggert diese Funktion
|
|
40
|
+
// Die setzt showOverlay auf true
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
if ((state === null || state === void 0 ? void 0 : state.message) != null || (state === null || state === void 0 ? void 0 : state.headline) != null) {
|
|
43
|
+
setInput((state === null || state === void 0 ? void 0 : state.preInput) != null ? state.preInput : "");
|
|
44
|
+
setShowOverlay(true);
|
|
45
|
+
setTimeout(() => { var _a; (_a = document.getElementById("confirmButton")) === null || _a === void 0 ? void 0 : _a.focus(); }, 1);
|
|
46
|
+
}
|
|
47
|
+
}, [state]);
|
|
48
|
+
const handleAction = (handler, useInput) => {
|
|
49
|
+
setShowOverlay(false);
|
|
50
|
+
var tempState = {
|
|
51
|
+
handler: handler,
|
|
52
|
+
handlerArgs: state.handlerArgs
|
|
53
|
+
};
|
|
54
|
+
setState(defaultMultipleRadioState);
|
|
55
|
+
if (typeof tempState.handler === 'function' && useInput)
|
|
56
|
+
tempState.handler(input, tempState.handlerArgs);
|
|
57
|
+
else if (typeof tempState.handler === 'function')
|
|
58
|
+
tempState.handler(tempState.handlerArgs);
|
|
59
|
+
};
|
|
60
|
+
return showOverlay ?
|
|
61
|
+
_jsx("div", { className: "multipleradio-overlay", children: _jsxs("div", { className: "multipleradio-box", children: [state.addCloseButton ?
|
|
62
|
+
_jsx("span", { className: "closeButton", children: _jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", tabIndex: 0, className: "close-icon", onClick: () => handleAction(undefined, false), onKeyDown: (e) => {
|
|
63
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
64
|
+
e.preventDefault(); // Verhindert Scroll bei Space
|
|
65
|
+
handleAction(undefined, false);
|
|
66
|
+
}
|
|
67
|
+
}, role: "button", "aria-label": "Dialog schlie\u00DFen", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), _jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })] }) }) :
|
|
68
|
+
_jsx(_Fragment, {}), _jsx("p", { className: "headline", id: "theHeadline", tabIndex: 0, style: { whiteSpace: "pre-line", wordBreak: "break-word" }, children: _jsx("strong", { children: (state === null || state === void 0 ? void 0 : state.headline) != null ? state.headline : "" }) }), _jsx("p", { tabIndex: 0, style: { whiteSpace: "pre-line", wordBreak: "break-word" }, children: (state === null || state === void 0 ? void 0 : state.message) != null ? state.message : "" }), _jsx("div", { className: "radios-input", children: _jsx("div", { className: "radios-container", children: state === null || state === void 0 ? void 0 : state.choices.map(choice => (_jsxs("label", { className: "radio-label", children: [_jsx("input", { type: "radio", checked: input === choice, onChange: () => setInput(choice), tabIndex: 0, onKeyDown: (e) => {
|
|
69
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
70
|
+
e.preventDefault(); // Verhindert Scroll bei Space
|
|
71
|
+
setInput(choice);
|
|
72
|
+
}
|
|
73
|
+
} }), choice] }, choice))) }) }), _jsxs("div", { className: "information-buttons", children: [_jsx("button", { onClick: () => handleAction(state.handlerCancel, false), onKeyDown: (event) => {
|
|
74
|
+
if (event.key === "Enter" || event.key === ' ') {
|
|
75
|
+
event.preventDefault(); // Verhindert Scroll bei Space
|
|
76
|
+
handleAction(state.handlerCancel, false);
|
|
77
|
+
}
|
|
78
|
+
}, className: "px-4 py-2 bg-gray-300 rounded", style: (state === null || state === void 0 ? void 0 : state.cancelButtonStyle) != null ? state.cancelButtonStyle : {}, children: (state === null || state === void 0 ? void 0 : state.cancelButtonText) != null ? state.cancelButtonText : "Abbrechen" }), _jsx("button", { onClick: () => handleAction(state.handlerOk, true), id: "confirmButton", onKeyDown: (event) => {
|
|
79
|
+
if (event.key === "Enter" || event.key === ' ') {
|
|
80
|
+
event.preventDefault(); // Verhindert Scroll bei Space
|
|
81
|
+
handleAction(state.handlerOk, true);
|
|
82
|
+
}
|
|
83
|
+
}, className: "px-4 py-2 bg-blue-600 text-white rounded", style: (state === null || state === void 0 ? void 0 : state.proceedButtonStyle) != null ? state.proceedButtonStyle : {}, children: (state === null || state === void 0 ? void 0 : state.proceedButtonText) != null ? state.proceedButtonText : "OK" })] })] }) }) : _jsx(_Fragment, {});
|
|
84
|
+
}
|
package/dist/Toast.d.ts
ADDED
package/dist/Toast.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
|
+
import './Toast.css';
|
|
4
|
+
// Zeigt einen kleinen Toast in der oberen rechten Ecke an, der nach 2,5 Sekunden wieder verschwindet
|
|
5
|
+
export function Toast({ state, setState }) {
|
|
6
|
+
// Wird verwendet um die Toast-Notification ein-/auszublenden
|
|
7
|
+
const [showToast, setShowToast] = useState(false);
|
|
8
|
+
// Wird verwendet um den Inhalt der Toast-Notification zu bestimmen
|
|
9
|
+
const [toastContent, setToastContent] = useState("");
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
setToastContent(state);
|
|
12
|
+
}, [state]);
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
if (toastContent && toastContent !== "") {
|
|
15
|
+
setShowToast(true);
|
|
16
|
+
setTimeout(() => { setState(""); }, 2500); // Hinweis nach 2,5 Sekunden wieder ausblenden
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
setShowToast(false);
|
|
20
|
+
}
|
|
21
|
+
}, [toastContent, setState]);
|
|
22
|
+
return _jsx(_Fragment, { children: showToast && (_jsx("div", { className: "toast-notification", children: toastContent })) });
|
|
23
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import "./ToggleSwitch.css";
|
|
2
|
+
export interface ToggleSwitchOption<T> {
|
|
3
|
+
value: T;
|
|
4
|
+
label: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function ToggleSwitch<T>({ optionLeft, optionRight, value, onChange }: {
|
|
7
|
+
optionLeft: ToggleSwitchOption<T>;
|
|
8
|
+
optionRight: ToggleSwitchOption<T>;
|
|
9
|
+
value: T;
|
|
10
|
+
onChange: (value: T) => void;
|
|
11
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useRef, useEffect, useState } from "react";
|
|
3
|
+
import "./ToggleSwitch.css";
|
|
4
|
+
// Attribute vom ToggleSwitch:
|
|
5
|
+
// - optionLeft: {value: valueLeft, label: labelLeft} Beschreibt die linke Option. valueLeft ist der Wert, der in "value" eingetragen wird und labelLeft, was als Option angezeigt wird.
|
|
6
|
+
// - optionRight: {value: valueLeft, label: labelRight} Beschreibt die rechte Option. valueRight ist der Wert, der in "value" eingetragen wird und labelRight, was als Option angezeigt wird.
|
|
7
|
+
// - value: Der Wert, der ausgewählt angezeigt werden soll (useState)
|
|
8
|
+
// - onChange: Die Funktion die bei Änderung ausgeführt werden soll.
|
|
9
|
+
// Standardmäßig könnte z.B. {(value) => {value === valueLeft ? setValue(valueLeft) : setValue(valueRight)}} genutzt werden
|
|
10
|
+
export function ToggleSwitch({ optionLeft, optionRight, value, onChange }) {
|
|
11
|
+
const containerRef = useRef(null);
|
|
12
|
+
const optionLeftRef = useRef(null);
|
|
13
|
+
const optionRightRef = useRef(null);
|
|
14
|
+
const [sliderStyle, setSliderStyle] = useState({});
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
const el = value === optionLeft.value ? optionLeftRef.current : optionRightRef.current;
|
|
17
|
+
const container = containerRef.current;
|
|
18
|
+
if (!el || !container)
|
|
19
|
+
return;
|
|
20
|
+
const { offsetLeft, offsetWidth } = el;
|
|
21
|
+
setSliderStyle({
|
|
22
|
+
transform: `translateX(calc(${offsetLeft}px - 1rem))`,
|
|
23
|
+
width: `calc(${offsetWidth}px + 2rem)`
|
|
24
|
+
});
|
|
25
|
+
}, [value, optionLeft, optionRight]);
|
|
26
|
+
return (_jsxs("div", { className: "toggleWrapper", ref: containerRef, children: [_jsx("div", { className: `toggleOption ${value === optionLeft.value ? "active" : ""}`, ref: el => { optionLeftRef.current = el; }, onClick: () => onChange(optionLeft.value), children: optionLeft.label }), _jsx("div", { className: `toggleOption ${value === optionRight.value ? "active" : ""}`, ref: el => { optionRightRef.current = el; }, onClick: () => onChange(optionRight.value), children: optionRight.label }), _jsx("div", { className: `toggleSlider ${value === optionLeft.value ? "left" : "right"}`, style: sliderStyle })] }));
|
|
27
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { ConfirmationBox, ConfirmationBoxState, defaultConfirmationState } from './ConfirmationBox.jsx';
|
|
2
|
+
export { Dropdown, DropdownOption } from './Dropdown.jsx';
|
|
3
|
+
export { InfoOverlay, InfoOverlayState, defaultInfoOverlayState } from './InfoOverlay.jsx';
|
|
4
|
+
export { InfoOverlayWithInput, InfoOverlayWithInputState, defaultInfoOverlayWithInputState } from './InfoOverlayWithInput.jsx';
|
|
5
|
+
export { setInputFilter } from './InputFilter.jsx';
|
|
6
|
+
export { LoadingOverlay, LoadingOverlayState, defaultLoadingOverlayState } from './LoadingOverlay.jsx';
|
|
7
|
+
export { MultipleChoiceOverlay, MultipleChoiceOverlayState, defaultMultipleChoiceState } from './MultipleChoiceOverlay.jsx';
|
|
8
|
+
export { MultipleRadioOverlay, MultipleRadioOverlayState, defaultMultipleRadioState } from './MultipleRadioOverlay.jsx';
|
|
9
|
+
export { Toast } from './Toast.jsx';
|
|
10
|
+
export { ToggleSwitch, ToggleSwitchOption } from './ToggleSwitch.jsx';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { ConfirmationBox, defaultConfirmationState } from './ConfirmationBox.jsx';
|
|
2
|
+
export { Dropdown } from './Dropdown.jsx';
|
|
3
|
+
export { InfoOverlay, defaultInfoOverlayState } from './InfoOverlay.jsx';
|
|
4
|
+
export { InfoOverlayWithInput, defaultInfoOverlayWithInputState } from './InfoOverlayWithInput.jsx';
|
|
5
|
+
export { setInputFilter } from './InputFilter.jsx';
|
|
6
|
+
export { LoadingOverlay, defaultLoadingOverlayState } from './LoadingOverlay.jsx';
|
|
7
|
+
export { MultipleChoiceOverlay, defaultMultipleChoiceState } from './MultipleChoiceOverlay.jsx';
|
|
8
|
+
export { MultipleRadioOverlay, defaultMultipleRadioState } from './MultipleRadioOverlay.jsx';
|
|
9
|
+
export { Toast } from './Toast.jsx';
|
|
10
|
+
export { ToggleSwitch } from './ToggleSwitch.jsx';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "typescript-overlay-essentials",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.3",
|
|
4
4
|
"description": "Eine kleine Ansammlung an praktischen Tools, die out of the Box genutzt werden können. Alle enthaltenen Overlays können als Reaktion auf etwas geöffnet werden und schließen sich danach automatisch. Es beinhaltet: \\n - [ConfirmationBox]: Ein Overlay mit einer ConfirmationBox (Fortfahren / Abbrechen), \\n - [InfoOverlay]: ein simples Overlay mit einer Informationsbox die man bestätigen kann, \\n - [InfoOverlayWithInput]: Ein Overlay bei dem ein User zusätzlich ein Freitext-Feld zur Eingabe hat, \\n - [LoadingOverlay]: Ein simples Overlay mit einer Lade-animation und optionalem Ladetext, \\n - [MultipleChoiceOverlay]: Ein simples Overlay bei dem ein Nutzer aus mehreren gegebenen Aktionen auswählen kann, \\n - [MultipleRadioOverlay]: Ein simples Overlay bei dem ein Nutzer genau eine aus mehreren gegebenen Aktionen auswählen kann, \\n - [Toast]: Ein simpler Toast der für kurze Zeit grün hinterlegt in der oberen rechten Ecke des Bildschirms angezeigt wird, \\n - [ToggleSwitch]: Eine Auswahl aus zwei Optionen aus denen ein Nutzer wählen kann in der Darstellung (Option 1 | Option 2), \\n - [Dropdown]: Ein simples Dropdown-Menü (auf Basis von react-select), welches einfacherer zu Konfigurieren ist und einige default-Einstellungen hat, \\n - [InputFilter]: Ein Tool was genutzt werden kann um auf einem Inputfeld einen Regex-Filter anzuwenden und dem User so nur Eingaben erlaubt die dem Filter entsprechen.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
@@ -38,7 +38,8 @@
|
|
|
38
38
|
"dist"
|
|
39
39
|
],
|
|
40
40
|
"scripts": {
|
|
41
|
-
"build": "tsc"
|
|
41
|
+
"build": "tsc",
|
|
42
|
+
"prepare": "npm run build"
|
|
42
43
|
},
|
|
43
44
|
"dependencies": {
|
|
44
45
|
"@emotion/react": "^11.14.0",
|