@thewhileloop/whileui 0.2.6 → 0.2.8

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 (59) hide show
  1. package/README.md +122 -33
  2. package/dist/blocks/datepicker/date-range-picker-modal.d.ts +39 -0
  3. package/dist/blocks/datepicker/date-range-picker-modal.d.ts.map +1 -0
  4. package/dist/blocks/datepicker/date-range-picker-modal.js +115 -0
  5. package/dist/blocks/datepicker/date-range-picker-modal.js.map +1 -0
  6. package/dist/blocks/datepicker/datepicker-inline.d.ts +16 -0
  7. package/dist/blocks/datepicker/datepicker-inline.d.ts.map +1 -0
  8. package/dist/blocks/datepicker/datepicker-inline.js +27 -0
  9. package/dist/blocks/datepicker/datepicker-inline.js.map +1 -0
  10. package/dist/blocks/datepicker/datepicker-modal.d.ts +35 -0
  11. package/dist/blocks/datepicker/datepicker-modal.d.ts.map +1 -0
  12. package/dist/blocks/datepicker/datepicker-modal.js +53 -0
  13. package/dist/blocks/datepicker/datepicker-modal.js.map +1 -0
  14. package/dist/blocks/datepicker/index.d.ts +5 -0
  15. package/dist/blocks/datepicker/index.d.ts.map +1 -0
  16. package/dist/blocks/datepicker/index.js +5 -0
  17. package/dist/blocks/datepicker/index.js.map +1 -0
  18. package/dist/blocks/datepicker/use-calendar-theme.d.ts +25 -0
  19. package/dist/blocks/datepicker/use-calendar-theme.d.ts.map +1 -0
  20. package/dist/blocks/datepicker/use-calendar-theme.js +35 -0
  21. package/dist/blocks/datepicker/use-calendar-theme.js.map +1 -0
  22. package/dist/blocks/layout/action-bar.js +1 -1
  23. package/dist/blocks/layout/action-bar.js.map +1 -1
  24. package/dist/blocks/layout/empty-state.d.ts.map +1 -1
  25. package/dist/blocks/layout/empty-state.js +4 -1
  26. package/dist/blocks/layout/empty-state.js.map +1 -1
  27. package/dist/blocks/layout/smart-input.d.ts +6 -0
  28. package/dist/blocks/layout/smart-input.d.ts.map +1 -1
  29. package/dist/blocks/layout/smart-input.js +4 -2
  30. package/dist/blocks/layout/smart-input.js.map +1 -1
  31. package/dist/components/input/input.d.ts +2 -2
  32. package/dist/components/input/input.d.ts.map +1 -1
  33. package/dist/components/input/input.js +4 -2
  34. package/dist/components/input/input.js.map +1 -1
  35. package/dist/components/numeric-input/numeric-input.d.ts.map +1 -1
  36. package/dist/components/numeric-input/numeric-input.js +3 -1
  37. package/dist/components/numeric-input/numeric-input.js.map +1 -1
  38. package/dist/components/select/select.js +1 -1
  39. package/dist/components/select/select.js.map +1 -1
  40. package/dist/components/spinner/spinner.d.ts +1 -1
  41. package/dist/components/spinner/spinner.d.ts.map +1 -1
  42. package/dist/components/spinner/spinner.js +4 -2
  43. package/dist/components/spinner/spinner.js.map +1 -1
  44. package/dist/components/textarea/textarea.d.ts.map +1 -1
  45. package/dist/components/textarea/textarea.js +3 -1
  46. package/dist/components/textarea/textarea.js.map +1 -1
  47. package/dist/index.d.ts +2 -0
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +2 -0
  50. package/dist/index.js.map +1 -1
  51. package/dist/lib/index.d.ts +1 -0
  52. package/dist/lib/index.d.ts.map +1 -1
  53. package/dist/lib/index.js +1 -0
  54. package/dist/lib/index.js.map +1 -1
  55. package/dist/lib/theme-colors.d.ts +26 -0
  56. package/dist/lib/theme-colors.d.ts.map +1 -0
  57. package/dist/lib/theme-colors.js +39 -0
  58. package/dist/lib/theme-colors.js.map +1 -0
  59. package/package.json +2 -1
package/README.md CHANGED
@@ -266,19 +266,19 @@ function MyScreen() {
266
266
 
267
267
  ### Layout
268
268
 
269
- | Block | Description |
270
- | ---------------------- | -------------------------------------------------- |
271
- | **ActionBar** | Sticky bottom action row with safe-area padding |
272
- | **ConfirmActionSheet** | Reusable destructive confirmation sheet |
273
- | **FormModalScreen** | Modal scaffold for forms with loading states |
274
- | **EmptyState** | Empty content placeholder |
275
- | **ErrorState** | Error display with retry |
276
- | **LoadingScreen** | Full-screen loading indicator |
277
- | **SmartInput** | Keyboard-aware compose input with left/right slots |
278
- | **OnboardingScreen** | Onboarding flow screen |
279
- | **SplashScreen** | Branded splash (fade/scale/slide variants) |
280
- | **MinimalSplash** | Minimal monochrome splash |
281
- | **BrandedSplash** | Splash with brand imagery |
269
+ | Block | Description |
270
+ | ---------------------- | ----------------------------------------------------------------------- |
271
+ | **ActionBar** | Sticky bottom action row with safe-area padding |
272
+ | **ConfirmActionSheet** | Reusable destructive confirmation sheet |
273
+ | **FormModalScreen** | Modal scaffold for forms with loading states |
274
+ | **EmptyState** | Empty content placeholder |
275
+ | **ErrorState** | Error display with retry |
276
+ | **LoadingScreen** | Full-screen loading indicator |
277
+ | **SmartInput** | Keyboard-aware compose input: left/center/right slots, bar/card variant |
278
+ | **OnboardingScreen** | Onboarding flow screen |
279
+ | **SplashScreen** | Branded splash (fade/scale/slide variants) |
280
+ | **MinimalSplash** | Minimal monochrome splash |
281
+ | **BrandedSplash** | Splash with brand imagery |
282
282
 
283
283
  ### Chat
284
284
 
@@ -321,6 +321,14 @@ function MyScreen() {
321
321
  | -------------- | ----------------------------------- |
322
322
  | **SmartImage** | Image with aspect ratio and loading |
323
323
 
324
+ ### Date Picker
325
+
326
+ | Block | Description |
327
+ | ------------------------ | ------------------------------------------------- |
328
+ | **DatePickerModal** | Bottom sheet modal with calendar, compact trigger |
329
+ | **DatePickerInline** | Inline calendar for forms or dashboards |
330
+ | **DateRangePickerModal** | Range selection modal with period marking |
331
+
324
332
  ## Layout Primitives (Stack, Row, Box)
325
333
 
326
334
  Use `Stack` for vertical layouts, `Row` for horizontal layouts. Both support `gap`, `align`, and `justify` variants.
@@ -377,6 +385,7 @@ import { AppShell, Header, BottomNav, ScrollView } from '@thewhileloop/whileui';
377
385
  | Flow | Blocks |
378
386
  | ---------- | ---------------------------------------------------------------------------------- |
379
387
  | Auth | SignInForm → SignUpForm → ForgotPasswordForm → VerifyEmailForm → ResetPasswordForm |
388
+ | Forms | FormField + Input/NumericInput/LabeledField + DatePickerModal + FormModalScreen |
380
389
  | Settings | ProfileHeader + SettingsSection + SettingsItem (+ FormModalScreen for edits) |
381
390
  | E-commerce | ProductCard list → CheckoutSummary + ActionBar |
382
391
  | Chat | Chat + ChatSuggestions + SmartInput (attach, send). Extensible for images/tags |
@@ -494,6 +503,29 @@ import { Uniwind } from 'uniwind';
494
503
  Uniwind.setTheme('dark'); // or 'light' or 'system'
495
504
  ```
496
505
 
506
+ ### Theme Colors for RN Primitives
507
+
508
+ Some React Native APIs require hex color strings (icons, ActivityIndicator, react-native-calendars). Use `useThemeColors` or `useIconColors` to read from your `global.css` theme:
509
+
510
+ ```tsx
511
+ import { useThemeColors, useIconColors } from '@thewhileloop/whileui';
512
+ import { Feather } from '@expo/vector-icons';
513
+
514
+ // Full palette (primary, foreground, muted, background, border, accent, destructive, etc.)
515
+ const colors = useThemeColors();
516
+
517
+ // Shorthand for icons: foreground, muted, primary, primaryForeground, accent, destructive
518
+ const iconColors = useIconColors();
519
+
520
+ <Feather name="heart" size={20} color={iconColors.muted} />
521
+ <Spinner color={colors.foreground} /> // Spinner defaults to this when color not passed
522
+ ```
523
+
524
+ - **useThemeColors** — Returns hex values for all semantic tokens. Use for Calendar themes, Spinner, placeholderTextColor overrides.
525
+ - **useIconColors** — Subset for icons. Maps `muted` → `mutedForeground` (readable on backgrounds).
526
+
527
+ Input, Textarea, NumericInput, SmartInput, Spinner, and LoadingScreen default to theme colors when you omit `placeholderTextColor` or `spinnerColor`.
528
+
497
529
  Or use the first-party ThemeBridge helper with optional persistence:
498
530
 
499
531
  ```tsx
@@ -550,12 +582,12 @@ import { Input } from '@thewhileloop/whileui';
550
582
  <Input placeholder="Email" variant="default" value={value} onChangeText={setValue} />;
551
583
  ```
552
584
 
553
- | Prop | Type | Default | Description |
554
- | -------------------- | ---------------------- | ----------- | ----------------------------------------------- |
555
- | variant | `'default' \| 'error'` | `'default'` | Input style variant |
556
- | placeholder | `string` | — | Placeholder text |
557
- | placeholderTextColor | `string` | — | Hex for placeholder (theme-aware when provided) |
558
- | editable | `boolean` | `true` | Whether input is editable |
585
+ | Prop | Type | Default | Description |
586
+ | -------------------- | ---------------------- | ----------- | -------------------------------------------------------- |
587
+ | variant | `'default' \| 'error'` | `'default'` | Input style variant |
588
+ | placeholder | `string` | — | Placeholder text |
589
+ | placeholderTextColor | `string` | — | Hex for placeholder; defaults to theme `mutedForeground` |
590
+ | editable | `boolean` | `true` | Whether input is editable |
559
591
 
560
592
  ## NumericInput
561
593
 
@@ -1092,7 +1124,7 @@ import { ActionBar, Button, ButtonText } from '@thewhileloop/whileui';
1092
1124
 
1093
1125
  ## SmartInput
1094
1126
 
1095
- Keyboard-aware compose input. Copy-paste block uses semantic tokens, theme via `global.css`. Forwards ref to `TextInput`.
1127
+ Keyboard-aware compose input. `variant`: "bar" (sticky bottom) or "card" (floating). Slots: `leftSlot`, `centerSlot` (intent selector), `rightSlot`. `submitBehavior`: "newline" (default) or "submit"/"blurAndSubmit". Forwards ref to `TextInput`.
1096
1128
 
1097
1129
  ```tsx
1098
1130
  import { SmartInput, Button, ButtonText } from '@thewhileloop/whileui';
@@ -1139,19 +1171,76 @@ const [value, setValue] = useState('');
1139
1171
  />;
1140
1172
  ```
1141
1173
 
1142
- | Prop | Type | Description |
1143
- | -------------------------- | ------------------------ | ------------------------------------------------- |
1144
- | `messages` | `ChatMessage[]` | `{ id, role, content, secondary?, contentSize? }` |
1145
- | `value` | `string` | Input value |
1146
- | `onChangeText` | `(text) => void` | Input change |
1147
- | `onSend` | `() => void` | Send handler |
1148
- | `suggestions` | `string[]` | Chips when empty |
1149
- | `leftSlot` / `rightSlot` | `ReactNode` | Attach, send, etc. |
1150
- | `exampleMessage` | `ChatMessage` | Shown in empty state |
1151
- | `renderMessage` | `(msg) => ReactNode` | Custom message (markdown, code, images) |
1152
- | `loadingIndicator` | `ReactNode` | Shown when loading (typing dots) |
1153
- | `inputSafeArea` | `boolean` | SmartInput safe-area (default `true`) |
1154
- | `keyboardVerticalOffset` | `number` | For header offset when keyboard opens |
1174
+ | Prop | Type | Description |
1175
+ | ------------------------ | -------------------- | ------------------------------------------------- |
1176
+ | `messages` | `ChatMessage[]` | `{ id, role, content, secondary?, contentSize? }` |
1177
+ | `value` | `string` | Input value |
1178
+ | `onChangeText` | `(text) => void` | Input change |
1179
+ | `onSend` | `() => void` | Send handler |
1180
+ | `suggestions` | `string[]` | Chips when empty |
1181
+ | `leftSlot` / `rightSlot` | `ReactNode` | Attach, send, etc. |
1182
+ | `exampleMessage` | `ChatMessage` | Shown in empty state |
1183
+ | `renderMessage` | `(msg) => ReactNode` | Custom message (markdown, code, images) |
1184
+ | `loadingIndicator` | `ReactNode` | Shown when loading (typing dots) |
1185
+ | `inputSafeArea` | `boolean` | SmartInput safe-area (default `true`) |
1186
+ | `keyboardVerticalOffset` | `number` | For header offset when keyboard opens |
1187
+
1188
+ ## DatePickerModal / DatePickerInline / DateRangePickerModal
1189
+
1190
+ Date selection blocks using react-native-calendars. Theme-aware via `useCalendarTheme` (Uniwind light/dark). Optional `theme` prop for custom hex colors.
1191
+
1192
+ **DatePickerModal** — Compact trigger opens bottom sheet with calendar. Use `DatePickerTrigger` as the trigger content.
1193
+
1194
+ **DatePickerInline** — Calendar embedded inline for forms or dashboards.
1195
+
1196
+ **DateRangePickerModal** — Range selection with period marking. Use `DateRangePickerTrigger` as the trigger content.
1197
+
1198
+ ```tsx
1199
+ import {
1200
+ DatePickerModal,
1201
+ DatePickerTrigger,
1202
+ DatePickerInline,
1203
+ DateRangePickerModal,
1204
+ DateRangePickerTrigger,
1205
+ type DateRange,
1206
+ } from '@thewhileloop/whileui';
1207
+
1208
+ // Single date (modal)
1209
+ const [date, setDate] = useState<string | null>(null);
1210
+ const [open, setOpen] = useState(false);
1211
+
1212
+ <DatePickerModal
1213
+ value={date}
1214
+ onValueChange={setDate}
1215
+ open={open}
1216
+ onOpenChange={setOpen}
1217
+ trigger={<DatePickerTrigger value={date} placeholder="Pick a date" />}
1218
+ title="Select date"
1219
+ />;
1220
+
1221
+ // Inline calendar
1222
+ <DatePickerInline value={date} onValueChange={setDate} />;
1223
+
1224
+ // Date range (modal)
1225
+ const [range, setRange] = useState<DateRange | null>(null);
1226
+
1227
+ <DateRangePickerModal
1228
+ value={range}
1229
+ onValueChange={setRange}
1230
+ open={rangeOpen}
1231
+ onOpenChange={setRangeOpen}
1232
+ trigger={<DateRangePickerTrigger value={range} placeholder="Pick range" />}
1233
+ />;
1234
+ ```
1235
+
1236
+ | Prop | Type | Description |
1237
+ | ----------------------- | -------------------------------------- | ------------------------------- |
1238
+ | `value` | `string \| null` / `DateRange \| null` | Selected date(s) YYYY-MM-DD |
1239
+ | `onValueChange` | `(date) => void` | Change handler |
1240
+ | `open` / `onOpenChange` | — | Modal state (modal variants) |
1241
+ | `trigger` | `ReactNode` | Custom trigger (modal variants) |
1242
+ | `minDate` / `maxDate` | `string` | YYYY-MM-DD bounds |
1243
+ | `theme` | `CalendarTheme` | Override calendar hex colors |
1155
1244
 
1156
1245
  ## ConfirmActionSheet
1157
1246
 
@@ -0,0 +1,39 @@
1
+ import React from 'react';
2
+ import { type CalendarTheme } from './use-calendar-theme';
3
+ export interface DateRange {
4
+ start: string;
5
+ end: string;
6
+ }
7
+ export interface DateRangePickerModalProps {
8
+ /** Controlled: selected range */
9
+ value?: DateRange | null;
10
+ /** Controlled: change handler */
11
+ onValueChange?: (range: DateRange | null) => void;
12
+ /** Modal open state */
13
+ open: boolean;
14
+ /** Modal open change handler */
15
+ onOpenChange: (open: boolean) => void;
16
+ /** Minimum selectable date YYYY-MM-DD */
17
+ minDate?: string;
18
+ /** Maximum selectable date YYYY-MM-DD */
19
+ maxDate?: string;
20
+ /** Override calendar theme (hex colors) */
21
+ theme?: CalendarTheme;
22
+ /** Trigger element. If not provided, no trigger is rendered. */
23
+ trigger?: React.ReactNode;
24
+ /** Title shown in modal header */
25
+ title?: string;
26
+ /** Button label for confirm */
27
+ confirmLabel?: string;
28
+ className?: string;
29
+ }
30
+ declare function formatRangeDisplay(range: DateRange | null | undefined): string;
31
+ export declare function DateRangePickerModal({ value, onValueChange, open, onOpenChange, minDate, maxDate, theme: customTheme, trigger, title, confirmLabel, className, }: DateRangePickerModalProps): import("react/jsx-runtime").JSX.Element;
32
+ /** Compact trigger showing formatted range. Use as DateRangePickerModal's trigger prop. */
33
+ export declare function DateRangePickerTrigger({ value, placeholder, className, }: {
34
+ value?: DateRange | null;
35
+ placeholder?: string;
36
+ className?: string;
37
+ }): import("react/jsx-runtime").JSX.Element;
38
+ export { formatRangeDisplay };
39
+ //# sourceMappingURL=date-range-picker-modal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date-range-picker-modal.d.ts","sourceRoot":"","sources":["../../../src/blocks/datepicker/date-range-picker-modal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAyC,MAAM,OAAO,CAAC;AAQ9D,OAAO,EAAoB,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAa5E,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,yBAAyB;IACxC,iCAAiC;IACjC,KAAK,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IACzB,iCAAiC;IACjC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,KAAK,IAAI,CAAC;IAClD,uBAAuB;IACvB,IAAI,EAAE,OAAO,CAAC;IACd,gCAAgC;IAChC,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,yCAAyC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yCAAyC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2CAA2C;IAC3C,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,gEAAgE;IAChE,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,kCAAkC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,iBAAS,kBAAkB,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAOvE;AAiCD,wBAAgB,oBAAoB,CAAC,EACnC,KAAK,EACL,aAAa,EACb,IAAI,EACJ,YAAY,EACZ,OAAO,EACP,OAAO,EACP,KAAK,EAAE,WAAW,EAClB,OAAO,EACP,KAA2B,EAC3B,YAAqB,EACrB,SAAS,GACV,EAAE,yBAAyB,2CAmH3B;AAED,2FAA2F;AAC3F,wBAAgB,sBAAsB,CAAC,EACrC,KAAK,EACL,WAAiC,EACjC,SAAS,GACV,EAAE;IACD,KAAK,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,2CAYA;AAED,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
@@ -0,0 +1,115 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useCallback, useMemo, useState } from 'react';
3
+ import { Modal, Pressable, View } from 'react-native';
4
+ import { useSafeAreaInsets } from 'react-native-safe-area-context';
5
+ import { useUniwind } from 'uniwind';
6
+ import { Calendar } from 'react-native-calendars';
7
+ import { Text } from '../../components/text';
8
+ import { Button, ButtonText } from '../../components/button';
9
+ import { cn } from '../../lib/cn';
10
+ import { useCalendarTheme } from './use-calendar-theme';
11
+ function formatRangeDisplay(range) {
12
+ if (!range)
13
+ return 'Select date range';
14
+ const start = new Date(range.start + 'T12:00:00');
15
+ const end = new Date(range.end + 'T12:00:00');
16
+ const fmt = (d) => d.toLocaleDateString(undefined, { month: 'short', day: 'numeric', year: 'numeric' });
17
+ return `${fmt(start)} – ${fmt(end)}`;
18
+ }
19
+ function toLocalDateString(d) {
20
+ const y = d.getFullYear();
21
+ const m = String(d.getMonth() + 1).padStart(2, '0');
22
+ const day = String(d.getDate()).padStart(2, '0');
23
+ return `${y}-${m}-${day}`;
24
+ }
25
+ function buildMarkedDates(start, end, theme) {
26
+ const color = theme.selectedDayBackgroundColor;
27
+ const textColor = theme.selectedDayTextColor;
28
+ const marked = {};
29
+ const [startY, startM, startD] = start.split('-').map(Number);
30
+ const [endY, endM, endD] = end.split('-').map(Number);
31
+ const curr = new Date(startY, startM - 1, startD);
32
+ const e = new Date(endY, endM - 1, endD);
33
+ while (curr.getTime() <= e.getTime()) {
34
+ const key = toLocalDateString(curr);
35
+ marked[key] = {
36
+ startingDay: key === start,
37
+ endingDay: key === end,
38
+ color,
39
+ textColor,
40
+ today: false, // Prefer range style over "today" when end/start date is today
41
+ };
42
+ curr.setDate(curr.getDate() + 1);
43
+ }
44
+ return marked;
45
+ }
46
+ export function DateRangePickerModal({ value, onValueChange, open, onOpenChange, minDate, maxDate, theme: customTheme, trigger, title = 'Select date range', confirmLabel = 'Done', className, }) {
47
+ const insets = useSafeAreaInsets();
48
+ const { theme } = useUniwind();
49
+ const calendarTheme = useCalendarTheme(customTheme);
50
+ const [draftStart, setDraftStart] = useState(value?.start ?? null);
51
+ const [draftEnd, setDraftEnd] = useState(value?.end ?? null);
52
+ const markedDates = useMemo(() => {
53
+ const color = calendarTheme.selectedDayBackgroundColor;
54
+ const textColor = calendarTheme.selectedDayTextColor;
55
+ if (!draftStart || !draftEnd) {
56
+ if (draftStart) {
57
+ return {
58
+ [draftStart]: {
59
+ startingDay: true,
60
+ endingDay: true,
61
+ color,
62
+ textColor,
63
+ today: false,
64
+ },
65
+ };
66
+ }
67
+ return {};
68
+ }
69
+ const [start, end] = draftStart <= draftEnd ? [draftStart, draftEnd] : [draftEnd, draftStart];
70
+ return buildMarkedDates(start, end, calendarTheme);
71
+ }, [draftStart, draftEnd, calendarTheme]);
72
+ const handleDayPress = useCallback((day) => {
73
+ const d = day.dateString;
74
+ if (!draftStart || draftEnd) {
75
+ setDraftStart(d);
76
+ setDraftEnd(null);
77
+ }
78
+ else {
79
+ setDraftEnd(d);
80
+ }
81
+ }, [draftStart, draftEnd]);
82
+ const handleConfirm = useCallback(() => {
83
+ if (draftStart) {
84
+ const start = draftStart;
85
+ const end = draftEnd ?? draftStart;
86
+ onValueChange?.({
87
+ start: start <= end ? start : end,
88
+ end: start <= end ? end : start,
89
+ });
90
+ }
91
+ else {
92
+ onValueChange?.(null);
93
+ }
94
+ onOpenChange(false);
95
+ setDraftStart(null);
96
+ setDraftEnd(null);
97
+ }, [draftStart, draftEnd, onValueChange, onOpenChange]);
98
+ const handleOpen = useCallback(() => {
99
+ setDraftStart(value?.start ?? null);
100
+ setDraftEnd(value?.end ?? null);
101
+ onOpenChange(true);
102
+ }, [value, onOpenChange]);
103
+ const handleBackdropPress = useCallback(() => {
104
+ onOpenChange(false);
105
+ setDraftStart(null);
106
+ setDraftEnd(null);
107
+ }, [onOpenChange]);
108
+ return (_jsxs(_Fragment, { children: [trigger ? (_jsx(Pressable, { onPress: handleOpen, className: cn('min-h-10 w-full flex-row items-center rounded-lg border border-input bg-background px-4', className), children: trigger })) : null, _jsx(Modal, { visible: open, transparent: true, animationType: "slide", children: _jsx(Pressable, { className: "flex-1 justify-end bg-black/40", onPress: handleBackdropPress, children: _jsxs(Pressable, { className: "rounded-t-xl border border-border bg-background", style: { paddingBottom: Math.max(insets.bottom, 16) }, onPress: (e) => e.stopPropagation(), children: [_jsxs(View, { className: "flex-row items-center justify-between border-b border-border px-4 py-3", children: [_jsx(Text, { className: "text-base font-medium text-foreground", children: title }), _jsx(Button, { size: "sm", onPress: handleConfirm, children: _jsx(ButtonText, { children: confirmLabel }) })] }), _jsx(View, { className: "p-4", children: _jsx(Calendar, { current: draftStart ?? value?.start ?? undefined, onDayPress: handleDayPress, markedDates: markedDates, markingType: "period", minDate: minDate, maxDate: maxDate, theme: calendarTheme, enableSwipeMonths: true }, theme) })] }) }) })] }));
109
+ }
110
+ /** Compact trigger showing formatted range. Use as DateRangePickerModal's trigger prop. */
111
+ export function DateRangePickerTrigger({ value, placeholder = 'Select date range', className, }) {
112
+ return (_jsxs(View, { className: cn('flex-1 flex-row items-center min-w-0', className), children: [_jsx(Text, { className: cn('flex-1 text-base', value ? 'text-foreground' : 'text-muted-foreground'), numberOfLines: 1, children: value ? formatRangeDisplay(value) : placeholder }), _jsx(View, { className: "ml-2 shrink-0 h-2 w-2 rotate-45 border-b-2 border-r-2 border-muted-foreground" })] }));
113
+ }
114
+ export { formatRangeDisplay };
115
+ //# sourceMappingURL=date-range-picker-modal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date-range-picker-modal.js","sourceRoot":"","sources":["../../../src/blocks/datepicker/date-range-picker-modal.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { type CalendarTheme } from './use-calendar-theme';
2
+ export interface DatePickerInlineProps {
3
+ /** Controlled: selected date in YYYY-MM-DD */
4
+ value?: string | null;
5
+ /** Controlled: change handler */
6
+ onValueChange?: (date: string | null) => void;
7
+ /** Minimum selectable date YYYY-MM-DD */
8
+ minDate?: string;
9
+ /** Maximum selectable date YYYY-MM-DD */
10
+ maxDate?: string;
11
+ /** Override calendar theme (hex colors) */
12
+ theme?: CalendarTheme;
13
+ className?: string;
14
+ }
15
+ export declare function DatePickerInline({ value, onValueChange, minDate, maxDate, theme: customTheme, className, }: DatePickerInlineProps): import("react/jsx-runtime").JSX.Element;
16
+ //# sourceMappingURL=datepicker-inline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"datepicker-inline.d.ts","sourceRoot":"","sources":["../../../src/blocks/datepicker/datepicker-inline.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAoB,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE5E,MAAM,WAAW,qBAAqB;IACpC,8CAA8C;IAC9C,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,iCAAiC;IACjC,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAC9C,yCAAyC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yCAAyC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2CAA2C;IAC3C,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,KAAK,EACL,aAAa,EACb,OAAO,EACP,OAAO,EACP,KAAK,EAAE,WAAW,EAClB,SAAS,GACV,EAAE,qBAAqB,2CAiCvB"}
@@ -0,0 +1,27 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useMemo } from 'react';
3
+ import { View } from 'react-native';
4
+ import { useUniwind } from 'uniwind';
5
+ import { Calendar } from 'react-native-calendars';
6
+ import { cn } from '../../lib/cn';
7
+ import { useCalendarTheme } from './use-calendar-theme';
8
+ export function DatePickerInline({ value, onValueChange, minDate, maxDate, theme: customTheme, className, }) {
9
+ const { theme } = useUniwind();
10
+ const calendarTheme = useCalendarTheme(customTheme);
11
+ const markedDates = useMemo(() => {
12
+ if (!value)
13
+ return undefined;
14
+ return {
15
+ [value]: {
16
+ selected: true,
17
+ disableTouchEvent: false,
18
+ today: false, // Prefer selected style over "today" when selected date is today
19
+ },
20
+ };
21
+ }, [value]);
22
+ const handleDayPress = (day) => {
23
+ onValueChange?.(day.dateString);
24
+ };
25
+ return (_jsx(View, { className: cn('overflow-hidden rounded-xl border border-border', className), children: _jsx(Calendar, { current: value ?? undefined, onDayPress: handleDayPress, markedDates: markedDates, minDate: minDate, maxDate: maxDate, theme: calendarTheme, enableSwipeMonths: true }, theme) }));
26
+ }
27
+ //# sourceMappingURL=datepicker-inline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"datepicker-inline.js","sourceRoot":"","sources":["../../../src/blocks/datepicker/datepicker-inline.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAiB,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,gBAAgB,EAAsB,MAAM,sBAAsB,CAAC;AAgB5E,MAAM,UAAU,gBAAgB,CAAC,EAC/B,KAAK,EACL,aAAa,EACb,OAAO,EACP,OAAO,EACP,KAAK,EAAE,WAAW,EAClB,SAAS,GACa;IACtB,MAAM,EAAE,KAAK,EAAE,GAAG,UAAU,EAAE,CAAC;IAC/B,MAAM,aAAa,GAAG,gBAAgB,CAAC,WAAW,CAAC,CAAC;IAEpD,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,EAAE;QAC/B,IAAI,CAAC,KAAK;YAAE,OAAO,SAAS,CAAC;QAC7B,OAAO;YACL,CAAC,KAAK,CAAC,EAAE;gBACP,QAAQ,EAAE,IAAI;gBACd,iBAAiB,EAAE,KAAK;gBACxB,KAAK,EAAE,KAAK,EAAE,iEAAiE;aAChF;SACF,CAAC;IACJ,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAEZ,MAAM,cAAc,GAAG,CAAC,GAAa,EAAE,EAAE;QACvC,aAAa,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAClC,CAAC,CAAC;IAEF,OAAO,CACL,KAAC,IAAI,IAAC,SAAS,EAAE,EAAE,CAAC,iDAAiD,EAAE,SAAS,CAAC,YAC/E,KAAC,QAAQ,IAEP,OAAO,EAAE,KAAK,IAAI,SAAS,EAC3B,UAAU,EAAE,cAAc,EAC1B,WAAW,EAAE,WAAW,EACxB,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,aAAwC,EAC/C,iBAAiB,UAPZ,KAAK,CAQV,GACG,CACR,CAAC;AACJ,CAAC"}
@@ -0,0 +1,35 @@
1
+ import React from 'react';
2
+ import { type CalendarTheme } from './use-calendar-theme';
3
+ export interface DatePickerModalProps {
4
+ /** Controlled: selected date in YYYY-MM-DD */
5
+ value?: string | null;
6
+ /** Controlled: change handler */
7
+ onValueChange?: (date: string | null) => void;
8
+ /** Modal open state */
9
+ open: boolean;
10
+ /** Modal open change handler */
11
+ onOpenChange: (open: boolean) => void;
12
+ /** Minimum selectable date YYYY-MM-DD */
13
+ minDate?: string;
14
+ /** Maximum selectable date YYYY-MM-DD */
15
+ maxDate?: string;
16
+ /** Override calendar theme (hex colors) */
17
+ theme?: CalendarTheme;
18
+ /** Trigger element. If not provided, no trigger is rendered. */
19
+ trigger?: React.ReactNode;
20
+ /** Title shown in modal header */
21
+ title?: string;
22
+ /** Button label for confirm */
23
+ confirmLabel?: string;
24
+ className?: string;
25
+ }
26
+ declare function formatDisplayDate(dateString: string | null | undefined): string;
27
+ export declare function DatePickerModal({ value, onValueChange, open, onOpenChange, minDate, maxDate, theme: customTheme, trigger, title, confirmLabel, className, }: DatePickerModalProps): import("react/jsx-runtime").JSX.Element;
28
+ /** Compact trigger showing formatted date. Use as DatePickerModal's trigger prop. */
29
+ export declare function DatePickerTrigger({ value, placeholder, className, }: {
30
+ value?: string | null;
31
+ placeholder?: string;
32
+ className?: string;
33
+ }): import("react/jsx-runtime").JSX.Element;
34
+ export { formatDisplayDate };
35
+ //# sourceMappingURL=datepicker-modal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"datepicker-modal.d.ts","sourceRoot":"","sources":["../../../src/blocks/datepicker/datepicker-modal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAQvC,OAAO,EAAoB,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE5E,MAAM,WAAW,oBAAoB;IACnC,8CAA8C;IAC9C,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,iCAAiC;IACjC,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAC9C,uBAAuB;IACvB,IAAI,EAAE,OAAO,CAAC;IACd,gCAAgC;IAChC,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,yCAAyC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yCAAyC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2CAA2C;IAC3C,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,gEAAgE;IAChE,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,kCAAkC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,iBAAS,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CASxE;AAED,wBAAgB,eAAe,CAAC,EAC9B,KAAK,EACL,aAAa,EACb,IAAI,EACJ,YAAY,EACZ,OAAO,EACP,OAAO,EACP,KAAK,EAAE,WAAW,EAClB,OAAO,EACP,KAAqB,EACrB,YAAqB,EACrB,SAAS,GACV,EAAE,oBAAoB,2CAwEtB;AAED,qFAAqF;AACrF,wBAAgB,iBAAiB,CAAC,EAChC,KAAK,EACL,WAA2B,EAC3B,SAAS,GACV,EAAE;IACD,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,2CAYA;AAED,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
@@ -0,0 +1,53 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useMemo } from 'react';
3
+ import { Modal, Pressable, View } from 'react-native';
4
+ import { useSafeAreaInsets } from 'react-native-safe-area-context';
5
+ import { useUniwind } from 'uniwind';
6
+ import { Calendar } from 'react-native-calendars';
7
+ import { Text } from '../../components/text';
8
+ import { Button, ButtonText } from '../../components/button';
9
+ import { cn } from '../../lib/cn';
10
+ import { useCalendarTheme } from './use-calendar-theme';
11
+ function formatDisplayDate(dateString) {
12
+ if (!dateString)
13
+ return 'Select date';
14
+ const d = new Date(dateString + 'T12:00:00');
15
+ return d.toLocaleDateString(undefined, {
16
+ weekday: 'short',
17
+ month: 'short',
18
+ day: 'numeric',
19
+ year: 'numeric',
20
+ });
21
+ }
22
+ export function DatePickerModal({ value, onValueChange, open, onOpenChange, minDate, maxDate, theme: customTheme, trigger, title = 'Select date', confirmLabel = 'Done', className, }) {
23
+ const insets = useSafeAreaInsets();
24
+ const { theme } = useUniwind();
25
+ const calendarTheme = useCalendarTheme(customTheme);
26
+ const markedDates = useMemo(() => {
27
+ if (!value)
28
+ return undefined;
29
+ return {
30
+ [value]: {
31
+ selected: true,
32
+ disableTouchEvent: false,
33
+ today: false,
34
+ },
35
+ };
36
+ }, [value]);
37
+ const handleDayPress = (day) => {
38
+ onValueChange?.(day.dateString);
39
+ };
40
+ const handleConfirm = () => {
41
+ onOpenChange(false);
42
+ };
43
+ const handleBackdropPress = () => {
44
+ onOpenChange(false);
45
+ };
46
+ return (_jsxs(_Fragment, { children: [trigger ? (_jsx(Pressable, { onPress: () => onOpenChange(true), className: cn('min-h-10 w-full flex-row items-center rounded-lg border border-input bg-background px-4', className), children: trigger })) : null, _jsx(Modal, { visible: open, transparent: true, animationType: "slide", children: _jsx(Pressable, { className: "flex-1 justify-end bg-black/40", onPress: handleBackdropPress, children: _jsxs(Pressable, { className: "rounded-t-xl border border-border bg-background", style: { paddingBottom: Math.max(insets.bottom, 16) }, onPress: (e) => e.stopPropagation(), children: [_jsxs(View, { className: "flex-row items-center justify-between border-b border-border px-4 py-3", children: [_jsx(Text, { className: "text-base font-medium text-foreground", children: title }), _jsx(Button, { size: "sm", onPress: handleConfirm, children: _jsx(ButtonText, { children: confirmLabel }) })] }), _jsx(View, { className: "p-4", children: _jsx(Calendar, { current: value ?? undefined, onDayPress: handleDayPress, markedDates: markedDates, minDate: minDate, maxDate: maxDate, theme: calendarTheme, enableSwipeMonths: true }, theme) })] }) }) })] }));
47
+ }
48
+ /** Compact trigger showing formatted date. Use as DatePickerModal's trigger prop. */
49
+ export function DatePickerTrigger({ value, placeholder = 'Select date', className, }) {
50
+ return (_jsxs(View, { className: cn('flex-1 flex-row items-center min-w-0', className), children: [_jsx(Text, { className: cn('flex-1 text-base', value ? 'text-foreground' : 'text-muted-foreground'), numberOfLines: 1, children: value ? formatDisplayDate(value) : placeholder }), _jsx(View, { className: "ml-2 shrink-0 h-2 w-2 rotate-45 border-b-2 border-r-2 border-muted-foreground" })] }));
51
+ }
52
+ export { formatDisplayDate };
53
+ //# sourceMappingURL=datepicker-modal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"datepicker-modal.js","sourceRoot":"","sources":["../../../src/blocks/datepicker/datepicker-modal.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export { DatePickerModal, DatePickerTrigger, formatDisplayDate, type DatePickerModalProps, } from './datepicker-modal';
2
+ export { DatePickerInline, type DatePickerInlineProps } from './datepicker-inline';
3
+ export { DateRangePickerModal, DateRangePickerTrigger, formatRangeDisplay, type DateRangePickerModalProps, type DateRange, } from './date-range-picker-modal';
4
+ export { useCalendarTheme, type CalendarTheme } from './use-calendar-theme';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/blocks/datepicker/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,KAAK,oBAAoB,GAC1B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,gBAAgB,EAAE,KAAK,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AACnF,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,kBAAkB,EAClB,KAAK,yBAAyB,EAC9B,KAAK,SAAS,GACf,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,gBAAgB,EAAE,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,5 @@
1
+ export { DatePickerModal, DatePickerTrigger, formatDisplayDate, } from './datepicker-modal';
2
+ export { DatePickerInline } from './datepicker-inline';
3
+ export { DateRangePickerModal, DateRangePickerTrigger, formatRangeDisplay, } from './date-range-picker-modal';
4
+ export { useCalendarTheme } from './use-calendar-theme';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/blocks/datepicker/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,iBAAiB,GAElB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,gBAAgB,EAA8B,MAAM,qBAAqB,CAAC;AACnF,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,kBAAkB,GAGnB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,gBAAgB,EAAsB,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,25 @@
1
+ /** Theme object for react-native-calendars. Pass to Calendar's theme prop. */
2
+ export interface CalendarTheme {
3
+ backgroundColor?: string;
4
+ calendarBackground?: string;
5
+ textSectionTitleColor?: string;
6
+ textSectionTitleDisabledColor?: string;
7
+ selectedDayBackgroundColor?: string;
8
+ selectedDayTextColor?: string;
9
+ todayTextColor?: string;
10
+ todayBackgroundColor?: string;
11
+ dayTextColor?: string;
12
+ textDisabledColor?: string;
13
+ dotColor?: string;
14
+ selectedDotColor?: string;
15
+ arrowColor?: string;
16
+ monthTextColor?: string;
17
+ indicatorColor?: string;
18
+ }
19
+ /**
20
+ * Returns a theme object for react-native-calendars based on current Uniwind theme.
21
+ * Derived from useThemeColors; apps can override by passing a custom theme.
22
+ * Only defined custom values override base; undefined keys keep base values.
23
+ */
24
+ export declare function useCalendarTheme(customTheme?: CalendarTheme): CalendarTheme;
25
+ //# sourceMappingURL=use-calendar-theme.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-calendar-theme.d.ts","sourceRoot":"","sources":["../../../src/blocks/datepicker/use-calendar-theme.ts"],"names":[],"mappings":"AAGA,8EAA8E;AAC9E,MAAM,WAAW,aAAa;IAC5B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,6BAA6B,CAAC,EAAE,MAAM,CAAC;IACvC,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAmBD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,CAAC,EAAE,aAAa,GAAG,aAAa,CAS3E"}
@@ -0,0 +1,35 @@
1
+ import { useThemeColors } from '../../lib/theme-colors';
2
+ function buildCalendarTheme(c) {
3
+ return {
4
+ calendarBackground: c.background,
5
+ textSectionTitleColor: c.mutedForeground,
6
+ selectedDayBackgroundColor: c.primary,
7
+ selectedDayTextColor: c.primaryForeground,
8
+ todayTextColor: c.foreground,
9
+ todayBackgroundColor: c.muted,
10
+ dayTextColor: c.foreground,
11
+ textDisabledColor: c.border,
12
+ dotColor: c.accent,
13
+ selectedDotColor: c.primaryForeground,
14
+ arrowColor: c.foreground,
15
+ monthTextColor: c.foreground,
16
+ };
17
+ }
18
+ /**
19
+ * Returns a theme object for react-native-calendars based on current Uniwind theme.
20
+ * Derived from useThemeColors; apps can override by passing a custom theme.
21
+ * Only defined custom values override base; undefined keys keep base values.
22
+ */
23
+ export function useCalendarTheme(customTheme) {
24
+ const c = useThemeColors();
25
+ const base = buildCalendarTheme(c);
26
+ if (!customTheme)
27
+ return base;
28
+ const merged = { ...base };
29
+ for (const [k, v] of Object.entries(customTheme)) {
30
+ if (v !== undefined)
31
+ merged[k] = v;
32
+ }
33
+ return merged;
34
+ }
35
+ //# sourceMappingURL=use-calendar-theme.js.map