@mailstep/design-system 0.10.7 → 0.11.0
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/package.json +1 -1
- package/ui/Blocks/Tabs/hooks/useTabs.d.ts +1 -1
- package/ui/Blocks/Tabs/hooks/useTabs.js +16 -4
- package/ui/Blocks/Tabs/index.d.ts +1 -1
- package/ui/Blocks/Tabs/types.d.ts +5 -1
- package/ui/Blocks/Tabs/utils/constants.d.ts +1 -0
- package/ui/Blocks/Tabs/utils/constants.js +4 -0
- package/ui/Blocks/Tabs/utils/getDefaultTab.d.ts +4 -0
- package/ui/Blocks/Tabs/utils/getDefaultTab.js +7 -0
- package/ui/Blocks/Tabs/utils/getInitialTab.d.ts +9 -0
- package/ui/Blocks/Tabs/utils/getInitialTab.js +12 -0
- package/ui/Blocks/Tabs/utils/index.d.ts +6 -0
- package/ui/Blocks/Tabs/utils/index.js +7 -0
- package/ui/Blocks/Tabs/utils/isSelectableTab.d.ts +8 -0
- package/ui/Blocks/Tabs/utils/isSelectableTab.js +7 -0
- package/ui/Blocks/Tabs/utils/readTabFromUrl.d.ts +8 -0
- package/ui/Blocks/Tabs/utils/readTabFromUrl.js +16 -0
- package/ui/Blocks/Tabs/utils/writeTabToUrl.d.ts +7 -0
- package/ui/Blocks/Tabs/utils/writeTabToUrl.js +10 -0
- package/ui/Elements/DatePicker/DatePicker.d.ts +1 -1
- package/ui/Elements/DatePicker/DatePicker.js +18 -25
- package/ui/Elements/DatePicker/Datetime/components/{Timepicker.d.ts → Timepicker/Timepicker.d.ts} +2 -2
- package/ui/Elements/DatePicker/Datetime/components/Timepicker/Timepicker.js +181 -0
- package/ui/Elements/DatePicker/Datetime/components/Timepicker/constants.d.ts +5 -0
- package/ui/Elements/DatePicker/Datetime/components/Timepicker/constants.js +8 -0
- package/ui/Elements/DatePicker/Datetime/components/Timepicker/index.d.ts +1 -0
- package/ui/Elements/DatePicker/Datetime/components/Timepicker/index.js +2 -0
- package/ui/Elements/DatePicker/Datetime/components/Timepicker/styles.d.ts +3 -0
- package/ui/Elements/DatePicker/Datetime/components/Timepicker/styles.js +48 -0
- package/ui/Elements/DatePicker/Datetime/components/Timepicker/utils/index.d.ts +3 -0
- package/ui/Elements/DatePicker/Datetime/components/Timepicker/utils/index.js +4 -0
- package/ui/Elements/DatePicker/Datetime/components/Timepicker/utils/padTime.d.ts +3 -0
- package/ui/Elements/DatePicker/Datetime/components/Timepicker/utils/padTime.js +4 -0
- package/ui/Elements/DatePicker/Datetime/components/Timepicker/utils/parseTimeField.d.ts +3 -0
- package/ui/Elements/DatePicker/Datetime/components/Timepicker/utils/parseTimeField.js +8 -0
- package/ui/Elements/DatePicker/Datetime/components/Timepicker/utils/sanitizeTimeField.d.ts +3 -0
- package/ui/Elements/DatePicker/Datetime/components/Timepicker/utils/sanitizeTimeField.js +4 -0
- package/ui/Elements/DatePicker/Datetime/views/DaysView.js +2 -1
- package/ui/Elements/DatePicker/components/DatePickerInput/DatePickerInput.d.ts +15 -0
- package/ui/Elements/DatePicker/components/DatePickerInput/DatePickerInput.js +33 -0
- package/ui/Elements/DatePicker/components/DatePickerInput/index.d.ts +1 -0
- package/ui/Elements/DatePicker/components/DatePickerInput/index.js +2 -0
- package/ui/index.js +1 -1
- package/ui/Elements/DatePicker/Datetime/components/Timepicker.js +0 -168
package/package.json
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { UseTabsHook } from '../types';
|
|
1
|
+
import type { UseTabsHook } from '../types';
|
|
2
2
|
export declare const useTabs: UseTabsHook;
|
|
@@ -1,13 +1,25 @@
|
|
|
1
|
+
import "../utils/constants.js";
|
|
2
|
+
import { getInitialTab } from "../utils/getInitialTab.js";
|
|
3
|
+
import { writeTabToUrl } from "../utils/writeTabToUrl.js";
|
|
1
4
|
import { useCallback, useState } from "react";
|
|
2
5
|
//#region packages/ui/Blocks/Tabs/hooks/useTabs.ts
|
|
3
|
-
const useTabs = (
|
|
4
|
-
const
|
|
5
|
-
const [activeTab, setActiveTab] = useState(
|
|
6
|
+
const useTabs = (tabsDefinition, options = {}) => {
|
|
7
|
+
const { syncWithUrl = false, queryParam = "tab" } = options;
|
|
8
|
+
const [activeTab, setActiveTab] = useState(() => getInitialTab({
|
|
9
|
+
tabsDefinition,
|
|
10
|
+
syncWithUrl,
|
|
11
|
+
queryParam
|
|
12
|
+
}));
|
|
6
13
|
return {
|
|
7
14
|
activeTab,
|
|
8
15
|
onTabSwitch: useCallback((value) => {
|
|
9
16
|
setActiveTab(value);
|
|
10
|
-
|
|
17
|
+
if (!syncWithUrl) return;
|
|
18
|
+
writeTabToUrl({
|
|
19
|
+
value,
|
|
20
|
+
queryParam
|
|
21
|
+
});
|
|
22
|
+
}, [syncWithUrl, queryParam])
|
|
11
23
|
};
|
|
12
24
|
};
|
|
13
25
|
//#endregion
|
|
@@ -21,7 +21,11 @@ export type TabElementProps = {
|
|
|
21
21
|
onTabSwitch: (tab: number) => void;
|
|
22
22
|
minWidth?: string | string[];
|
|
23
23
|
};
|
|
24
|
-
export type
|
|
24
|
+
export type UseTabsOptions = {
|
|
25
|
+
syncWithUrl?: boolean;
|
|
26
|
+
queryParam?: string;
|
|
27
|
+
};
|
|
28
|
+
export type UseTabsHook = (tabsDefinition: TabDefinition[], options?: UseTabsOptions) => {
|
|
25
29
|
activeTab: number;
|
|
26
30
|
onTabSwitch: (tab: number) => void;
|
|
27
31
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const TAB_PARAM = "tab";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { TabDefinition } from '../types';
|
|
2
|
+
type GetInitialTabProps = {
|
|
3
|
+
tabsDefinition: TabDefinition[];
|
|
4
|
+
syncWithUrl: boolean;
|
|
5
|
+
queryParam: string;
|
|
6
|
+
};
|
|
7
|
+
type GetInitialTabType = (props: GetInitialTabProps) => number;
|
|
8
|
+
export declare const getInitialTab: GetInitialTabType;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { getDefaultTab } from "./getDefaultTab.js";
|
|
2
|
+
import { readTabFromUrl } from "./readTabFromUrl.js";
|
|
3
|
+
//#region packages/ui/Blocks/Tabs/utils/getInitialTab.ts
|
|
4
|
+
const getInitialTab = ({ tabsDefinition, syncWithUrl, queryParam }) => {
|
|
5
|
+
if (!syncWithUrl) return getDefaultTab(tabsDefinition);
|
|
6
|
+
return readTabFromUrl({
|
|
7
|
+
tabsDefinition,
|
|
8
|
+
queryParam
|
|
9
|
+
}) ?? getDefaultTab(tabsDefinition);
|
|
10
|
+
};
|
|
11
|
+
//#endregion
|
|
12
|
+
export { getInitialTab };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { TAB_PARAM } from './constants';
|
|
2
|
+
export { getDefaultTab } from './getDefaultTab';
|
|
3
|
+
export { getInitialTab } from './getInitialTab';
|
|
4
|
+
export { isSelectableTab } from './isSelectableTab';
|
|
5
|
+
export { readTabFromUrl } from './readTabFromUrl';
|
|
6
|
+
export { writeTabToUrl } from './writeTabToUrl';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { TAB_PARAM } from "./constants.js";
|
|
2
|
+
import { getDefaultTab } from "./getDefaultTab.js";
|
|
3
|
+
import { isSelectableTab } from "./isSelectableTab.js";
|
|
4
|
+
import { readTabFromUrl } from "./readTabFromUrl.js";
|
|
5
|
+
import { getInitialTab } from "./getInitialTab.js";
|
|
6
|
+
import { writeTabToUrl } from "./writeTabToUrl.js";
|
|
7
|
+
export { TAB_PARAM, getDefaultTab, getInitialTab, isSelectableTab, readTabFromUrl, writeTabToUrl };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { TabDefinition } from '../types';
|
|
2
|
+
type IsSelectableTabProps = {
|
|
3
|
+
tabsDefinition: TabDefinition[];
|
|
4
|
+
value: number;
|
|
5
|
+
};
|
|
6
|
+
type IsSelectableTabType = (props: IsSelectableTabProps) => boolean;
|
|
7
|
+
export declare const isSelectableTab: IsSelectableTabType;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { TabDefinition } from '../types';
|
|
2
|
+
type ReadTabFromUrlProps = {
|
|
3
|
+
tabsDefinition: TabDefinition[];
|
|
4
|
+
queryParam: string;
|
|
5
|
+
};
|
|
6
|
+
type ReadTabFromUrlType = (props: ReadTabFromUrlProps) => number | null;
|
|
7
|
+
export declare const readTabFromUrl: ReadTabFromUrlType;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { isSelectableTab } from "./isSelectableTab.js";
|
|
2
|
+
//#region packages/ui/Blocks/Tabs/utils/readTabFromUrl.ts
|
|
3
|
+
const readTabFromUrl = ({ tabsDefinition, queryParam }) => {
|
|
4
|
+
if (typeof window === "undefined") return null;
|
|
5
|
+
const raw = new URLSearchParams(window.location.search).get(queryParam);
|
|
6
|
+
if (raw === null || raw.trim() === "") return null;
|
|
7
|
+
const value = Number(raw);
|
|
8
|
+
if (!Number.isInteger(value)) return null;
|
|
9
|
+
if (!isSelectableTab({
|
|
10
|
+
tabsDefinition,
|
|
11
|
+
value
|
|
12
|
+
})) return null;
|
|
13
|
+
return value;
|
|
14
|
+
};
|
|
15
|
+
//#endregion
|
|
16
|
+
export { readTabFromUrl };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
//#region packages/ui/Blocks/Tabs/utils/writeTabToUrl.ts
|
|
2
|
+
const writeTabToUrl = ({ value, queryParam }) => {
|
|
3
|
+
if (typeof window === "undefined") return;
|
|
4
|
+
const url = new URL(window.location.href);
|
|
5
|
+
if (url.searchParams.get(queryParam) === String(value)) return;
|
|
6
|
+
url.searchParams.set(queryParam, String(value));
|
|
7
|
+
window.history.replaceState(null, "", `${url.pathname}${url.search}${url.hash}`);
|
|
8
|
+
};
|
|
9
|
+
//#endregion
|
|
10
|
+
export { writeTabToUrl };
|
|
@@ -22,7 +22,7 @@ export type DatePickerType = DatetimepickerProps & {
|
|
|
22
22
|
isSecondDatePicker?: boolean;
|
|
23
23
|
others?: DateTimeOthers;
|
|
24
24
|
onClear?: () => void;
|
|
25
|
-
onInputChange?: () => void;
|
|
25
|
+
onInputChange?: (value: string) => void;
|
|
26
26
|
onChangeOthers?: (others: DateTimeOthers) => void;
|
|
27
27
|
};
|
|
28
28
|
declare const _default: React.NamedExoticComponent<DatePickerType>;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { LanguageContext } from "../../ThemeProvider/ThemeProvider.js";
|
|
2
2
|
import SpaceAround_default from "../SpaceAround/index.js";
|
|
3
|
-
import Input_default from "../../Forms/Input/index.js";
|
|
4
3
|
import Datetime from "./Datetime/DateTime.js";
|
|
4
|
+
import { DatePickerInput } from "./components/DatePickerInput/DatePickerInput.js";
|
|
5
|
+
import "./components/DatePickerInput/index.js";
|
|
5
6
|
import { DatePickerBase } from "./styles.js";
|
|
6
7
|
import React, { useCallback, useContext } from "react";
|
|
7
8
|
import { x } from "@xstyled/styled-components";
|
|
8
9
|
import { jsx } from "react/jsx-runtime";
|
|
9
|
-
import moment from "moment";
|
|
10
10
|
import "moment/dist/locale/cs";
|
|
11
11
|
import "moment/dist/locale/el";
|
|
12
12
|
import "moment/dist/locale/it";
|
|
@@ -15,34 +15,27 @@ import "moment/dist/locale/sk";
|
|
|
15
15
|
//#region packages/ui/Elements/DatePicker/DatePicker.tsx
|
|
16
16
|
const defaultDateFormat = "DD.MM.YYYY";
|
|
17
17
|
const DatePicker = ({ name, value, initialViewDate, error, label, disabled, isValidDate, onChange, dateFormat = defaultDateFormat, timeFormat = false, open, secondValue = null, input, icon = true, showInputLabel = false, showCalendarLabel = true, spaceAround = false, className, onClear, onInputChange, ...passProps }) => {
|
|
18
|
-
const format = `${dateFormat}${timeFormat ? ` ${timeFormat}` : ``}`;
|
|
19
|
-
const isValid = !!value && moment(value, format, true).isValid();
|
|
20
|
-
const stringValue = isValid ? moment(value, format).format(format) : value;
|
|
21
18
|
const locale = useContext(LanguageContext);
|
|
22
|
-
const handleRenderInput = useCallback((
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
icon: icon ? "calendar" : void 0,
|
|
26
|
-
name,
|
|
27
|
-
error,
|
|
28
|
-
disabled,
|
|
29
|
-
isInvalid: !!error,
|
|
30
|
-
onChange: onInputChange,
|
|
31
|
-
label: showInputLabel ? label : void 0,
|
|
32
|
-
value: stringValue,
|
|
33
|
-
onFocus: openCalendar,
|
|
34
|
-
iconOnClick: openCalendar,
|
|
35
|
-
onClear,
|
|
36
|
-
autoComplete: "off"
|
|
37
|
-
});
|
|
38
|
-
}, [
|
|
19
|
+
const handleRenderInput = useCallback((inputProps, openCalendar) => /* @__PURE__ */ jsx(DatePickerInput, {
|
|
20
|
+
inputProps,
|
|
21
|
+
openCalendar,
|
|
39
22
|
name,
|
|
40
|
-
|
|
23
|
+
label,
|
|
41
24
|
error,
|
|
25
|
+
disabled,
|
|
26
|
+
icon,
|
|
27
|
+
showInputLabel,
|
|
28
|
+
onClear,
|
|
29
|
+
onInputChange
|
|
30
|
+
}), [
|
|
31
|
+
name,
|
|
42
32
|
label,
|
|
33
|
+
error,
|
|
34
|
+
disabled,
|
|
35
|
+
icon,
|
|
43
36
|
showInputLabel,
|
|
44
|
-
|
|
45
|
-
|
|
37
|
+
onClear,
|
|
38
|
+
onInputChange
|
|
46
39
|
]);
|
|
47
40
|
const handleRenderView = useCallback((_, renderCalendar) => {
|
|
48
41
|
if (label && !showInputLabel) return /* @__PURE__ */ jsx(x.div, {
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import Icon from "../../../../Icon/Icon.js";
|
|
2
|
+
import { FooterRow } from "../FooterRow.js";
|
|
3
|
+
import { FooterRowLabel } from "../FooterRowLabel.js";
|
|
4
|
+
import "./constants.js";
|
|
5
|
+
import { TimeButton, TimeField, TimeWrapper } from "./styles.js";
|
|
6
|
+
import { padTime } from "./utils/padTime.js";
|
|
7
|
+
import { parseTimeField } from "./utils/parseTimeField.js";
|
|
8
|
+
import { sanitizeTimeField } from "./utils/sanitizeTimeField.js";
|
|
9
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
10
|
+
import { x } from "@xstyled/styled-components";
|
|
11
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
12
|
+
import { i18n } from "@lingui/core";
|
|
13
|
+
//#region packages/ui/Elements/DatePicker/Datetime/components/Timepicker/Timepicker.tsx
|
|
14
|
+
const Timepicker = ({ setTime, value, disabled }) => {
|
|
15
|
+
const hours = value?.getHours?.() ?? 0;
|
|
16
|
+
const minutes = value?.getMinutes?.() ?? 0;
|
|
17
|
+
const [hoursValue, setHoursValue] = useState(padTime(hours));
|
|
18
|
+
const [minutesValue, setMinutesValue] = useState(padTime(minutes));
|
|
19
|
+
const isHoursEdited = useRef(false);
|
|
20
|
+
const isMinutesEdited = useRef(false);
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
if (isHoursEdited.current) return;
|
|
23
|
+
setHoursValue(padTime(hours));
|
|
24
|
+
}, [hours]);
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
if (isMinutesEdited.current) return;
|
|
27
|
+
setMinutesValue(padTime(minutes));
|
|
28
|
+
}, [minutes]);
|
|
29
|
+
const commitTime = useCallback((type, nextValue) => {
|
|
30
|
+
if (!value) return;
|
|
31
|
+
setTime(type, nextValue);
|
|
32
|
+
}, [setTime, value]);
|
|
33
|
+
const changeHours = useCallback((nextValue) => {
|
|
34
|
+
setHoursValue(padTime(nextValue));
|
|
35
|
+
commitTime("hours", nextValue);
|
|
36
|
+
}, [commitTime]);
|
|
37
|
+
const changeMinutes = useCallback((nextValue) => {
|
|
38
|
+
setMinutesValue(padTime(nextValue));
|
|
39
|
+
commitTime("minutes", nextValue);
|
|
40
|
+
}, [commitTime]);
|
|
41
|
+
const increaseHours = useCallback(() => {
|
|
42
|
+
changeHours((parseTimeField(hoursValue, hours) + 1) % 24);
|
|
43
|
+
}, [
|
|
44
|
+
changeHours,
|
|
45
|
+
hoursValue,
|
|
46
|
+
hours
|
|
47
|
+
]);
|
|
48
|
+
const decreaseHours = useCallback(() => {
|
|
49
|
+
changeHours((parseTimeField(hoursValue, hours) - 1 + 24) % 24);
|
|
50
|
+
}, [
|
|
51
|
+
changeHours,
|
|
52
|
+
hoursValue,
|
|
53
|
+
hours
|
|
54
|
+
]);
|
|
55
|
+
const increaseMinutes = useCallback(() => {
|
|
56
|
+
changeMinutes((parseTimeField(minutesValue, minutes) + 5) % 60);
|
|
57
|
+
}, [
|
|
58
|
+
changeMinutes,
|
|
59
|
+
minutesValue,
|
|
60
|
+
minutes
|
|
61
|
+
]);
|
|
62
|
+
const decreaseMinutes = useCallback(() => {
|
|
63
|
+
changeMinutes((parseTimeField(minutesValue, minutes) - 5 + 60) % 60);
|
|
64
|
+
}, [
|
|
65
|
+
changeMinutes,
|
|
66
|
+
minutesValue,
|
|
67
|
+
minutes
|
|
68
|
+
]);
|
|
69
|
+
const onHoursChange = useCallback((e) => {
|
|
70
|
+
const nextValue = sanitizeTimeField(e.target.value);
|
|
71
|
+
setHoursValue(nextValue);
|
|
72
|
+
const parsed = parseTimeField(nextValue, NaN);
|
|
73
|
+
if (Number.isNaN(parsed) || parsed > 23) return;
|
|
74
|
+
commitTime("hours", parsed);
|
|
75
|
+
}, [commitTime]);
|
|
76
|
+
const onMinutesChange = useCallback((e) => {
|
|
77
|
+
const nextValue = sanitizeTimeField(e.target.value);
|
|
78
|
+
setMinutesValue(nextValue);
|
|
79
|
+
const parsed = parseTimeField(nextValue, NaN);
|
|
80
|
+
if (Number.isNaN(parsed) || parsed > 59) return;
|
|
81
|
+
commitTime("minutes", parsed);
|
|
82
|
+
}, [commitTime]);
|
|
83
|
+
const onFieldClick = useCallback((e) => {
|
|
84
|
+
e.currentTarget.select();
|
|
85
|
+
}, []);
|
|
86
|
+
const onHoursFocus = useCallback((e) => {
|
|
87
|
+
isHoursEdited.current = true;
|
|
88
|
+
e.target.select();
|
|
89
|
+
}, []);
|
|
90
|
+
const onMinutesFocus = useCallback((e) => {
|
|
91
|
+
isMinutesEdited.current = true;
|
|
92
|
+
e.target.select();
|
|
93
|
+
}, []);
|
|
94
|
+
const onHoursBlur = useCallback(() => {
|
|
95
|
+
isHoursEdited.current = false;
|
|
96
|
+
const parsed = parseTimeField(hoursValue, NaN);
|
|
97
|
+
setHoursValue(padTime(!Number.isNaN(parsed) && parsed <= 23 ? parsed : hours));
|
|
98
|
+
}, [hoursValue, hours]);
|
|
99
|
+
const onMinutesBlur = useCallback(() => {
|
|
100
|
+
isMinutesEdited.current = false;
|
|
101
|
+
const parsed = parseTimeField(minutesValue, NaN);
|
|
102
|
+
setMinutesValue(padTime(!Number.isNaN(parsed) && parsed <= 59 ? parsed : minutes));
|
|
103
|
+
}, [minutesValue, minutes]);
|
|
104
|
+
return /* @__PURE__ */ jsxs(FooterRow, {
|
|
105
|
+
disabled,
|
|
106
|
+
children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(Icon, { icon: "clock" }), /* @__PURE__ */ jsx(FooterRowLabel, { children: i18n._({
|
|
107
|
+
id: "dataGrid.filterCell.time",
|
|
108
|
+
message: "Time"
|
|
109
|
+
}) })] }), /* @__PURE__ */ jsx(x.div, {
|
|
110
|
+
display: "flex",
|
|
111
|
+
flexDirection: "column",
|
|
112
|
+
alignItems: "flex-start",
|
|
113
|
+
pt: "4px",
|
|
114
|
+
w: "fit-content",
|
|
115
|
+
children: /* @__PURE__ */ jsxs(x.div, {
|
|
116
|
+
display: "flex",
|
|
117
|
+
alignItems: "center",
|
|
118
|
+
children: [
|
|
119
|
+
/* @__PURE__ */ jsxs(x.div, {
|
|
120
|
+
display: "flex",
|
|
121
|
+
flexDirection: "column",
|
|
122
|
+
children: [/* @__PURE__ */ jsx(TimeButton, {
|
|
123
|
+
disabled,
|
|
124
|
+
onClick: increaseHours,
|
|
125
|
+
type: "button",
|
|
126
|
+
children: "‹"
|
|
127
|
+
}), /* @__PURE__ */ jsx(TimeButton, {
|
|
128
|
+
disabled,
|
|
129
|
+
onClick: decreaseHours,
|
|
130
|
+
type: "button",
|
|
131
|
+
children: "›"
|
|
132
|
+
})]
|
|
133
|
+
}),
|
|
134
|
+
/* @__PURE__ */ jsxs(TimeWrapper, { children: [
|
|
135
|
+
/* @__PURE__ */ jsx(TimeField, {
|
|
136
|
+
value: hoursValue,
|
|
137
|
+
disabled,
|
|
138
|
+
inputMode: "numeric",
|
|
139
|
+
maxLength: 2,
|
|
140
|
+
onChange: onHoursChange,
|
|
141
|
+
onFocus: onHoursFocus,
|
|
142
|
+
onClick: onFieldClick,
|
|
143
|
+
onBlur: onHoursBlur
|
|
144
|
+
}),
|
|
145
|
+
/* @__PURE__ */ jsx(x.div, {
|
|
146
|
+
mx: "1px",
|
|
147
|
+
children: ":"
|
|
148
|
+
}),
|
|
149
|
+
/* @__PURE__ */ jsx(TimeField, {
|
|
150
|
+
value: minutesValue,
|
|
151
|
+
disabled,
|
|
152
|
+
inputMode: "numeric",
|
|
153
|
+
maxLength: 2,
|
|
154
|
+
onChange: onMinutesChange,
|
|
155
|
+
onFocus: onMinutesFocus,
|
|
156
|
+
onClick: onFieldClick,
|
|
157
|
+
onBlur: onMinutesBlur
|
|
158
|
+
})
|
|
159
|
+
] }),
|
|
160
|
+
/* @__PURE__ */ jsxs(x.div, {
|
|
161
|
+
display: "flex",
|
|
162
|
+
flexDirection: "column",
|
|
163
|
+
children: [/* @__PURE__ */ jsx(TimeButton, {
|
|
164
|
+
disabled,
|
|
165
|
+
onClick: increaseMinutes,
|
|
166
|
+
type: "button",
|
|
167
|
+
children: "‹"
|
|
168
|
+
}), /* @__PURE__ */ jsx(TimeButton, {
|
|
169
|
+
disabled,
|
|
170
|
+
onClick: decreaseMinutes,
|
|
171
|
+
type: "button",
|
|
172
|
+
children: "›"
|
|
173
|
+
})]
|
|
174
|
+
})
|
|
175
|
+
]
|
|
176
|
+
})
|
|
177
|
+
})]
|
|
178
|
+
});
|
|
179
|
+
};
|
|
180
|
+
//#endregion
|
|
181
|
+
export { Timepicker };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
//#region packages/ui/Elements/DatePicker/Datetime/components/Timepicker/constants.ts
|
|
2
|
+
const HOURS_COUNT = 24;
|
|
3
|
+
const MINUTES_COUNT = 60;
|
|
4
|
+
const MINUTES_STEP = 5;
|
|
5
|
+
const MAX_HOURS = 23;
|
|
6
|
+
const MAX_MINUTES = 59;
|
|
7
|
+
//#endregion
|
|
8
|
+
export { HOURS_COUNT, MAX_HOURS, MAX_MINUTES, MINUTES_COUNT, MINUTES_STEP };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Timepicker } from './Timepicker';
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare const TimeButton: import("styled-components").StyledComponent<"button", import("@xstyled/styled-components").Theme, {}, never>;
|
|
2
|
+
export declare const TimeWrapper: import("styled-components").StyledComponent<"div", import("@xstyled/styled-components").Theme, {}, never>;
|
|
3
|
+
export declare const TimeField: import("styled-components").StyledComponent<"input", import("@xstyled/styled-components").Theme, {}, never>;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import styled$1 from "@xstyled/styled-components";
|
|
2
|
+
import { th as th$1 } from "@xstyled/system";
|
|
3
|
+
//#region packages/ui/Elements/DatePicker/Datetime/components/Timepicker/styles.ts
|
|
4
|
+
const TimeButton = styled$1.button`
|
|
5
|
+
transform: rotate(90deg);
|
|
6
|
+
font-size: 20px;
|
|
7
|
+
line-height: 1;
|
|
8
|
+
margin: -3px 0;
|
|
9
|
+
padding: 0;
|
|
10
|
+
background-color: transparent !important;
|
|
11
|
+
border: none;
|
|
12
|
+
color: ${th$1("colors.lightGray4")};
|
|
13
|
+
&:disabled:hover {
|
|
14
|
+
color: ${th$1("colors.lightGray4")};
|
|
15
|
+
cursor: default;
|
|
16
|
+
}
|
|
17
|
+
&:hover {
|
|
18
|
+
color: ${th$1("colors.red2")};
|
|
19
|
+
background-color: transparent !important;
|
|
20
|
+
}
|
|
21
|
+
`;
|
|
22
|
+
const TimeWrapper = styled$1.div`
|
|
23
|
+
display: flex;
|
|
24
|
+
align-items: baseline;
|
|
25
|
+
justify-content: center;
|
|
26
|
+
border: 1px solid ${th$1("colors.lightGray2")};
|
|
27
|
+
border-radius: 6px;
|
|
28
|
+
padding: 3px 8px;
|
|
29
|
+
margin: 0 4px;
|
|
30
|
+
`;
|
|
31
|
+
const TimeField = styled$1.input`
|
|
32
|
+
font-size: 16px;
|
|
33
|
+
font-weight: 600;
|
|
34
|
+
line-height: 20px;
|
|
35
|
+
width: 24px;
|
|
36
|
+
text-align: center;
|
|
37
|
+
margin: 0;
|
|
38
|
+
padding: 0;
|
|
39
|
+
border: none;
|
|
40
|
+
outline: none;
|
|
41
|
+
background-color: transparent;
|
|
42
|
+
color: ${th$1("colors.blue2")};
|
|
43
|
+
&:disabled {
|
|
44
|
+
opacity: 0.5;
|
|
45
|
+
}
|
|
46
|
+
`;
|
|
47
|
+
//#endregion
|
|
48
|
+
export { TimeButton, TimeField, TimeWrapper };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
//#region packages/ui/Elements/DatePicker/Datetime/components/Timepicker/utils/parseTimeField.ts
|
|
2
|
+
const parseTimeField = (text, fallback) => {
|
|
3
|
+
if (text === "") return fallback;
|
|
4
|
+
const parsed = Number(text);
|
|
5
|
+
return Number.isNaN(parsed) ? fallback : parsed;
|
|
6
|
+
};
|
|
7
|
+
//#endregion
|
|
8
|
+
export { parseTimeField };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { DateRepeater } from "../components/DateRepeater.js";
|
|
2
|
-
import { Timepicker } from "../components/Timepicker.js";
|
|
2
|
+
import { Timepicker } from "../components/Timepicker/Timepicker.js";
|
|
3
|
+
import "../components/Timepicker/index.js";
|
|
3
4
|
import ViewNavigation from "../components/ViewNavigation.js";
|
|
4
5
|
import React from "react";
|
|
5
6
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type FC, type InputHTMLAttributes } from 'react';
|
|
2
|
+
type DatePickerInputProps = {
|
|
3
|
+
inputProps: InputHTMLAttributes<HTMLInputElement>;
|
|
4
|
+
openCalendar: () => void;
|
|
5
|
+
name?: string;
|
|
6
|
+
label?: string;
|
|
7
|
+
error?: string;
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
icon?: boolean;
|
|
10
|
+
showInputLabel?: boolean;
|
|
11
|
+
onClear?: () => void;
|
|
12
|
+
onInputChange?: (value: string) => void;
|
|
13
|
+
};
|
|
14
|
+
export declare const DatePickerInput: FC<DatePickerInputProps>;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import Input_default from "../../../../Forms/Input/index.js";
|
|
2
|
+
import { useCallback, useState } from "react";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
//#region packages/ui/Elements/DatePicker/components/DatePickerInput/DatePickerInput.tsx
|
|
5
|
+
const DatePickerInput = ({ inputProps, openCalendar, name, label, error, disabled, icon, showInputLabel, onClear, onInputChange }) => {
|
|
6
|
+
const [typedValue, setTypedValue] = useState(null);
|
|
7
|
+
const handleChange = useCallback((e) => {
|
|
8
|
+
setTypedValue(e.target.value);
|
|
9
|
+
inputProps.onChange?.(e);
|
|
10
|
+
onInputChange?.(e.target.value);
|
|
11
|
+
}, [inputProps, onInputChange]);
|
|
12
|
+
const handleBlur = useCallback(() => {
|
|
13
|
+
setTypedValue(null);
|
|
14
|
+
}, []);
|
|
15
|
+
return /* @__PURE__ */ jsx(Input_default, {
|
|
16
|
+
type: "text",
|
|
17
|
+
icon: icon ? "calendar" : void 0,
|
|
18
|
+
name,
|
|
19
|
+
error,
|
|
20
|
+
disabled,
|
|
21
|
+
isInvalid: !!error,
|
|
22
|
+
onChange: handleChange,
|
|
23
|
+
onBlur: handleBlur,
|
|
24
|
+
label: showInputLabel ? label : void 0,
|
|
25
|
+
value: typedValue ?? inputProps.value,
|
|
26
|
+
onFocus: openCalendar,
|
|
27
|
+
iconOnClick: openCalendar,
|
|
28
|
+
onClear,
|
|
29
|
+
autoComplete: "off"
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
//#endregion
|
|
33
|
+
export { DatePickerInput };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { DatePickerInput } from './DatePickerInput';
|
package/ui/index.js
CHANGED
|
@@ -133,8 +133,8 @@ import SpaceAroundWrap from "./Elements/SpaceAround/SpaceAround.js";
|
|
|
133
133
|
import SpaceAround_default from "./Elements/SpaceAround/index.js";
|
|
134
134
|
import Select_default from "./Elements/Select/index.js";
|
|
135
135
|
import SingleSelect_default from "./Elements/SingleSelect/index.js";
|
|
136
|
-
import Input_default from "./Forms/Input/index.js";
|
|
137
136
|
import { DatePickerRepeat, TimePickerRepeat } from "./Elements/DatePicker/Datetime/types.js";
|
|
137
|
+
import Input_default from "./Forms/Input/index.js";
|
|
138
138
|
import DatePicker_default from "./Elements/DatePicker/index.js";
|
|
139
139
|
import { useEvent } from "./Blocks/CommonGrid/hooks/useEvent.js";
|
|
140
140
|
import { useAddFilter } from "./Blocks/CommonGrid/hooks/useAddFilter.js";
|
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
import Icon from "../../../Icon/Icon.js";
|
|
2
|
-
import { FooterRow } from "./FooterRow.js";
|
|
3
|
-
import { FooterRowLabel } from "./FooterRowLabel.js";
|
|
4
|
-
import { useCallback, useEffect, useState } from "react";
|
|
5
|
-
import styled$1, { x } from "@xstyled/styled-components";
|
|
6
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
-
import { th as th$1 } from "@xstyled/system";
|
|
8
|
-
import { i18n } from "@lingui/core";
|
|
9
|
-
//#region packages/ui/Elements/DatePicker/Datetime/components/Timepicker.tsx
|
|
10
|
-
const Btn = styled$1.button`
|
|
11
|
-
transform: rotate(90deg);
|
|
12
|
-
font-size: 18px;
|
|
13
|
-
margin: -4px 0;
|
|
14
|
-
background-color: transparent !important;
|
|
15
|
-
border: none;
|
|
16
|
-
color: ${th$1("colors.lightGray4")};
|
|
17
|
-
&:disabled:hover {
|
|
18
|
-
color: ${th$1("colors.lightGray4")};
|
|
19
|
-
cursor: default;
|
|
20
|
-
}
|
|
21
|
-
&:hover {
|
|
22
|
-
color: ${th$1("colors.red2")};
|
|
23
|
-
background-color: transparent !important;
|
|
24
|
-
}
|
|
25
|
-
`;
|
|
26
|
-
const TimeWrapper = styled$1.div`
|
|
27
|
-
display: flex;
|
|
28
|
-
align-items: baseline;
|
|
29
|
-
justify-content: center;
|
|
30
|
-
border: 1px solid ${th$1("colors.lightGray2")};
|
|
31
|
-
border-radius: 6px;
|
|
32
|
-
padding: 0 4px;
|
|
33
|
-
margin: 0 4px;
|
|
34
|
-
`;
|
|
35
|
-
const Hours = styled$1.input`
|
|
36
|
-
font-size: 14px;
|
|
37
|
-
font-weight: 600;
|
|
38
|
-
width: 17px;
|
|
39
|
-
margin: 0;
|
|
40
|
-
padding: 0;
|
|
41
|
-
border: none;
|
|
42
|
-
outline: none;
|
|
43
|
-
background-color: transparent;
|
|
44
|
-
color: #22394E;
|
|
45
|
-
&:disabled {
|
|
46
|
-
opacity: 0.5;
|
|
47
|
-
}
|
|
48
|
-
`;
|
|
49
|
-
const Minutes = styled$1.input`
|
|
50
|
-
font-weight: 600;
|
|
51
|
-
font-size: 14px;
|
|
52
|
-
width: 18px;
|
|
53
|
-
margin: 0;
|
|
54
|
-
padding: 0;
|
|
55
|
-
border: none;
|
|
56
|
-
outline: none;
|
|
57
|
-
background-color: transparent;
|
|
58
|
-
color: #22394E;
|
|
59
|
-
&:disabled {
|
|
60
|
-
opacity: 0.5;
|
|
61
|
-
}
|
|
62
|
-
`;
|
|
63
|
-
const regExp = "^[0-9]*$";
|
|
64
|
-
const Timepicker = ({ setTime, value, disabled }) => {
|
|
65
|
-
const initialHours = value?.getHours?.() ?? 0;
|
|
66
|
-
const initialMinutes = value?.getMinutes?.() ?? 0;
|
|
67
|
-
const [hours, setHours] = useState(initialHours);
|
|
68
|
-
const [minutes, setMinutes] = useState(initialMinutes);
|
|
69
|
-
const increaseHour = useCallback(() => {
|
|
70
|
-
setHours((prev) => (prev + 1) % 24);
|
|
71
|
-
}, []);
|
|
72
|
-
const decreaseHour = useCallback(() => {
|
|
73
|
-
setHours((prev) => prev === 0 ? 23 : prev - 1);
|
|
74
|
-
}, []);
|
|
75
|
-
const increaseMinutes = useCallback(() => {
|
|
76
|
-
setMinutes((prev) => (prev + 5) % 60);
|
|
77
|
-
}, []);
|
|
78
|
-
const decreaseMinutes = useCallback(() => {
|
|
79
|
-
setMinutes((prev) => (prev - 5 + 60) % 60);
|
|
80
|
-
}, []);
|
|
81
|
-
const onHoursChange = useCallback((e) => {
|
|
82
|
-
if (e.target.value.match(regExp) && Number(e.target.value) <= 23) setHours(Number(e.target.value));
|
|
83
|
-
else setHours(0);
|
|
84
|
-
}, []);
|
|
85
|
-
const onMinutesChange = useCallback((e) => {
|
|
86
|
-
if (e.target.value.match(regExp) && Number(e.target.value) <= 59) setMinutes(Number(e.target.value));
|
|
87
|
-
else setMinutes(0);
|
|
88
|
-
}, []);
|
|
89
|
-
useEffect(() => {
|
|
90
|
-
value && setTime("hours", hours);
|
|
91
|
-
}, [hours]);
|
|
92
|
-
useEffect(() => {
|
|
93
|
-
value && setTime("minutes", minutes);
|
|
94
|
-
}, [minutes]);
|
|
95
|
-
useEffect(() => {
|
|
96
|
-
setHours(initialHours);
|
|
97
|
-
}, [initialHours]);
|
|
98
|
-
useEffect(() => {
|
|
99
|
-
setMinutes(initialMinutes);
|
|
100
|
-
}, [initialMinutes]);
|
|
101
|
-
return /* @__PURE__ */ jsxs(FooterRow, {
|
|
102
|
-
disabled,
|
|
103
|
-
children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(Icon, { icon: "clock" }), /* @__PURE__ */ jsx(FooterRowLabel, { children: i18n._({
|
|
104
|
-
id: "dataGrid.filterCell.time",
|
|
105
|
-
message: "Time"
|
|
106
|
-
}) })] }), /* @__PURE__ */ jsx(x.div, {
|
|
107
|
-
display: "flex",
|
|
108
|
-
flexDirection: "column",
|
|
109
|
-
alignItems: "flex-start",
|
|
110
|
-
pt: "4px",
|
|
111
|
-
w: "fit-content",
|
|
112
|
-
children: /* @__PURE__ */ jsxs(x.div, {
|
|
113
|
-
display: "flex",
|
|
114
|
-
alignItems: "center",
|
|
115
|
-
children: [
|
|
116
|
-
/* @__PURE__ */ jsxs(x.div, {
|
|
117
|
-
display: "flex",
|
|
118
|
-
flexDirection: "column",
|
|
119
|
-
children: [/* @__PURE__ */ jsx(Btn, {
|
|
120
|
-
disabled,
|
|
121
|
-
onClick: increaseHour,
|
|
122
|
-
type: "button",
|
|
123
|
-
children: "‹"
|
|
124
|
-
}), /* @__PURE__ */ jsx(Btn, {
|
|
125
|
-
disabled,
|
|
126
|
-
onClick: decreaseHour,
|
|
127
|
-
type: "button",
|
|
128
|
-
children: "›"
|
|
129
|
-
})]
|
|
130
|
-
}),
|
|
131
|
-
/* @__PURE__ */ jsxs(TimeWrapper, { children: [
|
|
132
|
-
/* @__PURE__ */ jsx(Hours, {
|
|
133
|
-
value: String(hours).padStart(2, "0"),
|
|
134
|
-
disabled,
|
|
135
|
-
onChange: onHoursChange
|
|
136
|
-
}),
|
|
137
|
-
/* @__PURE__ */ jsx(x.div, {
|
|
138
|
-
mx: "1px",
|
|
139
|
-
children: ":"
|
|
140
|
-
}),
|
|
141
|
-
/* @__PURE__ */ jsx(Minutes, {
|
|
142
|
-
value: String(minutes).padStart(2, "0"),
|
|
143
|
-
disabled,
|
|
144
|
-
onChange: onMinutesChange
|
|
145
|
-
})
|
|
146
|
-
] }),
|
|
147
|
-
/* @__PURE__ */ jsxs(x.div, {
|
|
148
|
-
display: "flex",
|
|
149
|
-
flexDirection: "column",
|
|
150
|
-
children: [/* @__PURE__ */ jsx(Btn, {
|
|
151
|
-
disabled,
|
|
152
|
-
onClick: increaseMinutes,
|
|
153
|
-
type: "button",
|
|
154
|
-
children: "‹"
|
|
155
|
-
}), /* @__PURE__ */ jsx(Btn, {
|
|
156
|
-
disabled,
|
|
157
|
-
onClick: decreaseMinutes,
|
|
158
|
-
type: "button",
|
|
159
|
-
children: "›"
|
|
160
|
-
})]
|
|
161
|
-
})
|
|
162
|
-
]
|
|
163
|
-
})
|
|
164
|
-
})]
|
|
165
|
-
});
|
|
166
|
-
};
|
|
167
|
-
//#endregion
|
|
168
|
-
export { Timepicker };
|