react-native-molecules 0.5.0-beta.16 → 0.5.0-beta.17

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 (81) hide show
  1. package/components/DateField/DateField.tsx +110 -0
  2. package/components/DateField/index.tsx +6 -0
  3. package/components/{DatePickerInput/inputUtils.ts → DateField/useDateFieldState.ts} +17 -49
  4. package/components/DatePicker/DateCalendar.tsx +83 -0
  5. package/components/DatePicker/DatePickerActions.tsx +73 -0
  6. package/components/DatePicker/DatePickerModal.tsx +234 -0
  7. package/components/DatePicker/DatePickerPopover.tsx +79 -0
  8. package/components/DatePicker/DatePickerProvider.tsx +152 -0
  9. package/components/DatePicker/DatePickerTrigger.tsx +23 -0
  10. package/components/DatePicker/context.tsx +82 -0
  11. package/components/DatePicker/index.tsx +44 -0
  12. package/components/DatePicker/utils.ts +292 -0
  13. package/components/DatePickerInline/DatePickerContext.tsx +1 -0
  14. package/components/DatePickerInline/DatePickerDockedHeader.tsx +113 -0
  15. package/components/DatePickerInline/DatePickerInline.tsx +16 -15
  16. package/components/DatePickerInline/DatePickerInlineBase.tsx +7 -1
  17. package/components/DatePickerInline/Day.tsx +25 -1
  18. package/components/DatePickerInline/DayRange.tsx +2 -4
  19. package/components/DatePickerInline/HeaderItem.tsx +42 -27
  20. package/components/DatePickerInline/Month.tsx +45 -65
  21. package/components/DatePickerInline/MonthPicker.tsx +25 -41
  22. package/components/DatePickerInline/Swiper.native.tsx +21 -4
  23. package/components/DatePickerInline/Swiper.tsx +168 -13
  24. package/components/DatePickerInline/Week.tsx +6 -1
  25. package/components/DatePickerInline/YearPicker.tsx +206 -53
  26. package/components/DatePickerInline/dateUtils.tsx +17 -12
  27. package/components/DatePickerInline/types.ts +3 -0
  28. package/components/DatePickerInline/utils.ts +66 -29
  29. package/components/ListItem/ListItem.tsx +3 -1
  30. package/components/ListItem/utils.ts +1 -1
  31. package/components/LoadingIndicator/index.tsx +1 -1
  32. package/components/Popover/Popover.native.tsx +4 -25
  33. package/components/Popover/Popover.tsx +4 -26
  34. package/components/Popover/utils.ts +41 -0
  35. package/components/Select/Select.tsx +7 -8
  36. package/components/Select/context.tsx +72 -0
  37. package/components/Select/index.ts +1 -0
  38. package/components/Select/utils.ts +0 -71
  39. package/components/Slot/compose-refs.tsx +2 -0
  40. package/components/TimeField/TimeField.tsx +75 -0
  41. package/components/TimeField/index.tsx +6 -0
  42. package/components/TimeField/useTimeFieldState.ts +70 -0
  43. package/components/{TimePickerField/sanitizeTime.ts → TimeField/utils.ts} +77 -10
  44. package/components/TimePicker/TimePicker.tsx +53 -9
  45. package/components/TimePicker/TimePickerModal.tsx +186 -0
  46. package/components/TimePicker/context.tsx +17 -0
  47. package/components/TimePicker/index.tsx +15 -3
  48. package/components/TimePicker/utils.ts +50 -0
  49. package/hooks/useActionState.tsx +19 -8
  50. package/package.json +6 -1
  51. package/components/DatePickerDocked/DatePickerDocked.tsx +0 -30
  52. package/components/DatePickerDocked/DatePickerDockedHeader.tsx +0 -129
  53. package/components/DatePickerDocked/index.tsx +0 -17
  54. package/components/DatePickerDocked/types.ts +0 -11
  55. package/components/DatePickerDocked/utils.ts +0 -157
  56. package/components/DatePickerInput/DatePickerInput.tsx +0 -130
  57. package/components/DatePickerInput/DatePickerInputModal.tsx +0 -48
  58. package/components/DatePickerInput/DatePickerInputWithoutModal.tsx +0 -73
  59. package/components/DatePickerInput/DateRangeInput.tsx +0 -88
  60. package/components/DatePickerInput/index.tsx +0 -11
  61. package/components/DatePickerInput/types.ts +0 -26
  62. package/components/DatePickerInput/utils.ts +0 -24
  63. package/components/DatePickerModal/AnimatedCrossView.tsx +0 -94
  64. package/components/DatePickerModal/CalendarEdit.tsx +0 -140
  65. package/components/DatePickerModal/DatePickerModal.tsx +0 -85
  66. package/components/DatePickerModal/DatePickerModalContent.tsx +0 -155
  67. package/components/DatePickerModal/DatePickerModalContentHeader.tsx +0 -213
  68. package/components/DatePickerModal/DatePickerModalHeader.tsx +0 -74
  69. package/components/DatePickerModal/DatePickerModalHeaderBackground.tsx +0 -13
  70. package/components/DatePickerModal/index.tsx +0 -16
  71. package/components/DatePickerModal/types.ts +0 -92
  72. package/components/DatePickerModal/utils.ts +0 -122
  73. package/components/DateTimePicker/DateTimePicker.tsx +0 -172
  74. package/components/DateTimePicker/index.tsx +0 -10
  75. package/components/DateTimePicker/utils.ts +0 -12
  76. package/components/TimePickerField/TimePickerField.tsx +0 -154
  77. package/components/TimePickerField/index.tsx +0 -10
  78. package/components/TimePickerField/utils.ts +0 -94
  79. package/components/TimePickerModal/TimePickerModal.tsx +0 -119
  80. package/components/TimePickerModal/index.tsx +0 -10
  81. package/components/TimePickerModal/utils.ts +0 -47
@@ -1,9 +1,12 @@
1
1
  import { memo, useCallback, useMemo, useState } from 'react';
2
2
  import { type StyleProp, View, type ViewStyle } from 'react-native';
3
3
 
4
+ import { getRegisteredComponentWithFallback } from '../../core';
4
5
  import { useControlledValue } from '../../hooks';
5
6
  import { format, parse } from '../../utils/date-fns';
7
+ import { useOptionalDatePickerContext } from '../DatePicker/context';
6
8
  import AnalogClock from './AnalogClock';
9
+ import { useOptionalTimePickerContext } from './context';
7
10
  import { DisplayModeContext } from './DisplayModeContext';
8
11
  import TimeInputs from './TimeInputs';
9
12
  import {
@@ -26,10 +29,10 @@ type onChangeFunc = ({
26
29
 
27
30
  export type Props = {
28
31
  /**
29
- * hh:mm format
32
+ * hh:mm format. Optional when mounted inside a DatePickerProvider — the provider's Date is read instead.
30
33
  * */
31
- time: string;
32
- onTimeChange: (params: { time: string; focused?: undefined | PossibleClockTypes }) => any;
34
+ time?: string;
35
+ onTimeChange?: (params: { time: string; focused?: undefined | PossibleClockTypes }) => any;
33
36
 
34
37
  is24Hour?: boolean;
35
38
  inputType?: PossibleInputTypes;
@@ -40,16 +43,54 @@ export type Props = {
40
43
  style?: StyleProp<ViewStyle>;
41
44
  };
42
45
 
46
+ const toTimeString = (value: Date | null | undefined): string => {
47
+ if (!value) return '';
48
+ const h = value.getHours().toString().padStart(2, '0');
49
+ const m = value.getMinutes().toString().padStart(2, '0');
50
+ return `${h}:${m}`;
51
+ };
52
+
53
+ const applyTimeToDate = (base: Date | null | undefined, time: string): Date | null => {
54
+ if (!time) return null;
55
+ const [h, m] = time.split(':').map(n => parseInt(n, 10));
56
+ if (Number.isNaN(h) || Number.isNaN(m)) return base ?? null;
57
+ const next = base ? new Date(base) : new Date();
58
+ next.setHours(h, m, 0, 0);
59
+ return next;
60
+ };
61
+
43
62
  function TimePicker({
44
- is24Hour = false,
45
- time,
63
+ time: timeProp,
64
+ onTimeChange: onTimeChangeProp,
65
+ is24Hour: is24HourProp,
46
66
  focused: focusedProp,
47
67
  onFocusInput: onFocusInputProp,
48
- inputType = 'keyboard',
49
- onTimeChange,
68
+ inputType: inputTypeProp,
50
69
  isLandscape = false,
51
70
  style,
52
71
  }: Props) {
72
+ const ctx = useOptionalDatePickerContext();
73
+ const tpCtx = useOptionalTimePickerContext();
74
+
75
+ const ctxDate =
76
+ ctx && ctx.draftValue && typeof ctx.draftValue === 'object' && 'start' in ctx.draftValue
77
+ ? null
78
+ : (ctx?.draftValue as Date | null | undefined);
79
+
80
+ const time = timeProp ?? toTimeString(ctxDate);
81
+ const is24Hour = is24HourProp ?? ctx?.is24Hour ?? false;
82
+ const inputType = inputTypeProp ?? tpCtx?.inputType ?? (ctx ? 'picker' : 'keyboard');
83
+
84
+ const onTimeChange = useMemo(
85
+ () =>
86
+ onTimeChangeProp ??
87
+ ((params: { time: string; focused?: undefined | PossibleClockTypes }) => {
88
+ if (!ctx) return;
89
+ ctx.setValue(applyTimeToDate(ctxDate, params.time));
90
+ }),
91
+ [onTimeChangeProp, ctx, ctxDate],
92
+ );
93
+
53
94
  const { hours, minutes } = useMemo(() => {
54
95
  const date = time ? parse(time, 'HH:mm', new Date()) : new Date();
55
96
 
@@ -62,7 +103,6 @@ function TimePicker({
62
103
  onChange: onFocusInputProp,
63
104
  });
64
105
 
65
- // Initialize display Mode according the hours value
66
106
  const [displayMode, setDisplayMode] = useState<'AM' | 'PM' | undefined>(() =>
67
107
  !is24Hour ? (hours >= 12 ? 'PM' : 'AM') : undefined,
68
108
  );
@@ -127,4 +167,8 @@ function TimePicker({
127
167
  );
128
168
  }
129
169
 
130
- export default memo(TimePicker);
170
+ const TimePickerDefault = memo(TimePicker);
171
+
172
+ export default TimePickerDefault;
173
+
174
+ export const TimePickerClock = getRegisteredComponentWithFallback('TimePicker', TimePickerDefault);
@@ -0,0 +1,186 @@
1
+ import type { ReactNode } from 'react';
2
+ import { memo, useMemo } from 'react';
3
+ import { KeyboardAvoidingView, Platform, View } from 'react-native';
4
+
5
+ import { getRegisteredComponentWithFallback } from '../../core';
6
+ import { useControlledValue } from '../../hooks';
7
+ import { DatePickerActions, DatePickerProvider } from '../DatePicker';
8
+ import type { DatePickerContextType, DatePickerValue } from '../DatePicker/context';
9
+ import {
10
+ DatePickerContext,
11
+ useDatePickerContext,
12
+ useOptionalDatePickerContext,
13
+ withDraftLayer,
14
+ } from '../DatePicker/context';
15
+ import { IconButton } from '../IconButton';
16
+ import { Modal, type ModalProps } from '../Modal';
17
+ import { Portal } from '../Portal';
18
+ import { Text } from '../Text';
19
+ import { TimePickerContext } from './context';
20
+ import { TimePickerClock } from './TimePicker';
21
+ import {
22
+ getTimeInputTypeIcon,
23
+ inputTypes,
24
+ type PossibleInputTypes,
25
+ reverseInputTypes,
26
+ } from './timeUtils';
27
+ import { timePickerModalStyles as styles } from './utils';
28
+
29
+ export type TimePickerModalProps = Omit<ModalProps, 'children' | 'isOpen' | 'onClose'> & {
30
+ children?: ReactNode;
31
+ isOpen?: boolean;
32
+ onClose?: () => void;
33
+ value?: DatePickerValue;
34
+ onChange?: (value: DatePickerValue) => void;
35
+ is24Hour?: boolean;
36
+ inputType?: PossibleInputTypes;
37
+ defaultInputType?: PossibleInputTypes;
38
+ onInputTypeChange?: (next: PossibleInputTypes) => void;
39
+ label?: string;
40
+ uppercase?: boolean;
41
+ cancelLabel?: string;
42
+ confirmLabel?: string;
43
+ keyboardIcon?: string;
44
+ clockIcon?: string;
45
+ /** Override the surface default draft mode. Modal defaults to `true` (staged commit). */
46
+ draft?: boolean;
47
+ };
48
+
49
+ type BodyProps = Omit<
50
+ TimePickerModalProps,
51
+ 'isOpen' | 'onClose' | 'value' | 'onChange' | 'is24Hour' | 'draft'
52
+ >;
53
+
54
+ function TimePickerModalBody({
55
+ children,
56
+ style,
57
+ label = 'Select time',
58
+ uppercase = false,
59
+ cancelLabel = 'Cancel',
60
+ confirmLabel = 'OK',
61
+ keyboardIcon = 'keyboard-outline',
62
+ clockIcon = 'clock-outline',
63
+ inputType: inputTypeProp,
64
+ defaultInputType = inputTypes.picker,
65
+ onInputTypeChange,
66
+ ...rest
67
+ }: BodyProps) {
68
+ const ctx = useDatePickerContext();
69
+ const [inputType, setInputType] = useControlledValue<PossibleInputTypes>({
70
+ value: inputTypeProp,
71
+ defaultValue: defaultInputType,
72
+ onChange: onInputTypeChange,
73
+ });
74
+
75
+ const tpContextValue = useMemo(() => ({ inputType, setInputType }), [inputType, setInputType]);
76
+
77
+ const modalStyle = useMemo(() => [styles.modalContent, style], [style]);
78
+
79
+ return (
80
+ <Portal>
81
+ <TimePickerContext value={tpContextValue}>
82
+ <Modal {...rest} isOpen={ctx.open} onClose={ctx.cancel} style={modalStyle}>
83
+ <KeyboardAvoidingView
84
+ style={styles.keyboardView}
85
+ behavior={Platform.OS === 'ios' ? 'padding' : undefined}>
86
+ <View style={styles.frame}>
87
+ <View style={styles.labelContainer}>
88
+ <Text style={styles.label}>
89
+ {uppercase ? label.toUpperCase() : label}
90
+ </Text>
91
+ </View>
92
+ <View style={styles.timePickerContainer}>
93
+ {children ?? <TimePickerClock />}
94
+ </View>
95
+ <View style={styles.footer}>
96
+ <IconButton
97
+ name={getTimeInputTypeIcon(inputType, {
98
+ keyboard: keyboardIcon,
99
+ picker: clockIcon,
100
+ })}
101
+ onPress={() => setInputType(reverseInputTypes[inputType])}
102
+ style={styles.inputTypeToggle}
103
+ accessibilityLabel="toggle keyboard"
104
+ />
105
+ <View style={styles.fill} />
106
+ <DatePickerActions
107
+ cancelLabel={cancelLabel}
108
+ confirmLabel={confirmLabel}
109
+ />
110
+ </View>
111
+ </View>
112
+ </KeyboardAvoidingView>
113
+ </Modal>
114
+ </TimePickerContext>
115
+ </Portal>
116
+ );
117
+ }
118
+
119
+ function TimePickerModalLayer({
120
+ base,
121
+ draft: draftProp,
122
+ bodyProps,
123
+ }: {
124
+ base: DatePickerContextType;
125
+ draft: boolean | undefined;
126
+ bodyProps: BodyProps;
127
+ }) {
128
+ const effectiveDraft = draftProp ?? base.providerDraft ?? true;
129
+ const ctx = useMemo(() => withDraftLayer(base, effectiveDraft), [base, effectiveDraft]);
130
+ if (!base.open) return null;
131
+ return (
132
+ <DatePickerContext value={ctx}>
133
+ <TimePickerModalBody {...bodyProps} />
134
+ </DatePickerContext>
135
+ );
136
+ }
137
+
138
+ function TimePickerModalAdapter({
139
+ draft,
140
+ bodyProps,
141
+ }: {
142
+ draft: boolean | undefined;
143
+ bodyProps: BodyProps;
144
+ }) {
145
+ const base = useDatePickerContext();
146
+ return <TimePickerModalLayer base={base} draft={draft} bodyProps={bodyProps} />;
147
+ }
148
+
149
+ const TimePickerModalDefault = memo(
150
+ ({
151
+ isOpen: isOpenProp,
152
+ onClose: onCloseProp,
153
+ value: valueProp,
154
+ onChange: onChangeProp,
155
+ is24Hour,
156
+ draft: draftProp,
157
+ ...rest
158
+ }: TimePickerModalProps) => {
159
+ const outer = useOptionalDatePickerContext();
160
+
161
+ if (outer) {
162
+ return <TimePickerModalLayer base={outer} draft={draftProp} bodyProps={rest} />;
163
+ }
164
+
165
+ return (
166
+ <DatePickerProvider
167
+ mode="time"
168
+ value={valueProp}
169
+ onChange={onChangeProp}
170
+ open={isOpenProp}
171
+ onOpenChange={next => {
172
+ if (!next) onCloseProp?.();
173
+ }}
174
+ is24Hour={is24Hour}>
175
+ <TimePickerModalAdapter draft={draftProp} bodyProps={rest} />
176
+ </DatePickerProvider>
177
+ );
178
+ },
179
+ );
180
+
181
+ export const TimePickerModal = getRegisteredComponentWithFallback(
182
+ 'TimePickerModal',
183
+ TimePickerModalDefault,
184
+ );
185
+
186
+ export default TimePickerModal;
@@ -0,0 +1,17 @@
1
+ import { createContext, useContext } from 'react';
2
+
3
+ import { registerPortalContext } from '../Portal';
4
+ import type { PossibleInputTypes } from './timeUtils';
5
+
6
+ export type TimePickerContextType = {
7
+ inputType: PossibleInputTypes;
8
+ setInputType: (next: PossibleInputTypes) => void;
9
+ };
10
+
11
+ export const TimePickerContext = createContext<TimePickerContextType | null>(null);
12
+
13
+ export function useOptionalTimePickerContext(): TimePickerContextType | null {
14
+ return useContext(TimePickerContext);
15
+ }
16
+
17
+ registerPortalContext(TimePickerContext);
@@ -1,9 +1,20 @@
1
- import { getRegisteredComponentWithFallback } from '../../core';
2
- import TimePickerDefault from './TimePicker';
1
+ import { DatePickerProvider, DatePickerTrigger } from '../DatePicker';
2
+ import { TimePickerClock } from './TimePicker';
3
+ import { TimePickerModal } from './TimePickerModal';
3
4
 
4
- export const TimePicker = getRegisteredComponentWithFallback('TimePicker', TimePickerDefault);
5
+ export const TimePicker = {
6
+ Provider: DatePickerProvider,
7
+ Trigger: DatePickerTrigger,
8
+ Clock: TimePickerClock,
9
+ Modal: TimePickerModal,
10
+ };
5
11
 
12
+ export type { TimePickerContextType } from './context';
13
+ export { TimePickerContext, useOptionalTimePickerContext } from './context';
6
14
  export type { Props as TimePickerProps } from './TimePicker';
15
+ export { TimePickerClock } from './TimePicker';
16
+ export type { TimePickerModalProps } from './TimePickerModal';
17
+ export { TimePickerModal } from './TimePickerModal';
7
18
  export {
8
19
  timePickerAmPmSwitcherStyles,
9
20
  timePickerClockHoursStyles,
@@ -11,5 +22,6 @@ export {
11
22
  timePickerClockStyles,
12
23
  timePickerInputsStyles,
13
24
  timePickerInputStyles,
25
+ timePickerModalStyles,
14
26
  timePickerStyles,
15
27
  } from './utils';
@@ -218,6 +218,52 @@ const timePickerClockMinutesStylesDefault = StyleSheet.create(theme => ({
218
218
  textWhite: { color: '#fff' },
219
219
  }));
220
220
 
221
+ const timePickerModalStylesDefault = StyleSheet.create(theme => ({
222
+ keyboardView: {
223
+ justifyContent: 'center',
224
+ alignItems: 'center',
225
+ flex: 1,
226
+ },
227
+ modalContent: {
228
+ minWidth: 287,
229
+ width: undefined,
230
+ maxWidth: undefined,
231
+ flex: undefined,
232
+ borderRadius: theme.shapes.corner.extraLarge,
233
+ overflow: 'hidden',
234
+ },
235
+ frame: {
236
+ backgroundColor: theme.colors.surface,
237
+ },
238
+ labelContainer: {
239
+ minHeight: 56,
240
+ justifyContent: 'flex-end',
241
+ paddingLeft: theme.spacings['6'],
242
+ paddingRight: theme.spacings['6'],
243
+ paddingTop: theme.spacings['6'],
244
+ paddingBottom: theme.spacings['2'],
245
+ alignSelf: 'flex-start',
246
+ },
247
+ label: {
248
+ letterSpacing: 1,
249
+ fontSize: theme.typescale.labelLarge.fontSize,
250
+ color: theme.colors.onSurface,
251
+ fontWeight: theme.typescale.labelLarge.fontWeight,
252
+ },
253
+ timePickerContainer: {
254
+ padding: theme.spacings['6'],
255
+ paddingTop: theme.spacings['2'],
256
+ },
257
+ footer: {
258
+ flexDirection: 'row',
259
+ alignItems: 'center',
260
+ padding: theme.spacings['2'],
261
+ width: '100%',
262
+ },
263
+ inputTypeToggle: { margin: theme.spacings['1'] },
264
+ fill: { flex: 1 },
265
+ }));
266
+
221
267
  const timePickerAmPmSwitcherStylesDefault = StyleSheet.create(theme => ({
222
268
  container: {
223
269
  width: 50,
@@ -291,3 +337,7 @@ export const timePickerAmPmSwitcherStyles = getRegisteredComponentStylesWithFall
291
337
  'TimePicker_AmPmSwitcher',
292
338
  timePickerAmPmSwitcherStylesDefault,
293
339
  );
340
+ export const timePickerModalStyles = getRegisteredComponentStylesWithFallback(
341
+ 'TimePickerModal',
342
+ timePickerModalStylesDefault,
343
+ );
@@ -1,4 +1,4 @@
1
- import { type RefObject, useRef } from 'react';
1
+ import { type RefObject, useCallback, useRef } from 'react';
2
2
 
3
3
  import { useActive } from './useActive';
4
4
  import { useFocus } from './useFocus';
@@ -14,16 +14,27 @@ export type UseActionStateProps = {
14
14
  export const useActionState = (
15
15
  props: UseActionStateProps & { ref?: RefObject<any> | React.ForwardedRef<any> } = {},
16
16
  ) => {
17
- const ref = useRef(null);
18
- const actionsRef = (
19
- (props.ref as any)?.current === undefined ? ref : props.ref
20
- ) as RefObject<any>;
17
+ const internalRef = useRef(null);
18
+ const externalRef = props.ref;
19
+
20
+ const actionsRef = useCallback(
21
+ (node: any) => {
22
+ internalRef.current = node;
23
+ if (typeof externalRef === 'function') {
24
+ externalRef(node);
25
+ } else if (externalRef) {
26
+ (externalRef as RefObject<any>).current = node;
27
+ }
28
+ },
29
+ [externalRef],
30
+ ) as unknown as RefObject<any>;
31
+
21
32
  const hovered =
22
- useHover(actionsRef, props.actionsToListen?.includes('hover')) || !!props.hovered;
33
+ useHover(internalRef, props.actionsToListen?.includes('hover')) || !!props.hovered;
23
34
  const pressed =
24
- useActive(actionsRef, props.actionsToListen?.includes('press')) || !!props.pressed;
35
+ useActive(internalRef, props.actionsToListen?.includes('press')) || !!props.pressed;
25
36
  const focused =
26
- useFocus(actionsRef, props.actionsToListen?.includes('focus')) || !!props.focused;
37
+ useFocus(internalRef, props.actionsToListen?.includes('focus')) || !!props.focused;
27
38
 
28
39
  return {
29
40
  actionsRef,
package/package.json CHANGED
@@ -1,9 +1,14 @@
1
1
  {
2
2
  "name": "react-native-molecules",
3
- "version": "0.5.0-beta.16",
3
+ "version": "0.5.0-beta.17",
4
4
  "author": "Thet Aung <thetaung.dev@gmail.com>",
5
5
  "license": "MIT",
6
6
  "main": "index.ts",
7
+ "sideEffects": [
8
+ "components/DatePicker/context.tsx",
9
+ "components/Select/context.tsx",
10
+ "components/TimePicker/context.tsx"
11
+ ],
7
12
  "files": [
8
13
  "components",
9
14
  "context-bridge",
@@ -1,30 +0,0 @@
1
- import { memo } from 'react';
2
-
3
- import DatePickerInlineBase from '../DatePickerInline/DatePickerInlineBase';
4
- import { Popover } from '../Popover';
5
- import DatePickerDockedHeader from './DatePickerDockedHeader';
6
- import type { DatePickerDockedProps } from './types';
7
- import { datePickerDockedMonthStyles } from './utils';
8
-
9
- const DatePickerDocked = (props: DatePickerDockedProps) => {
10
- const { triggerRef, isOpen, onToggle, onClose } = props;
11
-
12
- return (
13
- <Popover
14
- triggerRef={triggerRef}
15
- isOpen={isOpen}
16
- onClose={onClose}
17
- {...props.popoverContentProps}>
18
- <DatePickerInlineBase
19
- {...props}
20
- // TODO - fix ts issues
21
- // @ts-ignore
22
- HeaderComponent={DatePickerDockedHeader}
23
- onToggle={onToggle}
24
- monthStyle={datePickerDockedMonthStyles}
25
- />
26
- </Popover>
27
- );
28
- };
29
-
30
- export default memo(DatePickerDocked);
@@ -1,129 +0,0 @@
1
- import { add, format } from 'date-fns';
2
- import { memo, useCallback, useMemo } from 'react';
3
- import { View, type ViewStyle } from 'react-native';
4
-
5
- import { useDatePickerStore } from '../DatePickerInline/DatePickerContext';
6
- import type { DisableWeekDaysType } from '../DatePickerInline/dateUtils';
7
- import DayNames from '../DatePickerInline/DayNames';
8
- import HeaderItem from '../DatePickerInline/HeaderItem';
9
- import { dayNamesHeight } from '../DatePickerInline/utils';
10
- import { datePickerDockedHeaderStyles } from './utils';
11
-
12
- const buttonContainerHeight = 56;
13
- const buttonContainerMarginTop = 4;
14
- const buttonContainerMarginBottom = 8;
15
-
16
- export type CalendarHeaderProps = {
17
- locale?: string;
18
- disableWeekDays?: DisableWeekDaysType;
19
- style?: ViewStyle;
20
- };
21
-
22
- function DatePickerDockedHeader({
23
- locale = 'en',
24
- disableWeekDays,
25
- style: styleProp,
26
- }: CalendarHeaderProps) {
27
- const [{ localDate, pickerType, startDateYear, endDateYear }, setStore] = useDatePickerStore(
28
- state => ({
29
- localDate: state.localDate,
30
- pickerType: state.pickerType,
31
- startDateYear: state.startDateYear,
32
- endDateYear: state.endDateYear,
33
- }),
34
- );
35
-
36
- // const componentStyles = useComponentStyles('DatePickerDocked_Header', styleProp);
37
-
38
- const monthName = useMemo(() => {
39
- return format(localDate, 'MMM');
40
- }, [localDate]);
41
-
42
- const { containerStyle, daysWrapperStyle } = useMemo(() => {
43
- return {
44
- containerStyle: [datePickerDockedHeaderStyles.datePickerHeader, styleProp],
45
- daysWrapperStyle: datePickerDockedHeaderStyles.daysWrapperStyle,
46
- };
47
- }, [styleProp]);
48
-
49
- const handlePressDropDown = useCallback(
50
- (type: 'month' | 'year') => {
51
- setStore(prev => ({
52
- pickerType: prev.pickerType ? undefined : type,
53
- }));
54
- },
55
- [setStore],
56
- );
57
-
58
- const isNotInRange = useCallback(
59
- (date: Date) => {
60
- const year = date.getFullYear();
61
- const month = date.getMonth();
62
- if (year < startDateYear || year > endDateYear || month > 11 || month < 0) {
63
- return true;
64
- }
65
- return false;
66
- },
67
- [startDateYear, endDateYear],
68
- );
69
-
70
- const handleChange = useCallback(
71
- (offset: number, type?: 'month' | 'year') => {
72
- let newDate = localDate;
73
- const prop = type === 'month' ? 'months' : 'years';
74
- newDate = add(newDate, { [prop]: offset });
75
-
76
- if (isNotInRange(newDate)) return;
77
-
78
- setStore(() => ({
79
- localDate: newDate,
80
- }));
81
- },
82
- [isNotInRange, localDate, setStore],
83
- );
84
-
85
- const handleChangePrevious = useMemo(() => handleChange.bind(null, -1), [handleChange]);
86
- const handleChangeNext = useMemo(() => handleChange.bind(null, 1), [handleChange]);
87
-
88
- return (
89
- <View>
90
- <View style={containerStyle} pointerEvents={'box-none'}>
91
- <HeaderItem
92
- selecting={!!pickerType}
93
- type="month"
94
- value={monthName}
95
- onNext={handleChangeNext}
96
- onPrev={handleChangePrevious}
97
- onPressDropdown={handlePressDropDown}
98
- pickerType={pickerType}
99
- />
100
- <HeaderItem
101
- selecting={!!pickerType}
102
- type="year"
103
- value={localDate.getFullYear()}
104
- onNext={handleChangeNext}
105
- onPrev={handleChangePrevious}
106
- onPressDropdown={handlePressDropDown}
107
- pickerType={pickerType}
108
- />
109
- </View>
110
- <View style={daysWrapperStyle}>
111
- <DayNames disableWeekDays={disableWeekDays} locale={locale} />
112
- </View>
113
- </View>
114
- );
115
- }
116
-
117
- export function getCalendarHeaderHeight(scrollMode: 'horizontal' | 'vertical') {
118
- if (scrollMode === 'horizontal') {
119
- return (
120
- buttonContainerHeight +
121
- buttonContainerMarginTop +
122
- buttonContainerMarginBottom +
123
- dayNamesHeight
124
- );
125
- }
126
- return dayNamesHeight;
127
- }
128
-
129
- export default memo(DatePickerDockedHeader);
@@ -1,17 +0,0 @@
1
- import { getRegisteredComponentWithFallback } from '../../core';
2
- import DatePickerDockedDefault from './DatePickerDocked';
3
-
4
- export const DatePickerDocked = getRegisteredComponentWithFallback(
5
- 'DatePickerDocked',
6
- DatePickerDockedDefault,
7
- );
8
-
9
- export type { DatePickerDockedProps } from './types';
10
- export {
11
- datePickerDockedHeaderStyles,
12
- datePickerDockedMonthItemStyles,
13
- datePickerDockedMonthStyles,
14
- datePickerDockedStyles,
15
- datePickerHeaderItemStyles,
16
- datePickerMonthPickerStyles,
17
- } from './utils';
@@ -1,11 +0,0 @@
1
- import type { ViewProps } from 'react-native';
2
-
3
- import type { DatePickerSingleProps } from '../DatePickerInline';
4
-
5
- export type DatePickerDockedProps = DatePickerSingleProps & {
6
- triggerRef: any;
7
- onToggle: () => void;
8
- onClose: () => void;
9
- isOpen: boolean;
10
- popoverContentProps?: ViewProps;
11
- };