panelui-native 0.25.0 → 0.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -1
- package/lib/module/components/accordion/index.js +8 -8
- package/lib/module/components/accordion/index.js.map +1 -1
- package/lib/module/components/alert/index.js +2 -2
- package/lib/module/components/alert/index.js.map +1 -1
- package/lib/module/components/area-chart/index.js +182 -50
- package/lib/module/components/area-chart/index.js.map +1 -1
- package/lib/module/components/attachment/index.js +2 -1
- package/lib/module/components/attachment/index.js.map +1 -1
- package/lib/module/components/avatar/index.js +3 -3
- package/lib/module/components/avatar/index.js.map +1 -1
- package/lib/module/components/badge/index.js +4 -4
- package/lib/module/components/badge/index.js.map +1 -1
- package/lib/module/components/bar-chart/index.js +197 -56
- package/lib/module/components/bar-chart/index.js.map +1 -1
- package/lib/module/components/bottom-sheet/index.js +15 -10
- package/lib/module/components/bottom-sheet/index.js.map +1 -1
- package/lib/module/components/breadcrumb/index.js +6 -6
- package/lib/module/components/breadcrumb/index.js.map +1 -1
- package/lib/module/components/button/index.js +11 -6
- package/lib/module/components/button/index.js.map +1 -1
- package/lib/module/components/calendar/index.js +792 -0
- package/lib/module/components/calendar/index.js.map +1 -0
- package/lib/module/components/carousel/index.js +680 -0
- package/lib/module/components/carousel/index.js.map +1 -0
- package/lib/module/components/chip/index.js +4 -4
- package/lib/module/components/chip/index.js.map +1 -1
- package/lib/module/components/code-block/highlight.js +363 -0
- package/lib/module/components/code-block/highlight.js.map +1 -0
- package/lib/module/components/code-block/index.js +313 -0
- package/lib/module/components/code-block/index.js.map +1 -0
- package/lib/module/components/date-picker/index.js +165 -0
- package/lib/module/components/date-picker/index.js.map +1 -0
- package/lib/module/components/dialog/index.js +7 -2
- package/lib/module/components/dialog/index.js.map +1 -1
- package/lib/module/components/direction/index.js +2 -1
- package/lib/module/components/direction/index.js.map +1 -1
- package/lib/module/components/empty-state/index.js +2 -2
- package/lib/module/components/empty-state/index.js.map +1 -1
- package/lib/module/components/field/index.js +5 -5
- package/lib/module/components/field/index.js.map +1 -1
- package/lib/module/components/flow/index.js +3 -3
- package/lib/module/components/flow/index.js.map +1 -1
- package/lib/module/components/frame/index.js +5 -5
- package/lib/module/components/frame/index.js.map +1 -1
- package/lib/module/components/input-group/index.js +3 -2
- package/lib/module/components/input-group/index.js.map +1 -1
- package/lib/module/components/item/index.js +9 -9
- package/lib/module/components/item/index.js.map +1 -1
- package/lib/module/components/label/index.js +4 -4
- package/lib/module/components/label/index.js.map +1 -1
- package/lib/module/components/line-chart/index.js +167 -44
- package/lib/module/components/line-chart/index.js.map +1 -1
- package/lib/module/components/map/index.js +7 -7
- package/lib/module/components/map/index.js.map +1 -1
- package/lib/module/components/marker/index.js +3 -3
- package/lib/module/components/marker/index.js.map +1 -1
- package/lib/module/components/menu/index.js +714 -0
- package/lib/module/components/menu/index.js.map +1 -0
- package/lib/module/components/message/index.js +7 -7
- package/lib/module/components/message/index.js.map +1 -1
- package/lib/module/components/message-scroller/index.js +5 -4
- package/lib/module/components/message-scroller/index.js.map +1 -1
- package/lib/module/components/plan/index.js +296 -0
- package/lib/module/components/plan/index.js.map +1 -0
- package/lib/module/components/popover/index.js +73 -10
- package/lib/module/components/popover/index.js.map +1 -1
- package/lib/module/components/radio-group/index.js +15 -10
- package/lib/module/components/radio-group/index.js.map +1 -1
- package/lib/module/components/reasoning/index.js +244 -0
- package/lib/module/components/reasoning/index.js.map +1 -0
- package/lib/module/components/section-rail/index.js +4 -4
- package/lib/module/components/section-rail/index.js.map +1 -1
- package/lib/module/components/select/index.js +10 -4
- package/lib/module/components/select/index.js.map +1 -1
- package/lib/module/components/sources/index.js +221 -0
- package/lib/module/components/sources/index.js.map +1 -0
- package/lib/module/components/steps/index.js +4 -4
- package/lib/module/components/steps/index.js.map +1 -1
- package/lib/module/components/tabs/index.js +7 -7
- package/lib/module/components/tabs/index.js.map +1 -1
- package/lib/module/components/task/index.js +300 -0
- package/lib/module/components/task/index.js.map +1 -0
- package/lib/module/components/textarea/index.js +295 -0
- package/lib/module/components/textarea/index.js.map +1 -0
- package/lib/module/components/timeline/index.js +4 -4
- package/lib/module/components/timeline/index.js.map +1 -1
- package/lib/module/components/toast/index.js +2 -2
- package/lib/module/components/toast/index.js.map +1 -1
- package/lib/module/components/toggle-button/index.js +5 -5
- package/lib/module/components/toggle-button/index.js.map +1 -1
- package/lib/module/components/tooltip/index.js +648 -0
- package/lib/module/components/tooltip/index.js.map +1 -0
- package/lib/module/components/typography/index.js +2 -2
- package/lib/module/components/typography/index.js.map +1 -1
- package/lib/module/hooks/index.js +1 -0
- package/lib/module/hooks/index.js.map +1 -1
- package/lib/module/hooks/use-back-handler.js +37 -0
- package/lib/module/hooks/use-back-handler.js.map +1 -0
- package/lib/module/icons/index.js +202 -0
- package/lib/module/icons/index.js.map +1 -1
- package/lib/module/index.js +13 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/primitives/collapse.js +112 -0
- package/lib/module/primitives/collapse.js.map +1 -0
- package/lib/module/primitives/keyboard-avoider.js +2 -1
- package/lib/module/primitives/keyboard-avoider.js.map +1 -1
- package/lib/module/primitives/text.js +25 -1
- package/lib/module/primitives/text.js.map +1 -1
- package/lib/module/utils/date.js +386 -0
- package/lib/module/utils/date.js.map +1 -0
- package/lib/typescript/src/components/accordion/index.d.ts.map +1 -1
- package/lib/typescript/src/components/alert/index.d.ts.map +1 -1
- package/lib/typescript/src/components/area-chart/index.d.ts +41 -1
- package/lib/typescript/src/components/area-chart/index.d.ts.map +1 -1
- package/lib/typescript/src/components/attachment/index.d.ts.map +1 -1
- package/lib/typescript/src/components/bar-chart/index.d.ts +44 -2
- package/lib/typescript/src/components/bar-chart/index.d.ts.map +1 -1
- package/lib/typescript/src/components/bottom-sheet/index.d.ts.map +1 -1
- package/lib/typescript/src/components/breadcrumb/index.d.ts.map +1 -1
- package/lib/typescript/src/components/button/index.d.ts.map +1 -1
- package/lib/typescript/src/components/calendar/index.d.ts +173 -0
- package/lib/typescript/src/components/calendar/index.d.ts.map +1 -0
- package/lib/typescript/src/components/carousel/index.d.ts +179 -0
- package/lib/typescript/src/components/carousel/index.d.ts.map +1 -0
- package/lib/typescript/src/components/chip/index.d.ts.map +1 -1
- package/lib/typescript/src/components/code-block/highlight.d.ts +39 -0
- package/lib/typescript/src/components/code-block/highlight.d.ts.map +1 -0
- package/lib/typescript/src/components/code-block/index.d.ts +113 -0
- package/lib/typescript/src/components/code-block/index.d.ts.map +1 -0
- package/lib/typescript/src/components/date-picker/index.d.ts +97 -0
- package/lib/typescript/src/components/date-picker/index.d.ts.map +1 -0
- package/lib/typescript/src/components/dialog/index.d.ts.map +1 -1
- package/lib/typescript/src/components/direction/index.d.ts.map +1 -1
- package/lib/typescript/src/components/empty-state/index.d.ts.map +1 -1
- package/lib/typescript/src/components/field/index.d.ts.map +1 -1
- package/lib/typescript/src/components/frame/index.d.ts.map +1 -1
- package/lib/typescript/src/components/input-group/index.d.ts.map +1 -1
- package/lib/typescript/src/components/item/index.d.ts.map +1 -1
- package/lib/typescript/src/components/label/index.d.ts.map +1 -1
- package/lib/typescript/src/components/line-chart/index.d.ts +41 -2
- package/lib/typescript/src/components/line-chart/index.d.ts.map +1 -1
- package/lib/typescript/src/components/map/index.d.ts.map +1 -1
- package/lib/typescript/src/components/marker/index.d.ts.map +1 -1
- package/lib/typescript/src/components/menu/index.d.ts +261 -0
- package/lib/typescript/src/components/menu/index.d.ts.map +1 -0
- package/lib/typescript/src/components/message/index.d.ts.map +1 -1
- package/lib/typescript/src/components/message-scroller/index.d.ts.map +1 -1
- package/lib/typescript/src/components/plan/index.d.ts +127 -0
- package/lib/typescript/src/components/plan/index.d.ts.map +1 -0
- package/lib/typescript/src/components/popover/index.d.ts +35 -1
- package/lib/typescript/src/components/popover/index.d.ts.map +1 -1
- package/lib/typescript/src/components/radio-group/index.d.ts.map +1 -1
- package/lib/typescript/src/components/reasoning/index.d.ts +97 -0
- package/lib/typescript/src/components/reasoning/index.d.ts.map +1 -0
- package/lib/typescript/src/components/select/index.d.ts.map +1 -1
- package/lib/typescript/src/components/sources/index.d.ts +85 -0
- package/lib/typescript/src/components/sources/index.d.ts.map +1 -0
- package/lib/typescript/src/components/steps/index.d.ts.map +1 -1
- package/lib/typescript/src/components/tabs/index.d.ts.map +1 -1
- package/lib/typescript/src/components/task/index.d.ts +103 -0
- package/lib/typescript/src/components/task/index.d.ts.map +1 -0
- package/lib/typescript/src/components/textarea/index.d.ts +175 -0
- package/lib/typescript/src/components/textarea/index.d.ts.map +1 -0
- package/lib/typescript/src/components/timeline/index.d.ts.map +1 -1
- package/lib/typescript/src/components/toast/index.d.ts.map +1 -1
- package/lib/typescript/src/components/toggle-button/index.d.ts.map +1 -1
- package/lib/typescript/src/components/tooltip/index.d.ts +180 -0
- package/lib/typescript/src/components/tooltip/index.d.ts.map +1 -0
- package/lib/typescript/src/components/typography/index.d.ts.map +1 -1
- package/lib/typescript/src/hooks/index.d.ts +1 -0
- package/lib/typescript/src/hooks/index.d.ts.map +1 -1
- package/lib/typescript/src/hooks/use-back-handler.d.ts +19 -0
- package/lib/typescript/src/hooks/use-back-handler.d.ts.map +1 -0
- package/lib/typescript/src/icons/index.d.ts +17 -0
- package/lib/typescript/src/icons/index.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +16 -4
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/primitives/collapse.d.ts +42 -0
- package/lib/typescript/src/primitives/collapse.d.ts.map +1 -0
- package/lib/typescript/src/primitives/keyboard-avoider.d.ts.map +1 -1
- package/lib/typescript/src/primitives/text.d.ts +20 -0
- package/lib/typescript/src/primitives/text.d.ts.map +1 -1
- package/lib/typescript/src/utils/date.d.ts +116 -0
- package/lib/typescript/src/utils/date.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/components/accordion/index.tsx +8 -12
- package/src/components/alert/index.tsx +2 -2
- package/src/components/area-chart/index.tsx +208 -55
- package/src/components/attachment/index.tsx +2 -2
- package/src/components/avatar/index.tsx +3 -3
- package/src/components/badge/index.tsx +6 -6
- package/src/components/bar-chart/index.tsx +214 -54
- package/src/components/bottom-sheet/index.tsx +17 -16
- package/src/components/breadcrumb/index.tsx +6 -8
- package/src/components/button/index.tsx +12 -8
- package/src/components/calendar/index.tsx +970 -0
- package/src/components/carousel/index.tsx +788 -0
- package/src/components/chip/index.tsx +4 -6
- package/src/components/code-block/highlight.ts +278 -0
- package/src/components/code-block/index.tsx +341 -0
- package/src/components/date-picker/index.tsx +255 -0
- package/src/components/dialog/index.tsx +7 -2
- package/src/components/direction/index.tsx +2 -1
- package/src/components/empty-state/index.tsx +2 -2
- package/src/components/field/index.tsx +3 -5
- package/src/components/flow/index.tsx +3 -3
- package/src/components/frame/index.tsx +5 -7
- package/src/components/input-group/index.tsx +3 -2
- package/src/components/item/index.tsx +9 -9
- package/src/components/label/index.tsx +2 -2
- package/src/components/line-chart/index.tsx +189 -50
- package/src/components/map/index.tsx +7 -9
- package/src/components/marker/index.tsx +3 -3
- package/src/components/menu/index.tsx +812 -0
- package/src/components/message/index.tsx +7 -7
- package/src/components/message-scroller/index.tsx +5 -4
- package/src/components/plan/index.tsx +325 -0
- package/src/components/popover/index.tsx +111 -8
- package/src/components/radio-group/index.tsx +13 -4
- package/src/components/reasoning/index.tsx +297 -0
- package/src/components/section-rail/index.tsx +4 -4
- package/src/components/select/index.tsx +10 -4
- package/src/components/sources/index.tsx +278 -0
- package/src/components/steps/index.tsx +4 -4
- package/src/components/tabs/index.tsx +7 -9
- package/src/components/task/index.tsx +329 -0
- package/src/components/textarea/index.tsx +381 -0
- package/src/components/timeline/index.tsx +4 -4
- package/src/components/toast/index.tsx +2 -2
- package/src/components/toggle-button/index.tsx +5 -7
- package/src/components/tooltip/index.tsx +793 -0
- package/src/components/typography/index.tsx +2 -2
- package/src/hooks/index.ts +1 -0
- package/src/hooks/use-back-handler.ts +37 -0
- package/src/icons/index.tsx +147 -0
- package/src/index.ts +116 -0
- package/src/primitives/collapse.tsx +128 -0
- package/src/primitives/keyboard-avoider.tsx +2 -1
- package/src/primitives/text.tsx +28 -1
- package/src/utils/date.ts +446 -0
- package/theme.css +112 -0
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DatePicker — a calendar behind a button.
|
|
3
|
+
*
|
|
4
|
+
* ```tsx
|
|
5
|
+
* const [day, setDay] = useState<Date>();
|
|
6
|
+
*
|
|
7
|
+
* <DatePicker selected={day} onSelect={setDay} placeholder="Pick a date" />
|
|
8
|
+
* ```
|
|
9
|
+
*
|
|
10
|
+
* It is the `Calendar` in a `Popover` with a trigger that reads back what was
|
|
11
|
+
* chosen, and it is a separate component from the calendar for the same reason
|
|
12
|
+
* `Select` is separate from a list: the hard parts are the ones around the
|
|
13
|
+
* grid — what a closed field says, when the panel closes, and what a range
|
|
14
|
+
* shows while only half of it has been picked.
|
|
15
|
+
*
|
|
16
|
+
* ## It closes when the selection is finished, not when it changes
|
|
17
|
+
*
|
|
18
|
+
* A single date is done in one tap, so the panel closes on it. A range needs
|
|
19
|
+
* two, so it stays open until the second — closing on the first would put
|
|
20
|
+
* someone back where they started with half a range on screen. Multiple never
|
|
21
|
+
* closes on its own; only the caller knows when a set is complete.
|
|
22
|
+
*
|
|
23
|
+
* ## An anchored panel, not a sheet
|
|
24
|
+
*
|
|
25
|
+
* A month grid is a fixed size that fits beside its trigger on any phone, and
|
|
26
|
+
* a sheet is the right container for a list of unknown length rather than for
|
|
27
|
+
* a shape that is always the same. Pass `presentation="bottom-sheet"` where the
|
|
28
|
+
* screen is busy — a form with the keyboard up is the usual case.
|
|
29
|
+
*/
|
|
30
|
+
import { useCallback, useMemo, useState, type ReactElement, type ReactNode } from 'react';
|
|
31
|
+
import { View } from 'react-native';
|
|
32
|
+
import { CalendarIcon } from '../../icons';
|
|
33
|
+
import { Text } from '../../primitives/text';
|
|
34
|
+
import { cn } from '../../utils/cn';
|
|
35
|
+
import { calendarShortDate, resolveCalendar, type CalendarSystem } from '../../utils/date';
|
|
36
|
+
import { Button } from '../button';
|
|
37
|
+
import {
|
|
38
|
+
Calendar,
|
|
39
|
+
type CalendarCaptionLayout,
|
|
40
|
+
type CalendarDisabled,
|
|
41
|
+
type CalendarMode,
|
|
42
|
+
type CalendarSelection,
|
|
43
|
+
type DateRange,
|
|
44
|
+
} from '../calendar';
|
|
45
|
+
import { Popover, type PopoverPresentation } from '../popover';
|
|
46
|
+
|
|
47
|
+
export type DatePickerMode = CalendarMode;
|
|
48
|
+
|
|
49
|
+
/** What a closed picker shows when nothing has been chosen yet. */
|
|
50
|
+
const DEFAULT_PLACEHOLDER = 'Pick a date';
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* The chosen value as one line of text.
|
|
54
|
+
*
|
|
55
|
+
* A half-picked range reads as its start followed by a dash rather than as
|
|
56
|
+
* just the start: the dash is what says the picker is waiting for the other
|
|
57
|
+
* end, and without it a half range looks like a finished single date.
|
|
58
|
+
*/
|
|
59
|
+
function describe<Mode extends DatePickerMode>(
|
|
60
|
+
mode: Mode,
|
|
61
|
+
value: CalendarSelection[Mode] | undefined,
|
|
62
|
+
locale: string | undefined,
|
|
63
|
+
system: 'gregory' | 'islamic'
|
|
64
|
+
): string | null {
|
|
65
|
+
if (!value) return null;
|
|
66
|
+
const write = (date: Date) => calendarShortDate(date, system, locale);
|
|
67
|
+
|
|
68
|
+
if (mode === 'range') {
|
|
69
|
+
const range = value as DateRange;
|
|
70
|
+
if (!range.from) return null;
|
|
71
|
+
return range.to ? `${write(range.from)} – ${write(range.to)}` : `${write(range.from)} –`;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (mode === 'multiple') {
|
|
75
|
+
const days = value as Date[];
|
|
76
|
+
if (!days.length) return null;
|
|
77
|
+
if (days.length === 1) return write(days[0]!);
|
|
78
|
+
return `${days.length} dates`;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return write(value as Date);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export interface DatePickerProps<Mode extends DatePickerMode = 'single'> {
|
|
85
|
+
/** One day, several, or a span with two ends. */
|
|
86
|
+
mode?: Mode;
|
|
87
|
+
/** Controlled selection. Its shape follows `mode`. */
|
|
88
|
+
selected?: CalendarSelection[Mode];
|
|
89
|
+
/** Starting selection when uncontrolled. */
|
|
90
|
+
defaultSelected?: CalendarSelection[Mode];
|
|
91
|
+
onSelect?: (selected: CalendarSelection[Mode]) => void;
|
|
92
|
+
/** Controlled open state of the panel. */
|
|
93
|
+
open?: boolean;
|
|
94
|
+
onOpenChange?: (open: boolean) => void;
|
|
95
|
+
/** What the trigger reads when nothing has been chosen. */
|
|
96
|
+
placeholder?: string;
|
|
97
|
+
/** Override how the chosen value is written on the trigger. */
|
|
98
|
+
format?: (selected: CalendarSelection[Mode]) => string;
|
|
99
|
+
/** Anchored panel, or a sheet from the bottom of the screen. */
|
|
100
|
+
presentation?: PopoverPresentation;
|
|
101
|
+
/** Stop the trigger opening it. */
|
|
102
|
+
disabled?: boolean;
|
|
103
|
+
/** Days that cannot be picked: a list, a span, or a rule. */
|
|
104
|
+
disabledDates?: CalendarDisabled;
|
|
105
|
+
/** Earliest selectable day. */
|
|
106
|
+
minDate?: Date;
|
|
107
|
+
/** Latest selectable day. */
|
|
108
|
+
maxDate?: Date;
|
|
109
|
+
/** Earliest month the `dropdown` caption offers. Defaults to `minDate`. */
|
|
110
|
+
startMonth?: Date;
|
|
111
|
+
/** Latest month the `dropdown` caption offers. Defaults to `maxDate`. */
|
|
112
|
+
endMonth?: Date;
|
|
113
|
+
/** Months side by side inside the panel. */
|
|
114
|
+
numberOfMonths?: number;
|
|
115
|
+
/** `dropdown` swaps the month caption for month and year pickers. */
|
|
116
|
+
captionLayout?: CalendarCaptionLayout;
|
|
117
|
+
/** `0` is Sunday. */
|
|
118
|
+
weekStartsOn?: number;
|
|
119
|
+
/** Let a tap on a neighbouring month's day select it. Off by default. */
|
|
120
|
+
selectOutsideDays?: boolean;
|
|
121
|
+
/** BCP 47 tag for the month and weekday names, and for the trigger's text. */
|
|
122
|
+
locale?: string;
|
|
123
|
+
/**
|
|
124
|
+
* Which calendar the months and day numbers are counted in. Forwarded to the
|
|
125
|
+
* grid, and used for the trigger's own text so the two always agree.
|
|
126
|
+
*/
|
|
127
|
+
calendar?: CalendarSystem;
|
|
128
|
+
className?: string;
|
|
129
|
+
/**
|
|
130
|
+
* A trigger of your own. Given one, it is cloned with an `onPress` that opens
|
|
131
|
+
* the panel — so a field row or an icon button can stand in for the default
|
|
132
|
+
* button without this component knowing what either looks like.
|
|
133
|
+
*/
|
|
134
|
+
children?: ReactElement<{ onPress?: () => void }> | ReactNode;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function DatePickerRoot<Mode extends DatePickerMode = 'single'>({
|
|
138
|
+
mode = 'single' as Mode,
|
|
139
|
+
selected,
|
|
140
|
+
defaultSelected,
|
|
141
|
+
onSelect,
|
|
142
|
+
open: openProp,
|
|
143
|
+
onOpenChange,
|
|
144
|
+
placeholder = DEFAULT_PLACEHOLDER,
|
|
145
|
+
format,
|
|
146
|
+
presentation = 'popover',
|
|
147
|
+
disabled = false,
|
|
148
|
+
disabledDates,
|
|
149
|
+
minDate,
|
|
150
|
+
maxDate,
|
|
151
|
+
startMonth,
|
|
152
|
+
endMonth,
|
|
153
|
+
numberOfMonths = 1,
|
|
154
|
+
captionLayout = 'label',
|
|
155
|
+
weekStartsOn = 0,
|
|
156
|
+
selectOutsideDays = false,
|
|
157
|
+
locale,
|
|
158
|
+
calendar = 'gregory',
|
|
159
|
+
className,
|
|
160
|
+
children,
|
|
161
|
+
}: DatePickerProps<Mode>) {
|
|
162
|
+
// Resolved here as well as in the grid, because the trigger's text has to be
|
|
163
|
+
// written in the same calendar the cells were tapped in.
|
|
164
|
+
const system = useMemo(() => resolveCalendar(calendar, locale), [calendar, locale]);
|
|
165
|
+
const [internalOpen, setInternalOpen] = useState(false);
|
|
166
|
+
const [internalSelected, setInternalSelected] = useState<CalendarSelection[Mode] | undefined>(
|
|
167
|
+
defaultSelected
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
const isOpenControlled = openProp !== undefined;
|
|
171
|
+
const open = isOpenControlled ? openProp : internalOpen;
|
|
172
|
+
|
|
173
|
+
const isControlled = selected !== undefined;
|
|
174
|
+
const value = (isControlled ? selected : internalSelected) as CalendarSelection[Mode];
|
|
175
|
+
|
|
176
|
+
const setOpen = useCallback(
|
|
177
|
+
(next: boolean) => {
|
|
178
|
+
if (!isOpenControlled) setInternalOpen(next);
|
|
179
|
+
onOpenChange?.(next);
|
|
180
|
+
},
|
|
181
|
+
[isOpenControlled, onOpenChange]
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
const handleSelect = useCallback(
|
|
185
|
+
(next: CalendarSelection[Mode]) => {
|
|
186
|
+
if (!isControlled) setInternalSelected(next);
|
|
187
|
+
onSelect?.(next);
|
|
188
|
+
|
|
189
|
+
// Done in one tap, so it closes on one. A range waits for its second end,
|
|
190
|
+
// and a set of dates is only the caller's to call finished.
|
|
191
|
+
if (mode === 'single' && next) setOpen(false);
|
|
192
|
+
if (mode === 'range' && (next as DateRange | undefined)?.to) setOpen(false);
|
|
193
|
+
},
|
|
194
|
+
[isControlled, onSelect, mode, setOpen]
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
const label = useMemo(() => {
|
|
198
|
+
if (format && value) return format(value);
|
|
199
|
+
return describe(mode, value, locale, system);
|
|
200
|
+
}, [format, value, mode, locale, system]);
|
|
201
|
+
|
|
202
|
+
const trigger = children ?? (
|
|
203
|
+
<Button
|
|
204
|
+
variant="outline"
|
|
205
|
+
disabled={disabled}
|
|
206
|
+
className={cn('justify-start gap-2', className)}
|
|
207
|
+
>
|
|
208
|
+
<CalendarIcon size={16} />
|
|
209
|
+
<Text className={label ? undefined : 'text-muted-foreground'}>
|
|
210
|
+
{label ?? placeholder}
|
|
211
|
+
</Text>
|
|
212
|
+
</Button>
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
return (
|
|
216
|
+
<Popover open={open} onOpenChange={setOpen} presentation={presentation}>
|
|
217
|
+
<Popover.Trigger>{trigger as ReactElement<{ onPress?: () => void }>}</Popover.Trigger>
|
|
218
|
+
{/* The padding is on the inner view, not the panel: in sheet mode a
|
|
219
|
+
className on the panel is merged into the sheet's own padding and
|
|
220
|
+
would replace it. `self-center` for the same reason — the panel does
|
|
221
|
+
not have to know which presentation it ended up in. */}
|
|
222
|
+
<Popover.Content width="content-fit">
|
|
223
|
+
<View className="w-[308px] max-w-full self-center p-3">
|
|
224
|
+
{/*
|
|
225
|
+
Unbordered: the panel around it already draws one, and a card
|
|
226
|
+
inside a card is a seam. The calendar frames itself only when it is
|
|
227
|
+
standing on a page.
|
|
228
|
+
*/}
|
|
229
|
+
<Calendar
|
|
230
|
+
bordered={false}
|
|
231
|
+
mode={mode}
|
|
232
|
+
selected={value}
|
|
233
|
+
onSelect={handleSelect}
|
|
234
|
+
disabled={disabledDates}
|
|
235
|
+
minDate={minDate}
|
|
236
|
+
maxDate={maxDate}
|
|
237
|
+
startMonth={startMonth}
|
|
238
|
+
endMonth={endMonth}
|
|
239
|
+
numberOfMonths={numberOfMonths}
|
|
240
|
+
captionLayout={captionLayout}
|
|
241
|
+
weekStartsOn={weekStartsOn}
|
|
242
|
+
selectOutsideDays={selectOutsideDays}
|
|
243
|
+
locale={locale}
|
|
244
|
+
calendar={calendar}
|
|
245
|
+
/>
|
|
246
|
+
</View>
|
|
247
|
+
</Popover.Content>
|
|
248
|
+
</Popover>
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
DatePickerRoot.displayName = 'DatePicker';
|
|
252
|
+
|
|
253
|
+
export const DatePicker = Object.assign(DatePickerRoot, {
|
|
254
|
+
Trigger: Popover.Trigger,
|
|
255
|
+
});
|
|
@@ -14,7 +14,8 @@ import { Pressable, View, type ViewProps } from 'react-native';
|
|
|
14
14
|
import Animated, { FadeIn, FadeOut, ZoomIn } from 'react-native-reanimated';
|
|
15
15
|
import { Portal } from '../../primitives/portal';
|
|
16
16
|
import { Scrim } from '../../primitives/scrim';
|
|
17
|
-
import { Text, type TextProps } from '../../primitives/text';
|
|
17
|
+
import { Text, type TextProps, textChildren } from '../../primitives/text';
|
|
18
|
+
import { useBackHandler } from '../../hooks/use-back-handler';
|
|
18
19
|
import { cn } from '../../utils/cn';
|
|
19
20
|
|
|
20
21
|
interface DialogContextValue {
|
|
@@ -102,6 +103,10 @@ function DialogContent({
|
|
|
102
103
|
const context = useDialog('Dialog.Content');
|
|
103
104
|
const { open, setOpen } = context;
|
|
104
105
|
|
|
106
|
+
// While the dialog is up, the Android back button closes it rather than
|
|
107
|
+
// popping the screen behind — but only when tapping outside would too.
|
|
108
|
+
useBackHandler(open && dismissible, () => setOpen(false));
|
|
109
|
+
|
|
105
110
|
if (!open) return null;
|
|
106
111
|
|
|
107
112
|
return (
|
|
@@ -130,7 +135,7 @@ function DialogContent({
|
|
|
130
135
|
)}
|
|
131
136
|
{...props}
|
|
132
137
|
>
|
|
133
|
-
{children}
|
|
138
|
+
{textChildren(children)}
|
|
134
139
|
</Animated.View>
|
|
135
140
|
</Animated.View>
|
|
136
141
|
</DialogContext.Provider>
|
|
@@ -42,6 +42,7 @@ import {
|
|
|
42
42
|
useDirectionSign,
|
|
43
43
|
type DirectionValue,
|
|
44
44
|
} from '../../hooks/use-direction';
|
|
45
|
+
import { textChildren } from '../../primitives/text';
|
|
45
46
|
|
|
46
47
|
export { useDirection, useDirectionSign };
|
|
47
48
|
export type { DirectionValue };
|
|
@@ -79,7 +80,7 @@ export function Direction({ className, children, dir, style, ...props }: Directi
|
|
|
79
80
|
return (
|
|
80
81
|
<DirectionContext.Provider value={value}>
|
|
81
82
|
<View className={className} style={[directionStyle, style]} {...props}>
|
|
82
|
-
{children}
|
|
83
|
+
{textChildren(children)}
|
|
83
84
|
</View>
|
|
84
85
|
</DirectionContext.Provider>
|
|
85
86
|
);
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
import { createContext, forwardRef, useContext, type ReactNode } from 'react';
|
|
10
10
|
import { View, type Text as RNText, type ViewProps } from 'react-native';
|
|
11
11
|
import { tv, type VariantProps } from 'tailwind-variants';
|
|
12
|
-
import { Text, type TextProps } from '../../primitives/text';
|
|
12
|
+
import { Text, type TextProps, textChildren } from '../../primitives/text';
|
|
13
13
|
|
|
14
14
|
type EmptyStateSize = 'sm' | 'default' | 'lg';
|
|
15
15
|
|
|
@@ -140,7 +140,7 @@ const EmptyStateMedia = forwardRef<View, EmptyStateMediaProps>(
|
|
|
140
140
|
/>
|
|
141
141
|
</>
|
|
142
142
|
) : null}
|
|
143
|
-
<View className={card()}>{children}</View>
|
|
143
|
+
<View className={card()}>{textChildren(children)}</View>
|
|
144
144
|
</View>
|
|
145
145
|
);
|
|
146
146
|
}
|
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
} from 'react';
|
|
32
32
|
import { View, type Text as RNText, type ViewProps } from 'react-native';
|
|
33
33
|
import { tv } from 'tailwind-variants';
|
|
34
|
-
import { Text, type TextProps } from '../../primitives/text';
|
|
34
|
+
import { Text, type TextProps, textChildren } from '../../primitives/text';
|
|
35
35
|
import { Label, type LabelProps } from '../label';
|
|
36
36
|
import { Separator } from '../separator';
|
|
37
37
|
|
|
@@ -121,7 +121,7 @@ const FieldRoot = forwardRef<View, FieldProps>(
|
|
|
121
121
|
className={root({ className })}
|
|
122
122
|
{...props}
|
|
123
123
|
>
|
|
124
|
-
{children}
|
|
124
|
+
{textChildren(children)}
|
|
125
125
|
</View>
|
|
126
126
|
</FieldContext.Provider>
|
|
127
127
|
);
|
|
@@ -227,10 +227,8 @@ const FieldError = forwardRef<View, FieldErrorProps>(
|
|
|
227
227
|
</View>
|
|
228
228
|
))
|
|
229
229
|
)
|
|
230
|
-
) : typeof children === 'string' ? (
|
|
231
|
-
<Text className={errorText()}>{children}</Text>
|
|
232
230
|
) : (
|
|
233
|
-
children
|
|
231
|
+
textChildren(children, (text) => <Text className={errorText()}>{text}</Text>)
|
|
234
232
|
)}
|
|
235
233
|
</View>
|
|
236
234
|
);
|
|
@@ -84,7 +84,7 @@ import Svg, {
|
|
|
84
84
|
import { tv } from 'tailwind-variants';
|
|
85
85
|
import { LockIcon, MaximizeIcon, MinusIcon, PlusIcon, UnlockIcon } from '../../icons';
|
|
86
86
|
import { AnimatedPressable } from '../../primitives/animated-pressable';
|
|
87
|
-
import { Text } from '../../primitives/text';
|
|
87
|
+
import { Text, textChildren } from '../../primitives/text';
|
|
88
88
|
import { cn } from '../../utils/cn';
|
|
89
89
|
import {
|
|
90
90
|
anchorOf,
|
|
@@ -1160,7 +1160,7 @@ function FlowNode({
|
|
|
1160
1160
|
accessibilityState={{ selected }}
|
|
1161
1161
|
{...props}
|
|
1162
1162
|
>
|
|
1163
|
-
{children}
|
|
1163
|
+
{textChildren(children)}
|
|
1164
1164
|
</Animated.View>
|
|
1165
1165
|
</GestureDetector>
|
|
1166
1166
|
</FlowNodeContext.Provider>
|
|
@@ -1772,7 +1772,7 @@ function FlowGroup({
|
|
|
1772
1772
|
inside an absolutely-positioned box would be positioned against that
|
|
1773
1773
|
box, and every graph coordinate would mean something different
|
|
1774
1774
|
depending on which group it happened to be in. */}
|
|
1775
|
-
{children}
|
|
1775
|
+
{textChildren(children)}
|
|
1776
1776
|
</FlowGroupContext.Provider>
|
|
1777
1777
|
);
|
|
1778
1778
|
}
|
|
@@ -80,7 +80,7 @@ import {
|
|
|
80
80
|
} from 'react-native';
|
|
81
81
|
import { tv } from 'tailwind-variants';
|
|
82
82
|
import { ChevronRightIcon } from '../../icons';
|
|
83
|
-
import { Text, type TextProps } from '../../primitives/text';
|
|
83
|
+
import { Text, type TextProps, textChildren } from '../../primitives/text';
|
|
84
84
|
import { cn } from '../../utils/cn';
|
|
85
85
|
|
|
86
86
|
const frameVariants = tv({
|
|
@@ -208,13 +208,11 @@ const FrameAction = forwardRef<View, FrameActionProps>(
|
|
|
208
208
|
className={cn('shrink-0 flex-row items-center gap-2', className)}
|
|
209
209
|
{...props}
|
|
210
210
|
>
|
|
211
|
-
{
|
|
211
|
+
{textChildren(children, (text) => (
|
|
212
212
|
<Text size="sm" muted>
|
|
213
|
-
{
|
|
213
|
+
{text}
|
|
214
214
|
</Text>
|
|
215
|
-
)
|
|
216
|
-
children
|
|
217
|
-
)}
|
|
215
|
+
))}
|
|
218
216
|
</View>
|
|
219
217
|
)
|
|
220
218
|
);
|
|
@@ -393,7 +391,7 @@ const FrameRow = forwardRef<View, FrameRowProps>(
|
|
|
393
391
|
|
|
394
392
|
const body = (
|
|
395
393
|
<>
|
|
396
|
-
{children}
|
|
394
|
+
{textChildren(children)}
|
|
397
395
|
{chevron ? <ChevronRightIcon size={16} /> : null}
|
|
398
396
|
</>
|
|
399
397
|
);
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
} from 'react-native';
|
|
23
23
|
import { tv } from 'tailwind-variants';
|
|
24
24
|
import { Input, type InputProps } from '../input';
|
|
25
|
+
import { textChildren } from '../../primitives/text';
|
|
25
26
|
|
|
26
27
|
const inputGroupVariants = tv({
|
|
27
28
|
slots: {
|
|
@@ -71,7 +72,7 @@ const InputGroupRoot = forwardRef<View, InputGroupProps>(
|
|
|
71
72
|
return (
|
|
72
73
|
<InputGroupContext.Provider value={value}>
|
|
73
74
|
<View ref={ref} className={root({ className })} {...props}>
|
|
74
|
-
{children}
|
|
75
|
+
{textChildren(children)}
|
|
75
76
|
</View>
|
|
76
77
|
</InputGroupContext.Provider>
|
|
77
78
|
);
|
|
@@ -116,7 +117,7 @@ function createDecorator(side: 'prefix' | 'suffix') {
|
|
|
116
117
|
className={slots[side]({ className })}
|
|
117
118
|
{...props}
|
|
118
119
|
>
|
|
119
|
-
{children}
|
|
120
|
+
{textChildren(children)}
|
|
120
121
|
</View>
|
|
121
122
|
);
|
|
122
123
|
}
|
|
@@ -28,7 +28,7 @@ import { createContext, forwardRef, useContext, type ReactNode } from 'react';
|
|
|
28
28
|
import { View, type ViewProps } from 'react-native';
|
|
29
29
|
import { tv, type VariantProps } from 'tailwind-variants';
|
|
30
30
|
import { AnimatedPressable, type AnimatedPressableProps } from '../../primitives/animated-pressable';
|
|
31
|
-
import { Text, type TextProps } from '../../primitives/text';
|
|
31
|
+
import { Text, type TextProps, textChildren } from '../../primitives/text';
|
|
32
32
|
import { cn } from '../../utils/cn';
|
|
33
33
|
|
|
34
34
|
type ItemSize = 'default' | 'sm' | 'xs';
|
|
@@ -152,7 +152,7 @@ const ItemRoot = forwardRef<View, ItemProps>(
|
|
|
152
152
|
className={root({ className })}
|
|
153
153
|
{...(props as ViewProps)}
|
|
154
154
|
>
|
|
155
|
-
{children}
|
|
155
|
+
{textChildren(children)}
|
|
156
156
|
</View>
|
|
157
157
|
) : (
|
|
158
158
|
<AnimatedPressable
|
|
@@ -164,7 +164,7 @@ const ItemRoot = forwardRef<View, ItemProps>(
|
|
|
164
164
|
className={root({ className })}
|
|
165
165
|
{...props}
|
|
166
166
|
>
|
|
167
|
-
{children}
|
|
167
|
+
{textChildren(children)}
|
|
168
168
|
</AnimatedPressable>
|
|
169
169
|
);
|
|
170
170
|
|
|
@@ -200,7 +200,7 @@ const ItemGroup = forwardRef<View, ItemGroupProps>(
|
|
|
200
200
|
)}
|
|
201
201
|
{...props}
|
|
202
202
|
>
|
|
203
|
-
{children}
|
|
203
|
+
{textChildren(children)}
|
|
204
204
|
</View>
|
|
205
205
|
)
|
|
206
206
|
);
|
|
@@ -246,7 +246,7 @@ const ItemMedia = forwardRef<View, ItemMediaProps>(
|
|
|
246
246
|
className={mediaVariants({ variant, size: size ?? item.size, className })}
|
|
247
247
|
{...props}
|
|
248
248
|
>
|
|
249
|
-
{children}
|
|
249
|
+
{textChildren(children)}
|
|
250
250
|
</View>
|
|
251
251
|
);
|
|
252
252
|
}
|
|
@@ -277,7 +277,7 @@ const ItemContent = forwardRef<View, ItemContentProps>(
|
|
|
277
277
|
)}
|
|
278
278
|
{...props}
|
|
279
279
|
>
|
|
280
|
-
{children}
|
|
280
|
+
{textChildren(children)}
|
|
281
281
|
</View>
|
|
282
282
|
);
|
|
283
283
|
}
|
|
@@ -326,7 +326,7 @@ const ItemActions = forwardRef<View, ItemActionsProps>(
|
|
|
326
326
|
className={cn('shrink-0 flex-row items-center gap-1.5', className)}
|
|
327
327
|
{...props}
|
|
328
328
|
>
|
|
329
|
-
{children}
|
|
329
|
+
{textChildren(children)}
|
|
330
330
|
</View>
|
|
331
331
|
)
|
|
332
332
|
);
|
|
@@ -349,7 +349,7 @@ const ItemHeader = forwardRef<View, ItemHeaderProps>(
|
|
|
349
349
|
className={cn('w-full flex-row items-center justify-between gap-2', className)}
|
|
350
350
|
{...props}
|
|
351
351
|
>
|
|
352
|
-
{children}
|
|
352
|
+
{textChildren(children)}
|
|
353
353
|
</View>
|
|
354
354
|
)
|
|
355
355
|
);
|
|
@@ -368,7 +368,7 @@ const ItemFooter = forwardRef<View, ItemFooterProps>(
|
|
|
368
368
|
className={cn('w-full flex-row items-center gap-2', className)}
|
|
369
369
|
{...props}
|
|
370
370
|
>
|
|
371
|
-
{children}
|
|
371
|
+
{textChildren(children)}
|
|
372
372
|
</View>
|
|
373
373
|
)
|
|
374
374
|
);
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
} from 'react';
|
|
17
17
|
import { View, type Text as RNText, type ViewProps } from 'react-native';
|
|
18
18
|
import { tv } from 'tailwind-variants';
|
|
19
|
-
import { Text, type TextProps } from '../../primitives/text';
|
|
19
|
+
import { Text, type TextProps, textChildren } from '../../primitives/text';
|
|
20
20
|
|
|
21
21
|
const labelVariants = tv({
|
|
22
22
|
slots: {
|
|
@@ -86,7 +86,7 @@ const LabelRoot = forwardRef<View, LabelProps>(
|
|
|
86
86
|
{...props}
|
|
87
87
|
>
|
|
88
88
|
{/* Bare strings are the common case — wrap them so callers don't have to. */}
|
|
89
|
-
{
|
|
89
|
+
{textChildren(children, (text) => <LabelText>{text}</LabelText>)}
|
|
90
90
|
</View>
|
|
91
91
|
</LabelContext.Provider>
|
|
92
92
|
);
|