typescript-overlay-essentials 1.2.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.
Files changed (41) hide show
  1. package/dist/ConfirmationBox.d.ts +23 -0
  2. package/dist/ConfirmationBox.js +90 -0
  3. package/dist/Dropdown.d.ts +21 -0
  4. package/dist/Dropdown.js +141 -0
  5. package/dist/InfoOverlay.d.ts +17 -0
  6. package/dist/InfoOverlay.js +57 -0
  7. package/dist/InfoOverlayWithInput.d.ts +22 -0
  8. package/dist/InfoOverlayWithInput.js +84 -0
  9. package/dist/InputFilter.d.ts +1 -0
  10. package/{InputFilter.tsx → dist/InputFilter.js} +12 -12
  11. package/dist/LoadingOverlay.d.ts +13 -0
  12. package/dist/LoadingOverlay.js +36 -0
  13. package/dist/MultipleChoiceOverlay.d.ts +22 -0
  14. package/dist/MultipleChoiceOverlay.js +94 -0
  15. package/dist/MultipleRadioOverlay.d.ts +22 -0
  16. package/dist/MultipleRadioOverlay.js +84 -0
  17. package/dist/Toast.d.ts +6 -0
  18. package/{Toast.tsx → dist/Toast.js} +7 -15
  19. package/dist/ToggleSwitch.d.ts +11 -0
  20. package/dist/ToggleSwitch.js +27 -0
  21. package/{index.ts → dist/index.d.ts} +10 -10
  22. package/dist/index.js +10 -0
  23. package/package.json +19 -3
  24. package/.github/workflows/npm-publish.yml +0 -32
  25. package/ConfirmationBox.css +0 -69
  26. package/ConfirmationBox.tsx +0 -148
  27. package/Dropdown.css +0 -31
  28. package/Dropdown.tsx +0 -211
  29. package/InfoOverlay.css +0 -65
  30. package/InfoOverlay.tsx +0 -101
  31. package/InfoOverlayWithInput.css +0 -88
  32. package/InfoOverlayWithInput.tsx +0 -157
  33. package/LoadingOverlay.css +0 -110
  34. package/LoadingOverlay.tsx +0 -57
  35. package/MultipleChoiceOverlay.css +0 -170
  36. package/MultipleChoiceOverlay.tsx +0 -170
  37. package/MultipleRadioOverlay.css +0 -170
  38. package/MultipleRadioOverlay.tsx +0 -158
  39. package/Toast.css +0 -13
  40. package/ToggleSwitch.tsx +0 -56
  41. package/Toggleswitch.css +0 -49
@@ -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
+ }
@@ -0,0 +1,6 @@
1
+ import { ReactElement } from 'react';
2
+ import './Toast.css';
3
+ export declare function Toast({ state, setState }: {
4
+ state: string;
5
+ setState: (value: string) => void;
6
+ }): ReactElement;
@@ -1,17 +1,15 @@
1
- import { useEffect, useState, ReactElement } from 'react';
2
- import './Toast.css'
3
-
1
+ import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useEffect, useState } from 'react';
3
+ import './Toast.css';
4
4
  // Zeigt einen kleinen Toast in der oberen rechten Ecke an, der nach 2,5 Sekunden wieder verschwindet
5
- export function Toast({ state, setState }: { state: string, setState: (value: string) => void }) : ReactElement {
5
+ export function Toast({ state, setState }) {
6
6
  // Wird verwendet um die Toast-Notification ein-/auszublenden
7
7
  const [showToast, setShowToast] = useState(false);
8
8
  // Wird verwendet um den Inhalt der Toast-Notification zu bestimmen
9
9
  const [toastContent, setToastContent] = useState("");
10
-
11
10
  useEffect(() => {
12
- setToastContent(state)
11
+ setToastContent(state);
13
12
  }, [state]);
14
-
15
13
  useEffect(() => {
16
14
  if (toastContent && toastContent !== "") {
17
15
  setShowToast(true);
@@ -21,11 +19,5 @@ export function Toast({ state, setState }: { state: string, setState: (value: st
21
19
  setShowToast(false);
22
20
  }
23
21
  }, [toastContent, setState]);
24
-
25
- return <>
26
- {showToast && (
27
- <div className="toast-notification">
28
- {toastContent}
29
- </div>)}
30
- </>
31
- }
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
+ }
@@ -1,10 +1,10 @@
1
- export { ConfirmationBox, ConfirmationBoxState, defaultConfirmationState } from './ConfirmationBox.tsx';
2
- export { Dropdown, DropdownOption } from './Dropdown.tsx';
3
- export { InfoOverlay, InfoOverlayState, defaultInfoOverlayState } from './InfoOverlay.tsx';
4
- export { InfoOverlayWithInput, InfoOverlayWithInputState, defaultInfoOverlayWithInputState } from './InfoOverlayWithInput.tsx';
5
- export { setInputFilter } from './InputFilter.tsx';
6
- export { LoadingOverlay, LoadingOverlayState, defaultLoadingOverlayState } from './LoadingOverlay.tsx';
7
- export { MultipleChoiceOverlay, MultipleChoiceOverlayState, defaultMultipleChoiceState } from './MultipleChoiceOverlay.tsx';
8
- export { MultipleRadioOverlay, MultipleRadioOverlayState, defaultMultipleRadioState } from './MultipleRadioOverlay.tsx';
9
- export { Toast } from './Toast.tsx';
10
- export { ToggleSwitch, ToggleSwitchOption } from './ToggleSwitch.tsx'
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.2.0",
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",
@@ -32,11 +32,27 @@
32
32
  "license": "ISC",
33
33
  "author": "Julian Koch",
34
34
  "type": "module",
35
- "main": "index.ts",
35
+ "main": "dist/index.js",
36
+ "types": "dist/index.d.ts",
37
+ "files": [
38
+ "dist"
39
+ ],
36
40
  "scripts": {
37
- "test": "echo \"No test needed\""
41
+ "build": "tsc",
42
+ "prepare": "npm run build"
38
43
  },
39
44
  "dependencies": {
45
+ "@emotion/react": "^11.14.0",
40
46
  "react-select": "^5.10.2"
47
+ },
48
+ "peerDependencies": {
49
+ "@types/react": "^19.2.14",
50
+ "@types/react-dom": "^19.2.3",
51
+ "react": "^18.0.0 || ^19.0.0",
52
+ "react-dom": "^18.0.0 || ^19.0.0"
53
+ },
54
+ "devDependencies": {
55
+ "@types/react": "^19.2.14",
56
+ "@types/react-dom": "^19.2.3"
41
57
  }
42
58
  }
@@ -1,32 +0,0 @@
1
- # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
2
- # For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages
3
-
4
- name: typescript-overlay-essentials
5
-
6
- on:
7
- release:
8
- types: [created]
9
-
10
- jobs:
11
- build:
12
- runs-on: ubuntu-latest
13
- steps:
14
- - uses: actions/checkout@v5
15
- - uses: actions/setup-node@v6
16
- with:
17
- node-version: 24
18
- - run: npm ci
19
-
20
- publish-npm:
21
- needs: build
22
- runs-on: ubuntu-latest
23
- steps:
24
- - uses: actions/checkout@v5
25
- - uses: actions/setup-node@v6
26
- with:
27
- node-version: 24
28
- registry-url: https://registry.npmjs.org/
29
- - run: npm ci
30
- - run: npm publish
31
- env:
32
- NODE_AUTH_TOKEN: ${{secrets.npm_token}}
@@ -1,69 +0,0 @@
1
- .confirmation-overlay {
2
- position: fixed;
3
- top: 0;
4
- left: 0;
5
- width: 100vw;
6
- height: 100vh;
7
- background-color: rgba(0, 0, 0, 0.6);
8
- display: flex;
9
- align-items: center;
10
- justify-content: center;
11
- z-index: 10000;
12
- }
13
-
14
- .confirmation-box {
15
- background-color: var(--Hellgrau, white);
16
- color: var(--HellSchwarz,#2c2c2c);
17
- padding: 2rem;
18
- border-radius: 12px;
19
- box-shadow: 0 8px 20px rgba(0, 0, 0, 0.5);
20
- max-width: 500px;
21
- width: 90%;
22
- text-align: center;
23
- animation: fadeIn 0.3s ease-in-out;
24
- position: relative;
25
- }
26
-
27
- @keyframes fadeIn {
28
- from {
29
- opacity: 0;
30
- transform: scale(0.95);
31
- }
32
-
33
- to {
34
- opacity: 1;
35
- transform: scale(1);
36
- }
37
- }
38
-
39
- .confirmation-box p {
40
- margin-bottom: 0.5em;
41
- }
42
-
43
- .confirmation-box .headline {
44
- margin-bottom: 0.75em;
45
- }
46
-
47
- .confirmation-box .confirmation-buttons {
48
- display: flex;
49
- justify-content: center;
50
- gap: 1rem;
51
- margin-top: 1.5rem;
52
- }
53
-
54
- .confirmation-box .confirmation-buttons button {
55
- font-size: 85%;
56
- padding: 0.5rem 1.1rem;
57
- }
58
-
59
- .confirmation-box .closeButton {
60
- right: 10px;
61
- top: 10px;
62
- position: absolute;
63
- }
64
-
65
- .confirmation-box .close-icon:hover {
66
- color: var(--HSDAkzent);
67
- cursor: pointer;
68
- }
69
-
@@ -1,148 +0,0 @@
1
- import { useEffect, useState, useRef, CSSProperties } from 'react';
2
- import * as React from 'react';
3
- import './ConfirmationBox.css';
4
-
5
- // Um die ConfirmationBox zu nutzen, muss der State die folgende Struktur haben:
6
- export interface ConfirmationBoxState {
7
- headline?: string | undefined;
8
- message?: string | undefined;
9
- message1?: string | undefined;
10
- message2?: string | undefined;
11
- cancelButtonText?: string | undefined;
12
- proceedButtonText?: string | undefined;
13
- handlerOk?: ((args?: unknown) => void) | undefined;
14
- handlerCancel?: ((args?: unknown) => void) | undefined;
15
- handlerArgs?: unknown;
16
- addCloseButton?: boolean | undefined;
17
- activateConfirm?: boolean | undefined;
18
- proceedButtonStyle?: CSSProperties | undefined;
19
- cancelButtonStyle?: CSSProperties | undefined;
20
- }
21
-
22
- // Der standard ComfirmationBox Status, der zur Initialisierung genutzt werden kann
23
- export const defaultConfirmationState: ConfirmationBoxState = {
24
- headline: undefined,
25
- message: undefined,
26
- message1: undefined,
27
- message2: undefined,
28
- cancelButtonText: undefined,
29
- proceedButtonText: undefined,
30
- handlerOk: undefined,
31
- handlerCancel: undefined,
32
- handlerArgs: undefined,
33
- addCloseButton: false,
34
- activateConfirm: undefined,
35
- proceedButtonStyle: undefined,
36
- cancelButtonStyle: undefined,
37
- };
38
-
39
- // Wobei alle Attribute grundsätzlich optional sind:
40
- // - headline: Eine fett hinterlegte Überschrift (optional)
41
- // - message1: ist die angezeigte Nachricht
42
- // - message2: ist optional und wird fett hinterlegt (z.B. ein wichtiger Hinweis oder ähnliches)
43
- // - message: ist optional und wird nur angezeigt, wenn message1 nicht gesetzt ist (damit message oder message1 genutzt werden kann)
44
- // - cancelButtonText: ist der Text der auf dem Cancel Button stehen soll (ohne Angabe wird "Abbrechen" verwendet)
45
- // - proceedButtonText: ist der Text der auf dem Proceed Button stehen soll (ohne Angabe wird "OK" verwendet)
46
- // - handlerOk: ist die Funktion die bei Bestätigung der Box ausgeführt wird (nutzt handlerargs, erwartet also nur 1 Argument!)
47
- // - handlerCancel: ist die Funktion die bei Ablehnung der Box ausgeführt wird (nutzt handlerargs, erwartet also nur 1 Argument!)
48
- // - 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)
49
- // - handlerArgs: kann im handler als weitere Argumente genutzt werden
50
- // - 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)
51
- // - proceedButtonStyle: ist der Style des Bestätigungsbuttons (Standardmäßig unverändert)
52
- // - cancelButtonStyle: ist der Style des Abbrechenbuttons (Standardmäßig unverändert)
53
-
54
- export function ConfirmationBox({ state, setState }: { state: ConfirmationBoxState, setState: (state: ConfirmationBoxState) => void }): React.ReactElement {
55
-
56
- // Wird verwendet um die Confirmation Boxen ein- und auszublenden
57
- const [showConfirm, setShowConfirm] = useState(false);
58
-
59
- // Damit der Fokus auf die Confirmation Box gesetzt wird, wenn sie geöffnet wird
60
- // Und man sie mit Enter bestätigen kann
61
- const overlayRef = useRef<HTMLDivElement>(null);
62
-
63
- // Sobald der State von außen aktualisiert wird triggert diese Funktion
64
- // Die setzt showConfirm auf true (oder ruft die übergebene Funktion auf wenn confirmationBoxen disabled sind)
65
- useEffect(() => {
66
- if (state?.handlerOk) {
67
- if (state.activateConfirm ?? true) {
68
- setShowConfirm(true);
69
- setTimeout(() => { document.getElementById("confirmButton")?.focus(); }, 1);
70
- }
71
- else {
72
- // Wenn activateConfirm explizit false ist, dann wird die übergebene Funktion direkt ausgeführt ohne ConfirmationBox
73
- if (typeof state.handlerOk === 'function')
74
- state.handlerOk(state.handlerArgs);
75
- }
76
- }
77
- setTimeout(() => {
78
- overlayRef.current?.focus();
79
- }, 0);
80
- }, [state]);
81
-
82
- const handleAction = (handler: ((args?: unknown) => void) | undefined) : void => {
83
- setShowConfirm(false);
84
- const tempState = {
85
- handler: handler,
86
- handlerArgs: state.handlerArgs
87
- };
88
- setState(defaultConfirmationState);
89
- if (typeof tempState.handler === 'function')
90
- tempState.handler(tempState.handlerArgs);
91
- }
92
-
93
- return showConfirm ?
94
- <div className="confirmation-overlay"
95
- tabIndex={0}
96
- ref={overlayRef}>
97
- <div className="confirmation-box">
98
- {state.addCloseButton?
99
- <span className="closeButton">
100
- <svg xmlns="http://www.w3.org/2000/svg"
101
- tabIndex={0}
102
- className="close-icon"
103
- onClick={() => handleAction(undefined)}
104
- onKeyDown={(e) => {
105
- if (e.key === 'Enter' || e.key === ' ') {
106
- e.preventDefault(); // Verhindert Scroll bei Space
107
- handleAction(undefined);
108
- }
109
- }}
110
- role="button" aria-label="Dialog schließen"
111
- width="24" height="24" viewBox="0 0 24 24" fill="none"
112
- stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
113
- <line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/>
114
- </svg>
115
- </span> :
116
- <></>}
117
- {state?.headline !== undefined ? <p className="headline" style={{ whiteSpace: "pre-line", wordBreak: "break-word" }}><strong>{state?.headline}</strong></p> : <></>}
118
- <p style={{ whiteSpace: "pre-line", wordBreak: "break-word" }}>{state.message1 ?? state.message ?? ""}</p>
119
- <p style={{ whiteSpace: "pre-line", wordBreak: "break-word" }}><strong>{state.message2 ?? ""}</strong></p>
120
- <div className="confirmation-buttons">
121
- <button
122
- onClick={() => handleAction(state.handlerCancel)}
123
- onKeyDown={(e) => {
124
- if (e.key === 'Enter' || e.key === ' ') {
125
- e.preventDefault(); // Verhindert Scroll bei Space
126
- handleAction(state.handlerCancel);
127
- }
128
- }}
129
- className="px-4 py-2 bg-gray-300 rounded"
130
- style={state?.cancelButtonStyle !== undefined ? state.cancelButtonStyle : {}}>
131
- {state.cancelButtonText ? state.cancelButtonText : "Abbrechen"}
132
- </button>
133
- <button onClick={() => handleAction(state.handlerOk)}
134
- id="confirmButton"
135
- onKeyDown={(e) => {
136
- if (e.key === 'Enter' || e.key === ' ') {
137
- e.preventDefault(); // Verhindert Scroll bei Space
138
- handleAction(state.handlerOk);
139
- }
140
- }}
141
- className="px-4 py-2 bg-blue-600 text-white rounded"
142
- style={state?.proceedButtonStyle !== undefined ? state.proceedButtonStyle : {}}>
143
- {state.proceedButtonText ? state.proceedButtonText : "OK"}
144
- </button>
145
- </div>
146
- </div>
147
- </div> : <></>;
148
- }