@pushwoosh/dumb-components 1.1.47 → 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.
Files changed (52) hide show
  1. package/Calendar/CalendarDropdown/CalendarDropdown.d.ts +3 -0
  2. package/Calendar/CalendarDropdown/CalendarDropdown.js +158 -0
  3. package/Calendar/CalendarDropdown/helpers.d.ts +3 -0
  4. package/Calendar/CalendarDropdown/helpers.js +29 -0
  5. package/Calendar/CalendarDropdown/index.d.ts +2 -0
  6. package/Calendar/CalendarDropdown/index.js +1 -0
  7. package/Calendar/CalendarDropdown/styles.d.ts +61 -0
  8. package/Calendar/CalendarDropdown/styles.js +16 -0
  9. package/Calendar/CalendarDropdown/types.d.ts +40 -0
  10. package/Calendar/CalendarDropdown/types.js +1 -0
  11. package/Calendar/CalendarMonth/CalendarMonth.d.ts +3 -0
  12. package/Calendar/CalendarMonth/CalendarMonth.js +109 -0
  13. package/Calendar/CalendarMonth/styles.d.ts +7 -0
  14. package/Calendar/CalendarMonth/styles.js +48 -0
  15. package/Calendar/CalendarMonth/types.d.ts +17 -0
  16. package/Calendar/CalendarMonth/types.js +1 -0
  17. package/Calendar/CalendarMonthSlider/CalendarMonthSlider.d.ts +11 -0
  18. package/Calendar/CalendarMonthSlider/CalendarMonthSlider.js +141 -0
  19. package/Calendar/CalendarMonthSlider/styles.d.ts +67 -0
  20. package/Calendar/CalendarMonthSlider/styles.js +40 -0
  21. package/Calendar/CalendarSuperForm/CalendarSuperForm.d.ts +3 -0
  22. package/Calendar/CalendarSuperForm/CalendarSuperForm.js +101 -0
  23. package/Calendar/CalendarSuperForm/components/CalendarRangePicker/CalendarRangePicker.d.ts +19 -0
  24. package/Calendar/CalendarSuperForm/components/CalendarRangePicker/CalendarRangePicker.js +57 -0
  25. package/Calendar/CalendarSuperForm/components/CalendarRangePicker/getDisabledRanges.d.ts +14 -0
  26. package/Calendar/CalendarSuperForm/components/CalendarRangePicker/getDisabledRanges.js +62 -0
  27. package/Calendar/CalendarSuperForm/components/CalendarTimeAndTimezoneSection/CalendarTimeAndTimezoneSection.d.ts +3 -0
  28. package/Calendar/CalendarSuperForm/components/CalendarTimeAndTimezoneSection/CalendarTimeAndTimezoneSection.js +135 -0
  29. package/Calendar/CalendarSuperForm/components/CalendarTimeAndTimezoneSection/types.d.ts +18 -0
  30. package/Calendar/CalendarSuperForm/components/CalendarTimeAndTimezoneSection/types.js +1 -0
  31. package/Calendar/CalendarSuperForm/components/CalendarTimeInput.d.ts +19 -0
  32. package/Calendar/CalendarSuperForm/components/CalendarTimeInput.js +25 -0
  33. package/Calendar/CalendarSuperForm/components/CalendarTimezoneSelect.d.ts +9 -0
  34. package/Calendar/CalendarSuperForm/components/CalendarTimezoneSelect.js +26 -0
  35. package/Calendar/CalendarSuperForm/index.d.ts +2 -0
  36. package/Calendar/CalendarSuperForm/index.js +1 -0
  37. package/Calendar/CalendarSuperForm/types.d.ts +56 -0
  38. package/Calendar/CalendarSuperForm/types.js +1 -0
  39. package/Calendar/constants.d.ts +5 -0
  40. package/Calendar/constants.js +10 -0
  41. package/Calendar/helpers-tz.d.ts +7 -0
  42. package/Calendar/helpers-tz.js +100 -0
  43. package/Calendar/helpers.d.ts +22 -0
  44. package/Calendar/helpers.js +134 -0
  45. package/Calendar/index.d.ts +2 -0
  46. package/Calendar/index.js +2 -0
  47. package/Calendar/types.d.ts +19 -0
  48. package/Calendar/types.js +1 -0
  49. package/index.d.ts +1 -0
  50. package/index.js +1 -0
  51. package/native/NativeTimeInput.js +2 -2
  52. package/package.json +3 -2
@@ -0,0 +1,141 @@
1
+ import React, { useState } from 'react';
2
+ import { Horizontal, usePersistentFunction, Vertical } from '@pushwoosh/kit-helpers';
3
+ import { ArrowIcon } from '@pushwoosh/kit-icons';
4
+ import { Root, Viewport, Strip, Panel, NavButtonLeft, NavButtonRight, StyledSelect } from './styles';
5
+ import { Button } from '../../Button';
6
+ import { CalendarMonth } from '../CalendarMonth/CalendarMonth';
7
+ import { addPeriod, monthName } from '../helpers';
8
+ function makeBaseline(a, count) {
9
+ return Array.from({
10
+ length: count
11
+ }, (_, i) => addPeriod(a, 'month', i));
12
+ }
13
+ function delayCallback(fn) {
14
+ return setTimeout(() => {
15
+ requestAnimationFrame(fn);
16
+ }, 10);
17
+ }
18
+ export const CalendarMonthSlider = ({
19
+ startMonth,
20
+ monthWidth = 224,
21
+ gap = 16,
22
+ visibleCount = 1,
23
+ renderAfter,
24
+ ...monthProps
25
+ }) => {
26
+ const [anchor, setAnchor] = useState(startMonth);
27
+ const [inTransition, setInTransition] = useState(false);
28
+ const [index, setIndex] = useState(0);
29
+ const [panels, setPanels] = useState(() => makeBaseline(anchor, visibleCount));
30
+ const stepPx = monthWidth + gap;
31
+ const shiftPx = index * (stepPx * -1);
32
+ const toBaseline = usePersistentFunction(mon => {
33
+ setInTransition(false);
34
+ setPanels(makeBaseline(mon, visibleCount));
35
+ setIndex(0);
36
+ });
37
+ const animateForward = () => {
38
+ const newAnchor = addPeriod(anchor, 'month', 1);
39
+ setPanels(makeBaseline(anchor, visibleCount + 1));
40
+ setIndex(0);
41
+ delayCallback(() => {
42
+ setInTransition(true);
43
+ setIndex(1);
44
+ });
45
+ setAnchor(newAnchor);
46
+ };
47
+ const animateBackward = () => {
48
+ const newAnchor = addPeriod(anchor, 'month', -1);
49
+ setPanels(makeBaseline(newAnchor, visibleCount + 1));
50
+ setIndex(1);
51
+ delayCallback(() => {
52
+ setInTransition(true);
53
+ setIndex(0);
54
+ });
55
+ setAnchor(newAnchor);
56
+ };
57
+ const handleMonthChange = (event, panelIndex, currentPanel) => {
58
+ const monthNumber = parseInt(event.target.value, 10);
59
+ const selectedDate = {
60
+ ...currentPanel,
61
+ month: monthNumber
62
+ };
63
+ const newAnchor = addPeriod(selectedDate, 'month', -panelIndex);
64
+ setAnchor(newAnchor);
65
+ setPanels(makeBaseline(newAnchor, visibleCount));
66
+ };
67
+ const handleYearChange = (event, panelIndex, currentPanel) => {
68
+ const yearNumber = parseInt(event.target.value, 10);
69
+ const selectedDate = {
70
+ ...currentPanel,
71
+ year: yearNumber
72
+ };
73
+ const newAnchor = addPeriod(selectedDate, 'month', -panelIndex);
74
+ setAnchor(newAnchor);
75
+ setPanels(makeBaseline(newAnchor, visibleCount));
76
+ };
77
+ const currentYear = new Date().getFullYear();
78
+ const yearOptions = Array.from({
79
+ length: 11
80
+ }, (_, i) => currentYear - 5 + i);
81
+ const viewportWidth = `${visibleCount * monthWidth + gap * (visibleCount - 1)}px`;
82
+ return React.createElement(Root, {
83
+ style: {
84
+ ['--slider-width']: viewportWidth,
85
+ ['--col-width']: `${monthWidth}px`,
86
+ ['--gap']: `${gap}px`,
87
+ ['--shift']: `${shiftPx}px`
88
+ }
89
+ }, React.createElement(Viewport, null, React.createElement(Strip, {
90
+ withTransition: inTransition,
91
+ onTransitionEnd: () => {
92
+ toBaseline(anchor);
93
+ }
94
+ }, panels.map((p, i) =>
95
+ // eslint-disable-next-line react/no-array-index-key
96
+ React.createElement(Panel, {
97
+ key: `${p.year}-${p.month}-${i}`
98
+ }, React.createElement(Vertical, {
99
+ "$gap": 4
100
+ }, React.createElement(Horizontal, {
101
+ "$justifyContent": "center",
102
+ "$gap": 6
103
+ }, React.createElement(StyledSelect, {
104
+ value: p.month,
105
+ onChange: e => handleMonthChange(e, i, p)
106
+ }, Array.from({
107
+ length: 12
108
+ }, (_, idx) => React.createElement("option", {
109
+ key: idx + 1,
110
+ value: idx + 1
111
+ }, monthName(idx + 1, 'long')))), React.createElement(StyledSelect, {
112
+ value: p.year,
113
+ onChange: e => handleYearChange(e, i, p)
114
+ }, yearOptions.map(year => React.createElement("option", {
115
+ key: year,
116
+ value: year
117
+ }, year)))), React.createElement(CalendarMonth, {
118
+ month: p,
119
+ ...monthProps
120
+ })))))), React.createElement(NavButtonLeft, null, React.createElement(Button, {
121
+ color: "secondary",
122
+ size: "compact",
123
+ view: "ghost",
124
+ icon: React.createElement(ArrowIcon, {
125
+ size: "small",
126
+ direction: "left"
127
+ }),
128
+ onClick: animateBackward,
129
+ isDisabled: inTransition
130
+ })), React.createElement(NavButtonRight, null, React.createElement(Button, {
131
+ color: "secondary",
132
+ size: "compact",
133
+ view: "ghost",
134
+ icon: React.createElement(ArrowIcon, {
135
+ size: "small",
136
+ direction: "right"
137
+ }),
138
+ onClick: animateForward,
139
+ isDisabled: inTransition
140
+ })), renderAfter === null || renderAfter === void 0 ? void 0 : renderAfter());
141
+ };
@@ -0,0 +1,67 @@
1
+ export declare const Root: 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
+ }, "$gridAutoFlow">;
57
+ export declare const Viewport: import("styled-components").StyledComponent<"div", any, {}, never>;
58
+ export declare const Strip: import("styled-components").StyledComponent<"div", any, {
59
+ withTransition: boolean;
60
+ }, never>;
61
+ export declare const Panel: import("styled-components").StyledComponent<"div", any, {}, never>;
62
+ export declare const Arrow: import("styled-components").StyledComponent<import("react").FC<import("@pushwoosh/kit-icons").ArrowIconProps>, any, {
63
+ size: "small";
64
+ }, "size">;
65
+ export declare const NavButtonLeft: import("styled-components").StyledComponent<"div", any, {}, never>;
66
+ export declare const NavButtonRight: import("styled-components").StyledComponent<"div", any, {}, never>;
67
+ export declare const StyledSelect: import("styled-components").StyledComponent<"select", any, {}, never>;
@@ -0,0 +1,40 @@
1
+ import styled, { css } from 'styled-components';
2
+ import { Color, FontFamily, FontSize, FontWeight, LineHeight, UnitSize } from '@pushwoosh/kit-constants';
3
+ import { Vertical } from '@pushwoosh/kit-helpers';
4
+ import { ArrowIcon } from '@pushwoosh/kit-icons';
5
+ export const Root = styled(Vertical).withConfig({
6
+ displayName: "Root",
7
+ componentId: "sc-1qqlxvi-0"
8
+ })(["position:relative;width:var(--slider-width,0px);"]);
9
+ export const Viewport = styled.div.withConfig({
10
+ displayName: "Viewport",
11
+ componentId: "sc-1qqlxvi-1"
12
+ })(["position:relative;overflow:hidden;width:var(--slider-width,0px);"]);
13
+ export const Strip = styled.div.withConfig({
14
+ displayName: "Strip",
15
+ componentId: "sc-1qqlxvi-2"
16
+ })(["display:grid;grid-auto-flow:column;grid-auto-columns:var(--col-width,0px);column-gap:var(--gap,0px);transform:translateX(var(--shift,0px));", ""], ({
17
+ withTransition
18
+ }) => withTransition && css(["transition:transform var(--duration,150ms) ease-out;"]));
19
+ export const Panel = styled.div.withConfig({
20
+ displayName: "Panel",
21
+ componentId: "sc-1qqlxvi-3"
22
+ })(["width:var(--col-width,0px);"]);
23
+ export const Arrow = styled(ArrowIcon).attrs({
24
+ size: 'small'
25
+ }).withConfig({
26
+ displayName: "Arrow",
27
+ componentId: "sc-1qqlxvi-4"
28
+ })(["color:", ";cursor:pointer;&:hover{color:", ";transform:scale(1.2);transition:transform 0.2s ease-in-out;}"], Color.SOFT_HOVER, Color.SOFT_HOVER);
29
+ export const NavButtonLeft = styled.div.withConfig({
30
+ displayName: "NavButtonLeft",
31
+ componentId: "sc-1qqlxvi-5"
32
+ })(["position:absolute;top:0;left:0;"]);
33
+ export const NavButtonRight = styled.div.withConfig({
34
+ displayName: "NavButtonRight",
35
+ componentId: "sc-1qqlxvi-6"
36
+ })(["position:absolute;top:0;right:0;"]);
37
+ export const StyledSelect = styled.select.withConfig({
38
+ displayName: "StyledSelect",
39
+ componentId: "sc-1qqlxvi-7"
40
+ })(["appearance:none;background:transparent;border:none;padding:0;height:", ";cursor:pointer;color:", ";font-family:", ";font-size:", ";font-weight:", ";line-height:", ";text-transform:uppercase;&:hover{color:", ";}&:focus{outline:none;}"], UnitSize.COMPACT_HEIGHT, Color.SOFT, FontFamily.MAIN, FontSize.HEADING5, FontWeight.MEDIUM, LineHeight.HEADING5, Color.PRIMARY_HOVER);
@@ -0,0 +1,3 @@
1
+ import { type FC } from 'react';
2
+ import { type CalendarSuperFormProps } from './types';
3
+ export declare const CalendarSuperForm: FC<CalendarSuperFormProps>;
@@ -0,0 +1,101 @@
1
+ import React from 'react';
2
+ import { Color } from '@pushwoosh/kit-constants';
3
+ import { Vertical } from '@pushwoosh/kit-helpers';
4
+ import { Text } from '@pushwoosh/kit-typography';
5
+ import { CalendarRangePicker } from './components/CalendarRangePicker/CalendarRangePicker';
6
+ import { CalendarTimeAndTimezoneSection } from './components/CalendarTimeAndTimezoneSection/CalendarTimeAndTimezoneSection';
7
+ export const CalendarSuperForm = props => {
8
+ const {
9
+ mode,
10
+ value,
11
+ onChange,
12
+ timezone,
13
+ onChangeTimezone,
14
+ disableOnAndBefore,
15
+ disableOnAndAfter,
16
+ minDays,
17
+ maxDays,
18
+ visibleCount,
19
+ monthWidth,
20
+ gap,
21
+ firstDayOfWeek
22
+ } = props;
23
+ const isRangePicker = mode === 'range-date' || mode === 'range-datetime';
24
+ const withTime = mode === 'single-datetime' || mode === 'range-datetime';
25
+ return React.createElement(Vertical, {
26
+ "$gap": 8
27
+ }, React.createElement(CalendarRangePicker, {
28
+ disableOnAndBefore: disableOnAndBefore,
29
+ disableOnAndAfter: disableOnAndAfter,
30
+ minDays: minDays,
31
+ maxDays: maxDays,
32
+ value: isRangePicker ? value : value ? [value] : [],
33
+ onChange: val => {
34
+ if (isRangePicker) {
35
+ if (withTime) {
36
+ if (val.length === 2) {
37
+ onChange([{
38
+ ...val[0],
39
+ hour: 0,
40
+ minute: 0,
41
+ second: 0,
42
+ millisecond: 0
43
+ }, {
44
+ ...val[1],
45
+ hour: 23,
46
+ minute: 59,
47
+ second: 59,
48
+ millisecond: 999
49
+ }]);
50
+ } else if (val.length === 1) {
51
+ onChange([{
52
+ hour: 0,
53
+ minute: 0,
54
+ second: 0,
55
+ millisecond: 0,
56
+ ...val[0]
57
+ }]);
58
+ }
59
+ } else {
60
+ onChange(val);
61
+ }
62
+ } else if (val[0]) {
63
+ if (withTime) {
64
+ onChange({
65
+ hour: 0,
66
+ minute: 0,
67
+ second: 0,
68
+ millisecond: 0,
69
+ ...value,
70
+ ...val[0]
71
+ });
72
+ } else {
73
+ onChange(val[0]);
74
+ }
75
+ }
76
+ },
77
+ singleMode: !isRangePicker,
78
+ visibleCount: visibleCount !== undefined ? visibleCount : isRangePicker ? 2 : 1,
79
+ monthWidth: monthWidth,
80
+ gap: gap,
81
+ renderAfter: withTime || maxDays && maxDays > 0 ? () => {
82
+ return React.createElement(Vertical, {
83
+ "$gap": 8,
84
+ "$margin": {
85
+ top: 16
86
+ }
87
+ }, maxDays && maxDays > 0 && React.createElement(Text, {
88
+ "$variant": "footnote",
89
+ "$color": Color.LOCKED
90
+ }, `Max length: ${maxDays} days`), withTime && timezone && onChangeTimezone && React.createElement(CalendarTimeAndTimezoneSection, {
91
+ isRangePicker: isRangePicker,
92
+ value: value,
93
+ onChange: onChange,
94
+ timezone: timezone,
95
+ onChangeTimezone: onChangeTimezone,
96
+ visibleCount: visibleCount
97
+ }));
98
+ } : undefined,
99
+ firstDayOfWeek: firstDayOfWeek
100
+ }));
101
+ };
@@ -0,0 +1,19 @@
1
+ import React, { type FC } from 'react';
2
+ import { type DateStruct } from '../../../types';
3
+ export type RangePickerValue = [DateStruct, DateStruct] | [DateStruct] | [];
4
+ type CalendarRangePickerProps = {
5
+ value: RangePickerValue;
6
+ visibleCount?: number;
7
+ monthWidth?: number;
8
+ gap?: number;
9
+ singleMode?: boolean;
10
+ disableOnAndBefore?: DateStruct;
11
+ disableOnAndAfter?: DateStruct;
12
+ minDays?: number;
13
+ maxDays?: number;
14
+ onChange: (range: RangePickerValue) => void;
15
+ renderAfter?: () => React.ReactNode;
16
+ firstDayOfWeek?: 0 | 1;
17
+ };
18
+ export declare const CalendarRangePicker: FC<CalendarRangePickerProps>;
19
+ export {};
@@ -0,0 +1,57 @@
1
+ import React, { useRef } from 'react';
2
+ import { getDisabledRanges } from './getDisabledRanges';
3
+ import { CalendarMonthSlider } from '../../../CalendarMonthSlider/CalendarMonthSlider';
4
+ import { compareStructs } from '../../../helpers';
5
+ export const CalendarRangePicker = ({
6
+ value,
7
+ visibleCount,
8
+ monthWidth = 224,
9
+ gap = 16,
10
+ singleMode,
11
+ disableOnAndBefore,
12
+ disableOnAndAfter,
13
+ minDays,
14
+ maxDays,
15
+ onChange,
16
+ renderAfter,
17
+ firstDayOfWeek
18
+ }) => {
19
+ const startMonthRef = useRef();
20
+ if (!startMonthRef.current) {
21
+ const d = new Date();
22
+ startMonthRef.current = value[0] || {
23
+ year: d.getFullYear(),
24
+ month: d.getMonth() + 1,
25
+ day: d.getDate()
26
+ };
27
+ }
28
+ return React.createElement(CalendarMonthSlider, {
29
+ startMonth: startMonthRef.current,
30
+ visibleCount: visibleCount,
31
+ monthWidth: monthWidth,
32
+ gap: gap,
33
+ renderAfter: renderAfter,
34
+ firstDayOfWeek: firstDayOfWeek,
35
+ selectedDay: singleMode ? value[0] : undefined,
36
+ periodFrom: !singleMode ? value[0] : undefined,
37
+ periodTo: !singleMode ? value[1] : undefined,
38
+ ...getDisabledRanges({
39
+ value,
40
+ disableOnAndBefore,
41
+ disableOnAndAfter,
42
+ minDays,
43
+ maxDays
44
+ }),
45
+ onDaySelect: day => {
46
+ if (singleMode || !value[0] || value.length === 2) {
47
+ onChange([day]);
48
+ } else if (value.length === 1) {
49
+ if (compareStructs(day, value[0]) < 0) {
50
+ onChange([day, value[0]]);
51
+ } else {
52
+ onChange([value[0], day]);
53
+ }
54
+ }
55
+ }
56
+ });
57
+ };
@@ -0,0 +1,14 @@
1
+ import { type DateStruct } from '../../../types';
2
+ export type DisableSpec = {
3
+ disableOnAndBefore?: DateStruct;
4
+ disableOnAndAfter?: DateStruct;
5
+ disablePeriod?: [from: DateStruct, to: DateStruct];
6
+ };
7
+ export type GetDisabledArgs = {
8
+ value?: [from: DateStruct, to: DateStruct] | [from: DateStruct] | [];
9
+ disableOnAndBefore?: DateStruct;
10
+ disableOnAndAfter?: DateStruct;
11
+ minDays?: number;
12
+ maxDays?: number;
13
+ };
14
+ export declare function getDisabledRanges(args: GetDisabledArgs): DisableSpec;
@@ -0,0 +1,62 @@
1
+ import { addPeriod, compareStructs } from '../../../helpers';
2
+ export function getDisabledRanges(args) {
3
+ const {
4
+ value,
5
+ disableOnAndBefore,
6
+ disableOnAndAfter,
7
+ minDays,
8
+ maxDays
9
+ } = args;
10
+ if (!value || value.length === 0) {
11
+ return {
12
+ disableOnAndBefore,
13
+ disableOnAndAfter
14
+ };
15
+ }
16
+ const result = {};
17
+ if (value.length === 1) {
18
+ const startDate = value[0];
19
+ if (minDays !== undefined && minDays > 1) {
20
+ const beforeDate = addPeriod(startDate, 'day', -(minDays - 2));
21
+ const afterDate = addPeriod(startDate, 'day', minDays - 2);
22
+ result.disablePeriod = [beforeDate, afterDate];
23
+ }
24
+ if (maxDays !== undefined) {
25
+ const maxBefore = addPeriod(startDate, 'day', -maxDays);
26
+ const maxAfter = addPeriod(startDate, 'day', maxDays);
27
+ if (result.disableOnAndBefore) {
28
+ if (compareStructs(maxBefore, result.disableOnAndBefore) > 0) {
29
+ result.disableOnAndBefore = maxBefore;
30
+ }
31
+ } else {
32
+ result.disableOnAndBefore = maxBefore;
33
+ }
34
+ if (result.disableOnAndAfter) {
35
+ if (compareStructs(maxAfter, result.disableOnAndAfter) < 0) {
36
+ result.disableOnAndAfter = maxAfter;
37
+ }
38
+ } else {
39
+ result.disableOnAndAfter = maxAfter;
40
+ }
41
+ }
42
+ }
43
+ if (disableOnAndBefore) {
44
+ if (result.disableOnAndBefore) {
45
+ if (compareStructs(disableOnAndBefore, result.disableOnAndBefore) > 0) {
46
+ result.disableOnAndBefore = disableOnAndBefore;
47
+ }
48
+ } else {
49
+ result.disableOnAndBefore = disableOnAndBefore;
50
+ }
51
+ }
52
+ if (disableOnAndAfter) {
53
+ if (result.disableOnAndAfter) {
54
+ if (compareStructs(disableOnAndAfter, result.disableOnAndAfter) < 0) {
55
+ result.disableOnAndAfter = disableOnAndAfter;
56
+ }
57
+ } else {
58
+ result.disableOnAndAfter = disableOnAndAfter;
59
+ }
60
+ }
61
+ return result;
62
+ }
@@ -0,0 +1,3 @@
1
+ import { type FC } from 'react';
2
+ import { type CalendarTimeAndTimezoneSectionProps } from './types';
3
+ export declare const CalendarTimeAndTimezoneSection: FC<CalendarTimeAndTimezoneSectionProps>;
@@ -0,0 +1,135 @@
1
+ import React, { useState } from 'react';
2
+ import { Color, ShapeRadius } from '@pushwoosh/kit-constants';
3
+ import { Columns, Horizontal, Vertical } from '@pushwoosh/kit-helpers';
4
+ import { TimeIcon } from '@pushwoosh/kit-icons';
5
+ import { H5, Text } from '@pushwoosh/kit-typography';
6
+ import { Button } from '../../../../Button';
7
+ import { extendPeriodStruct, formatTwoDigitNumber } from '../../../helpers';
8
+ import { formatTimezoneShort } from '../../../helpers-tz';
9
+ import { CalendarTimeInput } from '../CalendarTimeInput';
10
+ import { CalendarTimezoneSelect } from '../CalendarTimezoneSelect';
11
+ export const CalendarTimeAndTimezoneSection = ({
12
+ isRangePicker,
13
+ value,
14
+ onChange,
15
+ timezone,
16
+ onChangeTimezone,
17
+ visibleCount
18
+ }) => {
19
+ const [expanded, setExpanded] = useState(false);
20
+ const timezoneShort = formatTimezoneShort(timezone);
21
+ const getSelectedTimeText = () => {
22
+ if (isRangePicker) {
23
+ const [startValue, endValue] = value;
24
+ const startTime = startValue ? `${formatTwoDigitNumber(startValue.hour || 0)}:${formatTwoDigitNumber(startValue.minute || 0)}` : '00:00';
25
+ const endTime = endValue ? `${formatTwoDigitNumber(endValue.hour || 0)}:${formatTwoDigitNumber(endValue.minute || 0)}` : '23:59';
26
+ return `${startTime} – ${endTime}`;
27
+ }
28
+ return value ? `${formatTwoDigitNumber(value.hour || 0)}:${formatTwoDigitNumber(value.minute || 0)}` : '00:00';
29
+ };
30
+ const showCollapsed = isRangePicker && !expanded;
31
+ const isDisabled = isRangePicker ? value.length !== 2 : !value;
32
+ let padding;
33
+ let backgroundColor;
34
+ let borderRadius;
35
+ if (!isRangePicker) {
36
+ padding = 0;
37
+ backgroundColor = undefined;
38
+ borderRadius = undefined;
39
+ } else if (showCollapsed) {
40
+ padding = {
41
+ vertical: 6,
42
+ horizontal: 12
43
+ };
44
+ backgroundColor = Color.SOFT_LIGHT;
45
+ borderRadius = ShapeRadius.SECTION;
46
+ } else {
47
+ padding = {
48
+ top: 6,
49
+ horizontal: 12,
50
+ bottom: 12
51
+ };
52
+ backgroundColor = Color.SOFT_LIGHT;
53
+ borderRadius = ShapeRadius.SECTION;
54
+ }
55
+ return React.createElement(Vertical, {
56
+ "$padding": padding,
57
+ "$borderRadius": borderRadius,
58
+ "$bgColor": backgroundColor
59
+ }, showCollapsed ? React.createElement(Columns, {
60
+ "$sizes": "max-content 1fr max-content",
61
+ "$gap": 6,
62
+ "$alignItems": "center"
63
+ }, React.createElement(TimeIcon, {
64
+ size: "small",
65
+ view: "lined"
66
+ }), React.createElement(Text, {
67
+ "$variant": "footnote"
68
+ }, getSelectedTimeText(), ' ', timezoneShort), React.createElement(Button, {
69
+ color: "secondary",
70
+ size: "compact",
71
+ view: "ghost",
72
+ onClick: () => setExpanded(true)
73
+ }, "Expand time")) : React.createElement(React.Fragment, null, isRangePicker && React.createElement(Columns, {
74
+ "$sizes": "1fr max-content",
75
+ "$gap": 8,
76
+ "$alignItems": "center"
77
+ }, React.createElement(H5, null, "Time range:"), React.createElement(Button, {
78
+ color: "secondary",
79
+ size: "compact",
80
+ view: "ghost",
81
+ onClick: () => setExpanded(false)
82
+ }, "Collapse time")), !isRangePicker ? React.createElement(Horizontal, {
83
+ "$alignItems": "center",
84
+ "$gap": 8,
85
+ "$justifyContent": "start"
86
+ }, React.createElement(CalendarTimeInput, {
87
+ value: value,
88
+ onChange: time => {
89
+ const newStruct = extendPeriodStruct(value, time);
90
+ onChange(newStruct);
91
+ },
92
+ disabled: isDisabled
93
+ }), React.createElement(CalendarTimezoneSelect, {
94
+ timezone: timezone,
95
+ onChange: onChangeTimezone,
96
+ isDisabled: isDisabled
97
+ })) : React.createElement(Columns, {
98
+ "$sizes": visibleCount === 1 ? '1fr' : 'auto 1fr',
99
+ "$gap": 8
100
+ }, React.createElement(Horizontal, {
101
+ "$alignItems": "center",
102
+ "$gap": 8,
103
+ "$justifyContent": "start"
104
+ }, React.createElement(CalendarTimeInput, {
105
+ value: value[0],
106
+ onChange: time => {
107
+ const oldStruct = value[0];
108
+ const newStruct = extendPeriodStruct(oldStruct, time);
109
+ const newValue = value.length === 2 ? [newStruct, value[1]] : [newStruct];
110
+ onChange(newValue);
111
+ },
112
+ disabled: isDisabled
113
+ }), React.createElement("span", null, "\u2013"), React.createElement(CalendarTimeInput, {
114
+ value: value[1],
115
+ onChange: time => {
116
+ const oldStruct = value[1];
117
+ const newStruct = extendPeriodStruct(oldStruct, time);
118
+ const newValue = value.length === 2 ? [value[0], newStruct] : [newStruct];
119
+ onChange(newValue);
120
+ },
121
+ endPeriod: true,
122
+ disabled: isDisabled
123
+ })), React.createElement(CalendarTimezoneSelect, {
124
+ timezone: timezone,
125
+ onChange: onChangeTimezone,
126
+ isDisabled: isDisabled
127
+ })), isDisabled && React.createElement(Horizontal, {
128
+ "$margin": {
129
+ top: 4
130
+ }
131
+ }, React.createElement(Text, {
132
+ "$variant": "footnote",
133
+ "$color": Color.LOCKED
134
+ }, "Please select", ' ', isRangePicker ? 'date range' : 'date', ' ', "first to set time"))));
135
+ };
@@ -0,0 +1,18 @@
1
+ import { type DateTimeStruct, type RangeValue, type SingleValue } from '../../../types';
2
+ interface BaseProps {
3
+ timezone: string;
4
+ onChangeTimezone: (timezone: string) => void;
5
+ visibleCount?: number;
6
+ }
7
+ export interface CalendarTimeAndTimezoneSectionSingleProps extends BaseProps {
8
+ isRangePicker?: false;
9
+ value?: SingleValue<DateTimeStruct>;
10
+ onChange: (value: SingleValue<DateTimeStruct>) => void;
11
+ }
12
+ export interface CalendarTimeAndTimezoneSectionRangeProps extends BaseProps {
13
+ isRangePicker: true;
14
+ value: RangeValue<DateTimeStruct>;
15
+ onChange: (value: RangeValue<DateTimeStruct>) => void;
16
+ }
17
+ export type CalendarTimeAndTimezoneSectionProps = CalendarTimeAndTimezoneSectionSingleProps | CalendarTimeAndTimezoneSectionRangeProps;
18
+ export {};