@thewhileloop/whileui 2.0.0 → 3.0.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 -5
- package/dist/blocks/commerce/metric-card.d.ts +9 -29
- package/dist/blocks/datepicker/date-range-picker-modal.d.ts +1 -1
- package/dist/blocks/datepicker/date-range-picker-modal.js +6 -14
- package/dist/blocks/datepicker/datepicker-modal.d.ts +1 -1
- package/dist/blocks/datepicker/datepicker-modal.js +6 -12
- package/dist/blocks/layout/smart-input.d.ts +3 -2
- package/dist/blocks/layout/smart-input.js +33 -18
- package/dist/blocks/media/smart-image.d.ts +39 -98
- package/dist/blocks/navigation/drawer-menu.js +88 -72
- package/dist/components/alert/alert.d.ts +23 -55
- package/dist/components/alert/alert.js +1 -1
- package/dist/components/alert-dialog/alert-dialog.js +1 -4
- package/dist/components/avatar/avatar.d.ts +18 -45
- package/dist/components/avatar/avatar.js +1 -1
- package/dist/components/badge/badge.d.ts +84 -212
- package/dist/components/button/button.d.ts +69 -188
- package/dist/components/card/card.d.ts +29 -73
- package/dist/components/card/card.js +1 -1
- package/dist/components/container/container.d.ts +24 -96
- package/dist/components/data-row/data-row.d.ts +18 -38
- package/dist/components/data-row/data-row.js +1 -1
- package/dist/components/form-field/form-field.d.ts +31 -87
- package/dist/components/form-field/form-field.js +1 -1
- package/dist/components/hover-card/hover-card.d.ts +3 -2
- package/dist/components/input/input.d.ts +12 -31
- package/dist/components/label/label.d.ts +3 -3
- package/dist/components/labeled-field/labeled-field.d.ts +3 -2
- package/dist/components/numeric-input/numeric-input.d.ts +27 -82
- package/dist/components/numeric-input/numeric-input.js +69 -78
- package/dist/components/otp-input/otp-input.d.ts +21 -65
- package/dist/components/popover/popover.d.ts +4 -3
- package/dist/components/pressable/pressable.d.ts +3 -3
- package/dist/components/progress/progress.d.ts +15 -39
- package/dist/components/row/row.d.ts +63 -163
- package/dist/components/segmented-control/segmented-control.d.ts +69 -241
- package/dist/components/select/select.d.ts +10 -22
- package/dist/components/select/select.js +2 -2
- package/dist/components/separator/separator.d.ts +3 -3
- package/dist/components/skeleton/skeleton.d.ts +9 -29
- package/dist/components/spinner/spinner.d.ts +12 -36
- package/dist/components/stack/stack.d.ts +63 -163
- package/dist/components/tabs/tabs.d.ts +9 -29
- package/dist/components/text/text.d.ts +51 -131
- package/dist/components/textarea/textarea.d.ts +15 -39
- package/dist/components/textarea/textarea.js +1 -1
- package/dist/components/toast/toast.d.ts +12 -36
- package/dist/components/toggle/toggle.d.ts +42 -138
- package/dist/components/toggle-group/toggle-group.d.ts +42 -138
- package/dist/components/tooltip/tooltip.d.ts +3 -2
- package/dist/components/view/view.d.ts +3 -3
- package/dist/lib/ref-types.d.ts +3 -0
- package/dist/lib/ref-types.js +1 -0
- package/dist/lib/theme-bridge.d.ts +4 -2
- package/dist/lib/theme-bridge.js +13 -9
- package/package.json +29 -28
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
Beautiful, accessible, themeable components built with [Uniwind](https://uniwind.dev) + Tailwind CSS v4.
|
|
6
6
|
|
|
7
|
-
**Requirements:** React 19+, React Native 0.
|
|
7
|
+
**Requirements:** React 19.3+, React Native 0.88+, Expo 58+ (if using Expo). Supports React Native Web.
|
|
8
8
|
|
|
9
9
|
WhileUI has one renderer: React Native. iOS, Android and React Native Web are all
|
|
10
10
|
production targets — iOS and Android set the interaction baseline. See
|
|
@@ -15,7 +15,7 @@ production targets — iOS and Android set the interaction baseline. See
|
|
|
15
15
|
|
|
16
16
|
```bash
|
|
17
17
|
bun add @thewhileloop/whileui
|
|
18
|
-
bun add react@^19.
|
|
18
|
+
bun add react@^19.3.0 react-native@^0.88.0 uniwind@^1.12.2 tailwindcss@^4.0.0 react-native-reanimated react-native-safe-area-context react-native-screens
|
|
19
19
|
# Only if you use Select, Popover, Tooltip, or HoverCard:
|
|
20
20
|
bun add @rn-primitives/portal @rn-primitives/hooks @rn-primitives/slot @rn-primitives/select @rn-primitives/popover @rn-primitives/tooltip @rn-primitives/hover-card
|
|
21
21
|
```
|
|
@@ -851,7 +851,8 @@ Optional RN fallback tokens (hex/rgb/hsl/named):
|
|
|
851
851
|
}
|
|
852
852
|
```
|
|
853
853
|
|
|
854
|
-
Or use the first-party
|
|
854
|
+
Or use the first-party theme bridge with optional persistence. The hook owns theme
|
|
855
|
+
state and exposes event-driven setters:
|
|
855
856
|
|
|
856
857
|
```tsx
|
|
857
858
|
import { useThemeBridge, type ThemeBridgeAdapter } from '@thewhileloop/whileui';
|
|
@@ -866,6 +867,16 @@ const adapter: ThemeBridgeAdapter = {
|
|
|
866
867
|
const { mode, resolvedTheme, setMode, cycleMode } = useThemeBridge({ adapter });
|
|
867
868
|
```
|
|
868
869
|
|
|
870
|
+
When another store already owns the mode, mount the controlled bridge once near the
|
|
871
|
+
application root. Change `mode` in the owning event handler; the bridge applies and
|
|
872
|
+
persists it without mirroring state back through a callback effect.
|
|
873
|
+
|
|
874
|
+
```tsx
|
|
875
|
+
import { ThemeBridge } from '@thewhileloop/whileui';
|
|
876
|
+
|
|
877
|
+
<ThemeBridge mode={mode} adapter={adapter} />;
|
|
878
|
+
```
|
|
879
|
+
|
|
869
880
|
## Focus rings
|
|
870
881
|
|
|
871
882
|
Every interactive component draws a themed focus ring on web. It uses `:focus-visible`,
|
|
@@ -1550,7 +1561,8 @@ announces as a heading to assistive technology — as do `DropdownMenuLabel` and
|
|
|
1550
1561
|
|
|
1551
1562
|
## SignInForm
|
|
1552
1563
|
|
|
1553
|
-
Copy
|
|
1564
|
+
Copy `sign-in-form.tsx` and its sibling `auth-form-footer.tsx` from
|
|
1565
|
+
`apps/showcase/templates/auth/`, then:
|
|
1554
1566
|
|
|
1555
1567
|
```tsx
|
|
1556
1568
|
import { SignInForm } from './templates/auth'; // or your path
|
|
@@ -1574,7 +1586,8 @@ import { SignInForm } from './templates/auth'; // or your path
|
|
|
1574
1586
|
|
|
1575
1587
|
## SignUpForm
|
|
1576
1588
|
|
|
1577
|
-
Copy
|
|
1589
|
+
Copy `sign-up-form.tsx` and its sibling `auth-form-footer.tsx` from
|
|
1590
|
+
`apps/showcase/templates/auth/`, then:
|
|
1578
1591
|
|
|
1579
1592
|
```tsx
|
|
1580
1593
|
import { SignUpForm } from './templates/auth'; // or your path
|
|
@@ -3,40 +3,20 @@ import { type ViewProps } from 'react-native';
|
|
|
3
3
|
import { type VariantProps } from '../../lib/tv';
|
|
4
4
|
declare const metricCardVariants: import("tailwind-variants").TVReturnType<{
|
|
5
5
|
variant: {
|
|
6
|
-
default:
|
|
7
|
-
outlined:
|
|
6
|
+
default: "bg-card";
|
|
7
|
+
outlined: "bg-transparent border border-border";
|
|
8
8
|
};
|
|
9
|
-
}, undefined, "",
|
|
9
|
+
}, undefined, "", {
|
|
10
10
|
variant: {
|
|
11
|
-
default:
|
|
12
|
-
outlined:
|
|
11
|
+
default: "bg-card";
|
|
12
|
+
outlined: "bg-transparent border border-border";
|
|
13
13
|
};
|
|
14
|
-
}, {
|
|
14
|
+
}, undefined, import("tailwind-variants").TVReturnTypeLike<{
|
|
15
15
|
variant: {
|
|
16
|
-
default:
|
|
17
|
-
outlined:
|
|
16
|
+
default: "bg-card";
|
|
17
|
+
outlined: "bg-transparent border border-border";
|
|
18
18
|
};
|
|
19
|
-
}
|
|
20
|
-
variant: {
|
|
21
|
-
default: string;
|
|
22
|
-
outlined: string;
|
|
23
|
-
};
|
|
24
|
-
}, undefined, import("tailwind-variants").TVReturnType<{
|
|
25
|
-
variant: {
|
|
26
|
-
default: string;
|
|
27
|
-
outlined: string;
|
|
28
|
-
};
|
|
29
|
-
}, undefined, "", import("tailwind-variants/dist/config.js").TVConfig<{
|
|
30
|
-
variant: {
|
|
31
|
-
default: string;
|
|
32
|
-
outlined: string;
|
|
33
|
-
};
|
|
34
|
-
}, {
|
|
35
|
-
variant: {
|
|
36
|
-
default: string;
|
|
37
|
-
outlined: string;
|
|
38
|
-
};
|
|
39
|
-
}>, unknown, unknown, undefined>>;
|
|
19
|
+
}, undefined>>;
|
|
40
20
|
export interface MetricCardProps extends ViewProps, VariantProps<typeof metricCardVariants> {
|
|
41
21
|
className?: string;
|
|
42
22
|
label: string;
|
|
@@ -29,7 +29,7 @@ export interface DateRangePickerModalProps extends FrostedSurfaceProps {
|
|
|
29
29
|
className?: string;
|
|
30
30
|
}
|
|
31
31
|
declare function formatRangeDisplay(range: DateRange | null | undefined): string;
|
|
32
|
-
export declare function DateRangePickerModal(
|
|
32
|
+
export declare function DateRangePickerModal(props: DateRangePickerModalProps): React.JSX.Element;
|
|
33
33
|
/** Compact trigger showing formatted range. Use as DateRangePickerModal's trigger prop. */
|
|
34
34
|
export declare function DateRangePickerTrigger({ value, placeholder, className, }: {
|
|
35
35
|
value?: DateRange | null;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { useCallback,
|
|
2
|
+
import { useCallback, useMemo, useState } from 'react';
|
|
3
3
|
import { Modal, Pressable, View } from 'react-native';
|
|
4
4
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
5
5
|
import { useUniwind } from 'uniwind';
|
|
@@ -47,7 +47,7 @@ function buildMarkedDates(start, end, theme) {
|
|
|
47
47
|
}
|
|
48
48
|
return marked;
|
|
49
49
|
}
|
|
50
|
-
|
|
50
|
+
function DateRangePickerModalSession({ value, onValueChange, open, onOpenChange, minDate, maxDate, theme: customTheme, trigger, title = 'Select date range', confirmLabel = 'Done', className, frosted = false, blurIntensity, blurTintToken, }) {
|
|
51
51
|
const insets = useSafeAreaInsets();
|
|
52
52
|
const { theme } = useUniwind();
|
|
53
53
|
const colors = useThemeColors();
|
|
@@ -68,18 +68,6 @@ export function DateRangePickerModal({ value, onValueChange, open, onOpenChange,
|
|
|
68
68
|
const renderArrow = useCallback((direction) => (_jsx(Text, { className: "font-medium", style: { color: arrowColor, fontSize: arrowFontSize }, children: direction === 'left' ? '<' : '>' })), [arrowColor, arrowFontSize]);
|
|
69
69
|
const [draftStart, setDraftStart] = useState(value?.start ?? null);
|
|
70
70
|
const [draftEnd, setDraftEnd] = useState(value?.end ?? null);
|
|
71
|
-
const prevOpenRef = useRef(open);
|
|
72
|
-
useEffect(() => {
|
|
73
|
-
if (open && !prevOpenRef.current) {
|
|
74
|
-
setDraftStart(value?.start ?? null);
|
|
75
|
-
setDraftEnd(value?.end ?? null);
|
|
76
|
-
}
|
|
77
|
-
else if (!open && prevOpenRef.current) {
|
|
78
|
-
setDraftStart(null);
|
|
79
|
-
setDraftEnd(null);
|
|
80
|
-
}
|
|
81
|
-
prevOpenRef.current = open;
|
|
82
|
-
}, [open, value]);
|
|
83
71
|
const markedDates = useMemo(() => {
|
|
84
72
|
const color = calendarTheme.selectedDayBackgroundColor;
|
|
85
73
|
const textColor = calendarTheme.selectedDayTextColor;
|
|
@@ -151,6 +139,10 @@ export function DateRangePickerModal({ value, onValueChange, open, onOpenChange,
|
|
|
151
139
|
borderWidth: visual.borderWidthHairline,
|
|
152
140
|
}, children: _jsx(Calendar, { current: draftStart ?? value?.start ?? undefined, onDayPress: handleDayPress, markedDates: markedDates, markingType: "period", minDate: minDate, maxDate: maxDate, theme: calendarTheme, renderArrow: renderArrow, enableSwipeMonths: true }, theme) }) })] }) }) })] }));
|
|
153
141
|
}
|
|
142
|
+
export function DateRangePickerModal(props) {
|
|
143
|
+
const sessionKey = props.open ? 'open' : 'closed';
|
|
144
|
+
return _jsx(DateRangePickerModalSession, { ...props }, sessionKey);
|
|
145
|
+
}
|
|
154
146
|
/** Compact trigger showing formatted range. Use as DateRangePickerModal's trigger prop. */
|
|
155
147
|
export function DateRangePickerTrigger({ value, placeholder = 'Select date range', className, }) {
|
|
156
148
|
const visual = useVisualTokens();
|
|
@@ -25,7 +25,7 @@ export interface DatePickerModalProps extends FrostedSurfaceProps {
|
|
|
25
25
|
className?: string;
|
|
26
26
|
}
|
|
27
27
|
declare function formatDisplayDate(dateString: string | null | undefined): string;
|
|
28
|
-
export declare function DatePickerModal(
|
|
28
|
+
export declare function DatePickerModal(props: DatePickerModalProps): React.JSX.Element;
|
|
29
29
|
/** Compact trigger showing formatted date. Use as DatePickerModal's trigger prop. */
|
|
30
30
|
export declare function DatePickerTrigger({ value, placeholder, className, }: {
|
|
31
31
|
value?: string | null;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { useCallback,
|
|
2
|
+
import { useCallback, useMemo, useState } from 'react';
|
|
3
3
|
import { Modal, Pressable, View } from 'react-native';
|
|
4
4
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
5
5
|
import { useUniwind } from 'uniwind';
|
|
@@ -23,7 +23,7 @@ function formatDisplayDate(dateString) {
|
|
|
23
23
|
year: 'numeric',
|
|
24
24
|
});
|
|
25
25
|
}
|
|
26
|
-
|
|
26
|
+
function DatePickerModalSession({ value, onValueChange, open, onOpenChange, minDate, maxDate, theme: customTheme, trigger, title = 'Select date', confirmLabel = 'Done', className, frosted = false, blurIntensity, blurTintToken, }) {
|
|
27
27
|
const insets = useSafeAreaInsets();
|
|
28
28
|
const { theme } = useUniwind();
|
|
29
29
|
const colors = useThemeColors();
|
|
@@ -43,16 +43,6 @@ export function DatePickerModal({ value, onValueChange, open, onOpenChange, minD
|
|
|
43
43
|
const arrowFontSize = typographyStyle(visual, 'body').fontSize;
|
|
44
44
|
const renderArrow = useCallback((direction) => (_jsx(Text, { className: "font-medium", style: { color: arrowColor, fontSize: arrowFontSize }, children: direction === 'left' ? '<' : '>' })), [arrowColor, arrowFontSize]);
|
|
45
45
|
const [draftDate, setDraftDate] = useState(value ?? null);
|
|
46
|
-
const prevOpenRef = useRef(open);
|
|
47
|
-
useEffect(() => {
|
|
48
|
-
if (open && !prevOpenRef.current) {
|
|
49
|
-
setDraftDate(value ?? null);
|
|
50
|
-
}
|
|
51
|
-
else if (!open && prevOpenRef.current) {
|
|
52
|
-
setDraftDate(null);
|
|
53
|
-
}
|
|
54
|
-
prevOpenRef.current = open;
|
|
55
|
-
}, [open, value]);
|
|
56
46
|
const markedDates = useMemo(() => {
|
|
57
47
|
if (!draftDate)
|
|
58
48
|
return undefined;
|
|
@@ -95,6 +85,10 @@ export function DatePickerModal({ value, onValueChange, open, onOpenChange, minD
|
|
|
95
85
|
borderWidth: visual.borderWidthHairline,
|
|
96
86
|
}, children: _jsx(Calendar, { current: draftDate ?? value ?? undefined, onDayPress: handleDayPress, markedDates: markedDates, minDate: minDate, maxDate: maxDate, theme: calendarTheme, renderArrow: renderArrow, enableSwipeMonths: true }, theme) }) })] }) }) })] }));
|
|
97
87
|
}
|
|
88
|
+
export function DatePickerModal(props) {
|
|
89
|
+
const sessionKey = props.open ? 'open' : 'closed';
|
|
90
|
+
return _jsx(DatePickerModalSession, { ...props }, sessionKey);
|
|
91
|
+
}
|
|
98
92
|
/** Compact trigger showing formatted date. Use as DatePickerModal's trigger prop. */
|
|
99
93
|
export function DatePickerTrigger({ value, placeholder = 'Select date', className, }) {
|
|
100
94
|
const visual = useVisualTokens();
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { type TextInputInstance, type TextInputProps } from 'react-native';
|
|
3
|
+
import type { ForwardRefComponent } from '../../lib/ref-types';
|
|
3
4
|
export interface SmartInputProps extends TextInputProps {
|
|
4
5
|
/** Left slot: emoji, attach, etc. */
|
|
5
6
|
leftSlot?: React.ReactNode;
|
|
@@ -24,4 +25,4 @@ export interface SmartInputProps extends TextInputProps {
|
|
|
24
25
|
placeholderPauseDuration?: number;
|
|
25
26
|
placeholderClearInterval?: number;
|
|
26
27
|
}
|
|
27
|
-
export declare const SmartInput:
|
|
28
|
+
export declare const SmartInput: ForwardRefComponent<TextInputInstance, SmartInputProps>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef, useEffect, useRef, useState } from 'react';
|
|
3
|
-
import { AccessibilityInfo, View, TextInput } from 'react-native';
|
|
3
|
+
import { AccessibilityInfo, View, TextInput, } from 'react-native';
|
|
4
4
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
5
5
|
import { cn } from '../../lib/cn';
|
|
6
6
|
import { focusRing } from '../../lib/focus-ring';
|
|
@@ -79,6 +79,30 @@ function useRotatingPlaceholder({ active, examplesKey, prefix, typingInterval, p
|
|
|
79
79
|
}
|
|
80
80
|
return animatedPlaceholder || prefix;
|
|
81
81
|
}
|
|
82
|
+
function useSmartInputPlaceholder({ value, defaultValue, placeholder, examples, prefix, typingInterval, pauseDuration, clearInterval, onChangeText, }) {
|
|
83
|
+
const [uncontrolledHasText, setUncontrolledHasText] = useState(() => Boolean(defaultValue));
|
|
84
|
+
const hasText = value !== undefined ? Boolean(value) : uncontrolledHasText;
|
|
85
|
+
const examplesKey = examples?.join(SEPARATOR) ?? '';
|
|
86
|
+
const animatedPlaceholder = useRotatingPlaceholder({
|
|
87
|
+
active: placeholder === undefined && !hasText && Boolean(examplesKey),
|
|
88
|
+
examplesKey,
|
|
89
|
+
prefix,
|
|
90
|
+
typingInterval,
|
|
91
|
+
pauseDuration,
|
|
92
|
+
clearInterval,
|
|
93
|
+
});
|
|
94
|
+
return {
|
|
95
|
+
placeholder: placeholder ?? (hasText || !examplesKey ? undefined : animatedPlaceholder),
|
|
96
|
+
onChangeText: (text) => {
|
|
97
|
+
if (value === undefined)
|
|
98
|
+
setUncontrolledHasText(Boolean(text));
|
|
99
|
+
onChangeText?.(text);
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
function SmartInputSlot({ children }) {
|
|
104
|
+
return children ? _jsx(View, { className: "shrink-0", children: children }) : null;
|
|
105
|
+
}
|
|
82
106
|
export const SmartInput = forwardRef(function SmartInput({ leftSlot, centerSlot, rightSlot, variant = 'bar', className, inputClassName, submitBehavior = 'newline', safeArea = true, placeholderExamples, placeholderPrefix = 'e.g. ', placeholderTypingInterval = 65, placeholderPauseDuration = 2200, placeholderClearInterval = 25, placeholderTextColor, placeholder, value, defaultValue, onChangeText, editable = true, style, ...props }, ref) {
|
|
83
107
|
const insets = useSafeAreaInsets();
|
|
84
108
|
const colors = useThemeColors();
|
|
@@ -87,22 +111,17 @@ export const SmartInput = forwardRef(function SmartInput({ leftSlot, centerSlot,
|
|
|
87
111
|
const bottomPadding = safeArea
|
|
88
112
|
? Math.max(insets.bottom, visual.controlPaddingYSm)
|
|
89
113
|
: visual.controlPaddingYSm;
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
const examplesKey = placeholderExamples?.join(SEPARATOR) ?? '';
|
|
96
|
-
const animatePlaceholder = placeholder === undefined && !hasText && Boolean(examplesKey);
|
|
97
|
-
const animatedPlaceholder = useRotatingPlaceholder({
|
|
98
|
-
active: animatePlaceholder,
|
|
99
|
-
examplesKey,
|
|
114
|
+
const placeholderState = useSmartInputPlaceholder({
|
|
115
|
+
value,
|
|
116
|
+
defaultValue,
|
|
117
|
+
placeholder,
|
|
118
|
+
examples: placeholderExamples,
|
|
100
119
|
prefix: placeholderPrefix,
|
|
101
120
|
typingInterval: placeholderTypingInterval,
|
|
102
121
|
pauseDuration: placeholderPauseDuration,
|
|
103
122
|
clearInterval: placeholderClearInterval,
|
|
123
|
+
onChangeText,
|
|
104
124
|
});
|
|
105
|
-
const resolvedPlaceholder = placeholder ?? (hasText || !examplesKey ? undefined : animatedPlaceholder);
|
|
106
125
|
return (_jsxs(View, { className: cn('w-full flex-row items-center gap-2 bg-background', variant === 'bar' && 'border-border', variant === 'card' && 'border-border', className), style: [
|
|
107
126
|
{
|
|
108
127
|
paddingHorizontal: visual.controlPaddingXSm,
|
|
@@ -117,16 +136,12 @@ export const SmartInput = forwardRef(function SmartInput({ leftSlot, centerSlot,
|
|
|
117
136
|
...shadowStyle(visual, colors, 'md'),
|
|
118
137
|
}
|
|
119
138
|
: null,
|
|
120
|
-
], children: [
|
|
139
|
+
], children: [_jsx(SmartInputSlot, { children: leftSlot }), _jsx(SmartInputSlot, { children: centerSlot }), _jsx(TextInput, { ref: ref, style: [
|
|
121
140
|
controlRecipe(visual, 'default'),
|
|
122
141
|
typographyStyle(visual, 'label'),
|
|
123
142
|
variant === 'bar' ? { borderWidth: visual.borderWidthControl } : null,
|
|
124
143
|
{ maxHeight: visual.smartInputMaxHeight },
|
|
125
144
|
!editable ? { opacity: interaction.disabledOpacity } : null,
|
|
126
145
|
style,
|
|
127
|
-
], className: cn('flex-1 text-foreground placeholder:text-muted-foreground', focusRing, variant === 'bar' && 'border-border bg-muted', variant === 'card' && 'bg-transparent', inputClassName), multiline: true, submitBehavior: submitBehavior, textAlignVertical: "top", placeholderTextColor: placeholderTextColor ?? colors.placeholder, placeholder:
|
|
128
|
-
if (value === undefined)
|
|
129
|
-
setUncontrolledHasText(Boolean(text));
|
|
130
|
-
onChangeText?.(text);
|
|
131
|
-
}, editable: editable, ...props }), rightSlot && _jsx(View, { className: "shrink-0", children: rightSlot })] }));
|
|
146
|
+
], className: cn('flex-1 text-foreground placeholder:text-muted-foreground', focusRing, variant === 'bar' && 'border-border bg-muted', variant === 'card' && 'bg-transparent', inputClassName), multiline: true, submitBehavior: submitBehavior, textAlignVertical: "top", placeholderTextColor: placeholderTextColor ?? colors.placeholder, placeholder: placeholderState.placeholder, value: value, defaultValue: defaultValue, onChangeText: placeholderState.onChangeText, editable: editable, ...props }), _jsx(SmartInputSlot, { children: rightSlot })] }));
|
|
132
147
|
});
|
|
@@ -1,122 +1,63 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import { type ViewInstance, type ViewProps } from 'react-native';
|
|
2
|
+
import { type ImageProps } from 'expo-image';
|
|
3
3
|
import { type VariantProps } from '../../lib/tv';
|
|
4
|
+
import type { ForwardRefComponent } from '../../lib/ref-types';
|
|
4
5
|
declare const smartImageVariants: import("tailwind-variants").TVReturnType<{
|
|
5
6
|
radius: {
|
|
6
|
-
none:
|
|
7
|
-
sm:
|
|
8
|
-
md:
|
|
9
|
-
lg:
|
|
10
|
-
xl:
|
|
11
|
-
full:
|
|
7
|
+
none: "";
|
|
8
|
+
sm: "";
|
|
9
|
+
md: "";
|
|
10
|
+
lg: "";
|
|
11
|
+
xl: "";
|
|
12
|
+
full: "rounded-full";
|
|
12
13
|
};
|
|
13
14
|
objectFit: {
|
|
14
|
-
cover:
|
|
15
|
-
contain:
|
|
16
|
-
fill:
|
|
17
|
-
'scale-down':
|
|
15
|
+
cover: "object-cover";
|
|
16
|
+
contain: "object-contain";
|
|
17
|
+
fill: "object-fill";
|
|
18
|
+
'scale-down': "object-scale-down";
|
|
18
19
|
};
|
|
19
|
-
}, undefined, "overflow-hidden",
|
|
20
|
+
}, undefined, "overflow-hidden", {
|
|
20
21
|
radius: {
|
|
21
|
-
none:
|
|
22
|
-
sm:
|
|
23
|
-
md:
|
|
24
|
-
lg:
|
|
25
|
-
xl:
|
|
26
|
-
full:
|
|
22
|
+
none: "";
|
|
23
|
+
sm: "";
|
|
24
|
+
md: "";
|
|
25
|
+
lg: "";
|
|
26
|
+
xl: "";
|
|
27
|
+
full: "rounded-full";
|
|
27
28
|
};
|
|
28
29
|
objectFit: {
|
|
29
|
-
cover:
|
|
30
|
-
contain:
|
|
31
|
-
fill:
|
|
32
|
-
'scale-down':
|
|
30
|
+
cover: "object-cover";
|
|
31
|
+
contain: "object-contain";
|
|
32
|
+
fill: "object-fill";
|
|
33
|
+
'scale-down': "object-scale-down";
|
|
33
34
|
};
|
|
34
|
-
}, {
|
|
35
|
+
}, undefined, import("tailwind-variants").TVReturnTypeLike<{
|
|
35
36
|
radius: {
|
|
36
|
-
none:
|
|
37
|
-
sm:
|
|
38
|
-
md:
|
|
39
|
-
lg:
|
|
40
|
-
xl:
|
|
41
|
-
full:
|
|
37
|
+
none: "";
|
|
38
|
+
sm: "";
|
|
39
|
+
md: "";
|
|
40
|
+
lg: "";
|
|
41
|
+
xl: "";
|
|
42
|
+
full: "rounded-full";
|
|
42
43
|
};
|
|
43
44
|
objectFit: {
|
|
44
|
-
cover:
|
|
45
|
-
contain:
|
|
46
|
-
fill:
|
|
47
|
-
'scale-down':
|
|
45
|
+
cover: "object-cover";
|
|
46
|
+
contain: "object-contain";
|
|
47
|
+
fill: "object-fill";
|
|
48
|
+
'scale-down': "object-scale-down";
|
|
48
49
|
};
|
|
49
|
-
}
|
|
50
|
-
radius: {
|
|
51
|
-
none: string;
|
|
52
|
-
sm: string;
|
|
53
|
-
md: string;
|
|
54
|
-
lg: string;
|
|
55
|
-
xl: string;
|
|
56
|
-
full: string;
|
|
57
|
-
};
|
|
58
|
-
objectFit: {
|
|
59
|
-
cover: string;
|
|
60
|
-
contain: string;
|
|
61
|
-
fill: string;
|
|
62
|
-
'scale-down': string;
|
|
63
|
-
};
|
|
64
|
-
}, undefined, import("tailwind-variants").TVReturnType<{
|
|
65
|
-
radius: {
|
|
66
|
-
none: string;
|
|
67
|
-
sm: string;
|
|
68
|
-
md: string;
|
|
69
|
-
lg: string;
|
|
70
|
-
xl: string;
|
|
71
|
-
full: string;
|
|
72
|
-
};
|
|
73
|
-
objectFit: {
|
|
74
|
-
cover: string;
|
|
75
|
-
contain: string;
|
|
76
|
-
fill: string;
|
|
77
|
-
'scale-down': string;
|
|
78
|
-
};
|
|
79
|
-
}, undefined, "overflow-hidden", import("tailwind-variants/dist/config.js").TVConfig<{
|
|
80
|
-
radius: {
|
|
81
|
-
none: string;
|
|
82
|
-
sm: string;
|
|
83
|
-
md: string;
|
|
84
|
-
lg: string;
|
|
85
|
-
xl: string;
|
|
86
|
-
full: string;
|
|
87
|
-
};
|
|
88
|
-
objectFit: {
|
|
89
|
-
cover: string;
|
|
90
|
-
contain: string;
|
|
91
|
-
fill: string;
|
|
92
|
-
'scale-down': string;
|
|
93
|
-
};
|
|
94
|
-
}, {
|
|
95
|
-
radius: {
|
|
96
|
-
none: string;
|
|
97
|
-
sm: string;
|
|
98
|
-
md: string;
|
|
99
|
-
lg: string;
|
|
100
|
-
xl: string;
|
|
101
|
-
full: string;
|
|
102
|
-
};
|
|
103
|
-
objectFit: {
|
|
104
|
-
cover: string;
|
|
105
|
-
contain: string;
|
|
106
|
-
fill: string;
|
|
107
|
-
'scale-down': string;
|
|
108
|
-
};
|
|
109
|
-
}>, unknown, unknown, undefined>>;
|
|
50
|
+
}, undefined>>;
|
|
110
51
|
export interface SmartImageProps extends Omit<ViewProps, 'className'>, VariantProps<typeof smartImageVariants> {
|
|
111
52
|
className?: string;
|
|
112
|
-
source:
|
|
53
|
+
source: ImageProps['source'];
|
|
113
54
|
alt: string;
|
|
114
55
|
skeleton?: boolean;
|
|
115
56
|
skeletonClassName?: string;
|
|
116
57
|
transition?: number;
|
|
117
58
|
onLoad?: () => void;
|
|
118
59
|
onError?: () => void;
|
|
119
|
-
fallbackSource?:
|
|
60
|
+
fallbackSource?: ImageProps['source'];
|
|
120
61
|
}
|
|
121
|
-
declare const SmartImage:
|
|
62
|
+
declare const SmartImage: ForwardRefComponent<ViewInstance, SmartImageProps>;
|
|
122
63
|
export { SmartImage, smartImageVariants };
|