@thewhileloop/whileui 4.0.0 → 4.1.1
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 +186 -20
- package/dist/blocks/chat/chat-conversation.d.ts +8 -0
- package/dist/blocks/chat/chat-conversation.js +36 -0
- package/dist/blocks/chat/chat.js +5 -11
- package/dist/blocks/chat/index.d.ts +1 -0
- package/dist/blocks/chat/index.js +1 -0
- package/dist/blocks/layout/smart-input.js +2 -1
- package/dist/blocks/media/smart-image.js +5 -7
- package/dist/code.d.ts +1 -0
- package/dist/code.js +1 -0
- package/dist/components/avatar/avatar.d.ts +3 -2
- package/dist/components/avatar/avatar.js +19 -13
- package/dist/components/avatar/index.d.ts +1 -1
- package/dist/components/card/card.d.ts +1 -1
- package/dist/components/card/card.js +4 -25
- package/dist/components/code-block/code-block.d.ts +12 -0
- package/dist/components/code-block/code-block.js +13 -0
- package/dist/components/code-block/index.d.ts +1 -0
- package/dist/components/code-block/index.js +1 -0
- package/dist/components/form-field/form-field.d.ts +8 -0
- package/dist/components/form-field/form-field.js +3 -0
- package/dist/components/form-field/index.d.ts +1 -1
- package/dist/components/form-field/index.js +1 -1
- package/dist/components/input/input.d.ts +1 -0
- package/dist/components/input/input.js +11 -6
- package/dist/components/markdown/index.d.ts +1 -0
- package/dist/components/markdown/index.js +1 -0
- package/dist/components/markdown/markdown.d.ts +14 -0
- package/dist/components/markdown/markdown.js +94 -0
- package/dist/components/numeric-input/numeric-input.d.ts +1 -0
- package/dist/components/numeric-input/numeric-input.js +11 -6
- package/dist/components/select/select.d.ts +2 -1
- package/dist/components/select/select.js +44 -24
- package/dist/components/surface/index.d.ts +1 -0
- package/dist/components/surface/index.js +1 -0
- package/dist/components/surface/surface.d.ts +14 -0
- package/dist/components/surface/surface.js +35 -0
- package/dist/components/text/text.d.ts +42 -42
- package/dist/components/text/text.js +39 -17
- package/dist/components/textarea/textarea.d.ts +1 -0
- package/dist/components/textarea/textarea.js +7 -3
- package/dist/components/toast/toast.js +5 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +2 -1
- package/dist/lib/theme-bridge.d.ts +1 -1
- package/dist/lib/theme-bridge.js +52 -18
- package/dist/lib/web-autofill.d.ts +9 -0
- package/dist/lib/web-autofill.js +9 -0
- package/dist/markdown.d.ts +1 -0
- package/dist/markdown.js +1 -0
- package/package.json +16 -2
|
@@ -4,37 +4,59 @@ import { Text as RNText } from 'react-native';
|
|
|
4
4
|
import { cn } from '../../lib/cn';
|
|
5
5
|
import { tv } from '../../lib/tv';
|
|
6
6
|
import { useResolveFontFamily } from '../../lib/font-context';
|
|
7
|
+
import { useTypography } from '../../lib/recipes';
|
|
7
8
|
const textVariants = tv({
|
|
8
9
|
base: 'text-foreground',
|
|
9
10
|
variants: {
|
|
10
11
|
variant: {
|
|
11
12
|
default: 'font-normal',
|
|
12
|
-
heading: '
|
|
13
|
-
title: '
|
|
14
|
-
subtitle: '
|
|
15
|
-
body: '
|
|
16
|
-
caption: 'text-
|
|
17
|
-
label: '
|
|
18
|
-
code: 'font-mono
|
|
13
|
+
heading: 'font-bold tracking-tight',
|
|
14
|
+
title: 'font-semibold',
|
|
15
|
+
subtitle: 'font-medium',
|
|
16
|
+
body: 'font-normal',
|
|
17
|
+
caption: 'text-muted-foreground font-normal',
|
|
18
|
+
label: 'font-medium leading-tight',
|
|
19
|
+
code: 'font-mono bg-muted rounded px-1 py-0.5',
|
|
19
20
|
},
|
|
20
21
|
size: {
|
|
21
|
-
xs: '
|
|
22
|
-
sm: '
|
|
23
|
-
base: '
|
|
24
|
-
lg: '
|
|
25
|
-
xl: '
|
|
26
|
-
'2xl': '
|
|
27
|
-
'3xl': '
|
|
22
|
+
xs: '',
|
|
23
|
+
sm: '',
|
|
24
|
+
base: '',
|
|
25
|
+
lg: '',
|
|
26
|
+
xl: '',
|
|
27
|
+
'2xl': '',
|
|
28
|
+
'3xl': '',
|
|
28
29
|
},
|
|
29
30
|
},
|
|
30
31
|
defaultVariants: {
|
|
31
32
|
variant: 'default',
|
|
32
33
|
},
|
|
33
34
|
});
|
|
34
|
-
const
|
|
35
|
-
|
|
35
|
+
const VARIANT_ROLES = {
|
|
36
|
+
default: 'body',
|
|
37
|
+
heading: 'headline',
|
|
38
|
+
title: 'title',
|
|
39
|
+
subtitle: 'emphasis',
|
|
40
|
+
body: 'body',
|
|
41
|
+
caption: 'caption',
|
|
42
|
+
label: 'label',
|
|
43
|
+
code: 'label',
|
|
44
|
+
};
|
|
45
|
+
const SIZE_ROLES = {
|
|
46
|
+
xs: 'caption',
|
|
47
|
+
sm: 'label',
|
|
48
|
+
base: 'body',
|
|
49
|
+
lg: 'emphasis',
|
|
50
|
+
xl: 'title',
|
|
51
|
+
'2xl': 'headline',
|
|
52
|
+
'3xl': 'headline',
|
|
53
|
+
};
|
|
54
|
+
const Text = React.forwardRef(({ className, variant, size, style, accessibilityRole, ...props }, ref) => {
|
|
55
|
+
const effectiveVariant = variant ?? 'default';
|
|
56
|
+
const resolved = cn(textVariants({ variant: effectiveVariant, size }), className);
|
|
36
57
|
const font = useResolveFontFamily(resolved);
|
|
37
|
-
|
|
58
|
+
const semanticStyle = useTypography(size ? SIZE_ROLES[size] : VARIANT_ROLES[effectiveVariant]);
|
|
59
|
+
return (_jsx(RNText, { ref: ref, className: font ? font.className : resolved, accessibilityRole: accessibilityRole ?? (effectiveVariant === 'heading' ? 'header' : undefined), style: [variant || size ? semanticStyle : undefined, font?.style, style], ...props }));
|
|
38
60
|
});
|
|
39
61
|
Text.displayName = 'Text';
|
|
40
62
|
export { Text, textVariants };
|
|
@@ -21,6 +21,7 @@ declare const textareaVariants: import("tailwind-variants").TVReturnType<{
|
|
|
21
21
|
};
|
|
22
22
|
}, undefined>>;
|
|
23
23
|
export interface TextareaProps extends Omit<TextInputProps, 'style'>, VariantProps<typeof textareaVariants> {
|
|
24
|
+
'aria-invalid'?: boolean;
|
|
24
25
|
className?: string;
|
|
25
26
|
}
|
|
26
27
|
declare const Textarea: ForwardRefComponent<TextInputInstance, TextareaProps>;
|
|
@@ -8,6 +8,8 @@ import { useThemeColors } from '../../lib/theme-colors';
|
|
|
8
8
|
import { useInteractionTokens } from '../../lib/interaction-tokens';
|
|
9
9
|
import { useVisualTokens } from '../../lib/visual-tokens';
|
|
10
10
|
import { typographyStyle } from '../../lib/recipes';
|
|
11
|
+
import { webAutofillField } from '../../lib/web-autofill';
|
|
12
|
+
import { useFormFieldState } from '../form-field/form-field';
|
|
11
13
|
const textareaVariants = tv({
|
|
12
14
|
base: 'w-full border-border bg-muted text-foreground',
|
|
13
15
|
variants: {
|
|
@@ -26,10 +28,12 @@ const TEXTAREA_TEXT_ROLE = {
|
|
|
26
28
|
sm: 'caption',
|
|
27
29
|
lg: 'body',
|
|
28
30
|
};
|
|
29
|
-
const Textarea = React.forwardRef(({ className, size = 'default', placeholderTextColor, ...props }, ref) => {
|
|
31
|
+
const Textarea = React.forwardRef(({ className, size = 'default', placeholderTextColor, editable, 'aria-invalid': ariaInvalid, ...props }, ref) => {
|
|
30
32
|
const colors = useThemeColors();
|
|
31
33
|
const interaction = useInteractionTokens();
|
|
32
34
|
const visual = useVisualTokens();
|
|
35
|
+
const field = useFormFieldState();
|
|
36
|
+
const effectiveEditable = editable ?? !field.disabled;
|
|
33
37
|
const minHeight = size === 'sm'
|
|
34
38
|
? visual.textareaMinHeightSm
|
|
35
39
|
: size === 'lg'
|
|
@@ -42,9 +46,9 @@ const Textarea = React.forwardRef(({ className, size = 'default', placeholderTex
|
|
|
42
46
|
borderRadius: visual.radiusLg,
|
|
43
47
|
paddingHorizontal: visual.controlPaddingXDefault,
|
|
44
48
|
paddingVertical: visual.controlPaddingYDefault,
|
|
45
|
-
...(
|
|
49
|
+
...(!effectiveEditable ? { opacity: interaction.disabledOpacity } : null),
|
|
46
50
|
};
|
|
47
|
-
return (_jsx(TextInput, { ref: ref, className: cn(textareaVariants({ size }), focusField, className), style: style, multiline: true, textAlignVertical: "top", placeholderTextColor: placeholderTextColor ?? colors.placeholder, ...props }));
|
|
51
|
+
return (_jsx(TextInput, { ref: ref, className: cn(textareaVariants({ size }), field.invalid && 'border-destructive', focusField, webAutofillField, className), style: style, multiline: true, textAlignVertical: "top", placeholderTextColor: placeholderTextColor ?? colors.placeholder, editable: effectiveEditable, "aria-invalid": ariaInvalid ?? field.invalid, ...props }));
|
|
48
52
|
});
|
|
49
53
|
Textarea.displayName = 'Textarea';
|
|
50
54
|
export { Textarea, textareaVariants };
|
|
@@ -86,10 +86,14 @@ function Toast({ toast: toastData, onDismiss, className, style, ...props }) {
|
|
|
86
86
|
paddingVertical: visual.controlPaddingYSm,
|
|
87
87
|
}, children: _jsx(Text, { className: cn('font-medium', textColor), style: typographyStyle(visual, 'label'), children: action.label }) })), _jsx(Pressable, { accessibilityRole: "button", accessibilityLabel: "Dismiss", onPress: onDismiss, className: "p-1", children: _jsx(Text, { className: cn(textColor), style: typographyStyle(visual, 'emphasis'), children: "\u00D7" }) })] })] }));
|
|
88
88
|
}
|
|
89
|
+
function ToastContainerItem({ toast, dismiss, }) {
|
|
90
|
+
const handleDismiss = useCallback(() => dismiss(toast.id), [dismiss, toast.id]);
|
|
91
|
+
return (_jsx(View, { className: "mb-2", children: _jsx(Toast, { toast: toast, onDismiss: handleDismiss }) }));
|
|
92
|
+
}
|
|
89
93
|
export function ToastContainer({ position = 'top', className, style, ...props }) {
|
|
90
94
|
const { toasts, dismiss } = useToast();
|
|
91
95
|
const visual = useVisualTokens();
|
|
92
96
|
const positionClass = position === 'top' ? 'top-0' : 'bottom-0';
|
|
93
|
-
return (_jsx(View, { className: cn('absolute left-0 right-0 z-50 py-2', positionClass, className), style: [{ paddingHorizontal: visual.surfacePaddingSm }, style], pointerEvents: "box-none", ...props, children: toasts.map((toast) => (_jsx(
|
|
97
|
+
return (_jsx(View, { className: cn('absolute left-0 right-0 z-50 py-2', positionClass, className), style: [{ paddingHorizontal: visual.surfacePaddingSm }, style], pointerEvents: "box-none", ...props, children: toasts.map((toast) => (_jsx(ToastContainerItem, { toast: toast, dismiss: dismiss }, toast.id))) }));
|
|
94
98
|
}
|
|
95
99
|
export { Toast, toastVariants };
|
package/dist/index.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ export { controlRecipe, fieldRecipe, surfaceRecipe, surfacePadding, surfaceRadiu
|
|
|
16
16
|
export { WHILEUI_PRESET_SOFT, WHILEUI_PRESET_ATELIER, WHILEUI_THEME_PRESETS, themePresetToCssVariables, themePresetToCss, type ThemePreset, } from './lib/theme-presets';
|
|
17
17
|
export { deriveThemeColors, THEME_BASE_TOKEN_KEYS, type ThemeBaseColors } from './lib/theme-derive';
|
|
18
18
|
export { Text, textVariants, type TextProps } from './components/text';
|
|
19
|
+
export { Surface, type SurfaceLevel, type SurfaceProps } from './components/surface';
|
|
19
20
|
export { View, type ViewProps } from './components/view';
|
|
20
21
|
export { Pressable, type PressableProps } from './components/pressable';
|
|
21
22
|
export { Stack, stackVariants, type StackProps } from './components/stack';
|
|
@@ -25,7 +26,7 @@ export { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter,
|
|
|
25
26
|
export { Input, inputVariants, type InputProps } from './components/input';
|
|
26
27
|
export { NumericInput, numericInputVariants, numericInputTextVariants, type NumericInputProps, } from './components/numeric-input';
|
|
27
28
|
export { OTPInput, otpCellVariants, type OTPInputProps } from './components/otp-input';
|
|
28
|
-
export { FormField, FormLabel, FormControl, FormHint, FormMessage, formFieldVariants, formControlVariants, type FormFieldProps, type FormLabelProps, type FormControlProps, type FormHintProps, type FormMessageProps, } from './components/form-field';
|
|
29
|
+
export { FormField, FormLabel, FormControl, FormHint, FormMessage, useFormFieldState, formFieldVariants, formControlVariants, type FormFieldProps, type FormLabelProps, type FormControlProps, type FormHintProps, type FormMessageProps, type FormFieldState, } from './components/form-field';
|
|
29
30
|
export { LabeledField, LabeledFieldControl, type LabeledFieldProps, type LabeledFieldControlProps, } from './components/labeled-field';
|
|
30
31
|
export { Badge, BadgeText, badgeVariants, badgeTextVariants, type BadgeProps, type BadgeTextProps, } from './components/badge';
|
|
31
32
|
export { FAB, FABGroup, fabVariants, type FabProps, type FabGroupProps } from './components/fab';
|
|
@@ -39,7 +40,7 @@ export { Spinner, spinnerVariants, type SpinnerProps } from './components/spinne
|
|
|
39
40
|
export { Textarea, textareaVariants, type TextareaProps } from './components/textarea';
|
|
40
41
|
export { Skeleton, skeletonVariants, type SkeletonProps } from './components/skeleton';
|
|
41
42
|
export { AspectRatio, type AspectRatioProps } from './components/aspect-ratio';
|
|
42
|
-
export { Avatar, AvatarImage, AvatarFallback, avatarVariants, type AvatarProps, type AvatarImageProps, type AvatarFallbackProps, } from './components/avatar';
|
|
43
|
+
export { Avatar, AvatarImage, AvatarFallback, avatarVariants, type AvatarProps, type AvatarImageProps, type AvatarImageStatus, type AvatarFallbackProps, } from './components/avatar';
|
|
43
44
|
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent, type AccordionProps, type AccordionItemProps, type AccordionTriggerProps, type AccordionContentProps, } from './components/accordion';
|
|
44
45
|
export { Collapsible, CollapsibleTrigger, CollapsibleContent, type CollapsibleProps, type CollapsibleTriggerProps, type CollapsibleContentProps, } from './components/collapsible';
|
|
45
46
|
export { Container, containerVariants, type ContainerProps } from './components/container';
|
package/dist/index.js
CHANGED
|
@@ -16,6 +16,7 @@ export { controlRecipe, fieldRecipe, surfaceRecipe, surfacePadding, surfaceRadiu
|
|
|
16
16
|
export { WHILEUI_PRESET_SOFT, WHILEUI_PRESET_ATELIER, WHILEUI_THEME_PRESETS, themePresetToCssVariables, themePresetToCss, } from './lib/theme-presets';
|
|
17
17
|
export { deriveThemeColors, THEME_BASE_TOKEN_KEYS } from './lib/theme-derive';
|
|
18
18
|
export { Text, textVariants } from './components/text';
|
|
19
|
+
export { Surface } from './components/surface';
|
|
19
20
|
export { View } from './components/view';
|
|
20
21
|
export { Pressable } from './components/pressable';
|
|
21
22
|
export { Stack, stackVariants } from './components/stack';
|
|
@@ -25,7 +26,7 @@ export { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter,
|
|
|
25
26
|
export { Input, inputVariants } from './components/input';
|
|
26
27
|
export { NumericInput, numericInputVariants, numericInputTextVariants, } from './components/numeric-input';
|
|
27
28
|
export { OTPInput, otpCellVariants } from './components/otp-input';
|
|
28
|
-
export { FormField, FormLabel, FormControl, FormHint, FormMessage, formFieldVariants, formControlVariants, } from './components/form-field';
|
|
29
|
+
export { FormField, FormLabel, FormControl, FormHint, FormMessage, useFormFieldState, formFieldVariants, formControlVariants, } from './components/form-field';
|
|
29
30
|
export { LabeledField, LabeledFieldControl, } from './components/labeled-field';
|
|
30
31
|
export { Badge, BadgeText, badgeVariants, badgeTextVariants, } from './components/badge';
|
|
31
32
|
export { FAB, FABGroup, fabVariants } from './components/fab';
|
|
@@ -23,7 +23,7 @@ export declare function applyThemeMode(mode: ThemeMode): void;
|
|
|
23
23
|
export declare function resolveThemeMode(adapter?: ThemeBridgeAdapter, fallback?: ThemeMode): Promise<ThemeMode>;
|
|
24
24
|
export declare function syncThemeMode(mode: ThemeMode, adapter?: ThemeBridgeAdapter): Promise<ThemeMode>;
|
|
25
25
|
export declare function useThemeBridge({ initialMode, adapter, }?: UseThemeBridgeOptions): UseThemeBridgeResult;
|
|
26
|
-
export declare function ThemeBridge({ mode, initialMode, adapter }: ThemeBridgeProps): import("react").FunctionComponentElement<Pick<ThemeBridgeProps, "
|
|
26
|
+
export declare function ThemeBridge({ mode, initialMode, adapter }: ThemeBridgeProps): import("react").FunctionComponentElement<Pick<ThemeBridgeProps, "adapter" | "initialMode">> | import("react").FunctionComponentElement<{
|
|
27
27
|
mode: ThemeMode;
|
|
28
28
|
adapter?: ThemeBridgeAdapter;
|
|
29
29
|
}>;
|
package/dist/lib/theme-bridge.js
CHANGED
|
@@ -1,6 +1,37 @@
|
|
|
1
|
-
import { createElement, useCallback, useEffect, useMemo,
|
|
1
|
+
import { createElement, useCallback, useEffect, useMemo, useReducer } from 'react';
|
|
2
2
|
import { Uniwind, useUniwind } from 'uniwind';
|
|
3
3
|
const modeCycle = ['light', 'dark', 'system'];
|
|
4
|
+
function themeBridgeReducer(state, action) {
|
|
5
|
+
if (action.type === 'cycle') {
|
|
6
|
+
return {
|
|
7
|
+
...state,
|
|
8
|
+
status: 'ready',
|
|
9
|
+
mode: modeCycle[(modeCycle.indexOf(state.mode) + 1) % modeCycle.length],
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
if (action.type === 'select') {
|
|
13
|
+
return { ...state, status: 'ready', mode: action.mode };
|
|
14
|
+
}
|
|
15
|
+
if (action.type === 'hydrate') {
|
|
16
|
+
if (state.adapter === action.adapter &&
|
|
17
|
+
state.initialMode === action.initialMode &&
|
|
18
|
+
state.status === (action.adapter ? 'hydrating' : 'ready')) {
|
|
19
|
+
return state;
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
status: action.adapter ? 'hydrating' : 'ready',
|
|
23
|
+
mode: state.mode,
|
|
24
|
+
adapter: action.adapter,
|
|
25
|
+
initialMode: action.initialMode,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
if (state.status !== 'hydrating' ||
|
|
29
|
+
state.adapter !== action.adapter ||
|
|
30
|
+
state.initialMode !== action.initialMode) {
|
|
31
|
+
return state;
|
|
32
|
+
}
|
|
33
|
+
return { ...state, status: 'ready', mode: action.mode };
|
|
34
|
+
}
|
|
4
35
|
export function applyThemeMode(mode) {
|
|
5
36
|
Uniwind.setTheme(mode);
|
|
6
37
|
}
|
|
@@ -23,16 +54,21 @@ export async function syncThemeMode(mode, adapter) {
|
|
|
23
54
|
}
|
|
24
55
|
export function useThemeBridge({ initialMode = 'system', adapter, } = {}) {
|
|
25
56
|
const { theme } = useUniwind();
|
|
26
|
-
const [
|
|
27
|
-
|
|
57
|
+
const [state, dispatch] = useReducer(themeBridgeReducer, {
|
|
58
|
+
status: adapter ? 'hydrating' : 'ready',
|
|
59
|
+
mode: initialMode,
|
|
60
|
+
adapter,
|
|
61
|
+
initialMode,
|
|
62
|
+
});
|
|
28
63
|
useEffect(() => {
|
|
29
64
|
let mounted = true;
|
|
65
|
+
dispatch({ type: 'hydrate', adapter, initialMode });
|
|
30
66
|
if (!adapter) {
|
|
31
67
|
return;
|
|
32
68
|
}
|
|
33
69
|
// `loadThemeMode` is the consumer's storage. If it rejects — a corrupt store, a
|
|
34
70
|
// keychain prompt the user dismissed — the app must still render in the initial
|
|
35
|
-
// mode
|
|
71
|
+
// mode rather than remaining in the hydrating phase forever.
|
|
36
72
|
void (async () => {
|
|
37
73
|
let next;
|
|
38
74
|
try {
|
|
@@ -44,35 +80,33 @@ export function useThemeBridge({ initialMode = 'system', adapter, } = {}) {
|
|
|
44
80
|
if (!mounted) {
|
|
45
81
|
return;
|
|
46
82
|
}
|
|
47
|
-
|
|
48
|
-
setHydrated(true);
|
|
83
|
+
dispatch({ type: 'hydrated', adapter, initialMode, mode: next });
|
|
49
84
|
})();
|
|
50
85
|
return () => {
|
|
51
86
|
mounted = false;
|
|
52
87
|
};
|
|
53
88
|
}, [adapter, initialMode]);
|
|
54
89
|
useEffect(() => {
|
|
55
|
-
if (
|
|
90
|
+
if (state.status !== 'ready' ||
|
|
91
|
+
state.adapter !== adapter ||
|
|
92
|
+
state.initialMode !== initialMode) {
|
|
56
93
|
return;
|
|
57
94
|
}
|
|
58
|
-
applyThemeMode(mode);
|
|
95
|
+
applyThemeMode(state.mode);
|
|
59
96
|
if (adapter) {
|
|
60
|
-
void adapter.saveThemeMode(mode);
|
|
97
|
+
void adapter.saveThemeMode(state.mode);
|
|
61
98
|
}
|
|
62
|
-
}, [adapter,
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
const currentIndex = modeCycle.indexOf(currentMode);
|
|
66
|
-
const nextIndex = (currentIndex + 1) % modeCycle.length;
|
|
67
|
-
return modeCycle[nextIndex];
|
|
68
|
-
});
|
|
99
|
+
}, [adapter, initialMode, state]);
|
|
100
|
+
const setMode = useCallback((mode) => {
|
|
101
|
+
dispatch({ type: 'select', mode });
|
|
69
102
|
}, []);
|
|
103
|
+
const cycleMode = useCallback(() => dispatch({ type: 'cycle' }), []);
|
|
70
104
|
return useMemo(() => ({
|
|
71
|
-
mode,
|
|
105
|
+
mode: state.mode,
|
|
72
106
|
resolvedTheme: theme,
|
|
73
107
|
setMode,
|
|
74
108
|
cycleMode,
|
|
75
|
-
}), [cycleMode, mode, theme]);
|
|
109
|
+
}), [cycleMode, setMode, state.mode, theme]);
|
|
76
110
|
}
|
|
77
111
|
function ControlledThemeBridge({ mode, adapter, }) {
|
|
78
112
|
useEffect(() => {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser autofill paints its own field background and text colours. The large inset
|
|
3
|
+
* shadow covers that paint without changing the native style contract; the other two
|
|
4
|
+
* declarations restore the active theme's text and caret.
|
|
5
|
+
*
|
|
6
|
+
* Apply only to fields whose own surface is `bg-muted`. Transparent/unstyled inputs
|
|
7
|
+
* must keep inheriting the surface chosen by their composition.
|
|
8
|
+
*/
|
|
9
|
+
export declare const webAutofillField = "web:autofill:shadow-[inset_0_0_0_1000px_var(--color-muted)] web:autofill:[-webkit-text-fill-color:var(--color-foreground)] web:autofill:caret-foreground";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser autofill paints its own field background and text colours. The large inset
|
|
3
|
+
* shadow covers that paint without changing the native style contract; the other two
|
|
4
|
+
* declarations restore the active theme's text and caret.
|
|
5
|
+
*
|
|
6
|
+
* Apply only to fields whose own surface is `bg-muted`. Transparent/unstyled inputs
|
|
7
|
+
* must keep inheriting the surface chosen by their composition.
|
|
8
|
+
*/
|
|
9
|
+
export const webAutofillField = 'web:autofill:shadow-[inset_0_0_0_1000px_var(--color-muted)] web:autofill:[-webkit-text-fill-color:var(--color-foreground)] web:autofill:caret-foreground';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Markdown, type MarkdownProps } from './components/markdown';
|
package/dist/markdown.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Markdown } from './components/markdown';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thewhileloop/whileui",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.1.1",
|
|
4
4
|
"description": "WhileUI Native — Copy-paste components for React Native. You own the code.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -40,6 +40,14 @@
|
|
|
40
40
|
"types": "./dist/tokens.d.ts",
|
|
41
41
|
"import": "./dist/tokens.js"
|
|
42
42
|
},
|
|
43
|
+
"./code": {
|
|
44
|
+
"types": "./dist/code.d.ts",
|
|
45
|
+
"import": "./dist/code.js"
|
|
46
|
+
},
|
|
47
|
+
"./markdown": {
|
|
48
|
+
"types": "./dist/markdown.d.ts",
|
|
49
|
+
"import": "./dist/markdown.js"
|
|
50
|
+
},
|
|
43
51
|
"./package.json": "./package.json"
|
|
44
52
|
},
|
|
45
53
|
"files": [
|
|
@@ -78,11 +86,15 @@
|
|
|
78
86
|
"react-native-screens": ">=4.30.0",
|
|
79
87
|
"tailwindcss": ">=4.0.0",
|
|
80
88
|
"uniwind": ">=1.12.0",
|
|
81
|
-
"react-native-worklets": ">=0.13.0"
|
|
89
|
+
"react-native-worklets": ">=0.13.0",
|
|
90
|
+
"markdown-it": ">=14.1.0"
|
|
82
91
|
},
|
|
83
92
|
"peerDependenciesMeta": {
|
|
84
93
|
"expo-blur": {
|
|
85
94
|
"optional": true
|
|
95
|
+
},
|
|
96
|
+
"markdown-it": {
|
|
97
|
+
"optional": true
|
|
86
98
|
}
|
|
87
99
|
},
|
|
88
100
|
"dependencies": {
|
|
@@ -97,10 +109,12 @@
|
|
|
97
109
|
"@testing-library/react-native": "^14.1.0",
|
|
98
110
|
"@types/culori": "^4.0.1",
|
|
99
111
|
"@types/jest": "^30.0.0",
|
|
112
|
+
"@types/markdown-it": "^14.1.2",
|
|
100
113
|
"@types/react": "~19.3.0",
|
|
101
114
|
"expo-image": "~58.0.15",
|
|
102
115
|
"jest": "^30.5.2",
|
|
103
116
|
"jest-expo": "~58.0.11",
|
|
117
|
+
"markdown-it": "^14.1.0",
|
|
104
118
|
"react-native-screens": "~4.30.0",
|
|
105
119
|
"test-renderer": "^1.3.1",
|
|
106
120
|
"typescript": "~6.0.3"
|