@pushwoosh/dumb-components 1.1.46 → 1.1.48
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/Calendar/CalendarDropdown/CalendarDropdown.d.ts +3 -0
- package/Calendar/CalendarDropdown/CalendarDropdown.js +158 -0
- package/Calendar/CalendarDropdown/helpers.d.ts +3 -0
- package/Calendar/CalendarDropdown/helpers.js +29 -0
- package/Calendar/CalendarDropdown/index.d.ts +2 -0
- package/Calendar/CalendarDropdown/index.js +1 -0
- package/Calendar/CalendarDropdown/styles.d.ts +61 -0
- package/Calendar/CalendarDropdown/styles.js +16 -0
- package/Calendar/CalendarDropdown/types.d.ts +40 -0
- package/Calendar/CalendarDropdown/types.js +1 -0
- package/Calendar/CalendarMonth/CalendarMonth.d.ts +3 -0
- package/Calendar/CalendarMonth/CalendarMonth.js +109 -0
- package/Calendar/CalendarMonth/styles.d.ts +7 -0
- package/Calendar/CalendarMonth/styles.js +48 -0
- package/Calendar/CalendarMonth/types.d.ts +17 -0
- package/Calendar/CalendarMonth/types.js +1 -0
- package/Calendar/CalendarMonthSlider/CalendarMonthSlider.d.ts +11 -0
- package/Calendar/CalendarMonthSlider/CalendarMonthSlider.js +141 -0
- package/Calendar/CalendarMonthSlider/styles.d.ts +67 -0
- package/Calendar/CalendarMonthSlider/styles.js +40 -0
- package/Calendar/CalendarSuperForm/CalendarSuperForm.d.ts +3 -0
- package/Calendar/CalendarSuperForm/CalendarSuperForm.js +101 -0
- package/Calendar/CalendarSuperForm/components/CalendarRangePicker/CalendarRangePicker.d.ts +19 -0
- package/Calendar/CalendarSuperForm/components/CalendarRangePicker/CalendarRangePicker.js +57 -0
- package/Calendar/CalendarSuperForm/components/CalendarRangePicker/getDisabledRanges.d.ts +14 -0
- package/Calendar/CalendarSuperForm/components/CalendarRangePicker/getDisabledRanges.js +62 -0
- package/Calendar/CalendarSuperForm/components/CalendarTimeAndTimezoneSection/CalendarTimeAndTimezoneSection.d.ts +3 -0
- package/Calendar/CalendarSuperForm/components/CalendarTimeAndTimezoneSection/CalendarTimeAndTimezoneSection.js +135 -0
- package/Calendar/CalendarSuperForm/components/CalendarTimeAndTimezoneSection/types.d.ts +18 -0
- package/Calendar/CalendarSuperForm/components/CalendarTimeAndTimezoneSection/types.js +1 -0
- package/Calendar/CalendarSuperForm/components/CalendarTimeInput.d.ts +19 -0
- package/Calendar/CalendarSuperForm/components/CalendarTimeInput.js +25 -0
- package/Calendar/CalendarSuperForm/components/CalendarTimezoneSelect.d.ts +9 -0
- package/Calendar/CalendarSuperForm/components/CalendarTimezoneSelect.js +26 -0
- package/Calendar/CalendarSuperForm/index.d.ts +2 -0
- package/Calendar/CalendarSuperForm/index.js +1 -0
- package/Calendar/CalendarSuperForm/types.d.ts +56 -0
- package/Calendar/CalendarSuperForm/types.js +1 -0
- package/Calendar/constants.d.ts +5 -0
- package/Calendar/constants.js +10 -0
- package/Calendar/helpers-tz.d.ts +7 -0
- package/Calendar/helpers-tz.js +100 -0
- package/Calendar/helpers.d.ts +22 -0
- package/Calendar/helpers.js +134 -0
- package/Calendar/index.d.ts +2 -0
- package/Calendar/index.js +2 -0
- package/Calendar/types.d.ts +19 -0
- package/Calendar/types.js +1 -0
- package/Popover/styles.js +3 -3
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/native/NativeTimeInput.js +2 -2
- package/package.json +3 -2
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import React, { useRef, useState } from 'react';
|
|
2
|
+
import { createPortal } from 'react-dom';
|
|
3
|
+
import { Color } from '@pushwoosh/kit-constants';
|
|
4
|
+
import { Horizontal, useClickAway, Vertical } from '@pushwoosh/kit-helpers';
|
|
5
|
+
import { CalendarIcon } from '@pushwoosh/kit-icons';
|
|
6
|
+
import { stringifyValue } from './helpers';
|
|
7
|
+
import { DropdownRoot, PopoverContent } from './styles';
|
|
8
|
+
import { Button } from '../../Button';
|
|
9
|
+
import { Chip } from '../../Chip';
|
|
10
|
+
import { CalendarSuperForm } from '../CalendarSuperForm';
|
|
11
|
+
import { formatTimezoneShort } from '../helpers-tz';
|
|
12
|
+
export const CalendarDropdown = props => {
|
|
13
|
+
const {
|
|
14
|
+
mode,
|
|
15
|
+
calendarProps
|
|
16
|
+
} = props;
|
|
17
|
+
const isRangePicker = mode === 'range-date' || mode === 'range-datetime';
|
|
18
|
+
const withTime = mode === 'single-datetime' || mode === 'range-datetime';
|
|
19
|
+
const rootRef = useRef(null);
|
|
20
|
+
const popoverRef = useRef(null);
|
|
21
|
+
const [isShaking, setIsShaking] = useState(false);
|
|
22
|
+
const [popoverPosition, setPopoverPosition] = useState(null);
|
|
23
|
+
const [value, setValue] = useState(props.value ?? (isRangePicker ? [] : undefined));
|
|
24
|
+
const initialTimezone = 'timezone' in calendarProps ? calendarProps.timezone : 'UTC';
|
|
25
|
+
const [timezone, setTimezone] = useState(initialTimezone);
|
|
26
|
+
const closePopover = () => {
|
|
27
|
+
setPopoverPosition(null);
|
|
28
|
+
setValue(props.value ?? (isRangePicker ? [] : undefined));
|
|
29
|
+
setTimezone(initialTimezone);
|
|
30
|
+
};
|
|
31
|
+
useClickAway(!!popoverPosition, popoverRef, closePopover);
|
|
32
|
+
const openPopover = () => {
|
|
33
|
+
if (rootRef.current) {
|
|
34
|
+
const rect = rootRef.current.getBoundingClientRect();
|
|
35
|
+
setPopoverPosition({
|
|
36
|
+
top: rect.bottom + 4,
|
|
37
|
+
left: rect.left
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
const onChangeHandler = val => {
|
|
42
|
+
var _props$onChange;
|
|
43
|
+
setValue(val);
|
|
44
|
+
(_props$onChange = props.onChange) === null || _props$onChange === void 0 || _props$onChange.call(props, val);
|
|
45
|
+
};
|
|
46
|
+
const presets = 'presets' in props ? props.presets : undefined;
|
|
47
|
+
const noValue = isRangePicker ? (value === null || value === void 0 ? void 0 : value.length) === 0 : !value;
|
|
48
|
+
let buttonText;
|
|
49
|
+
if (noValue) {
|
|
50
|
+
buttonText = isRangePicker ? 'Select period' : 'Select date';
|
|
51
|
+
} else {
|
|
52
|
+
buttonText = stringifyValue(value, withTime);
|
|
53
|
+
if (withTime) {
|
|
54
|
+
const timezoneShort = formatTimezoneShort(timezone);
|
|
55
|
+
buttonText += ` ${timezoneShort}`;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
const popoverContent = popoverPosition && React.createElement(PopoverContent, {
|
|
59
|
+
ref: popoverRef,
|
|
60
|
+
"$isShaking": isShaking,
|
|
61
|
+
onAnimationEnd: () => setIsShaking(false),
|
|
62
|
+
style: {
|
|
63
|
+
top: `${popoverPosition.top}px`,
|
|
64
|
+
left: `${popoverPosition.left}px`
|
|
65
|
+
}
|
|
66
|
+
}, React.createElement(Vertical, null, presets && presets.length > 0 && React.createElement(Horizontal, {
|
|
67
|
+
"$padding": {
|
|
68
|
+
horizontal: 16,
|
|
69
|
+
vertical: 12
|
|
70
|
+
},
|
|
71
|
+
"$border": {
|
|
72
|
+
bottom: `1px solid ${Color.DIVIDER}`
|
|
73
|
+
},
|
|
74
|
+
"$justifyContent": "start",
|
|
75
|
+
"$gap": 4
|
|
76
|
+
}, presets.map((preset, i) => React.createElement(Chip, {
|
|
77
|
+
key: i,
|
|
78
|
+
onClick: () => onChangeHandler(preset.value)
|
|
79
|
+
}, preset.label))), React.createElement(Horizontal, {
|
|
80
|
+
"$padding": 16,
|
|
81
|
+
"$border": {
|
|
82
|
+
bottom: `1px solid ${Color.DIVIDER}`
|
|
83
|
+
}
|
|
84
|
+
}, mode === 'single-date' && React.createElement(CalendarSuperForm, {
|
|
85
|
+
mode: "single-date",
|
|
86
|
+
...calendarProps,
|
|
87
|
+
value: value,
|
|
88
|
+
onChange: onChangeHandler
|
|
89
|
+
}), mode === 'single-datetime' && React.createElement(CalendarSuperForm, {
|
|
90
|
+
mode: "single-datetime",
|
|
91
|
+
...calendarProps,
|
|
92
|
+
value: value,
|
|
93
|
+
onChange: onChangeHandler,
|
|
94
|
+
timezone: timezone,
|
|
95
|
+
onChangeTimezone: val => {
|
|
96
|
+
setTimezone(val);
|
|
97
|
+
if ('onChangeTimezone' in calendarProps) {
|
|
98
|
+
calendarProps.onChangeTimezone(val);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}), mode === 'range-date' && React.createElement(CalendarSuperForm, {
|
|
102
|
+
mode: "range-date",
|
|
103
|
+
...calendarProps,
|
|
104
|
+
value: value,
|
|
105
|
+
onChange: onChangeHandler
|
|
106
|
+
}), mode === 'range-datetime' && React.createElement(CalendarSuperForm, {
|
|
107
|
+
mode: "range-datetime",
|
|
108
|
+
...calendarProps,
|
|
109
|
+
value: value,
|
|
110
|
+
onChange: onChangeHandler,
|
|
111
|
+
timezone: timezone,
|
|
112
|
+
onChangeTimezone: val => {
|
|
113
|
+
setTimezone(val);
|
|
114
|
+
if ('onChangeTimezone' in calendarProps) {
|
|
115
|
+
calendarProps.onChangeTimezone(val);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
})), React.createElement(Horizontal, {
|
|
119
|
+
"$padding": 16,
|
|
120
|
+
"$justifyContent": "end",
|
|
121
|
+
"$gap": 8
|
|
122
|
+
}, React.createElement(Button, {
|
|
123
|
+
color: "secondary",
|
|
124
|
+
size: "compact",
|
|
125
|
+
onClick: () => {
|
|
126
|
+
if (noValue) {
|
|
127
|
+
closePopover();
|
|
128
|
+
} else {
|
|
129
|
+
setValue(isRangePicker ? [] : undefined);
|
|
130
|
+
setTimezone(initialTimezone);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}, noValue ? 'Cancel' : 'Reset'), React.createElement(Button, {
|
|
134
|
+
color: "primary",
|
|
135
|
+
size: "compact",
|
|
136
|
+
onClick: () => {
|
|
137
|
+
const isInvalid = isRangePicker ? (value === null || value === void 0 ? void 0 : value.length) !== 2 : !value;
|
|
138
|
+
if (isInvalid) {
|
|
139
|
+
setIsShaking(true);
|
|
140
|
+
} else {
|
|
141
|
+
props.onSubmit(value, timezone);
|
|
142
|
+
closePopover();
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}, "Apply"))));
|
|
146
|
+
return React.createElement(DropdownRoot, {
|
|
147
|
+
ref: rootRef
|
|
148
|
+
}, React.createElement(Button, {
|
|
149
|
+
type: "button",
|
|
150
|
+
color: "secondary",
|
|
151
|
+
icon: React.createElement(CalendarIcon, {
|
|
152
|
+
size: "medium",
|
|
153
|
+
view: "lined"
|
|
154
|
+
}),
|
|
155
|
+
onClick: () => popoverPosition ? closePopover() : openPopover(),
|
|
156
|
+
isOpen: !!popoverPosition
|
|
157
|
+
}, buttonText), popoverContent && createPortal(popoverContent, document.body));
|
|
158
|
+
};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { type DateStruct, type DateTimeStruct, type RangeValue, type SingleValue } from '../types';
|
|
2
|
+
export declare function formatDate(val: DateStruct | DateTimeStruct, withTime?: boolean): string;
|
|
3
|
+
export declare const stringifyValue: (value: SingleValue<DateStruct | DateTimeStruct> | RangeValue<DateStruct | DateTimeStruct>, withTime?: boolean) => string;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export function formatDate(val, withTime = true) {
|
|
2
|
+
const date = new Date(val.year, val.month - 1, val.day, 'hour' in val ? val.hour : 0, 'minute' in val ? val.minute : 0);
|
|
3
|
+
if (withTime) {
|
|
4
|
+
return date.toLocaleString('en-US', {
|
|
5
|
+
month: 'short',
|
|
6
|
+
day: '2-digit',
|
|
7
|
+
year: 'numeric',
|
|
8
|
+
hour: '2-digit',
|
|
9
|
+
minute: '2-digit',
|
|
10
|
+
hour12: false
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
return date.toLocaleString('en-US', {
|
|
14
|
+
month: 'short',
|
|
15
|
+
day: '2-digit',
|
|
16
|
+
year: 'numeric'
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
export const stringifyValue = (value, withTime) => {
|
|
20
|
+
if (Array.isArray(value)) {
|
|
21
|
+
if (value.length === 0) return '';
|
|
22
|
+
if (value.length === 1) return formatDate(value[0], withTime);
|
|
23
|
+
if (value.length === 2) return `${formatDate(value[0], withTime)} – ${formatDate(value[1], withTime)}`;
|
|
24
|
+
}
|
|
25
|
+
if (value) {
|
|
26
|
+
return formatDate(value, withTime);
|
|
27
|
+
}
|
|
28
|
+
return '';
|
|
29
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { CalendarDropdown } from './CalendarDropdown';
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export declare const DropdownRoot: import("styled-components").StyledComponent<"div", any, {
|
|
2
|
+
$alignContent?: "end" | "start" | "center" | "space-between" | "space-around" | "space-evenly" | "stretch" | undefined;
|
|
3
|
+
$alignItems?: "end" | "start" | "center" | "stretch" | "baseline" | undefined;
|
|
4
|
+
$bgColor?: string | undefined;
|
|
5
|
+
$border?: string | ({
|
|
6
|
+
top?: string | undefined;
|
|
7
|
+
right?: string | undefined;
|
|
8
|
+
bottom?: string | undefined;
|
|
9
|
+
left?: string | undefined;
|
|
10
|
+
} | {
|
|
11
|
+
horizontal: string;
|
|
12
|
+
top?: string | undefined;
|
|
13
|
+
bottom?: string | undefined;
|
|
14
|
+
} | {
|
|
15
|
+
vertical: string;
|
|
16
|
+
right?: string | undefined;
|
|
17
|
+
left?: string | undefined;
|
|
18
|
+
}) | undefined;
|
|
19
|
+
$borderRadius?: (string | number) | undefined;
|
|
20
|
+
$boxShadow?: string | undefined;
|
|
21
|
+
$gap?: (string | number) | undefined;
|
|
22
|
+
$gridAutoFlow?: "row" | "column" | "dense" | "row dense" | "column dense" | undefined;
|
|
23
|
+
$justifyContent?: "end" | "start" | "center" | "space-between" | "space-around" | "space-evenly" | "stretch" | undefined;
|
|
24
|
+
$justifyItems?: "end" | "start" | "center" | "stretch" | "baseline" | undefined;
|
|
25
|
+
$margin?: (string | number) | ({
|
|
26
|
+
top?: (string | number) | undefined;
|
|
27
|
+
right?: (string | number) | undefined;
|
|
28
|
+
bottom?: (string | number) | undefined;
|
|
29
|
+
left?: (string | number) | undefined;
|
|
30
|
+
} | {
|
|
31
|
+
horizontal: string | number;
|
|
32
|
+
top?: (string | number) | undefined;
|
|
33
|
+
bottom?: (string | number) | undefined;
|
|
34
|
+
} | {
|
|
35
|
+
vertical: string | number;
|
|
36
|
+
right?: (string | number) | undefined;
|
|
37
|
+
left?: (string | number) | undefined;
|
|
38
|
+
}) | undefined;
|
|
39
|
+
$padding?: (string | number) | ({
|
|
40
|
+
top?: (string | number) | undefined;
|
|
41
|
+
right?: (string | number) | undefined;
|
|
42
|
+
bottom?: (string | number) | undefined;
|
|
43
|
+
left?: (string | number) | undefined;
|
|
44
|
+
} | {
|
|
45
|
+
horizontal: string | number;
|
|
46
|
+
top?: (string | number) | undefined;
|
|
47
|
+
bottom?: (string | number) | undefined;
|
|
48
|
+
} | {
|
|
49
|
+
vertical: string | number;
|
|
50
|
+
right?: (string | number) | undefined;
|
|
51
|
+
left?: (string | number) | undefined;
|
|
52
|
+
}) | undefined;
|
|
53
|
+
$placeItems?: "end" | "start" | "center" | "stretch" | undefined;
|
|
54
|
+
} & {
|
|
55
|
+
$gridAutoFlow: string;
|
|
56
|
+
} & {
|
|
57
|
+
$justifyContent: string;
|
|
58
|
+
}, "$gridAutoFlow" | "$justifyContent">;
|
|
59
|
+
export declare const PopoverContent: import("styled-components").StyledComponent<"div", any, {
|
|
60
|
+
$isShaking?: boolean;
|
|
61
|
+
}, never>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import styled, { keyframes, css } from 'styled-components';
|
|
2
|
+
import { Shadow, ShapeRadius, Color } from '@pushwoosh/kit-constants';
|
|
3
|
+
import { Horizontal } from '@pushwoosh/kit-helpers';
|
|
4
|
+
const shakeAnimation = keyframes(["0%,100%{transform:translateX(0);}10%,30%,50%,70%,90%{transform:translateX(-4px);}20%,40%,60%,80%{transform:translateX(4px);}"]);
|
|
5
|
+
export const DropdownRoot = styled(Horizontal).attrs({
|
|
6
|
+
$justifyContent: 'start'
|
|
7
|
+
}).withConfig({
|
|
8
|
+
displayName: "DropdownRoot",
|
|
9
|
+
componentId: "sc-h6jz87-0"
|
|
10
|
+
})(["position:relative;"]);
|
|
11
|
+
export const PopoverContent = styled.div.withConfig({
|
|
12
|
+
displayName: "PopoverContent",
|
|
13
|
+
componentId: "sc-h6jz87-1"
|
|
14
|
+
})(["position:fixed;border-radius:", ";border:1px solid ", ";overflow:hidden;box-shadow:", ";background:", ";z-index:1000000;", ""], ShapeRadius.CONTROL, Color.FORM, Shadow.REGULAR, Color.CLEAR, ({
|
|
15
|
+
$isShaking
|
|
16
|
+
}) => $isShaking && css(["animation:", " 0.4s ease-in-out;"], shakeAnimation));
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import type { CalendarRangeDateProps, CalendarRangeDateTimeProps, CalendarSingleDateProps, CalendarSingleDateTimeProps } from '../CalendarSuperForm/types';
|
|
3
|
+
import type { DateStruct, DateTimeStruct, RangeValue, TzValue } from '../types';
|
|
4
|
+
export type CalendarDropdownSingleDateProps = {
|
|
5
|
+
mode: 'single-date';
|
|
6
|
+
calendarProps: Omit<CalendarSingleDateProps, 'mode' | 'value' | 'onChange'>;
|
|
7
|
+
value?: DateStruct;
|
|
8
|
+
onChange?: (value: DateStruct) => void;
|
|
9
|
+
onSubmit: (value: DateStruct, tz: TzValue) => void;
|
|
10
|
+
};
|
|
11
|
+
export type CalendarDropdownSingleDateTimeProps = {
|
|
12
|
+
mode: 'single-datetime';
|
|
13
|
+
calendarProps: Omit<CalendarSingleDateTimeProps, 'mode' | 'value' | 'onChange'>;
|
|
14
|
+
value?: DateTimeStruct;
|
|
15
|
+
onChange?: (value: DateTimeStruct) => void;
|
|
16
|
+
onSubmit: (value: DateTimeStruct, tz: TzValue) => void;
|
|
17
|
+
};
|
|
18
|
+
export type CalendarDropdownRangeDateProps = {
|
|
19
|
+
mode: 'range-date';
|
|
20
|
+
calendarProps: Omit<CalendarRangeDateProps, 'mode' | 'value' | 'onChange'>;
|
|
21
|
+
value?: RangeValue<DateStruct>;
|
|
22
|
+
onChange?: (value: RangeValue<DateStruct>) => void;
|
|
23
|
+
onSubmit: (value: RangeValue<DateStruct>, tz: TzValue) => void;
|
|
24
|
+
presets?: Array<{
|
|
25
|
+
label: ReactNode | string;
|
|
26
|
+
value: [DateStruct, DateStruct];
|
|
27
|
+
}>;
|
|
28
|
+
};
|
|
29
|
+
export type CalendarDropdownRangeDateTimeProps = {
|
|
30
|
+
mode: 'range-datetime';
|
|
31
|
+
calendarProps: Omit<CalendarRangeDateTimeProps, 'mode' | 'value' | 'onChange'>;
|
|
32
|
+
value?: RangeValue<DateTimeStruct>;
|
|
33
|
+
onChange?: (value: RangeValue<DateTimeStruct>) => void;
|
|
34
|
+
onSubmit: (value: RangeValue<DateTimeStruct>, tz: TzValue) => void;
|
|
35
|
+
presets?: Array<{
|
|
36
|
+
label: ReactNode | string;
|
|
37
|
+
value: [DateTimeStruct, DateTimeStruct];
|
|
38
|
+
}>;
|
|
39
|
+
};
|
|
40
|
+
export type CalendarDropdownProps = CalendarDropdownSingleDateProps | CalendarDropdownSingleDateTimeProps | CalendarDropdownRangeDateProps | CalendarDropdownRangeDateTimeProps;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import { Columns } from '@pushwoosh/kit-helpers';
|
|
3
|
+
import { CellBox, DayHeader } from './styles';
|
|
4
|
+
import { addPeriod, differenceInDays, getLastDayOfMonth, getFirstDayOfWeek, isSamePeriod, compareStructs, pickDateStruct } from '../helpers';
|
|
5
|
+
export const CalendarMonth = ({
|
|
6
|
+
month,
|
|
7
|
+
selectedDay,
|
|
8
|
+
highlightDay,
|
|
9
|
+
periodFrom,
|
|
10
|
+
periodTo,
|
|
11
|
+
disableOnAndBefore,
|
|
12
|
+
disableOnAndAfter,
|
|
13
|
+
disablePeriod,
|
|
14
|
+
onDaySelect,
|
|
15
|
+
onDayMouseEnter,
|
|
16
|
+
onDayMouseLeave,
|
|
17
|
+
firstDayOfWeek = 0
|
|
18
|
+
}) => {
|
|
19
|
+
const [firstDayDate, days] = useMemo(() => {
|
|
20
|
+
const firstDayOfMonth = {
|
|
21
|
+
...month,
|
|
22
|
+
day: 1
|
|
23
|
+
};
|
|
24
|
+
const lastDayOfMonth = getLastDayOfMonth(month);
|
|
25
|
+
const firstDayOfFirstWeek = getFirstDayOfWeek(firstDayOfMonth, firstDayOfWeek);
|
|
26
|
+
const firstDayOfLastWeek = getFirstDayOfWeek(lastDayOfMonth, firstDayOfWeek);
|
|
27
|
+
const daysInCalendar = differenceInDays(firstDayOfLastWeek, firstDayOfFirstWeek) + 7;
|
|
28
|
+
return [firstDayOfFirstWeek, daysInCalendar];
|
|
29
|
+
}, [month, firstDayOfWeek]);
|
|
30
|
+
const today = useMemo(() => {
|
|
31
|
+
const now = new Date();
|
|
32
|
+
return {
|
|
33
|
+
year: now.getFullYear(),
|
|
34
|
+
month: now.getMonth() + 1,
|
|
35
|
+
day: now.getDate()
|
|
36
|
+
};
|
|
37
|
+
}, []);
|
|
38
|
+
const dayLabels = firstDayOfWeek === 0 ? ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'] : ['Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su'];
|
|
39
|
+
return React.createElement(Columns, {
|
|
40
|
+
"$sizes": 7,
|
|
41
|
+
"$gap": 2
|
|
42
|
+
}, dayLabels.map(l => React.createElement(DayHeader, {
|
|
43
|
+
key: l
|
|
44
|
+
}, l)), Array.from({
|
|
45
|
+
length: days
|
|
46
|
+
}).map((_, i) => {
|
|
47
|
+
const curDay = addPeriod(firstDayDate, 'day', i);
|
|
48
|
+
let variant;
|
|
49
|
+
if (!isSamePeriod(month, curDay, 'month')) {
|
|
50
|
+
if (periodFrom && periodTo && compareStructs(periodFrom, periodTo) !== 0 && !isSamePeriod(periodFrom, periodTo, 'month')) {
|
|
51
|
+
const currentMonthStruct = {
|
|
52
|
+
year: month.year,
|
|
53
|
+
month: month.month,
|
|
54
|
+
day: 1
|
|
55
|
+
};
|
|
56
|
+
const outdatedMonthStruct = {
|
|
57
|
+
year: curDay.year,
|
|
58
|
+
month: curDay.month,
|
|
59
|
+
day: 1
|
|
60
|
+
};
|
|
61
|
+
const periodFromMonthStruct = {
|
|
62
|
+
year: periodFrom.year,
|
|
63
|
+
month: periodFrom.month,
|
|
64
|
+
day: 1
|
|
65
|
+
};
|
|
66
|
+
const periodToMonthStruct = {
|
|
67
|
+
year: periodTo.year,
|
|
68
|
+
month: periodTo.month,
|
|
69
|
+
day: 1
|
|
70
|
+
};
|
|
71
|
+
const isCurrentMonthInPeriod = compareStructs(currentMonthStruct, periodFromMonthStruct) >= 0 && compareStructs(currentMonthStruct, periodToMonthStruct) <= 0;
|
|
72
|
+
const isOutdatedMonthInPeriod = compareStructs(outdatedMonthStruct, periodFromMonthStruct) >= 0 && compareStructs(outdatedMonthStruct, periodToMonthStruct) <= 0;
|
|
73
|
+
if (isCurrentMonthInPeriod && isOutdatedMonthInPeriod) {
|
|
74
|
+
variant = 'periodOutdated';
|
|
75
|
+
} else {
|
|
76
|
+
variant = 'outdated';
|
|
77
|
+
}
|
|
78
|
+
} else {
|
|
79
|
+
variant = 'outdated';
|
|
80
|
+
}
|
|
81
|
+
} else if (disableOnAndBefore && compareStructs(curDay, disableOnAndBefore) <= 0 || disableOnAndAfter && compareStructs(curDay, disableOnAndAfter) >= 0 || disablePeriod && compareStructs(curDay, disablePeriod[0]) >= 0 && compareStructs(curDay, disablePeriod[1]) <= 0) {
|
|
82
|
+
if (periodFrom && isSamePeriod(curDay, periodFrom, 'day')) {
|
|
83
|
+
variant = 'selectedDisabled';
|
|
84
|
+
} else {
|
|
85
|
+
variant = 'disabled';
|
|
86
|
+
}
|
|
87
|
+
} else if (selectedDay && isSamePeriod(curDay, selectedDay, 'day')) {
|
|
88
|
+
variant = 'selected';
|
|
89
|
+
} else if (periodFrom && periodTo && isSamePeriod(periodFrom, periodTo, 'day') && isSamePeriod(curDay, periodFrom, 'day')) {
|
|
90
|
+
variant = 'selected';
|
|
91
|
+
} else if (periodFrom && isSamePeriod(curDay, periodFrom, 'day')) {
|
|
92
|
+
variant = 'periodFrom';
|
|
93
|
+
} else if (periodTo && isSamePeriod(curDay, periodTo, 'day')) {
|
|
94
|
+
variant = 'periodTo';
|
|
95
|
+
} else if (highlightDay && isSamePeriod(curDay, highlightDay, 'day')) {
|
|
96
|
+
variant = 'highlighted';
|
|
97
|
+
} else if (periodFrom && periodTo && compareStructs(curDay, periodFrom) > 0 && compareStructs(curDay, periodTo) < 0) {
|
|
98
|
+
variant = 'period';
|
|
99
|
+
}
|
|
100
|
+
return React.createElement(CellBox, {
|
|
101
|
+
key: `${curDay.year}-${curDay.month}-${curDay.day}`,
|
|
102
|
+
"$variant": variant,
|
|
103
|
+
"$isToday": isSamePeriod(curDay, today, 'day'),
|
|
104
|
+
onClick: () => onDaySelect(pickDateStruct(curDay)),
|
|
105
|
+
onMouseEnter: onDayMouseEnter ? () => onDayMouseEnter(curDay) : undefined,
|
|
106
|
+
onMouseLeave: onDayMouseLeave ? () => onDayMouseLeave(curDay) : undefined
|
|
107
|
+
}, curDay.day);
|
|
108
|
+
}));
|
|
109
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type CellBoxVariant = 'selected' | 'selectedDisabled' | 'disabled' | 'outdated' | 'highlighted' | 'period' | 'periodOutdated' | 'periodFrom' | 'periodTo';
|
|
2
|
+
export declare const CellBox: import("styled-components").StyledComponent<"div", any, {
|
|
3
|
+
$variant?: CellBoxVariant;
|
|
4
|
+
$height?: number | string;
|
|
5
|
+
$isToday?: boolean;
|
|
6
|
+
}, never>;
|
|
7
|
+
export declare const DayHeader: import("styled-components").StyledComponent<"div", any, {}, never>;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import styled, { css } from 'styled-components';
|
|
2
|
+
import { Color, ShapeRadius, FontSize, FontWeight, LineHeight } from '@pushwoosh/kit-constants';
|
|
3
|
+
const calendarCellHeight = '28px';
|
|
4
|
+
const selectedCss = css(["color:", ";background:", ";&:hover{background:", ";}"], Color.CLEAR, Color.MAIN, Color.PRIMARY_HOVER);
|
|
5
|
+
const selectedDisabledCss = css(["pointer-events:none;", ""], selectedCss);
|
|
6
|
+
const periodFromCss = css(["border-top-right-radius:0;border-bottom-right-radius:0;", ""], selectedCss);
|
|
7
|
+
const periodToCss = css(["border-top-left-radius:0;border-bottom-left-radius:0;", ""], selectedCss);
|
|
8
|
+
const disabledCss = css(["font-weight:", ";color:", ";border:1px solid ", ";background:linear-gradient( to top left,rgba(0,0,0,0) 0%,rgba(0,0,0,0) calc(50% - 0.8px),", " 50%,rgba(0,0,0,0) calc(50% + 0.8px),rgba(0,0,0,0) 100% );pointer-events:none;"], FontWeight.REGULAR, Color.PHANTOM, Color.DIVIDER, Color.DIVIDER);
|
|
9
|
+
const outdatedCss = css(["opacity:0;pointer-events:none;"]);
|
|
10
|
+
const highlightedCss = css(["outline:1px solid ", ";"], Color.SOFT_LIGHT);
|
|
11
|
+
const periodCss = css(["position:relative;z-index:0;:before{content:'';position:absolute;top:0;left:-1px;right:-1px;bottom:0;background:", ";z-index:-1;}"], Color.SOFT_LIGHT);
|
|
12
|
+
const periodOutdatedCss = css(["position:relative;z-index:0;color:transparent;pointer-events:none;:before{content:'';position:absolute;top:0;left:-1px;right:-1px;bottom:0;background:", ";z-index:-1;}"], Color.SOFT_LIGHT);
|
|
13
|
+
const cssMap = {
|
|
14
|
+
selected: selectedCss,
|
|
15
|
+
selectedDisabled: selectedDisabledCss,
|
|
16
|
+
disabled: disabledCss,
|
|
17
|
+
outdated: outdatedCss,
|
|
18
|
+
highlighted: highlightedCss,
|
|
19
|
+
period: periodCss,
|
|
20
|
+
periodOutdated: periodOutdatedCss,
|
|
21
|
+
periodFrom: periodFromCss,
|
|
22
|
+
periodTo: periodToCss
|
|
23
|
+
};
|
|
24
|
+
const CalendarCellBaseStyled = styled.div.withConfig({
|
|
25
|
+
displayName: "CalendarCellBaseStyled",
|
|
26
|
+
componentId: "sc-hqj3qr-0"
|
|
27
|
+
})(["display:grid;place-items:center;"]);
|
|
28
|
+
export const CellBox = styled(CalendarCellBaseStyled).withConfig({
|
|
29
|
+
displayName: "CellBox",
|
|
30
|
+
componentId: "sc-hqj3qr-1"
|
|
31
|
+
})(["font-size:", ";font-weight:", ";line-height:", ";height:", ";color:", ";border-radius:", ";cursor:pointer;&:hover{background:", ";}", " ", ""], FontSize.SMALL, FontWeight.REGULAR, LineHeight.SMALL, calendarCellHeight, Color.MAIN, ShapeRadius.CONTROL, Color.SOFT_LIGHT, ({
|
|
32
|
+
$variant
|
|
33
|
+
}) => $variant && cssMap[$variant] || '', ({
|
|
34
|
+
$isToday,
|
|
35
|
+
$variant
|
|
36
|
+
}) => $isToday && css(["position:relative;&::after{content:'';position:absolute;bottom:4px;left:50%;transform:translateX(-50%);width:8px;height:2px;border-radius:1px;background:", ";}"], (() => {
|
|
37
|
+
if ($variant === 'selected' || $variant === 'selectedDisabled' || $variant === 'periodFrom' || $variant === 'periodTo') {
|
|
38
|
+
return Color.CLEAR;
|
|
39
|
+
}
|
|
40
|
+
if ($variant === 'disabled') {
|
|
41
|
+
return Color.PHANTOM;
|
|
42
|
+
}
|
|
43
|
+
return Color.MAIN;
|
|
44
|
+
})()));
|
|
45
|
+
export const DayHeader = styled(CalendarCellBaseStyled).withConfig({
|
|
46
|
+
displayName: "DayHeader",
|
|
47
|
+
componentId: "sc-hqj3qr-2"
|
|
48
|
+
})(["height:", ";color:", ";font-weight:", ";font-size:", ";line-height:", ";"], calendarCellHeight, Color.LOCKED, FontWeight.REGULAR, FontSize.SMALL, LineHeight.SMALL);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type DateStruct } from '../types';
|
|
2
|
+
export interface MonthCommonProps {
|
|
3
|
+
selectedDay?: DateStruct;
|
|
4
|
+
highlightDay?: DateStruct;
|
|
5
|
+
periodFrom?: DateStruct;
|
|
6
|
+
periodTo?: DateStruct;
|
|
7
|
+
disableOnAndBefore?: DateStruct;
|
|
8
|
+
disableOnAndAfter?: DateStruct;
|
|
9
|
+
disablePeriod?: [from: DateStruct, to: DateStruct];
|
|
10
|
+
onDaySelect: (day: DateStruct) => void;
|
|
11
|
+
onDayMouseEnter?: (day: DateStruct) => void;
|
|
12
|
+
onDayMouseLeave?: (day: DateStruct) => void;
|
|
13
|
+
firstDayOfWeek?: 0 | 1;
|
|
14
|
+
}
|
|
15
|
+
export interface MonthProps extends MonthCommonProps {
|
|
16
|
+
month: DateStruct;
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React, { type FC } from 'react';
|
|
2
|
+
import { type MonthCommonProps } from '../CalendarMonth/types';
|
|
3
|
+
import { type DateStruct } from '../types';
|
|
4
|
+
export interface CalendarMonthSliderProps extends MonthCommonProps {
|
|
5
|
+
startMonth: DateStruct;
|
|
6
|
+
monthWidth?: number;
|
|
7
|
+
gap?: number;
|
|
8
|
+
visibleCount?: number;
|
|
9
|
+
renderAfter?: () => React.ReactNode;
|
|
10
|
+
}
|
|
11
|
+
export declare const CalendarMonthSlider: FC<CalendarMonthSliderProps>;
|