@cdx-ui/components 0.0.1-beta.140 → 0.0.1-beta.141

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 (148) hide show
  1. package/lib/commonjs/components/BottomSheet/index.js +8 -2
  2. package/lib/commonjs/components/BottomSheet/index.js.map +1 -1
  3. package/lib/commonjs/components/Calendar/CalendarMonthHeader.js +96 -0
  4. package/lib/commonjs/components/Calendar/CalendarMonthHeader.js.map +1 -0
  5. package/lib/commonjs/components/Calendar/CalendarYearPickerGrid.js +74 -0
  6. package/lib/commonjs/components/Calendar/CalendarYearPickerGrid.js.map +1 -0
  7. package/lib/commonjs/components/Calendar/flashCalendarAdapter.js +298 -0
  8. package/lib/commonjs/components/Calendar/flashCalendarAdapter.js.map +1 -0
  9. package/lib/commonjs/components/Calendar/index.js +149 -0
  10. package/lib/commonjs/components/Calendar/index.js.map +1 -0
  11. package/lib/commonjs/components/Calendar/styles.js +70 -0
  12. package/lib/commonjs/components/Calendar/styles.js.map +1 -0
  13. package/lib/commonjs/components/DateField/index.js +147 -0
  14. package/lib/commonjs/components/DateField/index.js.map +1 -0
  15. package/lib/commonjs/components/DateField/styles.js +34 -0
  16. package/lib/commonjs/components/DateField/styles.js.map +1 -0
  17. package/lib/commonjs/components/DatePicker/index.js +163 -0
  18. package/lib/commonjs/components/DatePicker/index.js.map +1 -0
  19. package/lib/commonjs/components/DateRangePicker/index.js +177 -0
  20. package/lib/commonjs/components/DateRangePicker/index.js.map +1 -0
  21. package/lib/commonjs/components/DateTimeField/index.js +96 -0
  22. package/lib/commonjs/components/DateTimeField/index.js.map +1 -0
  23. package/lib/commonjs/components/DateTimeList/index.js +180 -0
  24. package/lib/commonjs/components/DateTimeList/index.js.map +1 -0
  25. package/lib/commonjs/components/DateTimeList/styles.js +55 -0
  26. package/lib/commonjs/components/DateTimeList/styles.js.map +1 -0
  27. package/lib/commonjs/components/DateTimePicker/index.js +187 -0
  28. package/lib/commonjs/components/DateTimePicker/index.js.map +1 -0
  29. package/lib/commonjs/components/MonthCalendar/index.js +229 -0
  30. package/lib/commonjs/components/MonthCalendar/index.js.map +1 -0
  31. package/lib/commonjs/components/MonthPicker/index.js +163 -0
  32. package/lib/commonjs/components/MonthPicker/index.js.map +1 -0
  33. package/lib/commonjs/components/RangeCalendar/index.js +165 -0
  34. package/lib/commonjs/components/RangeCalendar/index.js.map +1 -0
  35. package/lib/commonjs/components/index.js +120 -0
  36. package/lib/commonjs/components/index.js.map +1 -1
  37. package/lib/commonjs/components/picker/PickerTrigger.js +49 -0
  38. package/lib/commonjs/components/picker/PickerTrigger.js.map +1 -0
  39. package/lib/commonjs/components/picker/styles.js +15 -0
  40. package/lib/commonjs/components/picker/styles.js.map +1 -0
  41. package/lib/commonjs/components/picker/surfaces.js +141 -0
  42. package/lib/commonjs/components/picker/surfaces.js.map +1 -0
  43. package/lib/module/components/BottomSheet/index.js +8 -2
  44. package/lib/module/components/BottomSheet/index.js.map +1 -1
  45. package/lib/module/components/Calendar/CalendarMonthHeader.js +92 -0
  46. package/lib/module/components/Calendar/CalendarMonthHeader.js.map +1 -0
  47. package/lib/module/components/Calendar/CalendarYearPickerGrid.js +70 -0
  48. package/lib/module/components/Calendar/CalendarYearPickerGrid.js.map +1 -0
  49. package/lib/module/components/Calendar/flashCalendarAdapter.js +290 -0
  50. package/lib/module/components/Calendar/flashCalendarAdapter.js.map +1 -0
  51. package/lib/module/components/Calendar/index.js +145 -0
  52. package/lib/module/components/Calendar/index.js.map +1 -0
  53. package/lib/module/components/Calendar/styles.js +66 -0
  54. package/lib/module/components/Calendar/styles.js.map +1 -0
  55. package/lib/module/components/DateField/index.js +143 -0
  56. package/lib/module/components/DateField/index.js.map +1 -0
  57. package/lib/module/components/DateField/styles.js +30 -0
  58. package/lib/module/components/DateField/styles.js.map +1 -0
  59. package/lib/module/components/DatePicker/index.js +159 -0
  60. package/lib/module/components/DatePicker/index.js.map +1 -0
  61. package/lib/module/components/DateRangePicker/index.js +173 -0
  62. package/lib/module/components/DateRangePicker/index.js.map +1 -0
  63. package/lib/module/components/DateTimeField/index.js +92 -0
  64. package/lib/module/components/DateTimeField/index.js.map +1 -0
  65. package/lib/module/components/DateTimeList/index.js +176 -0
  66. package/lib/module/components/DateTimeList/index.js.map +1 -0
  67. package/lib/module/components/DateTimeList/styles.js +52 -0
  68. package/lib/module/components/DateTimeList/styles.js.map +1 -0
  69. package/lib/module/components/DateTimePicker/index.js +183 -0
  70. package/lib/module/components/DateTimePicker/index.js.map +1 -0
  71. package/lib/module/components/MonthCalendar/index.js +225 -0
  72. package/lib/module/components/MonthCalendar/index.js.map +1 -0
  73. package/lib/module/components/MonthPicker/index.js +159 -0
  74. package/lib/module/components/MonthPicker/index.js.map +1 -0
  75. package/lib/module/components/RangeCalendar/index.js +161 -0
  76. package/lib/module/components/RangeCalendar/index.js.map +1 -0
  77. package/lib/module/components/index.js +10 -0
  78. package/lib/module/components/index.js.map +1 -1
  79. package/lib/module/components/picker/PickerTrigger.js +45 -0
  80. package/lib/module/components/picker/PickerTrigger.js.map +1 -0
  81. package/lib/module/components/picker/styles.js +12 -0
  82. package/lib/module/components/picker/styles.js.map +1 -0
  83. package/lib/module/components/picker/surfaces.js +135 -0
  84. package/lib/module/components/picker/surfaces.js.map +1 -0
  85. package/lib/typescript/components/BottomSheet/index.d.ts +2 -2
  86. package/lib/typescript/components/BottomSheet/index.d.ts.map +1 -1
  87. package/lib/typescript/components/Calendar/CalendarMonthHeader.d.ts +14 -0
  88. package/lib/typescript/components/Calendar/CalendarMonthHeader.d.ts.map +1 -0
  89. package/lib/typescript/components/Calendar/CalendarYearPickerGrid.d.ts +12 -0
  90. package/lib/typescript/components/Calendar/CalendarYearPickerGrid.d.ts.map +1 -0
  91. package/lib/typescript/components/Calendar/flashCalendarAdapter.d.ts +18 -0
  92. package/lib/typescript/components/Calendar/flashCalendarAdapter.d.ts.map +1 -0
  93. package/lib/typescript/components/Calendar/index.d.ts +19 -0
  94. package/lib/typescript/components/Calendar/index.d.ts.map +1 -0
  95. package/lib/typescript/components/Calendar/styles.d.ts +23 -0
  96. package/lib/typescript/components/Calendar/styles.d.ts.map +1 -0
  97. package/lib/typescript/components/DateField/index.d.ts +43 -0
  98. package/lib/typescript/components/DateField/index.d.ts.map +1 -0
  99. package/lib/typescript/components/DateField/styles.d.ts +15 -0
  100. package/lib/typescript/components/DateField/styles.d.ts.map +1 -0
  101. package/lib/typescript/components/DatePicker/index.d.ts +40 -0
  102. package/lib/typescript/components/DatePicker/index.d.ts.map +1 -0
  103. package/lib/typescript/components/DateRangePicker/index.d.ts +45 -0
  104. package/lib/typescript/components/DateRangePicker/index.d.ts.map +1 -0
  105. package/lib/typescript/components/DateTimeField/index.d.ts +29 -0
  106. package/lib/typescript/components/DateTimeField/index.d.ts.map +1 -0
  107. package/lib/typescript/components/DateTimeList/index.d.ts +19 -0
  108. package/lib/typescript/components/DateTimeList/index.d.ts.map +1 -0
  109. package/lib/typescript/components/DateTimeList/styles.d.ts +17 -0
  110. package/lib/typescript/components/DateTimeList/styles.d.ts.map +1 -0
  111. package/lib/typescript/components/DateTimePicker/index.d.ts +40 -0
  112. package/lib/typescript/components/DateTimePicker/index.d.ts.map +1 -0
  113. package/lib/typescript/components/MonthCalendar/index.d.ts +29 -0
  114. package/lib/typescript/components/MonthCalendar/index.d.ts.map +1 -0
  115. package/lib/typescript/components/MonthPicker/index.d.ts +40 -0
  116. package/lib/typescript/components/MonthPicker/index.d.ts.map +1 -0
  117. package/lib/typescript/components/RangeCalendar/index.d.ts +19 -0
  118. package/lib/typescript/components/RangeCalendar/index.d.ts.map +1 -0
  119. package/lib/typescript/components/index.d.ts +10 -0
  120. package/lib/typescript/components/index.d.ts.map +1 -1
  121. package/lib/typescript/components/picker/PickerTrigger.d.ts +25 -0
  122. package/lib/typescript/components/picker/PickerTrigger.d.ts.map +1 -0
  123. package/lib/typescript/components/picker/styles.d.ts +4 -0
  124. package/lib/typescript/components/picker/styles.d.ts.map +1 -0
  125. package/lib/typescript/components/picker/surfaces.d.ts +28 -0
  126. package/lib/typescript/components/picker/surfaces.d.ts.map +1 -0
  127. package/package.json +6 -4
  128. package/src/components/BottomSheet/index.tsx +7 -1
  129. package/src/components/Calendar/CalendarMonthHeader.tsx +124 -0
  130. package/src/components/Calendar/CalendarYearPickerGrid.tsx +101 -0
  131. package/src/components/Calendar/flashCalendarAdapter.ts +362 -0
  132. package/src/components/Calendar/index.tsx +151 -0
  133. package/src/components/Calendar/styles.ts +80 -0
  134. package/src/components/DateField/index.tsx +196 -0
  135. package/src/components/DateField/styles.ts +51 -0
  136. package/src/components/DatePicker/index.tsx +187 -0
  137. package/src/components/DateRangePicker/index.tsx +202 -0
  138. package/src/components/DateTimeField/index.tsx +128 -0
  139. package/src/components/DateTimeList/index.tsx +187 -0
  140. package/src/components/DateTimeList/styles.ts +59 -0
  141. package/src/components/DateTimePicker/index.tsx +233 -0
  142. package/src/components/MonthCalendar/index.tsx +252 -0
  143. package/src/components/MonthPicker/index.tsx +188 -0
  144. package/src/components/RangeCalendar/index.tsx +162 -0
  145. package/src/components/index.ts +10 -0
  146. package/src/components/picker/PickerTrigger.tsx +65 -0
  147. package/src/components/picker/styles.ts +17 -0
  148. package/src/components/picker/surfaces.tsx +174 -0
@@ -0,0 +1,196 @@
1
+ import { forwardRef, useMemo, type ReactNode } from 'react';
2
+ import { View, type ViewProps } from 'react-native';
3
+ import {
4
+ DateFieldInput as DateFieldInputPrimitive,
5
+ DateFieldRoot as DateFieldRootPrimitive,
6
+ DateFieldSegment as DateFieldSegmentPrimitive,
7
+ InputRoot as InputRootPrimitive,
8
+ Slot,
9
+ dataAttributes,
10
+ mergeDataAttributes,
11
+ type DateFieldRootProps as DateFieldRootPrimitiveProps,
12
+ type DateFieldSegmentProps as DateFieldSegmentPrimitiveProps,
13
+ } from '@cdx-ui/primitives';
14
+ import type { DateComponentLabels } from '@cdx-ui/formatters';
15
+ import { cn, ParentContext, useParentContext } from '@cdx-ui/utils';
16
+ import {
17
+ dateFieldGroupVariants,
18
+ dateFieldInputVariants,
19
+ dateFieldRootVariants,
20
+ dateFieldSegmentVariants,
21
+ dateFieldSuffixVariants,
22
+ type DateFieldGroupVariantProps,
23
+ } from './styles';
24
+
25
+ const SCOPE = 'DATE_FIELD';
26
+
27
+ type DateFieldStyleContext = DateFieldGroupVariantProps & {
28
+ fullWidth?: boolean;
29
+ };
30
+
31
+ const useDateFieldStyleContext = (): DateFieldStyleContext =>
32
+ (useParentContext()[SCOPE] as DateFieldStyleContext | undefined) ?? {};
33
+
34
+ export interface DateFieldProps extends DateFieldRootPrimitiveProps, DateFieldGroupVariantProps {
35
+ className?: string;
36
+ /** When true (the default), the group stretches to fill its container; when false, it hugs the segments. */
37
+ fullWidth?: boolean;
38
+ labels?: Partial<DateComponentLabels>;
39
+ }
40
+
41
+ const DateFieldRoot = forwardRef<View, DateFieldProps>(
42
+ (
43
+ {
44
+ mode = 'date',
45
+ locale = 'en-US',
46
+ labels,
47
+ variant = 'outline',
48
+ size = 'default',
49
+ fullWidth,
50
+ className,
51
+ children,
52
+ style,
53
+ ...props
54
+ },
55
+ ref,
56
+ ) => {
57
+ const parent = useParentContext();
58
+ const ctx = useMemo(
59
+ () => ({ ...parent, [SCOPE]: { variant, size, fullWidth } }),
60
+ [parent, variant, size, fullWidth],
61
+ );
62
+
63
+ return (
64
+ <ParentContext.Provider value={ctx}>
65
+ <DateFieldRootPrimitive
66
+ ref={ref}
67
+ mode={mode}
68
+ locale={locale}
69
+ labels={labels}
70
+ className={cn(dateFieldRootVariants(), className)}
71
+ style={style}
72
+ {...props}
73
+ {...mergeDataAttributes(props, dataAttributes({ slot: 'date-field' }))}
74
+ >
75
+ {children}
76
+ </DateFieldRootPrimitive>
77
+ </ParentContext.Provider>
78
+ );
79
+ },
80
+ );
81
+
82
+ DateFieldRoot.displayName = 'DateField';
83
+
84
+ export interface DateFieldGroupProps extends ViewProps, DateFieldGroupVariantProps {
85
+ className?: string;
86
+ children?: ReactNode;
87
+ fullWidth?: boolean;
88
+ }
89
+
90
+ const DateFieldGroup = forwardRef<View, DateFieldGroupProps>(
91
+ ({ variant, size, fullWidth, className, children, style, ...props }, ref) => {
92
+ const inherited = useDateFieldStyleContext();
93
+ const resolvedVariant = variant ?? inherited.variant ?? 'outline';
94
+ const resolvedSize = size ?? inherited.size ?? 'default';
95
+ const resolvedFullWidth = fullWidth ?? inherited.fullWidth ?? true;
96
+ const computedClassName = cn(
97
+ dateFieldGroupVariants({ variant: resolvedVariant, size: resolvedSize }),
98
+ !resolvedFullWidth && 'w-auto self-start',
99
+ className,
100
+ );
101
+
102
+ return (
103
+ <InputRootPrimitive ref={ref} className={computedClassName} style={style} {...props}>
104
+ {children}
105
+ </InputRootPrimitive>
106
+ );
107
+ },
108
+ );
109
+
110
+ DateFieldGroup.displayName = 'DateField.Group';
111
+
112
+ export interface DateFieldInputProps extends Omit<ViewProps, 'children'> {
113
+ children?: (segment: DateFieldSegmentPrimitiveProps['segment']) => ReactNode;
114
+ slot?: 'start' | 'end';
115
+ className?: string;
116
+ }
117
+
118
+ export interface DateFieldSegmentProps extends DateFieldSegmentPrimitiveProps {
119
+ className?: string;
120
+ }
121
+
122
+ const DateFieldSegment = forwardRef<View, DateFieldSegmentProps>(
123
+ ({ segment, className, style, ...props }, ref) => (
124
+ <DateFieldSegmentPrimitive
125
+ ref={ref}
126
+ segment={segment}
127
+ className={cn(dateFieldSegmentVariants({ literal: !segment.isEditable }), className)}
128
+ style={style}
129
+ {...props}
130
+ {...mergeDataAttributes(props, dataAttributes({ slot: 'date-field-segment' }))}
131
+ />
132
+ ),
133
+ );
134
+
135
+ DateFieldSegment.displayName = 'DateField.Segment';
136
+
137
+ const renderDefaultDateFieldSegment = (segment: DateFieldSegmentPrimitiveProps['segment']) => (
138
+ <DateFieldSegment segment={segment} />
139
+ );
140
+
141
+ const DateFieldInput = forwardRef<View, DateFieldInputProps>(
142
+ ({ children = renderDefaultDateFieldSegment, className, style, ...props }, ref) => {
143
+ const { size } = useDateFieldStyleContext();
144
+ return (
145
+ <DateFieldInputPrimitive
146
+ ref={ref}
147
+ className={cn(dateFieldInputVariants({ size: size ?? 'default' }), className)}
148
+ style={style}
149
+ {...props}
150
+ >
151
+ {children}
152
+ </DateFieldInputPrimitive>
153
+ );
154
+ },
155
+ );
156
+
157
+ DateFieldInput.displayName = 'DateField.Input';
158
+
159
+ export interface DateFieldSuffixProps extends ViewProps {
160
+ asChild?: boolean;
161
+ className?: string;
162
+ children?: ReactNode;
163
+ }
164
+
165
+ const DateFieldSuffix = forwardRef<View, DateFieldSuffixProps>(
166
+ ({ asChild, className, children, style, ...props }, ref) => {
167
+ const Comp = asChild ? Slot : View;
168
+ return (
169
+ <Comp
170
+ ref={ref}
171
+ className={cn(dateFieldSuffixVariants(), className)}
172
+ style={style}
173
+ {...props}
174
+ {...mergeDataAttributes(props, dataAttributes({ slot: 'date-field-suffix' }))}
175
+ >
176
+ {children}
177
+ </Comp>
178
+ );
179
+ },
180
+ );
181
+
182
+ DateFieldSuffix.displayName = 'DateField.Suffix';
183
+
184
+ type DateFieldCompound = typeof DateFieldRoot & {
185
+ Group: typeof DateFieldGroup;
186
+ Input: typeof DateFieldInput;
187
+ Segment: typeof DateFieldSegment;
188
+ Suffix: typeof DateFieldSuffix;
189
+ };
190
+
191
+ export const DateField = Object.assign(DateFieldRoot, {
192
+ Group: DateFieldGroup,
193
+ Input: DateFieldInput,
194
+ Segment: DateFieldSegment,
195
+ Suffix: DateFieldSuffix,
196
+ }) as DateFieldCompound;
@@ -0,0 +1,51 @@
1
+ import { cva, type VariantProps } from '@cdx-ui/utils';
2
+ import { inputRootVariants, inputSlotVariants } from '../Input/styles';
3
+
4
+ export const dateFieldRootVariants = cva('gap-1.5');
5
+
6
+ export const dateFieldGroupVariants = inputRootVariants;
7
+
8
+ export const dateFieldInputVariants = cva(
9
+ [
10
+ 'flex-1 min-w-0 flex-row flex-wrap items-center gap-px bg-transparent p-0',
11
+ 'text-content-primary',
12
+ 'web:outline-none',
13
+ 'tracking-normal',
14
+ 'tabular-nums',
15
+ ],
16
+ {
17
+ variants: {
18
+ size: {
19
+ default: 'text-[0.875rem]',
20
+ small: 'text-[0.75rem]',
21
+ },
22
+ },
23
+ defaultVariants: {
24
+ size: 'default',
25
+ },
26
+ },
27
+ );
28
+
29
+ export const dateFieldSegmentVariants = cva(
30
+ [
31
+ 'body-md shrink-0 rounded-[var(--border-radius-default)] px-0.5 text-end tabular-nums',
32
+ 'text-content-primary',
33
+ 'data-[placeholder=true]:text-content-tertiary',
34
+ 'data-[focus=true]:bg-surface-action-subtle data-[focus=true]:text-content-primary',
35
+ ],
36
+ {
37
+ variants: {
38
+ literal: {
39
+ true: 'text-content-secondary px-0',
40
+ false: '',
41
+ },
42
+ },
43
+ defaultVariants: {
44
+ literal: false,
45
+ },
46
+ },
47
+ );
48
+
49
+ export const dateFieldSuffixVariants = inputSlotVariants;
50
+
51
+ export type DateFieldGroupVariantProps = VariantProps<typeof dateFieldGroupVariants>;
@@ -0,0 +1,187 @@
1
+ import { forwardRef, useCallback, useMemo, type ReactNode } from 'react';
2
+ import { View, type ViewProps } from 'react-native';
3
+ import { CalendarToday } from '@cdx-ui/icons';
4
+ import type { DateId } from '@cdx-ui/formatters';
5
+ import {
6
+ dataAttributes,
7
+ DatePickerContext,
8
+ DatePickerRoot as DatePickerRootPrimitive,
9
+ mergeDataAttributes,
10
+ useDatePickerContext,
11
+ type DatePickerRootProps as DatePickerRootPrimitiveProps,
12
+ } from '@cdx-ui/primitives';
13
+ import { cn, ParentContext, useParentContext } from '@cdx-ui/utils';
14
+ import { Dialog } from '../Dialog';
15
+ import { Icon } from '../Icon';
16
+ import { Calendar, type CalendarProps } from '../Calendar';
17
+ import { PickerTrigger, type PickerTriggerProps } from '../picker/PickerTrigger';
18
+ import {
19
+ PickerBottomSheetSurface,
20
+ PickerDialogSurface,
21
+ PickerPopoverSurface,
22
+ } from '../picker/surfaces';
23
+
24
+ export interface DatePickerProps extends DatePickerRootPrimitiveProps, Omit<ViewProps, 'children'> {
25
+ className?: string;
26
+ children?: ReactNode;
27
+ }
28
+
29
+ const DATE_FIELD_SCOPE = 'DATE_FIELD';
30
+
31
+ const DatePickerRoot = forwardRef<View, DatePickerProps>(
32
+ ({ className, children, style, ...props }, ref) => {
33
+ const parent = useParentContext();
34
+ const ctx = useMemo(
35
+ () => ({
36
+ ...parent,
37
+ [DATE_FIELD_SCOPE]: { variant: 'outline', size: 'default', fullWidth: true },
38
+ }),
39
+ [parent],
40
+ );
41
+
42
+ return (
43
+ <ParentContext.Provider value={ctx}>
44
+ <DatePickerRootPrimitive
45
+ ref={ref}
46
+ className={cn('gap-2', className)}
47
+ style={style}
48
+ {...props}
49
+ {...mergeDataAttributes(props, dataAttributes({ slot: 'date-picker' }))}
50
+ >
51
+ {children}
52
+ </DatePickerRootPrimitive>
53
+ </ParentContext.Provider>
54
+ );
55
+ },
56
+ );
57
+
58
+ DatePickerRoot.displayName = 'DatePicker';
59
+
60
+ type DatePickerTriggerProps = Omit<
61
+ PickerTriggerProps,
62
+ 'open' | 'setOpen' | 'disabled' | 'triggerRef' | 'accessibilityLabel'
63
+ > & {
64
+ accessibilityLabel?: string;
65
+ };
66
+
67
+ const DatePickerTrigger = forwardRef<View, DatePickerTriggerProps>(
68
+ ({ accessibilityLabel, ...props }, ref) => {
69
+ const { open, setOpen, disabled, triggerRef, labels } = useDatePickerContext();
70
+ return (
71
+ <PickerTrigger
72
+ ref={ref}
73
+ open={open}
74
+ setOpen={setOpen}
75
+ disabled={disabled}
76
+ triggerRef={triggerRef}
77
+ accessibilityLabel={accessibilityLabel ?? labels.openDatePicker}
78
+ {...props}
79
+ />
80
+ );
81
+ },
82
+ );
83
+
84
+ DatePickerTrigger.displayName = 'DatePicker.Trigger';
85
+
86
+ const DatePickerTriggerIndicator = () => (
87
+ <Icon as={CalendarToday} className="text-content-secondary" />
88
+ );
89
+
90
+ DatePickerTriggerIndicator.displayName = 'DatePicker.TriggerIndicator';
91
+
92
+ type DatePickerCalendarProps = Omit<
93
+ CalendarProps,
94
+ 'value' | 'onValueChange' | 'minValue' | 'maxValue'
95
+ >;
96
+
97
+ const DatePickerCalendar = forwardRef<View, DatePickerCalendarProps>(({ ...props }, ref) => {
98
+ const { value, onValueChange, open, setOpen, minValue, maxValue, locale, labels } =
99
+ useDatePickerContext();
100
+
101
+ const handleValueChange = useCallback(
102
+ (next: DateId | undefined) => {
103
+ onValueChange?.(next);
104
+ if (open) {
105
+ setOpen(false);
106
+ }
107
+ },
108
+ [onValueChange, open, setOpen],
109
+ );
110
+
111
+ return (
112
+ <Calendar
113
+ ref={ref}
114
+ value={value}
115
+ onValueChange={handleValueChange}
116
+ minValue={minValue}
117
+ maxValue={maxValue}
118
+ locale={locale}
119
+ labels={labels}
120
+ {...props}
121
+ />
122
+ );
123
+ });
124
+
125
+ DatePickerCalendar.displayName = 'DatePicker.Calendar';
126
+
127
+ function DatePickerDialog({ children }: { children: ReactNode }) {
128
+ const ctx = useDatePickerContext();
129
+ return (
130
+ <PickerDialogSurface
131
+ open={ctx.open}
132
+ setOpen={ctx.setOpen}
133
+ registerSurface={ctx.registerSurface}
134
+ >
135
+ <Dialog.Popup className="p-4">
136
+ <DatePickerContext.Provider value={ctx}>{children}</DatePickerContext.Provider>
137
+ </Dialog.Popup>
138
+ </PickerDialogSurface>
139
+ );
140
+ }
141
+
142
+ function DatePickerBottomSheet({ children }: { children: ReactNode }) {
143
+ const ctx = useDatePickerContext();
144
+ return (
145
+ <PickerBottomSheetSurface
146
+ open={ctx.open}
147
+ setOpen={ctx.setOpen}
148
+ registerSurface={ctx.registerSurface}
149
+ >
150
+ <DatePickerContext.Provider value={ctx}>{children}</DatePickerContext.Provider>
151
+ </PickerBottomSheetSurface>
152
+ );
153
+ }
154
+
155
+ function DatePickerPopover({ children, className }: { children: ReactNode; className?: string }) {
156
+ const ctx = useDatePickerContext();
157
+ return (
158
+ <PickerPopoverSurface
159
+ open={ctx.open}
160
+ setOpen={ctx.setOpen}
161
+ registerSurface={ctx.registerSurface}
162
+ anchorRef={ctx.anchorRef}
163
+ triggerRef={ctx.triggerRef}
164
+ className={className}
165
+ >
166
+ <DatePickerContext.Provider value={ctx}>{children}</DatePickerContext.Provider>
167
+ </PickerPopoverSurface>
168
+ );
169
+ }
170
+
171
+ type DatePickerCompound = typeof DatePickerRoot & {
172
+ Trigger: typeof DatePickerTrigger;
173
+ TriggerIndicator: typeof DatePickerTriggerIndicator;
174
+ Calendar: typeof DatePickerCalendar;
175
+ Popover: typeof DatePickerPopover;
176
+ Dialog: typeof DatePickerDialog;
177
+ BottomSheet: typeof DatePickerBottomSheet;
178
+ };
179
+
180
+ export const DatePicker = Object.assign(DatePickerRoot, {
181
+ Trigger: DatePickerTrigger,
182
+ TriggerIndicator: DatePickerTriggerIndicator,
183
+ Calendar: DatePickerCalendar,
184
+ Popover: DatePickerPopover,
185
+ Dialog: DatePickerDialog,
186
+ BottomSheet: DatePickerBottomSheet,
187
+ }) as DatePickerCompound;
@@ -0,0 +1,202 @@
1
+ import { forwardRef, useMemo, type ReactNode } from 'react';
2
+ import { Text, View, type ViewProps } from 'react-native';
3
+ import { CalendarToday } from '@cdx-ui/icons';
4
+ import {
5
+ dataAttributes,
6
+ DateRangePickerContext,
7
+ DateRangePickerRoot as DateRangePickerRootPrimitive,
8
+ mergeDataAttributes,
9
+ useDateRangePickerContext,
10
+ type DateRangePickerRootProps as DateRangePickerRootPrimitiveProps,
11
+ } from '@cdx-ui/primitives';
12
+ import { cn, ParentContext, useParentContext } from '@cdx-ui/utils';
13
+ import { Dialog } from '../Dialog';
14
+ import { Icon } from '../Icon';
15
+ import { RangeCalendar, type RangeCalendarProps } from '../RangeCalendar';
16
+ import { PickerTrigger, type PickerTriggerProps } from '../picker/PickerTrigger';
17
+ import {
18
+ PickerBottomSheetSurface,
19
+ PickerDialogSurface,
20
+ PickerPopoverSurface,
21
+ } from '../picker/surfaces';
22
+
23
+ export type { DateRangeValue } from '@cdx-ui/primitives';
24
+
25
+ export interface DateRangePickerProps
26
+ extends DateRangePickerRootPrimitiveProps, Omit<ViewProps, 'children'> {
27
+ className?: string;
28
+ children?: ReactNode;
29
+ }
30
+
31
+ const DATE_FIELD_SCOPE = 'DATE_FIELD';
32
+
33
+ const DateRangePickerRoot = forwardRef<View, DateRangePickerProps>(
34
+ ({ className, children, style, ...props }, ref) => {
35
+ const parent = useParentContext();
36
+ const ctx = useMemo(
37
+ () => ({
38
+ ...parent,
39
+ [DATE_FIELD_SCOPE]: { variant: 'outline', size: 'default', fullWidth: true },
40
+ }),
41
+ [parent],
42
+ );
43
+
44
+ return (
45
+ <ParentContext.Provider value={ctx}>
46
+ <DateRangePickerRootPrimitive
47
+ ref={ref}
48
+ className={cn('gap-2', className)}
49
+ style={style}
50
+ {...props}
51
+ {...mergeDataAttributes(props, dataAttributes({ slot: 'date-range-picker' }))}
52
+ >
53
+ {children}
54
+ </DateRangePickerRootPrimitive>
55
+ </ParentContext.Provider>
56
+ );
57
+ },
58
+ );
59
+
60
+ DateRangePickerRoot.displayName = 'DateRangePicker';
61
+
62
+ type DateRangePickerTriggerProps = Omit<
63
+ PickerTriggerProps,
64
+ 'open' | 'setOpen' | 'disabled' | 'triggerRef' | 'accessibilityLabel'
65
+ > & {
66
+ accessibilityLabel?: string;
67
+ };
68
+
69
+ const DateRangePickerTrigger = forwardRef<View, DateRangePickerTriggerProps>(
70
+ ({ accessibilityLabel, ...props }, ref) => {
71
+ const { open, setOpen, disabled, triggerRef, labels } = useDateRangePickerContext();
72
+ return (
73
+ <PickerTrigger
74
+ ref={ref}
75
+ open={open}
76
+ setOpen={setOpen}
77
+ disabled={disabled}
78
+ triggerRef={triggerRef}
79
+ accessibilityLabel={accessibilityLabel ?? labels.openDateRangePicker}
80
+ {...props}
81
+ />
82
+ );
83
+ },
84
+ );
85
+
86
+ DateRangePickerTrigger.displayName = 'DateRangePicker.Trigger';
87
+
88
+ const DateRangePickerTriggerIndicator = () => (
89
+ <Icon as={CalendarToday} className="text-content-secondary" />
90
+ );
91
+
92
+ DateRangePickerTriggerIndicator.displayName = 'DateRangePicker.TriggerIndicator';
93
+
94
+ const DateRangePickerRangeSeparator = () => {
95
+ const { labels } = useDateRangePickerContext();
96
+ return <Text className="body-md text-content-secondary px-1">{labels.rangeSeparator}</Text>;
97
+ };
98
+
99
+ DateRangePickerRangeSeparator.displayName = 'DateRangePicker.RangeSeparator';
100
+
101
+ type DateRangePickerCalendarProps = Omit<
102
+ RangeCalendarProps,
103
+ 'startValue' | 'endValue' | 'onRangeChange' | 'focusedField' | 'onFocusedFieldChange'
104
+ >;
105
+
106
+ const DateRangePickerCalendar = forwardRef<View, DateRangePickerCalendarProps>(
107
+ ({ ...props }, ref) => {
108
+ const { startValue, endValue, onRangeChange, focusedField, setFocusedField, locale, labels } =
109
+ useDateRangePickerContext();
110
+
111
+ return (
112
+ <RangeCalendar
113
+ ref={ref}
114
+ startValue={startValue}
115
+ endValue={endValue}
116
+ focusedField={focusedField}
117
+ onFocusedFieldChange={setFocusedField}
118
+ locale={locale}
119
+ labels={labels}
120
+ onRangeChange={(range) => {
121
+ if (!range.startId) {
122
+ return;
123
+ }
124
+ onRangeChange?.({ startId: range.startId, endId: range.endId });
125
+ }}
126
+ {...props}
127
+ />
128
+ );
129
+ },
130
+ );
131
+
132
+ DateRangePickerCalendar.displayName = 'DateRangePicker.Calendar';
133
+
134
+ function DateRangePickerDialog({ children }: { children: ReactNode }) {
135
+ const ctx = useDateRangePickerContext();
136
+ return (
137
+ <PickerDialogSurface
138
+ open={ctx.open}
139
+ setOpen={ctx.setOpen}
140
+ registerSurface={ctx.registerSurface}
141
+ >
142
+ <Dialog.Popup className="p-4">
143
+ <DateRangePickerContext.Provider value={ctx}>{children}</DateRangePickerContext.Provider>
144
+ </Dialog.Popup>
145
+ </PickerDialogSurface>
146
+ );
147
+ }
148
+
149
+ function DateRangePickerBottomSheet({ children }: { children: ReactNode }) {
150
+ const ctx = useDateRangePickerContext();
151
+ return (
152
+ <PickerBottomSheetSurface
153
+ open={ctx.open}
154
+ setOpen={ctx.setOpen}
155
+ registerSurface={ctx.registerSurface}
156
+ >
157
+ <DateRangePickerContext.Provider value={ctx}>{children}</DateRangePickerContext.Provider>
158
+ </PickerBottomSheetSurface>
159
+ );
160
+ }
161
+
162
+ function DateRangePickerPopover({
163
+ children,
164
+ className,
165
+ }: {
166
+ children: ReactNode;
167
+ className?: string;
168
+ }) {
169
+ const ctx = useDateRangePickerContext();
170
+ return (
171
+ <PickerPopoverSurface
172
+ open={ctx.open}
173
+ setOpen={ctx.setOpen}
174
+ registerSurface={ctx.registerSurface}
175
+ anchorRef={ctx.anchorRef}
176
+ triggerRef={ctx.triggerRef}
177
+ className={className}
178
+ >
179
+ <DateRangePickerContext.Provider value={ctx}>{children}</DateRangePickerContext.Provider>
180
+ </PickerPopoverSurface>
181
+ );
182
+ }
183
+
184
+ type DateRangePickerCompound = typeof DateRangePickerRoot & {
185
+ Trigger: typeof DateRangePickerTrigger;
186
+ TriggerIndicator: typeof DateRangePickerTriggerIndicator;
187
+ RangeSeparator: typeof DateRangePickerRangeSeparator;
188
+ Calendar: typeof DateRangePickerCalendar;
189
+ Popover: typeof DateRangePickerPopover;
190
+ Dialog: typeof DateRangePickerDialog;
191
+ BottomSheet: typeof DateRangePickerBottomSheet;
192
+ };
193
+
194
+ export const DateRangePicker = Object.assign(DateRangePickerRoot, {
195
+ Trigger: DateRangePickerTrigger,
196
+ TriggerIndicator: DateRangePickerTriggerIndicator,
197
+ RangeSeparator: DateRangePickerRangeSeparator,
198
+ Calendar: DateRangePickerCalendar,
199
+ Popover: DateRangePickerPopover,
200
+ Dialog: DateRangePickerDialog,
201
+ BottomSheet: DateRangePickerBottomSheet,
202
+ }) as DateRangePickerCompound;