@helpwave/hightide 0.0.9 → 0.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/coloring/shading.d.ts +2 -0
- package/dist/coloring/shading.js +40 -0
- package/dist/coloring/types.d.ts +11 -0
- package/dist/coloring/types.js +1 -0
- package/dist/components/Avatar.d.ts +14 -0
- package/dist/components/Avatar.js +35 -0
- package/dist/components/AvatarGroup.d.ts +10 -0
- package/dist/components/AvatarGroup.js +13 -0
- package/dist/components/BreadCrumb.d.ts +16 -0
- package/dist/components/BreadCrumb.js +12 -0
- package/dist/components/Button.d.ts +41 -0
- package/dist/components/Button.js +84 -0
- package/dist/components/ChipList.d.ts +21 -0
- package/dist/components/ChipList.js +38 -0
- package/dist/components/Circle.d.ts +6 -0
- package/dist/components/Circle.js +10 -0
- package/dist/components/ErrorComponent.d.ts +13 -0
- package/dist/components/ErrorComponent.js +19 -0
- package/dist/components/Expandable.d.ts +30 -0
- package/dist/components/Expandable.js +16 -0
- package/dist/components/HelpwaveBadge.d.ts +11 -0
- package/dist/components/HelpwaveBadge.js +14 -0
- package/dist/components/HideableContentSection.d.ts +10 -0
- package/dist/components/HideableContentSection.js +15 -0
- package/dist/components/InputGroup.d.ts +13 -0
- package/dist/components/InputGroup.js +33 -0
- package/dist/components/LoadingAndErrorComponent.d.ts +17 -0
- package/dist/components/LoadingAndErrorComponent.js +25 -0
- package/dist/components/LoadingAnimation.d.ts +13 -0
- package/dist/components/LoadingAnimation.js +19 -0
- package/dist/components/LoadingButton.d.ts +6 -0
- package/dist/components/LoadingButton.js +10 -0
- package/dist/components/MarkdownInterpreter.d.ts +25 -0
- package/dist/components/MarkdownInterpreter.js +190 -0
- package/dist/components/Pagination.d.ts +14 -0
- package/dist/components/Pagination.js +25 -0
- package/dist/components/Profile.d.ts +28 -0
- package/dist/components/Profile.js +45 -0
- package/dist/components/ProgressIndicator.d.ts +21 -0
- package/dist/components/ProgressIndicator.js +24 -0
- package/dist/components/Ring.d.ts +31 -0
- package/dist/components/Ring.js +113 -0
- package/dist/components/SearchableList.d.ts +18 -0
- package/dist/components/SearchableList.js +27 -0
- package/dist/components/SortButton.d.ts +10 -0
- package/dist/components/SortButton.js +9 -0
- package/dist/components/Span.js +1 -0
- package/dist/components/StepperBar.d.ts +23 -0
- package/dist/components/StepperBar.js +47 -0
- package/dist/components/Table.d.ts +87 -0
- package/dist/components/Table.js +187 -0
- package/dist/components/TechRadar.d.ts +36 -0
- package/dist/components/TechRadar.js +191 -0
- package/dist/components/TextImage.d.ts +20 -0
- package/dist/components/TextImage.js +31 -0
- package/dist/components/TimeDisplay.d.ts +30 -0
- package/dist/components/TimeDisplay.js +83 -0
- package/dist/components/Tooltip.d.ts +34 -0
- package/dist/components/Tooltip.js +38 -0
- package/dist/components/VerticalDivider.d.ts +11 -0
- package/dist/components/VerticalDivider.js +7 -0
- package/dist/components/date/DatePicker.d.ts +26 -0
- package/dist/components/date/DatePicker.js +58 -0
- package/dist/components/date/DayPicker.d.ts +16 -0
- package/dist/components/date/DayPicker.js +37 -0
- package/dist/components/date/TimePicker.d.ts +12 -0
- package/dist/components/date/TimePicker.js +79 -0
- package/dist/components/date/YearMonthPicker.d.ts +11 -0
- package/dist/components/date/YearMonthPicker.js +59 -0
- package/dist/components/examples/InputGroupExample.d.ts +6 -0
- package/dist/components/examples/InputGroupExample.js +21 -0
- package/dist/components/examples/MultiSelectExample.d.ts +7 -0
- package/dist/components/examples/MultiSelectExample.js +27 -0
- package/dist/components/examples/SearchableSelectExample.d.ts +6 -0
- package/dist/components/examples/SearchableSelectExample.js +17 -0
- package/dist/components/examples/SelectExample.d.ts +4 -0
- package/dist/components/examples/SelectExample.js +15 -0
- package/dist/components/examples/StackingModals.d.ts +4 -0
- package/dist/components/examples/StackingModals.js +15 -0
- package/dist/components/examples/TableExample.d.ts +9 -0
- package/dist/components/examples/TableExample.js +92 -0
- package/dist/components/examples/TextareaExample.d.ts +6 -0
- package/dist/components/examples/TextareaExample.js +10 -0
- package/dist/components/examples/TileExample.d.ts +9 -0
- package/dist/components/examples/TileExample.js +9 -0
- package/dist/components/examples/Title.js +1 -0
- package/dist/components/examples/date/DateTimePickerExample.d.ts +10 -0
- package/dist/components/examples/date/DateTimePickerExample.js +21 -0
- package/dist/components/examples/properties/CheckboxPropertyExample.d.ts +8 -0
- package/dist/components/examples/properties/CheckboxPropertyExample.js +13 -0
- package/dist/components/examples/properties/DatePropertyExample.d.ts +8 -0
- package/dist/components/examples/properties/DatePropertyExample.js +23 -0
- package/dist/components/examples/properties/MultiSelectPropertyExample.d.ts +8 -0
- package/dist/components/examples/properties/MultiSelectPropertyExample.js +16 -0
- package/dist/components/examples/properties/NumberPropertyExample.d.ts +6 -0
- package/dist/components/examples/properties/NumberPropertyExample.js +13 -0
- package/dist/components/examples/properties/SelectPropertyExample.d.ts +6 -0
- package/dist/components/examples/properties/SelectPropertyExample.js +18 -0
- package/dist/components/examples/properties/TextPropertyExample.d.ts +8 -0
- package/dist/components/examples/properties/TextPropertyExample.js +13 -0
- package/dist/components/icons/Helpwave.d.ts +10 -0
- package/dist/components/icons/Helpwave.js +20 -0
- package/dist/components/icons/Tag.d.ts +10 -0
- package/dist/components/icons/Tag.js +12 -0
- package/dist/components/layout/Carousel.d.ts +22 -0
- package/dist/components/layout/Carousel.js +233 -0
- package/dist/components/layout/DividerInserter.d.ts +11 -0
- package/dist/components/layout/DividerInserter.js +20 -0
- package/dist/components/layout/FAQSection.d.ts +23 -0
- package/dist/components/layout/FAQSection.js +14 -0
- package/dist/components/layout/Tile.d.ts +34 -0
- package/dist/components/layout/Tile.js +18 -0
- package/dist/components/modals/ConfirmDialog.d.ts +34 -0
- package/dist/components/modals/ConfirmDialog.js +31 -0
- package/dist/components/modals/DiscardChangesDialog.d.ts +19 -0
- package/dist/components/modals/DiscardChangesDialog.js +24 -0
- package/dist/components/modals/InputModal.d.ts +9 -0
- package/dist/components/modals/InputModal.js +9 -0
- package/dist/components/modals/LanguageModal.d.ts +17 -0
- package/dist/components/modals/LanguageModal.js +35 -0
- package/dist/components/modals/Modal.d.ts +38 -0
- package/dist/components/modals/Modal.js +57 -0
- package/dist/components/modals/ModalRegister.d.ts +11 -0
- package/dist/components/modals/ModalRegister.js +28 -0
- package/dist/components/properties/CheckboxProperty.d.ts +15 -0
- package/dist/components/properties/CheckboxProperty.js +27 -0
- package/dist/components/properties/DateProperty.d.ts +11 -0
- package/dist/components/properties/DateProperty.js +22 -0
- package/dist/components/properties/MultiSelectProperty.d.ts +12 -0
- package/dist/components/properties/MultiSelectProperty.js +33 -0
- package/dist/components/properties/NumberProperty.d.ts +16 -0
- package/dist/components/properties/NumberProperty.js +42 -0
- package/dist/components/properties/PropertyBase.d.ts +23 -0
- package/dist/components/properties/PropertyBase.js +27 -0
- package/dist/components/properties/SelectProperty.d.ts +12 -0
- package/dist/components/properties/SelectProperty.js +22 -0
- package/dist/components/properties/TextProperty.d.ts +15 -0
- package/dist/components/properties/TextProperty.js +37 -0
- package/dist/components/user-input/Checkbox.d.ts +37 -0
- package/dist/components/user-input/Checkbox.js +63 -0
- package/dist/components/user-input/DateAndTimePicker.d.ts +39 -0
- package/dist/components/user-input/DateAndTimePicker.js +65 -0
- package/dist/components/user-input/Input.d.ts +61 -0
- package/dist/components/user-input/Input.js +61 -0
- package/dist/components/user-input/Label.d.ts +12 -0
- package/dist/components/user-input/Label.js +12 -0
- package/dist/components/user-input/Menu.d.ts +21 -0
- package/dist/components/user-input/Menu.js +26 -0
- package/dist/components/user-input/MultiSelect.d.ts +39 -0
- package/dist/components/user-input/MultiSelect.js +57 -0
- package/dist/components/user-input/ScrollPicker.d.ts +11 -0
- package/dist/components/user-input/ScrollPicker.js +151 -0
- package/dist/components/user-input/SearchableSelect.d.ts +8 -0
- package/dist/components/user-input/SearchableSelect.js +14 -0
- package/dist/components/user-input/Select.d.ts +32 -0
- package/dist/components/user-input/Select.js +48 -0
- package/dist/components/user-input/Textarea.d.ts +20 -0
- package/dist/components/user-input/Textarea.js +33 -0
- package/dist/components/user-input/ToggleableInput.d.ts +32 -0
- package/dist/components/user-input/ToggleableInput.js +40 -0
- package/dist/css/globals.css +2450 -0
- package/dist/hooks/useHoverState.d.ts +40 -0
- package/dist/hooks/useHoverState.js +46 -0
- package/dist/hooks/useLanguage.d.ts +17 -0
- package/dist/hooks/useLanguage.js +51 -0
- package/dist/hooks/useLocalStorage.d.ts +4 -0
- package/dist/hooks/useLocalStorage.js +24 -0
- package/dist/hooks/useOutsideClick.d.ts +2 -0
- package/dist/hooks/useOutsideClick.js +22 -0
- package/dist/hooks/useSaveDelay.d.ts +5 -0
- package/dist/hooks/useSaveDelay.js +41 -0
- package/dist/hooks/useTheme.d.ts +16 -0
- package/dist/hooks/useTheme.js +32 -0
- package/dist/hooks/useTranslation.d.ts +24 -0
- package/dist/hooks/useTranslation.js +11 -0
- package/dist/util/array.d.ts +23 -0
- package/dist/util/array.js +103 -0
- package/{util/builder.ts → dist/util/builder.d.ts} +1 -4
- package/dist/util/builder.js +9 -0
- package/dist/util/date.d.ts +28 -0
- package/dist/util/date.js +133 -0
- package/dist/util/easeFunctions.d.ts +9 -0
- package/dist/util/easeFunctions.js +30 -0
- package/dist/util/emailValidation.d.ts +1 -0
- package/dist/util/emailValidation.js +3 -0
- package/dist/util/loopingArray.d.ts +23 -0
- package/dist/util/loopingArray.js +67 -0
- package/dist/util/math.d.ts +1 -0
- package/dist/util/math.js +3 -0
- package/dist/util/news.d.ts +98 -0
- package/dist/util/news.js +27 -0
- package/dist/util/noop.d.ts +1 -0
- package/dist/util/noop.js +1 -0
- package/{util/simpleSearch.ts → dist/util/simpleSearch.d.ts} +4 -21
- package/dist/util/simpleSearch.js +62 -0
- package/dist/util/storage.d.ts +15 -0
- package/dist/util/storage.js +32 -0
- package/dist/util/types.d.ts +1 -0
- package/dist/util/types.js +1 -0
- package/package.json +7 -8
- package/coloring/shading.ts +0 -46
- package/coloring/types.ts +0 -13
- package/components/Avatar.tsx +0 -58
- package/components/AvatarGroup.tsx +0 -48
- package/components/BreadCrumb.tsx +0 -35
- package/components/Button.tsx +0 -236
- package/components/ChipList.tsx +0 -89
- package/components/Circle.tsx +0 -27
- package/components/ErrorComponent.tsx +0 -40
- package/components/Expandable.tsx +0 -61
- package/components/HelpwaveBadge.tsx +0 -35
- package/components/HideableContentSection.tsx +0 -43
- package/components/InputGroup.tsx +0 -72
- package/components/LoadingAndErrorComponent.tsx +0 -47
- package/components/LoadingAnimation.tsx +0 -40
- package/components/LoadingButton.tsx +0 -27
- package/components/MarkdownInterpreter.tsx +0 -278
- package/components/Pagination.tsx +0 -65
- package/components/Profile.tsx +0 -124
- package/components/ProgressIndicator.tsx +0 -58
- package/components/Ring.tsx +0 -286
- package/components/SearchableList.tsx +0 -69
- package/components/SortButton.tsx +0 -33
- package/components/StepperBar.tsx +0 -124
- package/components/Table.tsx +0 -330
- package/components/TechRadar.tsx +0 -247
- package/components/TextImage.tsx +0 -86
- package/components/TimeDisplay.tsx +0 -121
- package/components/Tooltip.tsx +0 -92
- package/components/VerticalDivider.tsx +0 -51
- package/components/date/DatePicker.tsx +0 -164
- package/components/date/DayPicker.tsx +0 -95
- package/components/date/TimePicker.tsx +0 -167
- package/components/date/YearMonthPicker.tsx +0 -130
- package/components/examples/InputGroupExample.tsx +0 -58
- package/components/examples/MultiSelectExample.tsx +0 -57
- package/components/examples/SearchableSelectExample.tsx +0 -34
- package/components/examples/SelectExample.tsx +0 -28
- package/components/examples/StackingModals.tsx +0 -54
- package/components/examples/TableExample.tsx +0 -159
- package/components/examples/TextareaExample.tsx +0 -23
- package/components/examples/TileExample.tsx +0 -25
- package/components/examples/date/DateTimePickerExample.tsx +0 -53
- package/components/examples/properties/CheckboxPropertyExample.tsx +0 -29
- package/components/examples/properties/DatePropertyExample.tsx +0 -44
- package/components/examples/properties/MultiSelectPropertyExample.tsx +0 -39
- package/components/examples/properties/NumberPropertyExample.tsx +0 -28
- package/components/examples/properties/SelectPropertyExample.tsx +0 -39
- package/components/examples/properties/TextPropertyExample.tsx +0 -30
- package/components/icons/Helpwave.tsx +0 -51
- package/components/icons/Tag.tsx +0 -29
- package/components/layout/Carousel.tsx +0 -396
- package/components/layout/DividerInserter.tsx +0 -37
- package/components/layout/FAQSection.tsx +0 -57
- package/components/layout/Tile.tsx +0 -67
- package/components/modals/ConfirmDialog.tsx +0 -105
- package/components/modals/DiscardChangesDialog.tsx +0 -71
- package/components/modals/InputModal.tsx +0 -26
- package/components/modals/LanguageModal.tsx +0 -76
- package/components/modals/Modal.tsx +0 -149
- package/components/modals/ModalRegister.tsx +0 -45
- package/components/properties/CheckboxProperty.tsx +0 -62
- package/components/properties/DateProperty.tsx +0 -58
- package/components/properties/MultiSelectProperty.tsx +0 -82
- package/components/properties/NumberProperty.tsx +0 -86
- package/components/properties/PropertyBase.tsx +0 -84
- package/components/properties/SelectProperty.tsx +0 -67
- package/components/properties/TextProperty.tsx +0 -81
- package/components/user-input/Checkbox.tsx +0 -139
- package/components/user-input/DateAndTimePicker.tsx +0 -156
- package/components/user-input/Input.tsx +0 -192
- package/components/user-input/Label.tsx +0 -32
- package/components/user-input/Menu.tsx +0 -75
- package/components/user-input/MultiSelect.tsx +0 -158
- package/components/user-input/ScrollPicker.tsx +0 -240
- package/components/user-input/SearchableSelect.tsx +0 -36
- package/components/user-input/Select.tsx +0 -132
- package/components/user-input/Textarea.tsx +0 -86
- package/components/user-input/ToggleableInput.tsx +0 -115
- package/globals.css +0 -488
- package/hooks/useHoverState.ts +0 -88
- package/hooks/useLanguage.tsx +0 -78
- package/hooks/useLocalStorage.tsx +0 -33
- package/hooks/useOutsideClick.ts +0 -25
- package/hooks/useSaveDelay.ts +0 -46
- package/hooks/useTheme.tsx +0 -57
- package/hooks/useTranslation.ts +0 -43
- package/index.ts +0 -0
- package/util/array.ts +0 -115
- package/util/date.ts +0 -180
- package/util/easeFunctions.ts +0 -37
- package/util/emailValidation.ts +0 -3
- package/util/loopingArray.ts +0 -94
- package/util/math.ts +0 -3
- package/util/news.ts +0 -43
- package/util/noop.ts +0 -1
- package/util/storage.ts +0 -37
- package/util/types.ts +0 -4
- /package/{components/Span.tsx → dist/components/Span.d.ts} +0 -0
- /package/{components/examples/Title.tsx → dist/components/examples/Title.d.ts} +0 -0
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
4
|
+
import { ChevronLeft, ChevronRight } from 'lucide-react';
|
|
5
|
+
import { createLoopingListWithIndex, range } from '../../util/array';
|
|
6
|
+
import { clamp } from '../../util/math';
|
|
7
|
+
import { EaseFunctions } from '../../util/easeFunctions';
|
|
8
|
+
import { LoopingArrayCalculator } from '../../util/loopingArray';
|
|
9
|
+
export const Carousel = ({ children, animationTime = 200, isLooping = false, isAutoLooping = false, autoLoopingTimeOut = 5000, autoLoopAnimationTime = 500, hintNext = false, arrows = false, dots = true, overScrollThreshold = 0.1, blurColor = 'from-white', className = '', heightClassName = 'h-[24rem]', widthClassName = 'w-[70%] desktop:w-1/2', }) => {
|
|
10
|
+
if (isAutoLooping && !isLooping) {
|
|
11
|
+
console.error('When isAutoLooping is true, isLooping should also be true');
|
|
12
|
+
isLooping = true;
|
|
13
|
+
}
|
|
14
|
+
const [{ currentPosition, dragState, animationState, }, setCarouselInformation] = useState({
|
|
15
|
+
currentPosition: 0,
|
|
16
|
+
});
|
|
17
|
+
const animationId = useRef(undefined);
|
|
18
|
+
const timeOut = useRef(undefined);
|
|
19
|
+
autoLoopingTimeOut = Math.max(0, autoLoopingTimeOut);
|
|
20
|
+
const length = children.length;
|
|
21
|
+
const paddingItemCount = 3; // The number of items to append left and right of the list to allow for clean transition when looping
|
|
22
|
+
const util = useMemo(() => new LoopingArrayCalculator(length, isLooping, overScrollThreshold), [length, isLooping, overScrollThreshold]);
|
|
23
|
+
const currentIndex = util.getCorrectedPosition(LoopingArrayCalculator.withoutOffset(currentPosition));
|
|
24
|
+
animationTime = Math.max(200, animationTime); // in ms, must be > 0
|
|
25
|
+
autoLoopAnimationTime = Math.max(200, autoLoopAnimationTime);
|
|
26
|
+
const getStyleOffset = (index) => {
|
|
27
|
+
const baseOffset = -50 + (index - currentPosition) * 100;
|
|
28
|
+
return `${baseOffset}%`;
|
|
29
|
+
};
|
|
30
|
+
const animation = useCallback((time) => {
|
|
31
|
+
let keepAnimating = true;
|
|
32
|
+
// Other calculation in the setState call to avoid updating the useCallback to often
|
|
33
|
+
setCarouselInformation((state) => {
|
|
34
|
+
const { animationState, dragState } = state;
|
|
35
|
+
if (animationState === undefined || dragState !== undefined) {
|
|
36
|
+
keepAnimating = false;
|
|
37
|
+
return state;
|
|
38
|
+
}
|
|
39
|
+
if (!animationState.startTime || !animationState.lastUpdateTime) {
|
|
40
|
+
return {
|
|
41
|
+
...state,
|
|
42
|
+
animationState: {
|
|
43
|
+
...animationState,
|
|
44
|
+
startTime: time,
|
|
45
|
+
lastUpdateTime: time
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
const useAnimationTime = animationState.isAutoLooping ? autoLoopAnimationTime : animationTime;
|
|
50
|
+
const progress = clamp((time - animationState.startTime) / useAnimationTime); // progress
|
|
51
|
+
const easedProgress = EaseFunctions.easeInEaseOut(progress);
|
|
52
|
+
const distance = util.getDistanceDirectional(animationState.startPosition, animationState.targetPosition, animationState.direction);
|
|
53
|
+
const newPosition = util.getCorrectedPosition(easedProgress * distance * animationState.direction + animationState.startPosition);
|
|
54
|
+
if (animationState.targetPosition === newPosition || progress === 1) {
|
|
55
|
+
keepAnimating = false;
|
|
56
|
+
return ({
|
|
57
|
+
currentPosition: LoopingArrayCalculator.withoutOffset(newPosition),
|
|
58
|
+
animationState: undefined
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
return ({
|
|
62
|
+
currentPosition: newPosition,
|
|
63
|
+
animationState: {
|
|
64
|
+
...animationState,
|
|
65
|
+
lastUpdateTime: time
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
if (keepAnimating) {
|
|
70
|
+
animationId.current = requestAnimationFrame(time1 => animation(time1));
|
|
71
|
+
}
|
|
72
|
+
}, [animationTime, autoLoopAnimationTime, util]);
|
|
73
|
+
useEffect(() => {
|
|
74
|
+
if (animationState) {
|
|
75
|
+
animationId.current = requestAnimationFrame(animation);
|
|
76
|
+
}
|
|
77
|
+
return () => {
|
|
78
|
+
if (animationId.current) {
|
|
79
|
+
cancelAnimationFrame(animationId.current);
|
|
80
|
+
animationId.current = 0;
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
}, [animationState]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
84
|
+
const startAutoLoop = () => setCarouselInformation(prevState => ({
|
|
85
|
+
...prevState,
|
|
86
|
+
dragState: prevState.dragState,
|
|
87
|
+
animationState: prevState.animationState || prevState.dragState ? prevState.animationState : {
|
|
88
|
+
startPosition: currentPosition,
|
|
89
|
+
targetPosition: (currentPosition + 1) % length,
|
|
90
|
+
direction: 1, // always move forward
|
|
91
|
+
isAutoLooping: true
|
|
92
|
+
}
|
|
93
|
+
}));
|
|
94
|
+
useEffect(() => {
|
|
95
|
+
if (!animationId.current && !animationState && !dragState && !timeOut.current) {
|
|
96
|
+
if (autoLoopingTimeOut > 0) {
|
|
97
|
+
timeOut.current = setTimeout(() => {
|
|
98
|
+
startAutoLoop();
|
|
99
|
+
timeOut.current = undefined;
|
|
100
|
+
}, autoLoopingTimeOut);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
startAutoLoop();
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}, [animationState, dragState, animationId.current, timeOut.current]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
107
|
+
const startAnimation = (targetPosition) => {
|
|
108
|
+
if (targetPosition === undefined) {
|
|
109
|
+
targetPosition = LoopingArrayCalculator.withoutOffset(currentPosition);
|
|
110
|
+
}
|
|
111
|
+
if (targetPosition === currentPosition) {
|
|
112
|
+
return; // we are exactly where we want to be
|
|
113
|
+
}
|
|
114
|
+
// find target index and fastest path to it
|
|
115
|
+
const direction = util.getBestDirection(currentPosition, targetPosition);
|
|
116
|
+
clearTimeout(timeOut.current);
|
|
117
|
+
timeOut.current = undefined;
|
|
118
|
+
if (animationId.current) {
|
|
119
|
+
cancelAnimationFrame(animationId.current);
|
|
120
|
+
animationId.current = undefined;
|
|
121
|
+
}
|
|
122
|
+
setCarouselInformation(prevState => ({
|
|
123
|
+
...prevState,
|
|
124
|
+
dragState: undefined,
|
|
125
|
+
animationState: {
|
|
126
|
+
targetPosition: targetPosition,
|
|
127
|
+
direction,
|
|
128
|
+
startPosition: currentPosition,
|
|
129
|
+
isAutoLooping: false
|
|
130
|
+
},
|
|
131
|
+
timeOut: undefined
|
|
132
|
+
}));
|
|
133
|
+
};
|
|
134
|
+
const canGoLeft = () => {
|
|
135
|
+
return isLooping || currentPosition !== 0;
|
|
136
|
+
};
|
|
137
|
+
const canGoRight = () => {
|
|
138
|
+
return isLooping || currentPosition !== length - 1;
|
|
139
|
+
};
|
|
140
|
+
const left = () => {
|
|
141
|
+
if (canGoLeft()) {
|
|
142
|
+
startAnimation(currentPosition === 0 ? length - 1 : LoopingArrayCalculator.withoutOffset(currentPosition - 1));
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
const right = () => {
|
|
146
|
+
if (canGoRight()) {
|
|
147
|
+
startAnimation(LoopingArrayCalculator.withoutOffset((currentPosition + 1) % length));
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
let items = children.map((item, index) => ({
|
|
151
|
+
index,
|
|
152
|
+
item
|
|
153
|
+
}));
|
|
154
|
+
if (isLooping) {
|
|
155
|
+
const before = createLoopingListWithIndex(children, length - 1, paddingItemCount, false).reverse().map(([index, item]) => ({
|
|
156
|
+
index,
|
|
157
|
+
item
|
|
158
|
+
}));
|
|
159
|
+
const after = createLoopingListWithIndex(children, 0, paddingItemCount).map(([index, item]) => ({
|
|
160
|
+
index,
|
|
161
|
+
item
|
|
162
|
+
}));
|
|
163
|
+
items = [
|
|
164
|
+
...before,
|
|
165
|
+
...items,
|
|
166
|
+
...after
|
|
167
|
+
];
|
|
168
|
+
}
|
|
169
|
+
const onDragStart = (x) => setCarouselInformation(prevState => ({
|
|
170
|
+
...prevState,
|
|
171
|
+
dragState: {
|
|
172
|
+
lastX: x,
|
|
173
|
+
startX: x,
|
|
174
|
+
startTime: Date.now(),
|
|
175
|
+
startIndex: currentPosition,
|
|
176
|
+
},
|
|
177
|
+
animationState: undefined // cancel animation
|
|
178
|
+
}));
|
|
179
|
+
const onDrag = (x, width) => {
|
|
180
|
+
// For some weird reason the clientX is 0 on the last dragUpdate before drag end causing issues
|
|
181
|
+
if (!dragState || x === 0) {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
const offsetUpdate = (dragState.lastX - x) / width;
|
|
185
|
+
const newPosition = util.getCorrectedPosition(currentPosition + offsetUpdate);
|
|
186
|
+
setCarouselInformation(prevState => ({
|
|
187
|
+
...prevState,
|
|
188
|
+
currentPosition: newPosition,
|
|
189
|
+
dragState: {
|
|
190
|
+
...dragState,
|
|
191
|
+
lastX: x
|
|
192
|
+
},
|
|
193
|
+
}));
|
|
194
|
+
};
|
|
195
|
+
const onDragEnd = (x, width) => {
|
|
196
|
+
if (!dragState) {
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
const distance = dragState.startX - x;
|
|
200
|
+
const relativeDistance = distance / width;
|
|
201
|
+
const duration = (Date.now() - dragState.startTime); // in milliseconds
|
|
202
|
+
const velocity = distance / (Date.now() - dragState.startTime);
|
|
203
|
+
const isSlide = Math.abs(velocity) > 2 || (duration < 200 && (Math.abs(relativeDistance) > 0.2 || Math.abs(distance) > 50));
|
|
204
|
+
if (isSlide) {
|
|
205
|
+
if (distance > 0 && canGoRight()) {
|
|
206
|
+
right();
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
else if (distance < 0 && canGoLeft()) {
|
|
210
|
+
left();
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
startAnimation();
|
|
215
|
+
};
|
|
216
|
+
const dragHandlers = {
|
|
217
|
+
draggable: true,
|
|
218
|
+
onDragStart: (event) => {
|
|
219
|
+
onDragStart(event.clientX);
|
|
220
|
+
event.dataTransfer.setDragImage(document.createElement('div'), 0, 0);
|
|
221
|
+
},
|
|
222
|
+
onDrag: (event) => onDrag(event.clientX, event.target.getBoundingClientRect().width),
|
|
223
|
+
onDragEnd: (event) => onDragEnd(event.clientX, event.target.getBoundingClientRect().width),
|
|
224
|
+
onTouchStart: (event) => onDragStart(event.touches[0].clientX),
|
|
225
|
+
onTouchMove: (event) => onDrag(event.touches[0].clientX, event.target.getBoundingClientRect().width),
|
|
226
|
+
onTouchEnd: (event) => onDragEnd(event.changedTouches[0].clientX, event.target.getBoundingClientRect().width),
|
|
227
|
+
onTouchCancel: (event) => onDragEnd(event.changedTouches[0].clientX, event.target.getBoundingClientRect().width),
|
|
228
|
+
};
|
|
229
|
+
return (_jsxs("div", { className: "col items-center w-full gap-y-2", children: [_jsxs("div", { className: clsx(`relative w-full overflow-hidden`, heightClassName, className), children: [arrows && (_jsxs(_Fragment, { children: [_jsx("div", { className: clsx('absolute z-10 left-0 top-1/2 -translate-y-1/2 bg-gray-200 hover:bg-gray-300 rounded-lg cursor-pointer border-black border-2', { hidden: !canGoLeft() }), onClick: () => left(), children: _jsx(ChevronLeft, { size: 32 }) }), _jsx("div", { className: clsx('absolute z-10 right-0 top-1/2 -translate-y-1/2 bg-gray-200 hover:bg-gray-300 rounded-lg cursor-pointer border-black border-2', { hidden: !canGoRight() }), onClick: () => right(), children: _jsx(ChevronRight, { size: 32 }) })] })), hintNext ? (_jsxs("div", { className: clsx(`relative row h-full`, heightClassName), children: [_jsx("div", { className: "relative row h-full w-full px-2 overflow-hidden", children: items.map(({ item, index }, listIndex) => (_jsx("div", { className: clsx(`absolute left-[50%] h-full overflow-hidden`, widthClassName, { '!cursor-grabbing': !!dragState }), style: { translate: getStyleOffset(listIndex - (isLooping ? paddingItemCount : 0)) }, ...dragHandlers, onClick: () => startAnimation(index), children: item }, listIndex))) }), _jsx("div", { className: clsx(`hidden pointer-events-none desktop:block absolute left-0 h-full w-[20%] bg-gradient-to-r to-transparent`, blurColor) }), _jsx("div", { className: clsx(`hidden pointer-events-none desktop:block absolute right-0 h-full w-[20%] bg-gradient-to-l to-transparent`, blurColor) })] })) : (_jsx("div", { className: clsx('px-16 h-full', { '!cursor-grabbing': !!dragState }), ...dragHandlers, children: children[currentIndex] }))] }), dots && (_jsx("div", { className: "row items-center justify-center w-full my-2", children: range(0, length - 1).map(index => (_jsx("button", { className: clsx('w-[2rem] min-w-[2rem] h-[0.75rem] min-h-[0.75rem] hover:bg-primary hover:brightness-90 first:rounded-l-md last:rounded-r-md', {
|
|
230
|
+
'bg-gray-200': currentIndex !== index,
|
|
231
|
+
'bg-primary': currentIndex === index
|
|
232
|
+
}), onClick: () => startAnimation(index) }, index))) }))] }));
|
|
233
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
export type DividerInserterProps = Omit<HTMLAttributes<HTMLDivElement>, 'children'> & {
|
|
3
|
+
children: ReactNode[];
|
|
4
|
+
divider: (index: number) => ReactNode;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* A Component for inserting a divider in the middle of each child element
|
|
8
|
+
*
|
|
9
|
+
* undefined elements are removed
|
|
10
|
+
*/
|
|
11
|
+
export declare const DividerInserter: ({ children, divider, className, ...restProps }: DividerInserterProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
/**
|
|
4
|
+
* A Component for inserting a divider in the middle of each child element
|
|
5
|
+
*
|
|
6
|
+
* undefined elements are removed
|
|
7
|
+
*/
|
|
8
|
+
export const DividerInserter = ({ children, divider, className, ...restProps }) => {
|
|
9
|
+
const nodes = [];
|
|
10
|
+
for (let index = 0; index < children.length; index++) {
|
|
11
|
+
const element = children[index];
|
|
12
|
+
if (element !== undefined) {
|
|
13
|
+
nodes.push(element);
|
|
14
|
+
if (index < children.length - 1) {
|
|
15
|
+
nodes.push(divider(index));
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return (_jsx("div", { className: clsx(className), ...restProps, children: nodes }));
|
|
20
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import type { ExpandableProps } from '../Expandable';
|
|
3
|
+
type ContentType = {
|
|
4
|
+
type: 'markdown';
|
|
5
|
+
value: string;
|
|
6
|
+
} | {
|
|
7
|
+
type: 'custom';
|
|
8
|
+
value: ReactNode;
|
|
9
|
+
};
|
|
10
|
+
export type FAQItem = Pick<ExpandableProps, 'initialExpansion' | 'className'> & {
|
|
11
|
+
id: string;
|
|
12
|
+
title: string;
|
|
13
|
+
content: ContentType;
|
|
14
|
+
};
|
|
15
|
+
export type FAQSectionProps = {
|
|
16
|
+
entries: FAQItem[];
|
|
17
|
+
expandableClassName?: string;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Description
|
|
21
|
+
*/
|
|
22
|
+
export declare const FAQSection: ({ entries, expandableClassName }: FAQSectionProps) => import("react/jsx-runtime").JSX.Element;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
import { ChevronDown, ChevronUp } from 'lucide-react';
|
|
4
|
+
import { Expandable } from '../Expandable';
|
|
5
|
+
import { MarkdownInterpreter } from '../MarkdownInterpreter';
|
|
6
|
+
/**
|
|
7
|
+
* Description
|
|
8
|
+
*/
|
|
9
|
+
export const FAQSection = ({ entries, expandableClassName }) => {
|
|
10
|
+
const chevronSize = 28;
|
|
11
|
+
return (_jsx("div", { className: "col gap-y-4", children: entries.map(({ id, title, content, ...restProps }) => (_jsx(Expandable, { ...restProps, label: (_jsx("h3", { id: id, className: "textstyle-title-md", children: title })), clickOnlyOnHeader: false, icon: (expanded) => expanded ?
|
|
12
|
+
(_jsx(ChevronUp, { size: chevronSize, className: "text-primary", style: { minWidth: `${chevronSize}px` } })) :
|
|
13
|
+
(_jsx(ChevronDown, { size: chevronSize, className: "text-primary" })), className: clsx('rounded-xl', expandableClassName), headerClassName: "px-6 py-4", children: _jsx("div", { className: "mt-2 px-6 pb-4", children: content.type === 'markdown' ? (_jsx(MarkdownInterpreter, { text: content.value })) : content.value }) }, id))) }));
|
|
14
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
export type TileProps = {
|
|
3
|
+
title: {
|
|
4
|
+
value: string;
|
|
5
|
+
className?: string;
|
|
6
|
+
};
|
|
7
|
+
description?: {
|
|
8
|
+
value: string;
|
|
9
|
+
className?: string;
|
|
10
|
+
};
|
|
11
|
+
prefix?: ReactNode;
|
|
12
|
+
suffix?: ReactNode;
|
|
13
|
+
className?: string;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* A component for creating a tile similar to the flutter ListTile
|
|
17
|
+
*/
|
|
18
|
+
export declare const Tile: ({ title, description, prefix, suffix, className }: TileProps) => import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
type ImageLocation = 'prefix' | 'suffix';
|
|
20
|
+
type ImageSize = {
|
|
21
|
+
width: number;
|
|
22
|
+
height: number;
|
|
23
|
+
};
|
|
24
|
+
export type TileWithImageProps = Omit<TileProps, 'suffix' | 'prefix'> & {
|
|
25
|
+
url: string;
|
|
26
|
+
imageLocation?: ImageLocation;
|
|
27
|
+
imageSize?: ImageSize;
|
|
28
|
+
imageClassName?: string;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* A Tile with an image as prefix or suffix
|
|
32
|
+
*/
|
|
33
|
+
export declare const TileWithImage: ({ url, imageLocation, imageSize, imageClassName, ...tileProps }: TileWithImageProps) => import("react/jsx-runtime").JSX.Element;
|
|
34
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import Image from 'next/image';
|
|
3
|
+
import clsx from 'clsx';
|
|
4
|
+
/**
|
|
5
|
+
* A component for creating a tile similar to the flutter ListTile
|
|
6
|
+
*/
|
|
7
|
+
export const Tile = ({ title, description, prefix, suffix, className }) => {
|
|
8
|
+
var _a;
|
|
9
|
+
return (_jsxs("div", { className: clsx('row gap-x-4 w-full items-center', className), children: [prefix, _jsxs("div", { className: "col w-full", children: [_jsx("span", { className: clsx(title.className), children: title.value }), !!description &&
|
|
10
|
+
_jsx("span", { className: clsx((_a = description.className) !== null && _a !== void 0 ? _a : 'textstyle-description'), children: description.value })] }), suffix] }));
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* A Tile with an image as prefix or suffix
|
|
14
|
+
*/
|
|
15
|
+
export const TileWithImage = ({ url, imageLocation = 'prefix', imageSize = { width: 24, height: 24 }, imageClassName = '', ...tileProps }) => {
|
|
16
|
+
const image = _jsx(Image, { src: url, alt: "", ...imageSize, className: clsx(imageClassName) });
|
|
17
|
+
return (_jsx(Tile, { ...tileProps, prefix: imageLocation === 'prefix' ? image : undefined, suffix: imageLocation === 'suffix' ? image : undefined }));
|
|
18
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { PropsWithChildren } from 'react';
|
|
2
|
+
import type { SolidButtonColor } from '../Button';
|
|
3
|
+
import type { PropsForTranslation } from '../../hooks/useTranslation';
|
|
4
|
+
import { type ModalProps } from './Modal';
|
|
5
|
+
type ConfirmDialogTranslation = {
|
|
6
|
+
confirm: string;
|
|
7
|
+
cancel: string;
|
|
8
|
+
decline: string;
|
|
9
|
+
};
|
|
10
|
+
export type ConfirmDialogType = 'positive' | 'negative' | 'neutral';
|
|
11
|
+
export type ButtonOverwriteType = {
|
|
12
|
+
text?: string;
|
|
13
|
+
color?: SolidButtonColor;
|
|
14
|
+
disabled?: boolean;
|
|
15
|
+
};
|
|
16
|
+
export type ConfirmDialogProps = ModalProps & {
|
|
17
|
+
isShowingDecline?: boolean;
|
|
18
|
+
requireAnswer?: boolean;
|
|
19
|
+
onCancel?: () => void;
|
|
20
|
+
onConfirm: () => void;
|
|
21
|
+
onDecline?: () => void;
|
|
22
|
+
confirmType?: ConfirmDialogType;
|
|
23
|
+
/**
|
|
24
|
+
* Order: Cancel, Decline, Confirm
|
|
25
|
+
*/
|
|
26
|
+
buttonOverwrites?: [ButtonOverwriteType, ButtonOverwriteType, ButtonOverwriteType];
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* A Dialog for asking the user for Confirmation
|
|
30
|
+
*
|
|
31
|
+
* To require an answer omit the onBackgroundClick
|
|
32
|
+
*/
|
|
33
|
+
export declare const ConfirmDialog: ({ overwriteTranslation, children, onCancel, onConfirm, onDecline, confirmType, buttonOverwrites, ...restProps }: PropsForTranslation<ConfirmDialogTranslation, PropsWithChildren<ConfirmDialogProps>>) => import("react/jsx-runtime").JSX.Element;
|
|
34
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { SolidButton } from '../Button';
|
|
3
|
+
import { useTranslation } from '../../hooks/useTranslation';
|
|
4
|
+
import { Modal } from './Modal';
|
|
5
|
+
const defaultConfirmDialogTranslation = {
|
|
6
|
+
en: {
|
|
7
|
+
confirm: 'Confirm',
|
|
8
|
+
cancel: 'Cancel',
|
|
9
|
+
decline: 'Decline'
|
|
10
|
+
},
|
|
11
|
+
de: {
|
|
12
|
+
confirm: 'Bestätigen',
|
|
13
|
+
cancel: 'Abbrechen',
|
|
14
|
+
decline: 'Ablehnen'
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* A Dialog for asking the user for Confirmation
|
|
19
|
+
*
|
|
20
|
+
* To require an answer omit the onBackgroundClick
|
|
21
|
+
*/
|
|
22
|
+
export const ConfirmDialog = ({ overwriteTranslation, children, onCancel, onConfirm, onDecline, confirmType = 'positive', buttonOverwrites, ...restProps }) => {
|
|
23
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
24
|
+
const translation = useTranslation(defaultConfirmDialogTranslation, overwriteTranslation);
|
|
25
|
+
const mapping = {
|
|
26
|
+
neutral: 'primary',
|
|
27
|
+
negative: 'negative',
|
|
28
|
+
positive: 'positive'
|
|
29
|
+
};
|
|
30
|
+
return (_jsxs(Modal, { ...restProps, children: [children, _jsxs("div", { className: "row mt-3 gap-x-4 justify-end", children: [onCancel && (_jsx(SolidButton, { color: (_a = buttonOverwrites === null || buttonOverwrites === void 0 ? void 0 : buttonOverwrites[0].color) !== null && _a !== void 0 ? _a : 'primary', onClick: onCancel, disabled: (_b = buttonOverwrites === null || buttonOverwrites === void 0 ? void 0 : buttonOverwrites[0].disabled) !== null && _b !== void 0 ? _b : false, children: (_c = buttonOverwrites === null || buttonOverwrites === void 0 ? void 0 : buttonOverwrites[0].text) !== null && _c !== void 0 ? _c : translation.cancel })), onDecline && (_jsx(SolidButton, { color: (_d = buttonOverwrites === null || buttonOverwrites === void 0 ? void 0 : buttonOverwrites[1].color) !== null && _d !== void 0 ? _d : 'negative', onClick: onDecline, disabled: (_e = buttonOverwrites === null || buttonOverwrites === void 0 ? void 0 : buttonOverwrites[1].disabled) !== null && _e !== void 0 ? _e : false, children: (_f = buttonOverwrites === null || buttonOverwrites === void 0 ? void 0 : buttonOverwrites[1].text) !== null && _f !== void 0 ? _f : translation.decline })), _jsx(SolidButton, { autoFocus: true, color: (_g = buttonOverwrites === null || buttonOverwrites === void 0 ? void 0 : buttonOverwrites[2].color) !== null && _g !== void 0 ? _g : mapping[confirmType], onClick: onConfirm, disabled: (_h = buttonOverwrites === null || buttonOverwrites === void 0 ? void 0 : buttonOverwrites[2].disabled) !== null && _h !== void 0 ? _h : false, children: (_j = buttonOverwrites === null || buttonOverwrites === void 0 ? void 0 : buttonOverwrites[2].text) !== null && _j !== void 0 ? _j : translation.confirm })] })] }));
|
|
31
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { PropsWithChildren } from 'react';
|
|
2
|
+
import type { PropsForTranslation } from '../../hooks/useTranslation';
|
|
3
|
+
import { type ModalProps } from './Modal';
|
|
4
|
+
type DiscardChangesDialogTranslation = {
|
|
5
|
+
save: string;
|
|
6
|
+
cancel: string;
|
|
7
|
+
dontSave: string;
|
|
8
|
+
title: string;
|
|
9
|
+
description: string;
|
|
10
|
+
};
|
|
11
|
+
type DiscardChangesDialogProps = ModalProps & {
|
|
12
|
+
isShowingDecline?: boolean;
|
|
13
|
+
requireAnswer?: boolean;
|
|
14
|
+
onCancel: () => void;
|
|
15
|
+
onSave: () => void;
|
|
16
|
+
onDontSave: () => void;
|
|
17
|
+
};
|
|
18
|
+
export declare const DiscardChangesDialog: ({ overwriteTranslation, children, title, description, onCancel, onSave, onDontSave, ...modalProps }: PropsForTranslation<DiscardChangesDialogTranslation, PropsWithChildren<DiscardChangesDialogProps>>) => import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { SolidButton } from '../Button';
|
|
3
|
+
import { useTranslation } from '../../hooks/useTranslation';
|
|
4
|
+
import { Modal } from './Modal';
|
|
5
|
+
const defaultDiscardChangesDialogTranslation = {
|
|
6
|
+
en: {
|
|
7
|
+
save: 'Save',
|
|
8
|
+
cancel: 'Cancel',
|
|
9
|
+
dontSave: 'Don\'t save',
|
|
10
|
+
title: 'Unsaved Changes',
|
|
11
|
+
description: 'Do you want to save your changes?'
|
|
12
|
+
},
|
|
13
|
+
de: {
|
|
14
|
+
save: 'Speichern',
|
|
15
|
+
cancel: 'Abbrechen',
|
|
16
|
+
dontSave: 'Nicht Speichern',
|
|
17
|
+
title: 'Ungespeicherte Änderungen',
|
|
18
|
+
description: 'Möchtest du die Änderungen speichern?'
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
export const DiscardChangesDialog = ({ overwriteTranslation, children, title, description, onCancel, onSave, onDontSave, ...modalProps }) => {
|
|
22
|
+
const translation = useTranslation(defaultDiscardChangesDialogTranslation, overwriteTranslation);
|
|
23
|
+
return (_jsxs(Modal, { title: title !== null && title !== void 0 ? title : translation.title, description: description !== null && description !== void 0 ? description : translation.description, ...modalProps, children: [children, _jsxs("div", { className: "row mt-3 gap-x-4 justify-end", children: [_jsx(SolidButton, { color: "positive", onClick: onSave, children: translation.save }), _jsx(SolidButton, { color: "negative", onClick: onDontSave, children: translation.dontSave }), _jsx(SolidButton, { autoFocus: true, color: "primary", onClick: onCancel, children: translation.cancel })] })] }));
|
|
24
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { InputProps } from '../user-input/Input';
|
|
2
|
+
import type { ConfirmDialogProps } from './ConfirmDialog';
|
|
3
|
+
export type InputModalProps = ConfirmDialogProps & {
|
|
4
|
+
inputs: InputProps[];
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* A modal for receiving multiple inputs
|
|
8
|
+
*/
|
|
9
|
+
export declare const InputModal: ({ inputs, buttonOverwrites, ...restProps }: InputModalProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Input } from '../user-input/Input';
|
|
3
|
+
import { ConfirmDialog } from './ConfirmDialog';
|
|
4
|
+
/**
|
|
5
|
+
* A modal for receiving multiple inputs
|
|
6
|
+
*/
|
|
7
|
+
export const InputModal = ({ inputs, buttonOverwrites, ...restProps }) => {
|
|
8
|
+
return (_jsx(ConfirmDialog, { buttonOverwrites: buttonOverwrites, ...restProps, children: inputs.map((inputProps, index) => _jsx(Input, { ...inputProps }, `input ${index}`)) }));
|
|
9
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type PropsWithChildren } from 'react';
|
|
2
|
+
import type { PropsForTranslation } from '../../hooks/useTranslation';
|
|
3
|
+
import { type ModalProps } from './Modal';
|
|
4
|
+
type LanguageModalTranslation = {
|
|
5
|
+
message: string;
|
|
6
|
+
done: string;
|
|
7
|
+
};
|
|
8
|
+
type LanguageModalProps = ModalProps & {
|
|
9
|
+
onDone: () => void;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* A Modal for selecting the Language
|
|
13
|
+
*
|
|
14
|
+
* The State of open needs to be managed by the parent
|
|
15
|
+
*/
|
|
16
|
+
export declare const LanguageModal: ({ overwriteTranslation, onDone, onBackgroundClick, ...modalProps }: PropsForTranslation<LanguageModalTranslation, PropsWithChildren<LanguageModalProps>>) => import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useTranslation } from '../../hooks/useTranslation';
|
|
3
|
+
import { Select } from '../user-input/Select';
|
|
4
|
+
import { useLanguage } from '../../hooks/useLanguage';
|
|
5
|
+
import { SolidButton } from '../Button';
|
|
6
|
+
import { Modal } from './Modal';
|
|
7
|
+
const languageDetails = {
|
|
8
|
+
en: 'English',
|
|
9
|
+
de: 'Deutsch'
|
|
10
|
+
};
|
|
11
|
+
const defaultConfirmDialogTranslation = {
|
|
12
|
+
en: {
|
|
13
|
+
message: 'Choose your language',
|
|
14
|
+
done: 'Done',
|
|
15
|
+
},
|
|
16
|
+
de: {
|
|
17
|
+
message: 'Wählen Sie Ihre Sprache',
|
|
18
|
+
done: 'Fertig',
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* A Modal for selecting the Language
|
|
23
|
+
*
|
|
24
|
+
* The State of open needs to be managed by the parent
|
|
25
|
+
*/
|
|
26
|
+
export const LanguageModal = ({ overwriteTranslation, onDone, onBackgroundClick, ...modalProps }) => {
|
|
27
|
+
const { language, setLanguage } = useLanguage();
|
|
28
|
+
const translation = useTranslation(defaultConfirmDialogTranslation, overwriteTranslation);
|
|
29
|
+
return (_jsx(Modal, { titleText: translation.message, onBackgroundClick: (eventData) => {
|
|
30
|
+
onDone();
|
|
31
|
+
if (onBackgroundClick) {
|
|
32
|
+
onBackgroundClick(eventData);
|
|
33
|
+
}
|
|
34
|
+
}, ...modalProps, children: _jsxs("div", { className: "w-[320px]", children: [_jsx(Select, { className: "mt-2", value: language, options: Object.entries(languageDetails).map(([tag, name]) => ({ label: name, value: tag })), onChange: (language) => setLanguage(language) }), _jsx("div", { className: "row mt-3 gap-x-4 justify-end", children: _jsx(SolidButton, { autoFocus: true, color: "positive", onClick: onDone, children: translation.done }) })] }) }));
|
|
35
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type MouseEventHandler, type PropsWithChildren, type ReactNode } from 'react';
|
|
2
|
+
import type { PropsForTranslation } from '../../hooks/useTranslation';
|
|
3
|
+
type ModalHeaderTranslation = {
|
|
4
|
+
close: string;
|
|
5
|
+
};
|
|
6
|
+
export type ModalHeaderProps = {
|
|
7
|
+
onCloseClick?: () => void;
|
|
8
|
+
/** The title of the Modal. If you want to only set the text use `titleText` instead */
|
|
9
|
+
title?: ReactNode;
|
|
10
|
+
/** The title text of the Modal. If you want to set a custom title use `title` instead */
|
|
11
|
+
titleText?: string;
|
|
12
|
+
/** The description of the Modal. If you want to only set the text use `descriptionText` instead */
|
|
13
|
+
description?: ReactNode;
|
|
14
|
+
/** The description text of the Modal. If you want to set a custom description use `description` instead */
|
|
15
|
+
descriptionText?: string;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* A default Header to be used by modals to have a uniform design
|
|
19
|
+
*/
|
|
20
|
+
export declare const ModalHeader: ({ overwriteTranslation, onCloseClick, title, titleText, description, descriptionText }: PropsForTranslation<ModalHeaderTranslation, ModalHeaderProps>) => import("react/jsx-runtime").JSX.Element;
|
|
21
|
+
export declare const modalRootName = "modal-root";
|
|
22
|
+
export type ModalProps = {
|
|
23
|
+
id: string;
|
|
24
|
+
isOpen: boolean;
|
|
25
|
+
onBackgroundClick?: MouseEventHandler<HTMLDivElement>;
|
|
26
|
+
backgroundClassName?: string;
|
|
27
|
+
modalClassName?: string;
|
|
28
|
+
containerClassName?: string;
|
|
29
|
+
} & ModalHeaderProps;
|
|
30
|
+
/**
|
|
31
|
+
* A Generic Modal Window
|
|
32
|
+
*
|
|
33
|
+
* The state needs to be managed by the parent of this component
|
|
34
|
+
*
|
|
35
|
+
* DO NOT Conditionally render this always use the isOpen to ensure that the ModalRegister is working properly
|
|
36
|
+
*/
|
|
37
|
+
export declare const Modal: ({ children, id, isOpen, onBackgroundClick, backgroundClassName, modalClassName, containerClassName, ...modalHeaderProps }: PropsWithChildren<ModalProps>) => import("react").ReactPortal | null;
|
|
38
|
+
export {};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useContext, useEffect } from 'react';
|
|
3
|
+
import ReactDOM from 'react-dom';
|
|
4
|
+
import { X } from 'lucide-react';
|
|
5
|
+
import clsx from 'clsx';
|
|
6
|
+
import { useTranslation } from '../../hooks/useTranslation';
|
|
7
|
+
import { Tooltip } from '../Tooltip';
|
|
8
|
+
import { ModalContext } from './ModalRegister';
|
|
9
|
+
const defaultModalHeaderTranslation = {
|
|
10
|
+
en: {
|
|
11
|
+
close: 'Close'
|
|
12
|
+
},
|
|
13
|
+
de: {
|
|
14
|
+
close: 'Schließen'
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* A default Header to be used by modals to have a uniform design
|
|
19
|
+
*/
|
|
20
|
+
export const ModalHeader = ({ overwriteTranslation, onCloseClick, title, titleText = '', description, descriptionText = '' }) => {
|
|
21
|
+
const translation = useTranslation(defaultModalHeaderTranslation, overwriteTranslation);
|
|
22
|
+
return (_jsxs("div", { className: "col", children: [_jsxs("div", { className: "row justify-between items-start gap-x-8", children: [title !== null && title !== void 0 ? title : (_jsx("span", { className: clsx('textstyle-title-lg', {
|
|
23
|
+
'mb-1': description || descriptionText,
|
|
24
|
+
}), children: titleText })), !!onCloseClick && (_jsx(Tooltip, { tooltip: translation.close, children: _jsx("button", { className: "row bg-gray-200 hover:bg-gray-300 rounded-md p-1", onClick: onCloseClick, children: _jsx(X, {}) }) }))] }), description !== null && description !== void 0 ? description : (_jsx("span", { className: "textstyle-description", children: descriptionText }))] }));
|
|
25
|
+
};
|
|
26
|
+
export const modalRootName = 'modal-root';
|
|
27
|
+
/**
|
|
28
|
+
* A Generic Modal Window
|
|
29
|
+
*
|
|
30
|
+
* The state needs to be managed by the parent of this component
|
|
31
|
+
*
|
|
32
|
+
* DO NOT Conditionally render this always use the isOpen to ensure that the ModalRegister is working properly
|
|
33
|
+
*/
|
|
34
|
+
export const Modal = ({ children, id, isOpen, onBackgroundClick, backgroundClassName = '', modalClassName = '', containerClassName = '', ...modalHeaderProps }) => {
|
|
35
|
+
const modalRoot = typeof window !== 'undefined' ? document.getElementById(modalRootName) : null;
|
|
36
|
+
const { register, addToRegister, removeFromRegister } = useContext(ModalContext);
|
|
37
|
+
if (!id) {
|
|
38
|
+
console.error('the id cannot be empty');
|
|
39
|
+
}
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
if (isOpen) {
|
|
42
|
+
addToRegister(id);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
removeFromRegister(id);
|
|
46
|
+
}
|
|
47
|
+
}, [addToRegister, id, removeFromRegister, isOpen]);
|
|
48
|
+
if (modalRoot === null || !isOpen)
|
|
49
|
+
return null;
|
|
50
|
+
const isLast = register.length < 1 || register[register.length - 1] === id;
|
|
51
|
+
const isSecondLast = register.length < 2 || register[register.length - 2] === id;
|
|
52
|
+
return ReactDOM.createPortal(_jsxs("div", { className: clsx('fixed inset-0 overflow-y-auto z-[99]', containerClassName), id: id, children: [isLast && (_jsx("div", { className: clsx('fixed inset-0 h-screen w-screen', backgroundClassName, {
|
|
53
|
+
'bg-black/70': isLast && register.length === 1,
|
|
54
|
+
}), onClick: onBackgroundClick })), _jsxs("div", { className: clsx('fixed left-1/2 top-1/2 -translate-y-1/2 -translate-x-1/2 col p-4 bg-white text-black rounded-xl shadow-xl', modalClassName), children: [_jsx(ModalHeader, { ...modalHeaderProps }), children] }), !isLast && (_jsx("div", { className: clsx('fixed inset-0 h-screen w-screen', backgroundClassName, {
|
|
55
|
+
'bg-black/70': isSecondLast && register.length > 1,
|
|
56
|
+
}) }))] }), modalRoot, id);
|
|
57
|
+
};
|