@via-profit/ui-kit 0.1.0-rc.63 → 0.1.0-rc.64

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.
@@ -34,6 +34,10 @@ export interface AutocompleteProps<T, Multiple extends boolean | undefined = und
34
34
  * Should the autocomplete element be cleared when blur and if no element is selected
35
35
  */
36
36
  readonly clearIfNotSelected?: boolean;
37
+ /**
38
+ * Show clear button if clearable is true
39
+ */
40
+ readonly clearable?: boolean;
37
41
  /**
38
42
  * items render function
39
43
  */
@@ -44,7 +48,7 @@ export interface AutocompleteProps<T, Multiple extends boolean | undefined = und
44
48
  readonly getOptionSelected?: GetOptionSelected<T>;
45
49
  readonly onRequestClose?: OnRequestClose;
46
50
  readonly onInputChange?: React.ChangeEventHandler<HTMLInputElement>;
47
- readonly onRequestOpen?: (event: React.KeyboardEvent<HTMLInputElement> | React.MouseEvent<HTMLInputElement> | React.FocusEvent<HTMLInputElement, Element>) => void;
51
+ readonly onRequestOpen?: (event: React.KeyboardEvent<HTMLElement> | React.MouseEvent<HTMLElement> | React.FocusEvent<HTMLInputElement, Element>) => void;
48
52
  /**
49
53
  * Overridable components map
50
54
  */
@@ -46,7 +46,7 @@ const context_1 = __importStar(require("./context"));
46
46
  const IconClear_1 = __importDefault(require("./IconClear"));
47
47
  const ClickOutside_1 = require("../ClickOutside");
48
48
  const Autocomplete = react_1.default.forwardRef((props, ref) => {
49
- const { items, value, multiple, isOpen = false, isLoading = false, clearIfNotSelected = true, anchorPos = 'auto-start-end', requiredAsterisk, startIcon, fullWidth, placeholder, label, error, errorText, inputRef, filterItems, children, onChange, selectedItemToString, onInputChange, getOptionSelected, onRequestOpen = () => undefined, onRequestClose = () => undefined, overrides } = props, nativeInputProps = __rest(props, ["items", "value", "multiple", "isOpen", "isLoading", "clearIfNotSelected", "anchorPos", "requiredAsterisk", "startIcon", "fullWidth", "placeholder", "label", "error", "errorText", "inputRef", "filterItems", "children", "onChange", "selectedItemToString", "onInputChange", "getOptionSelected", "onRequestOpen", "onRequestClose", "overrides"]);
49
+ const { items, value, multiple, isOpen = false, isLoading = false, clearIfNotSelected = true, anchorPos = 'auto-start-end', requiredAsterisk, startIcon, fullWidth, placeholder, label, error, errorText, inputRef, filterItems, children, onChange, selectedItemToString, clearable = true, onInputChange, getOptionSelected, onRequestOpen = () => undefined, onRequestClose = () => undefined, overrides } = props, nativeInputProps = __rest(props, ["items", "value", "multiple", "isOpen", "isLoading", "clearIfNotSelected", "anchorPos", "requiredAsterisk", "startIcon", "fullWidth", "placeholder", "label", "error", "errorText", "inputRef", "filterItems", "children", "onChange", "selectedItemToString", "clearable", "onInputChange", "getOptionSelected", "onRequestOpen", "onRequestClose", "overrides"]);
50
50
  const menuRef = react_1.default.useRef(null);
51
51
  const fieldInputRef = react_1.default.useRef(null);
52
52
  const isFocusedRef = react_1.default.useRef(false);
@@ -178,7 +178,7 @@ const Autocomplete = react_1.default.forwardRef((props, ref) => {
178
178
  };
179
179
  }, [onRequestClose, anchorElement]);
180
180
  return (react_1.default.createElement("div", null,
181
- react_1.default.useMemo(() => (react_1.default.createElement(overridesMap.TextField, Object.assign({ placeholder: placeholder, label: label, error: error, requiredAsterisk: requiredAsterisk, errorText: errorText, fullWidth: fullWidth, startIcon: startIcon, isLoading: currentLoading, endIcon: react_1.default.createElement(Button_1.default, { iconOnly: true, type: "button", onClick: () => (currentLoading ? 'undefined' : clear()) }, currentLoading ? react_1.default.createElement(Spinner_1.default, null) : react_1.default.createElement(IconClear_1.default, null)) }, nativeInputProps, { onKeyDown: event => {
181
+ react_1.default.useMemo(() => (react_1.default.createElement(overridesMap.TextField, Object.assign({ placeholder: placeholder, label: label, error: error, requiredAsterisk: requiredAsterisk, errorText: errorText, fullWidth: fullWidth, startIcon: startIcon, isLoading: currentLoading, endIcon: clearable ? (react_1.default.createElement(Button_1.default, { iconOnly: true, type: "button", onClick: () => (currentLoading ? 'undefined' : clear()) }, currentLoading ? react_1.default.createElement(Spinner_1.default, null) : react_1.default.createElement(IconClear_1.default, null))) : undefined }, nativeInputProps, { onKeyDown: event => {
182
182
  inputKeydownEvent(event);
183
183
  if (typeof nativeInputProps.onKeyDown === 'function') {
184
184
  nativeInputProps.onKeyDown(event);
@@ -228,6 +228,7 @@ const Autocomplete = react_1.default.forwardRef((props, ref) => {
228
228
  }));
229
229
  // dispatch(actionSetPartial({ inputValue: event.currentTarget.value }));
230
230
  } }))), [
231
+ overridesMap,
231
232
  placeholder,
232
233
  label,
233
234
  error,
@@ -236,14 +237,14 @@ const Autocomplete = react_1.default.forwardRef((props, ref) => {
236
237
  fullWidth,
237
238
  startIcon,
238
239
  currentLoading,
239
- inputKeydownEvent,
240
+ clearable,
241
+ nativeInputProps,
240
242
  inputValue,
241
243
  clear,
242
- overridesMap,
244
+ inputKeydownEvent,
243
245
  anchorElement,
244
246
  dispatch,
245
247
  inputRef,
246
- nativeInputProps,
247
248
  onRequestOpen,
248
249
  onInputChange,
249
250
  filterItems,
@@ -5,5 +5,5 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const react_1 = __importDefault(require("react"));
7
7
  const TextField_1 = __importDefault(require("../TextField"));
8
- const AutocompletetextField = (props, ref) => react_1.default.createElement(TextField_1.default, Object.assign({}, props, { ref: ref }));
9
- exports.default = react_1.default.forwardRef(AutocompletetextField);
8
+ const AutocompleteTextField = (props, ref) => react_1.default.createElement(TextField_1.default, Object.assign({}, props, { ref: ref }));
9
+ exports.default = react_1.default.forwardRef(AutocompleteTextField);
@@ -24,9 +24,11 @@ const Container = styled_1.default.div `
24
24
  `;
25
25
  const CalendarWeekDaysBar = (props, ref) => {
26
26
  const { locale, week, format } = props, restProps = __rest(props, ["locale", "week", "format"]);
27
- const weekDayLabels = react_1.default.useMemo(() => week.days.map(day => new Intl.DateTimeFormat(locale, {
28
- weekday: format,
29
- }).format(day.date)), [format, locale, week]);
27
+ const weekDayLabels = react_1.default.useMemo(() => week.days.map(day => typeof Intl !== 'undefined'
28
+ ? new Intl.DateTimeFormat(locale, {
29
+ weekday: format,
30
+ }).format(day.date)
31
+ : '\u{0020}'), [format, locale, week]);
30
32
  return (react_1.default.createElement(Container, Object.assign({}, restProps, { ref: ref }), weekDayLabels.map(label => (react_1.default.createElement(CalendarWeekDayLabel_1.default, { key: label }, label)))));
31
33
  };
32
34
  exports.default = react_1.default.forwardRef(CalendarWeekDaysBar);
@@ -3,11 +3,9 @@ import { WeekNameLabelFormat } from './CalendarWeekDaysBar';
3
3
  import { WeekDayName } from './use-calendar';
4
4
  export type CalendarProps = {
5
5
  readonly value?: Date;
6
- readonly onChange?: (date: Date) => void;
7
- readonly onDateSelect?: (date: readonly Date[]) => void;
6
+ readonly defaultValue?: Date;
7
+ readonly onChange: (dates: Date) => void;
8
8
  readonly locale?: string;
9
- readonly selected?: readonly Date[];
10
- readonly selectMultiple?: boolean;
11
9
  readonly badges?: readonly CalendarDadge[];
12
10
  readonly maxDate?: Date;
13
11
  readonly minDate?: Date;
package/Calendar/index.js CHANGED
@@ -25,6 +25,7 @@ const CalendarControlButton_1 = __importDefault(require("./CalendarControlButton
25
25
  const CalendarHeading_1 = __importDefault(require("./CalendarHeading"));
26
26
  const CalendarSubheading_1 = __importDefault(require("./CalendarSubheading"));
27
27
  const defaultState = {
28
+ calendarValue: new Date(),
28
29
  calendarDate: new Date(),
29
30
  calendarCurrentView: 'days',
30
31
  calendarViewVariants: ['years', 'monthes', 'days'],
@@ -38,9 +39,22 @@ const reducer = (state, action) => {
38
39
  }
39
40
  };
40
41
  const Calendar = props => {
41
- const { minDate = new Date(new Date().getFullYear() - 100, 0, 1, 0, 0, 0), maxDate = new Date(new Date().getFullYear() + 100, 0, 1, 0, 0, 0), weekStartDay = 'monday', locale = 'ru-RU', displayLeadingZero = false, onDateSelect, onChange, selected = [], badges = [], selectMultiple = false, value, markToday, weekDayLabelFormat = 'short', accentColor = 'primary', prevMonthButtonTooltip, nextMonthButtonTooltip, changeMonthButtonTooltip, changeYearButtonTooltip, views = defaultState.calendarViewVariants, initialView = defaultState.calendarCurrentView, resetButtonLabel, toodayButtonLabel, heading, subheading, footer, } = props;
42
- const initialProps = react_1.default.useRef({ value, selected, badges, initialView });
43
- const [state, dispatch] = react_1.default.useReducer(reducer, Object.assign(Object.assign({}, defaultState), { calendarDate: typeof value === 'undefined' ? new Date() : value, calendarViewVariants: views, calendarCurrentView: initialView }));
42
+ const { minDate = new Date(new Date().getFullYear() - 100, 0, 1, 0, 0, 0), maxDate = new Date(new Date().getFullYear() + 100, 0, 1, 0, 0, 0), weekStartDay = 'monday', locale = 'ru-RU', displayLeadingZero = false, onChange,
43
+ // selected = [],
44
+ badges = [],
45
+ // selectMultiple = false,
46
+ value, defaultValue, markToday, weekDayLabelFormat = 'short', accentColor = 'primary', prevMonthButtonTooltip, nextMonthButtonTooltip, changeMonthButtonTooltip, changeYearButtonTooltip, views = defaultState.calendarViewVariants, initialView = defaultState.calendarCurrentView, resetButtonLabel, toodayButtonLabel, heading, subheading, footer, } = props;
47
+ const realValue = react_1.default.useMemo(() => typeof value !== 'undefined'
48
+ ? value
49
+ : typeof defaultValue !== 'undefined'
50
+ ? defaultValue
51
+ : new Date(), [value, defaultValue]);
52
+ const initialProps = react_1.default.useRef({
53
+ value: realValue,
54
+ badges,
55
+ initialView,
56
+ });
57
+ const [state, dispatch] = react_1.default.useReducer(reducer, Object.assign(Object.assign({}, defaultState), { calendarValue: realValue, calendarViewVariants: views, calendarDate: realValue, calendarCurrentView: initialView }));
44
58
  const { isSameDay, getWeeks, getDayLabel, getMonthLabel, getYearLabel, getYearsRange, getMonthesRange, } = (0, use_calendar_1.useCalendar)({
45
59
  minDate,
46
60
  maxDate,
@@ -48,42 +62,57 @@ const Calendar = props => {
48
62
  locale,
49
63
  displayLeadingZero,
50
64
  });
51
- const { calendarCurrentView, calendarViewVariants, calendarDate } = state;
65
+ const { calendarCurrentView, calendarViewVariants, calendarValue, calendarDate } = state;
66
+ /**
67
+ * Prev and next month buttons
68
+ */
52
69
  const handleChangeMonthClick = react_1.default.useCallback((type) => () => {
53
70
  const newDate = type === 'prev'
54
71
  ? new Date(calendarDate.getFullYear(), calendarDate.getMonth() - 1, 1)
55
72
  : new Date(calendarDate.getFullYear(), calendarDate.getMonth() + 1, 1);
56
- if (!isSameDay(newDate, calendarDate)) {
57
- dispatch({ type: 'setPartial', payload: { calendarDate: newDate } });
58
- if (typeof onChange === 'function') {
59
- onChange(newDate);
60
- }
61
- }
62
- }, [calendarDate, isSameDay, onChange]);
63
- // Date props was changed
73
+ dispatch({ type: 'setPartial', payload: { calendarDate: newDate } });
74
+ }, [calendarDate]);
75
+ /**
76
+ * Date props was changed
77
+ */
64
78
  react_1.default.useEffect(() => {
65
- if (typeof value !== 'undefined' && !isSameDay(value, calendarDate)) {
66
- dispatch({ type: 'setPartial', payload: { calendarDate: value } });
79
+ if (typeof value !== 'undefined' && !isSameDay(value, calendarValue)) {
80
+ dispatch({
81
+ type: 'setPartial',
82
+ payload: {
83
+ calendarValue: value,
84
+ calendarDate: value,
85
+ },
86
+ });
67
87
  }
68
- }, [value, calendarDate, isSameDay, dispatch]);
88
+ }, [value, calendarValue, isSameDay, dispatch]);
89
+ /**
90
+ * Handle click on Day button
91
+ */
69
92
  const handleCellDateClick = react_1.default.useCallback((selectedDate) => () => {
70
- if (typeof onDateSelect === 'function') {
71
- if (selectMultiple) {
72
- const selectedAsTime = selectedDate.getTime();
73
- const selectedSet = new Set(selected.map(s => s.getTime()));
74
- if (selectedSet.has(selectedAsTime)) {
75
- selectedSet.delete(selectedAsTime);
76
- }
77
- else {
78
- selectedSet.add(selectedAsTime);
79
- }
80
- onDateSelect([...selectedSet].map(s => new Date(s)));
81
- }
82
- else {
83
- onDateSelect([selectedDate]);
84
- }
93
+ if (typeof onChange === 'function') {
94
+ // if (selectMultiple) {
95
+ // const selectedAsTime = selectedDate.getTime();
96
+ // const selectedSet = new Set(selected.map(s => s.getTime()));
97
+ // if (selectedSet.has(selectedAsTime)) {
98
+ // selectedSet.delete(selectedAsTime);
99
+ // } else {
100
+ // selectedSet.add(selectedAsTime);
101
+ // }
102
+ // onChange([...selectedSet].map(s => new Date(s)));
103
+ // } else {
104
+ // }
105
+ onChange(selectedDate);
106
+ }
107
+ if (!value) {
108
+ dispatch({
109
+ type: 'setPartial',
110
+ payload: {
111
+ calendarValue: selectedDate,
112
+ },
113
+ });
85
114
  }
86
- }, [onDateSelect, selected, selectMultiple]);
115
+ }, [onChange, value]);
87
116
  const getNextPossibleView = react_1.default.useCallback(() => {
88
117
  const currentViewIndex = calendarViewVariants.findIndex(v => v === calendarCurrentView);
89
118
  if (currentViewIndex !== -1 && calendarViewVariants.length > currentViewIndex + 1) {
@@ -98,6 +127,9 @@ const Calendar = props => {
98
127
  }
99
128
  return calendarViewVariants[calendarViewVariants.length - 1];
100
129
  }, [calendarCurrentView, calendarViewVariants]);
130
+ /**
131
+ * Handle of click on year item
132
+ */
101
133
  const handleYearSelected = react_1.default.useCallback((selectedYear) => () => {
102
134
  const newDate = new Date(calendarDate);
103
135
  newDate.setFullYear(selectedYear);
@@ -115,11 +147,11 @@ const Calendar = props => {
115
147
  calendarCurrentView: nextView,
116
148
  },
117
149
  });
118
- if (typeof onChange === 'function') {
119
- onChange(newDate);
120
- }
121
150
  }
122
- }, [calendarDate, getNextPossibleView, onChange]);
151
+ }, [calendarDate, getNextPossibleView]);
152
+ /**
153
+ * Handle of click on month item
154
+ */
123
155
  const handleMonthSelected = react_1.default.useCallback((monthIndex) => () => {
124
156
  const newDate = new Date(calendarDate);
125
157
  newDate.setMonth(monthIndex);
@@ -135,11 +167,11 @@ const Calendar = props => {
135
167
  calendarCurrentView: getNextPossibleView(),
136
168
  },
137
169
  });
138
- if (typeof onChange === 'function') {
139
- onChange(newDate);
140
- }
141
170
  }
142
- }, [calendarDate, getNextPossibleView, onChange]);
171
+ }, [calendarDate, getNextPossibleView]);
172
+ /**
173
+ * Manual view changing
174
+ */
143
175
  const handleChangeView = react_1.default.useCallback((selectedView) => () => {
144
176
  dispatch({
145
177
  type: 'setPartial',
@@ -148,21 +180,25 @@ const Calendar = props => {
148
180
  },
149
181
  });
150
182
  }, []);
183
+ /**
184
+ * Handle click on «Reset» button
185
+ */
151
186
  const handleReset = react_1.default.useCallback(() => {
152
187
  dispatch({
153
188
  type: 'setPartial',
154
189
  payload: {
155
190
  calendarCurrentView: initialProps.current.initialView,
156
191
  calendarDate: initialProps.current.value,
192
+ calendarValue: initialProps.current.value,
157
193
  },
158
194
  });
159
- if (typeof onChange === 'function' && initialProps.current.value instanceof Date) {
195
+ if (typeof onChange === 'function') {
160
196
  onChange(initialProps.current.value);
161
197
  }
162
- if (typeof onDateSelect === 'function') {
163
- onDateSelect(initialProps.current.selected);
164
- }
165
- }, [onChange, onDateSelect]);
198
+ }, [onChange]);
199
+ /**
200
+ * Handle click on «Today» button
201
+ */
166
202
  const handleToday = react_1.default.useCallback(() => {
167
203
  const today = new Date();
168
204
  today.setHours(0);
@@ -172,17 +208,10 @@ const Calendar = props => {
172
208
  dispatch({
173
209
  type: 'setPartial',
174
210
  payload: {
175
- // calendarCurrentView: initialProps.current.initialView,
176
211
  calendarDate: today,
177
212
  },
178
213
  });
179
- if (typeof onChange === 'function') {
180
- onChange(today);
181
- }
182
- if (typeof onDateSelect === 'function' && !selectMultiple) {
183
- onDateSelect([today]);
184
- }
185
- }, [onChange, onDateSelect, selectMultiple]);
214
+ }, []);
186
215
  return (react_1.default.createElement(CalendarPaper_1.default, null,
187
216
  react_1.default.createElement(CalendarHeader_1.default, null,
188
217
  typeof heading !== 'undefined' && react_1.default.createElement(CalendarHeading_1.default, null, heading),
@@ -194,12 +223,12 @@ const Calendar = props => {
194
223
  react_1.default.createElement(CalendarMonthControl_1.default, { displayIcon: "next", onClick: handleChangeMonthClick('next'), title: nextMonthButtonTooltip, disabled: calendarCurrentView !== 'days' }))),
195
224
  react_1.default.createElement(CalendarWeekDaysBar_1.default, { locale: locale, week: getWeeks(calendarDate)[0], format: weekDayLabelFormat || 'short' }),
196
225
  react_1.default.createElement(CalendarBody_1.default, null,
197
- calendarCurrentView === 'years' && (react_1.default.createElement(CalendarYearsSelector_1.default, null, getYearsRange(minDate, maxDate).map(year => (react_1.default.createElement(CalendarYearCell_1.default, { key: year, accentColor: accentColor, isSelected: year === calendarDate.getFullYear(), onClick: handleYearSelected(year) }, getYearLabel(new Date(year, calendarDate.getMonth(), calendarDate.getDate(), 0, 0, 0, 0))))))),
198
- calendarCurrentView === 'monthes' && (react_1.default.createElement(CalendarMonthesSelector_1.default, null, getMonthesRange(minDate, maxDate).map(monthIndex => (react_1.default.createElement(CalendarMonthCell_1.default, { key: monthIndex, accentColor: accentColor, isSelected: monthIndex === calendarDate.getMonth(), onClick: handleMonthSelected(monthIndex) }, getMonthLabel(new Date(calendarDate.getFullYear(), monthIndex, 1, 0, 0, 0, 0))))))),
226
+ calendarCurrentView === 'years' && (react_1.default.createElement(CalendarYearsSelector_1.default, null, getYearsRange(minDate, maxDate).map(year => (react_1.default.createElement(CalendarYearCell_1.default, { key: year, accentColor: accentColor, isSelected: year === calendarValue.getFullYear(), onClick: handleYearSelected(year) }, getYearLabel(new Date(year, calendarDate.getMonth(), calendarDate.getDate(), 0, 0, 0, 0))))))),
227
+ calendarCurrentView === 'monthes' && (react_1.default.createElement(CalendarMonthesSelector_1.default, null, getMonthesRange(minDate, maxDate).map(monthIndex => (react_1.default.createElement(CalendarMonthCell_1.default, { key: monthIndex, accentColor: accentColor, isSelected: monthIndex === calendarValue.getMonth(), onClick: handleMonthSelected(monthIndex) }, getMonthLabel(new Date(calendarDate.getFullYear(), monthIndex, 1, 0, 0, 0, 0))))))),
199
228
  calendarCurrentView === 'days' && (react_1.default.createElement(CalendarDateContainer_1.default, null, getWeeks(calendarDate).map(week => (react_1.default.createElement(CalendarWeekRow_1.default, { key: week.weekNumber.toString() }, week.days.map(day => {
200
229
  if (day.date.getMonth() === calendarDate.getMonth()) {
201
230
  const badge = badges.find(b => isSameDay(b.date, day.date));
202
- return (react_1.default.createElement(CalendarCell_1.default, { key: day.date.getTime(), isToday: markToday && day.isToday, isDisabled: day.isDisabled, accentColor: accentColor, isSelected: selected.find(s => isSameDay(s, day.date)) !== undefined, onClick: handleCellDateClick(day.date) },
231
+ return (react_1.default.createElement(CalendarCell_1.default, { key: day.date.getTime(), isToday: markToday && day.isToday, isDisabled: day.isDisabled, accentColor: accentColor, isSelected: isSameDay(calendarValue, day.date), onClick: handleCellDateClick(day.date) },
203
232
  getDayLabel(day.date),
204
233
  typeof badge !== 'undefined' && (react_1.default.createElement(CalendarDayBadge_1.default, { badgeContent: badge.badgeContent, isToday: day.isToday, accentColor: badge.accentColor }))));
205
234
  }
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.useCalendar = void 0;
7
7
  const react_1 = __importDefault(require("react"));
8
+ const WHITESPACE = '\u{0020}';
8
9
  const useCalendar = (props) => {
9
10
  const { minDate, maxDate, weekStartDay, displayLeadingZero, locale } = props;
10
11
  const isSameDay = react_1.default.useCallback((a, b) => a.getFullYear() === b.getFullYear() &&
@@ -46,18 +47,18 @@ const useCalendar = (props) => {
46
47
  return numStr.substring(numStr.length - 2);
47
48
  }, [displayLeadingZero]);
48
49
  const getMonthLabel = react_1.default.useCallback((dateValue) => {
49
- const intl = new Intl.DateTimeFormat(locale, {
50
- month: 'long',
51
- });
52
- const title = intl.format(dateValue);
50
+ const title = typeof Intl !== 'undefined'
51
+ ? new Intl.DateTimeFormat(locale, {
52
+ month: 'long',
53
+ }).format(dateValue)
54
+ : WHITESPACE;
53
55
  return title.charAt(0).toUpperCase() + title.slice(1);
54
56
  }, [locale]);
55
- const getYearLabel = react_1.default.useCallback((dateValue) => {
56
- const intl = new Intl.DateTimeFormat(locale, {
57
+ const getYearLabel = react_1.default.useCallback((dateValue) => typeof Intl !== 'undefined'
58
+ ? new Intl.DateTimeFormat(locale, {
57
59
  year: 'numeric',
58
- });
59
- return intl.format(dateValue);
60
- }, [locale]);
60
+ }).format(dateValue)
61
+ : WHITESPACE, [locale]);
61
62
  const getYearsRange = react_1.default.useCallback((minDate, maxDate) => {
62
63
  const y = [];
63
64
  for (let year = minDate.getFullYear(); year >= minDate.getFullYear() && year <= maxDate.getFullYear(); year++) {
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ declare const _default: React.ForwardRefExoticComponent<Omit<React.SVGProps<SVGSVGElement>, "ref"> & React.RefAttributes<SVGSVGElement>>;
3
+ export default _default;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const react_1 = __importDefault(require("react"));
7
+ const DatePickerIcon = (props, ref) => (react_1.default.createElement("svg", Object.assign({ xmlns: "http://www.w3.org/2000/svg", version: "1.1", width: "1em", height: "1em", viewBox: "0 0 512 512" }, props, { ref: ref }),
8
+ react_1.default.createElement("path", { d: "m128 32a16 16 0 0 0-16 16v16h-16c-35.179 0-64 28.821-64 64v288c0 35.179 28.821 64 64 64h320c35.179 0 64-28.821 64-64v-288c0-35.179-28.821-64-64-64h-16v-16a16 16 0 0 0-16-16 16 16 0 0 0-16 16v16h-224v-16a16 16 0 0 0-16-16zm-32 64h320c18.005 0 32 13.995 32 32v16h-384v-16c0-18.005 13.995-32 32-32zm-32 80h384v240c0 18.005-13.995 32-32 32h-320c-18.005 0-32-13.995-32-32v-240zm232 32a24 24 0 0 0-24 24 24 24 0 0 0 24 24 24 24 0 0 0 24-24 24 24 0 0 0-24-24zm80 0a24 24 0 0 0-24 24 24 24 0 0 0 24 24 24 24 0 0 0 24-24 24 24 0 0 0-24-24zm-240 80a24 24 0 0 0-24 24 24 24 0 0 0 24 24 24 24 0 0 0 24-24 24 24 0 0 0-24-24zm80 0a24 24 0 0 0-24 24 24 24 0 0 0 24 24 24 24 0 0 0 24-24 24 24 0 0 0-24-24zm80 0a24 24 0 0 0-24 24 24 24 0 0 0 24 24 24 24 0 0 0 24-24 24 24 0 0 0-24-24zm80 0a24 24 0 0 0-24 24 24 24 0 0 0 24 24 24 24 0 0 0 24-24 24 24 0 0 0-24-24zm-240 80a24 24 0 0 0-24 24 24 24 0 0 0 24 24 24 24 0 0 0 24-24 24 24 0 0 0-24-24zm80 0a24 24 0 0 0-24 24 24 24 0 0 0 24 24 24 24 0 0 0 24-24 24 24 0 0 0-24-24zm80 0a24 24 0 0 0-24 24 24 24 0 0 0 24 24 24 24 0 0 0 24-24 24 24 0 0 0-24-24z", fill: "currentColor" })));
9
+ exports.default = react_1.default.forwardRef(DatePickerIcon);
@@ -1,3 +1,29 @@
1
1
  import React from 'react';
2
- declare const DatePicker: React.FC;
2
+ import { CalendarProps } from '../Calendar';
3
+ import type { TextFieldProps } from '../TextField';
4
+ export type DatePickerProps = Omit<TextFieldProps, 'value' | 'onChange'> & Omit<CalendarProps, 'defaultValue' | 'value' | 'onChange'> & {
5
+ /**
6
+ * Current date
7
+ */
8
+ readonly value: Date | null;
9
+ /**
10
+ * Will be invoked when date would be changed
11
+ */
12
+ readonly onChange: (date: Date) => void;
13
+ /**
14
+ * Date template like one of format: \
15
+ * `dd.mm.yyyy` or `yyyy/mm/dd`, etc.\
16
+ * Posibility chars: `y`, `Y`, `yy`, `yyyy`, `d`, `dd`, `D`, `m`, `mm`, `M`
17
+ */
18
+ readonly template: string;
19
+ /**
20
+ * Tooltip text for a calendar button
21
+ */
22
+ readonly calendarButtonTooltip?: string;
23
+ /**
24
+ * Calendar properties
25
+ */
26
+ readonly calendarProps?: Omit<CalendarProps, 'value' | 'defaultValue' | 'onChange'>;
27
+ };
28
+ declare const DatePicker: React.FC<DatePickerProps>;
3
29
  export default DatePicker;
@@ -1,8 +1,74 @@
1
1
  "use strict";
2
+ var __rest = (this && this.__rest) || function (s, e) {
3
+ var t = {};
4
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
+ t[p] = s[p];
6
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
+ t[p[i]] = s[p[i]];
10
+ }
11
+ return t;
12
+ };
2
13
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
14
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
15
  };
5
16
  Object.defineProperty(exports, "__esModule", { value: true });
6
17
  const react_1 = __importDefault(require("react"));
7
- const DatePicker = () => react_1.default.createElement(react_1.default.Fragment, null, "Date picker");
18
+ const styled_1 = __importDefault(require("@emotion/styled"));
19
+ const react_2 = require("@emotion/react");
20
+ const Calendar_1 = __importDefault(require("../Calendar"));
21
+ const Button_1 = __importDefault(require("../Button"));
22
+ const Popper_1 = __importDefault(require("../Popper"));
23
+ const ClickOutside_1 = __importDefault(require("../ClickOutside"));
24
+ const MaskedField_1 = __importDefault(require("../MaskedField"));
25
+ const DatePickerIcon_1 = __importDefault(require("./DatePickerIcon"));
26
+ const useDatePickerFormat_1 = __importDefault(require("./useDatePickerFormat"));
27
+ const StyledMaskedField = (0, styled_1.default)(MaskedField_1.default) `
28
+ ${({ readOnly, disabled }) => readOnly &&
29
+ !disabled &&
30
+ (0, react_2.css) `
31
+ & input {
32
+ cursor: pointer;
33
+ }
34
+ `}
35
+ `;
36
+ const DatePicker = props => {
37
+ const { value, template, onChange, calendarProps, calendarButtonTooltip, readOnly, disabled } = props, restProps = __rest(props, ["value", "template", "onChange", "calendarProps", "calendarButtonTooltip", "readOnly", "disabled"]);
38
+ const [currentValue, setCurrentValue] = react_1.default.useState(value);
39
+ const valueRef = react_1.default.useRef(value);
40
+ const [textFieldRef, setTextFieldRef] = react_1.default.useState(null);
41
+ const [isOpen, setOpenSate] = react_1.default.useState(false);
42
+ const { getMaskByTemplate, formatInputByTemplate, parseInputByTemplate } = (0, useDatePickerFormat_1.default)();
43
+ react_1.default.useEffect(() => {
44
+ const a = value || new Date();
45
+ const b = valueRef.current || new Date();
46
+ if (a.getFullYear() !== b.getFullYear() ||
47
+ a.getMonth() !== b.getMonth() ||
48
+ a.getDate() !== b.getDate()) {
49
+ valueRef.current = value;
50
+ setCurrentValue(value);
51
+ }
52
+ }, [value]);
53
+ return (react_1.default.createElement(react_1.default.Fragment, null,
54
+ react_1.default.createElement(StyledMaskedField, Object.assign({ onClick: () => {
55
+ if (readOnly) {
56
+ setOpenSate(!isOpen);
57
+ }
58
+ }, disabled: disabled, mask: getMaskByTemplate(template), ref: setTextFieldRef, readOnly: readOnly, endIcon: react_1.default.createElement(Button_1.default, { disabled: disabled, iconOnly: true, type: "button", onClick: () => setOpenSate(true), title: calendarButtonTooltip },
59
+ react_1.default.createElement(DatePickerIcon_1.default, null)) }, restProps, { value: currentValue ? formatInputByTemplate(currentValue, template) : '', onChange: ({ isValid, text }) => {
60
+ if (isValid) {
61
+ const parsedDate = parseInputByTemplate(text, template);
62
+ if (parsedDate instanceof Date && !isNaN(parsedDate.getTime())) {
63
+ onChange(parsedDate);
64
+ }
65
+ }
66
+ } })),
67
+ react_1.default.createElement(ClickOutside_1.default, { onOutsideClick: () => setOpenSate(false), mouseEvent: "onMouseDown" },
68
+ react_1.default.createElement(Popper_1.default, { isOpen: isOpen, anchorElement: textFieldRef },
69
+ react_1.default.createElement(Calendar_1.default, Object.assign({}, calendarProps, { value: currentValue || new Date(), onChange: date => {
70
+ onChange(date);
71
+ setOpenSate(false);
72
+ } }))))));
73
+ };
8
74
  exports.default = DatePicker;
@@ -0,0 +1,9 @@
1
+ export declare const useDatePickerFormat: () => {
2
+ templateValidChars: string[];
3
+ isValidTemplate: (template: string) => boolean;
4
+ validateTemplate: (template: string) => void;
5
+ getMaskByTemplate: (template: string) => (string | RegExp)[];
6
+ parseInputByTemplate: (input: string, template: string) => Date | null;
7
+ formatInputByTemplate: (date: Date, template: string) => string;
8
+ };
9
+ export default useDatePickerFormat;
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.useDatePickerFormat = void 0;
7
+ const react_1 = __importDefault(require("react"));
8
+ const useDatePickerFormat = () => {
9
+ const templateValidChars = react_1.default.useMemo(() => ['y', 'Y', 'yy', 'yyyy', 'd', 'dd', 'D', 'm', 'mm', 'M'], []);
10
+ const isValidTemplate = react_1.default.useCallback((template) => {
11
+ const matches = template.match(/[yYmMdD]+/g);
12
+ if (!matches) {
13
+ return false;
14
+ }
15
+ return matches.every(char => templateValidChars.includes(char));
16
+ }, [templateValidChars]);
17
+ const validateTemplate = react_1.default.useCallback((template) => {
18
+ if (!isValidTemplate(template)) {
19
+ throw new Error(`The template «${template}» is not valid. Check the posibility chars: [${templateValidChars.join(', ')}]`);
20
+ }
21
+ }, [isValidTemplate, templateValidChars]);
22
+ /**
23
+ * Generate the array of RegExp by template string
24
+ */
25
+ const getMaskByTemplate = react_1.default.useCallback((template) => {
26
+ validateTemplate(template);
27
+ return template.split('').map(char => {
28
+ if (['m', 'M', 'd', 'D', 'y', 'Y'].includes(char)) {
29
+ return /\d/;
30
+ }
31
+ return char;
32
+ });
33
+ }, [validateTemplate]);
34
+ /**
35
+ * Parse input string ny template
36
+ * @returns Date
37
+ */
38
+ const parseInputByTemplate = react_1.default.useCallback((input, template) => {
39
+ validateTemplate(template);
40
+ if (input.length !== template.length) {
41
+ return null;
42
+ }
43
+ const data = {
44
+ days: [],
45
+ monthes: [],
46
+ years: [],
47
+ };
48
+ template.split('').forEach((char, charIndex) => {
49
+ switch (char) {
50
+ case 'y':
51
+ data.years.push(input[charIndex]);
52
+ break;
53
+ case 'm':
54
+ data.monthes.push(input[charIndex]);
55
+ break;
56
+ case 'd':
57
+ data.days.push(input[charIndex]);
58
+ break;
59
+ default:
60
+ // do nothing
61
+ break;
62
+ }
63
+ });
64
+ return new Date(parseInt(data.years.join(''), 10), parseInt(data.monthes.join(''), 10) - 1, // Fucking month indexes
65
+ parseInt(data.days.join(''), 10));
66
+ }, [validateTemplate]);
67
+ /**
68
+ * Format date to string by template
69
+ */
70
+ const formatInputByTemplate = react_1.default.useCallback((date, template) => {
71
+ validateTemplate(template);
72
+ return (template
73
+ .replace(/(d{1,2}|D{1,2})/, entries => {
74
+ const day = `${date.getDate()}`;
75
+ if (['DD', 'D', 'dd'].includes(entries)) {
76
+ const str = `0${day}`;
77
+ return str.substring(str.length - entries.length);
78
+ }
79
+ return day;
80
+ })
81
+ // mm or M - month with leading zero
82
+ // m - month without leading zero
83
+ .replace(/(m{1,2}|M{1,2})/, entries => {
84
+ const month = `${date.getMonth() + 1}`;
85
+ if (['MM', 'M', 'mm'].includes(entries)) {
86
+ const str = `0${month}`;
87
+ return str.substring(str.length - entries.length);
88
+ }
89
+ return month;
90
+ })
91
+ // yyyy or Y - full year
92
+ // yy or y - last two digits
93
+ .replace(/(y{4}|y{1,2}|Y{1,2})/, entries => {
94
+ const str = `${date.getFullYear()}`;
95
+ if (['YY', 'Y'].includes(entries)) {
96
+ return str;
97
+ }
98
+ return str.substring(str.length - entries.length);
99
+ }));
100
+ }, [validateTemplate]);
101
+ return {
102
+ templateValidChars,
103
+ isValidTemplate,
104
+ validateTemplate,
105
+ getMaskByTemplate,
106
+ parseInputByTemplate,
107
+ formatInputByTemplate,
108
+ };
109
+ };
110
+ exports.useDatePickerFormat = useDatePickerFormat;
111
+ exports.default = exports.useDatePickerFormat;
@@ -2,11 +2,6 @@ import React from 'react';
2
2
  import { Mask, FormatParsedPayload, ParseInput } from './useMasked';
3
3
  import { TextFieldProps } from '../TextField';
4
4
  export type GetMask = (input: string) => Mask;
5
- export interface Payload {
6
- readonly text: string;
7
- readonly caret: number;
8
- readonly isValid: boolean;
9
- }
10
5
  export interface MaskedFieldProps extends Omit<TextFieldProps, 'value' | 'onChange'> {
11
6
  /**
12
7
  * Field value
@@ -19,6 +19,7 @@ const useMasked_1 = require("./useMasked");
19
19
  const TextField_1 = __importDefault(require("../TextField"));
20
20
  const MaskedField = (props, ref) => {
21
21
  const { value: propValue, mask, parseInput, onChange, transform } = props, nativeProps = __rest(props, ["value", "mask", "parseInput", "onChange", "transform"]);
22
+ const propValueRef = react_1.default.useRef(propValue);
22
23
  const textInputRef = react_1.default.useRef(null);
23
24
  const decoratorsErrorDisplayed = react_1.default.useRef(false);
24
25
  const masked = (0, useMasked_1.useMasked)();
@@ -34,13 +35,20 @@ const MaskedField = (props, ref) => {
34
35
  }
35
36
  return currentMask;
36
37
  }, [mask, parseInput]);
37
- const [inputValue, setInputValue] = react_1.default.useState(() => {
38
+ const getInputValue = react_1.default.useCallback((v) => {
38
39
  var _a;
39
- const mask = getMask(propValue || '');
40
- const parsed = parseInputFn(propValue || '', mask, ((_a = textInputRef.current) === null || _a === void 0 ? void 0 : _a.selectionStart) || 0);
40
+ const mask = getMask(v || '');
41
+ const parsed = parseInputFn(v || '', mask, ((_a = textInputRef.current) === null || _a === void 0 ? void 0 : _a.selectionStart) || 0);
41
42
  const { text } = masked.formatParsedInput(parsed.text, mask, parsed.caret);
42
43
  return text;
43
- });
44
+ }, [getMask, masked, parseInputFn]);
45
+ const [inputValue, setInputValue] = react_1.default.useState(getInputValue(propValue || ''));
46
+ react_1.default.useEffect(() => {
47
+ if (propValueRef.current !== propValue) {
48
+ propValueRef.current = propValue;
49
+ setInputValue(getInputValue(propValue || ''));
50
+ }
51
+ }, [getInputValue, getMask, parseInputFn, masked, propValue]);
44
52
  const handleOnChange = react_1.default.useCallback(event => {
45
53
  var _a;
46
54
  const mask = getMask(event.currentTarget.value);
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ declare const _default: React.ForwardRefExoticComponent<Omit<React.SVGProps<SVGSVGElement>, "ref"> & React.RefAttributes<SVGSVGElement>>;
3
+ export default _default;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const react_1 = __importDefault(require("react"));
7
+ const IconShow = (props, ref) => (react_1.default.createElement("svg", Object.assign({ xmlns: "http://www.w3.org/2000/svg", version: "1.1", width: "1em", height: "1em", viewBox: "0 0 512 512" }, props, { ref: ref }),
8
+ react_1.default.createElement("path", { d: "m105.79 160.82a24 24 0 0 0-10.76 6.2109 24 24 0 0 0 0 33.941l144 144a24.002 24.002 0 0 0 33.941 0l144-144a24 24 0 0 0 0-33.941 24 24 0 0 0-33.941 0l-127.03 127.03-127.03-127.03a24 24 0 0 0-23.182-6.2109z", fill: "currentColor" })));
9
+ exports.default = react_1.default.forwardRef(IconShow);
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import { AutocompleteProps, AutocompleteRef } from '../Autocomplete';
3
+ import SelectboxItem from '../Menu/MenuItem';
4
+ export * from '../Autocomplete/AutocompleteContainer';
5
+ export { SelectboxItem };
6
+ declare const _default: <T, Multiple extends boolean | undefined = undefined>(props: AutocompleteProps<T, Multiple> & {
7
+ ref?: React.Ref<AutocompleteRef> | undefined;
8
+ }) => JSX.Element;
9
+ export default _default;
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ var __rest = (this && this.__rest) || function (s, e) {
17
+ var t = {};
18
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
19
+ t[p] = s[p];
20
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
21
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
22
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
23
+ t[p[i]] = s[p[i]];
24
+ }
25
+ return t;
26
+ };
27
+ var __importDefault = (this && this.__importDefault) || function (mod) {
28
+ return (mod && mod.__esModule) ? mod : { "default": mod };
29
+ };
30
+ Object.defineProperty(exports, "__esModule", { value: true });
31
+ exports.SelectboxItem = void 0;
32
+ const react_1 = __importDefault(require("react"));
33
+ const styled_1 = __importDefault(require("@emotion/styled"));
34
+ const react_2 = require("@emotion/react");
35
+ const Button_1 = __importDefault(require("../Button"));
36
+ const IconShow_1 = __importDefault(require("./IconShow"));
37
+ const Autocomplete_1 = __importDefault(require("../Autocomplete"));
38
+ const MenuItem_1 = __importDefault(require("../Menu/MenuItem"));
39
+ exports.SelectboxItem = MenuItem_1.default;
40
+ const TextField_1 = __importDefault(require("../TextField"));
41
+ __exportStar(require("../Autocomplete/AutocompleteContainer"), exports);
42
+ const StyledTextField = (0, styled_1.default)(TextField_1.default) `
43
+ ${({ readOnly, disabled }) => readOnly &&
44
+ !disabled &&
45
+ (0, react_2.css) `
46
+ & input {
47
+ cursor: pointer;
48
+ }
49
+ `}
50
+ `;
51
+ const Selectbox = react_1.default.forwardRef((props, ref) => {
52
+ const { children, onRequestOpen, onRequestClose, isOpen } = props, restProps = __rest(props, ["children", "onRequestOpen", "onRequestClose", "isOpen"]);
53
+ const toggle = react_1.default.useCallback((e) => {
54
+ if (isOpen) {
55
+ onRequestClose && onRequestClose(e);
56
+ }
57
+ else {
58
+ onRequestOpen && onRequestOpen(e);
59
+ }
60
+ }, [onRequestOpen, onRequestClose, isOpen]);
61
+ return (react_1.default.createElement(Autocomplete_1.default, Object.assign({ clearable: false, endIcon: react_1.default.createElement(Button_1.default, { onClick: toggle, iconOnly: true },
62
+ react_1.default.createElement(IconShow_1.default, null)), overrides: {
63
+ TextField: react_1.default.forwardRef(function TextFieldOverride(p, r) {
64
+ return react_1.default.createElement(StyledTextField, Object.assign({ onClick: toggle, readOnly: true }, p, { ref: r }));
65
+ }),
66
+ } }, restProps, { ref: ref, onRequestOpen: onRequestOpen, onRequestClose: onRequestClose, isOpen: isOpen }), children));
67
+ });
68
+ Selectbox.displayName = 'Selectbox';
69
+ exports.default = Selectbox;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@via-profit/ui-kit",
3
- "version": "0.1.0-rc.63",
3
+ "version": "0.1.0-rc.64",
4
4
  "description": "UI Kit",
5
5
  "repository": {
6
6
  "type": "git",