fluent-styles 1.62.14 → 1.62.15
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/lib/commonjs/button/index.js +12 -4
- package/lib/commonjs/button/index.js.map +1 -1
- package/lib/commonjs/datePicker/index.js +7 -2
- package/lib/commonjs/datePicker/index.js.map +1 -1
- package/lib/commonjs/dropdown/index.js +49 -16
- package/lib/commonjs/dropdown/index.js.map +1 -1
- package/lib/commonjs/input/index.js +32 -8
- package/lib/commonjs/input/index.js.map +1 -1
- package/lib/commonjs/page/index.js +24 -3
- package/lib/commonjs/page/index.js.map +1 -1
- package/lib/commonjs/pressable/index.js +6 -0
- package/lib/commonjs/pressable/index.js.map +1 -1
- package/lib/commonjs/safeAreaView/index.js +10 -0
- package/lib/commonjs/safeAreaView/index.js.map +1 -1
- package/lib/commonjs/utiles/styled.js +12 -2
- package/lib/commonjs/utiles/styled.js.map +1 -1
- package/lib/module/button/index.js +12 -4
- package/lib/module/button/index.js.map +1 -1
- package/lib/module/datePicker/index.js +7 -2
- package/lib/module/datePicker/index.js.map +1 -1
- package/lib/module/dropdown/index.js +49 -16
- package/lib/module/dropdown/index.js.map +1 -1
- package/lib/module/input/index.js +32 -8
- package/lib/module/input/index.js.map +1 -1
- package/lib/module/page/index.js +25 -4
- package/lib/module/page/index.js.map +1 -1
- package/lib/module/pressable/index.js +7 -1
- package/lib/module/pressable/index.js.map +1 -1
- package/lib/module/safeAreaView/index.js +11 -1
- package/lib/module/safeAreaView/index.js.map +1 -1
- package/lib/module/utiles/styled.js +12 -2
- package/lib/module/utiles/styled.js.map +1 -1
- package/lib/typescript/badge/index.d.ts +1 -6
- package/lib/typescript/badge/index.d.ts.map +1 -1
- package/lib/typescript/button/index.d.ts +3 -8
- package/lib/typescript/button/index.d.ts.map +1 -1
- package/lib/typescript/card/index.d.ts +1 -6
- package/lib/typescript/card/index.d.ts.map +1 -1
- package/lib/typescript/checkBox/index.d.ts +1 -6
- package/lib/typescript/checkBox/index.d.ts.map +1 -1
- package/lib/typescript/datePicker/index.d.ts.map +1 -1
- package/lib/typescript/dialog/index.d.ts +1 -6
- package/lib/typescript/dialog/index.d.ts.map +1 -1
- package/lib/typescript/divider/index.d.ts +1 -6
- package/lib/typescript/divider/index.d.ts.map +1 -1
- package/lib/typescript/dropdown/index.d.ts +27 -2
- package/lib/typescript/dropdown/index.d.ts.map +1 -1
- package/lib/typescript/image/index.d.ts +1 -6
- package/lib/typescript/image/index.d.ts.map +1 -1
- package/lib/typescript/input/index.d.ts +20 -1
- package/lib/typescript/input/index.d.ts.map +1 -1
- package/lib/typescript/page/index.d.ts.map +1 -1
- package/lib/typescript/pressable/index.d.ts +1 -6
- package/lib/typescript/pressable/index.d.ts.map +1 -1
- package/lib/typescript/safeAreaProvider/index.d.ts +1 -6
- package/lib/typescript/safeAreaProvider/index.d.ts.map +1 -1
- package/lib/typescript/safeAreaView/index.d.ts +1 -6
- package/lib/typescript/safeAreaView/index.d.ts.map +1 -1
- package/lib/typescript/scrollView/index.d.ts +1 -6
- package/lib/typescript/scrollView/index.d.ts.map +1 -1
- package/lib/typescript/shape/cycle.d.ts +1 -6
- package/lib/typescript/shape/cycle.d.ts.map +1 -1
- package/lib/typescript/shape/index.d.ts +1 -6
- package/lib/typescript/shape/index.d.ts.map +1 -1
- package/lib/typescript/spacer/index.d.ts +1 -6
- package/lib/typescript/spacer/index.d.ts.map +1 -1
- package/lib/typescript/stack/index.d.ts +3 -18
- package/lib/typescript/stack/index.d.ts.map +1 -1
- package/lib/typescript/text/index.d.ts +1 -6
- package/lib/typescript/text/index.d.ts.map +1 -1
- package/lib/typescript/utiles/styled.d.ts +1 -6
- package/lib/typescript/utiles/styled.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/button/index.tsx +14 -2
- package/src/datePicker/index.tsx +5 -1
- package/src/dropdown/index.tsx +72 -11
- package/src/input/index.tsx +56 -10
- package/src/page/index.tsx +36 -3
- package/src/pressable/index.tsx +8 -2
- package/src/safeAreaView/index.tsx +11 -1
- package/src/utiles/styled.tsx +12 -3
package/src/button/index.tsx
CHANGED
|
@@ -285,7 +285,19 @@ function spinnerColor(props: StyledButtonProps): string {
|
|
|
285
285
|
|
|
286
286
|
// ─── Button ──────────────────────────────────────────────────────────────────
|
|
287
287
|
|
|
288
|
-
|
|
288
|
+
// `ref` is destructured straight from props above the button, which only
|
|
289
|
+
// works unpatched on React 19's "ref as prop" model — on React 18 (still the
|
|
290
|
+
// baseline for RN/Expo consumers of this library) a plain function component
|
|
291
|
+
// can never receive a ref at all; React strips it before the function runs.
|
|
292
|
+
// `forwardRef` is the compatible way to accept a ref on both, so wrap here
|
|
293
|
+
// instead of destructuring `ref` out of the props object directly. Any
|
|
294
|
+
// caller relying on that ref — e.g. StyledDropdown's Trigger, which measures
|
|
295
|
+
// this button's on-screen position to place its option panel — silently got
|
|
296
|
+
// `null` without this, and the panel fell back to {top:0,left:0,width:0}.
|
|
297
|
+
const Button = React.forwardRef<
|
|
298
|
+
React.ComponentRef<typeof ButtonBase>,
|
|
299
|
+
StyledButtonProps
|
|
300
|
+
>(({ children, loading, leftIcon, rightIcon, disabled, ...rest }, ref) => {
|
|
289
301
|
const isDisabled = disabled || loading
|
|
290
302
|
|
|
291
303
|
return (
|
|
@@ -315,7 +327,7 @@ const Button = ({ children, loading, leftIcon, rightIcon, disabled, ref, ...rest
|
|
|
315
327
|
{!loading && rightIcon ? rightIcon : null}
|
|
316
328
|
</ButtonBase>
|
|
317
329
|
);
|
|
318
|
-
};
|
|
330
|
+
});
|
|
319
331
|
|
|
320
332
|
Button.displayName = 'StyledButton'
|
|
321
333
|
|
package/src/datePicker/index.tsx
CHANGED
|
@@ -799,7 +799,11 @@ const InputTrigger: React.FC<{
|
|
|
799
799
|
borderRadius={12}
|
|
800
800
|
paddingHorizontal={14}
|
|
801
801
|
paddingVertical={12}
|
|
802
|
-
|
|
802
|
+
// PATCHED: was hard-coded to palettes.white regardless of theme — the
|
|
803
|
+
// "background" token is already themeable via the `colors` prop (it
|
|
804
|
+
// already drives the calendar sheet below), so reuse it here too
|
|
805
|
+
// instead of introducing a second, disconnected background colour.
|
|
806
|
+
backgroundColor={C.background}
|
|
803
807
|
onPress={onPress}
|
|
804
808
|
disabled={disabled}
|
|
805
809
|
>
|
package/src/dropdown/index.tsx
CHANGED
|
@@ -81,6 +81,32 @@ interface DropdownBaseProps<TItem extends DropdownOptionItem>
|
|
|
81
81
|
emptyText?: string;
|
|
82
82
|
focusColor?: string;
|
|
83
83
|
groupBy?: (item: TItem) => string;
|
|
84
|
+
/**
|
|
85
|
+
* Resting-surface + option-panel colour overrides — lets a consumer theme
|
|
86
|
+
* the dropdown (e.g. for dark mode) without the trigger's own focus/error
|
|
87
|
+
* border logic needing to change. A nested `colors` object (rather than
|
|
88
|
+
* a flat `backgroundColor` prop) avoids colliding with the `ViewStyle`
|
|
89
|
+
* props this interface already extends, which style the outer wrapper,
|
|
90
|
+
* not the trigger box.
|
|
91
|
+
*/
|
|
92
|
+
colors?: StyledDropdownColors;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export interface StyledDropdownColors {
|
|
96
|
+
/** Trigger box resting background. @default '#fff' */
|
|
97
|
+
background?: string;
|
|
98
|
+
/** Trigger box resting border (overridden by focus/error). @default gray[200] */
|
|
99
|
+
border?: string;
|
|
100
|
+
/** Selected value text colour. @default gray[800] */
|
|
101
|
+
text?: string;
|
|
102
|
+
/** Open option-panel background. @default '#fff' */
|
|
103
|
+
panelBackground?: string;
|
|
104
|
+
/** Open option-panel border. @default gray[200] */
|
|
105
|
+
panelBorder?: string;
|
|
106
|
+
/** Option row label text colour. @default gray[800] */
|
|
107
|
+
panelText?: string;
|
|
108
|
+
/** Dividers / section-header strip background inside the panel. @default gray[100] */
|
|
109
|
+
panelDivider?: string;
|
|
84
110
|
}
|
|
85
111
|
|
|
86
112
|
export interface StyledDropdownProps<
|
|
@@ -221,11 +247,12 @@ const OptionRow: React.FC<{
|
|
|
221
247
|
multiSelect: boolean;
|
|
222
248
|
size: DropdownSize;
|
|
223
249
|
focusColor: string;
|
|
224
|
-
|
|
250
|
+
textColor: string;
|
|
251
|
+
}> = ({ item, selected, onPress, multiSelect, size, focusColor, textColor: baseTextColor }) => {
|
|
225
252
|
const sz = SZ[size];
|
|
226
253
|
const textColor = item.disabled
|
|
227
254
|
? theme.colors.gray[300]
|
|
228
|
-
:
|
|
255
|
+
: baseTextColor;
|
|
229
256
|
|
|
230
257
|
return (
|
|
231
258
|
<StyledButton
|
|
@@ -309,6 +336,7 @@ interface ListPanelProps {
|
|
|
309
336
|
allSelected?: boolean;
|
|
310
337
|
onSelectAll?: () => void;
|
|
311
338
|
onPanelLayout?: (height: number) => void;
|
|
339
|
+
colors: Required<StyledDropdownColors>;
|
|
312
340
|
}
|
|
313
341
|
|
|
314
342
|
type ListEntry = DropdownOptionItem | { _header: string };
|
|
@@ -333,6 +361,7 @@ const ListPanel: React.FC<ListPanelProps> = ({
|
|
|
333
361
|
allSelected,
|
|
334
362
|
onSelectAll,
|
|
335
363
|
onPanelLayout,
|
|
364
|
+
colors,
|
|
336
365
|
}) => {
|
|
337
366
|
const [query, setQuery] = useState("");
|
|
338
367
|
const sz = SZ[size];
|
|
@@ -376,7 +405,7 @@ const ListPanel: React.FC<ListPanelProps> = ({
|
|
|
376
405
|
paddingHorizontal={sz.px}
|
|
377
406
|
paddingTop={10}
|
|
378
407
|
paddingBottom={4}
|
|
379
|
-
backgroundColor={
|
|
408
|
+
backgroundColor={colors.panelDivider}
|
|
380
409
|
>
|
|
381
410
|
<StyledText
|
|
382
411
|
fontSize={11}
|
|
@@ -398,10 +427,11 @@ const ListPanel: React.FC<ListPanelProps> = ({
|
|
|
398
427
|
multiSelect={multiSelect}
|
|
399
428
|
size={size}
|
|
400
429
|
focusColor={focusColor}
|
|
430
|
+
textColor={colors.panelText}
|
|
401
431
|
/>
|
|
402
432
|
);
|
|
403
433
|
},
|
|
404
|
-
[selectedKeys, onSelect, multiSelect, size, focusColor, sz.px],
|
|
434
|
+
[selectedKeys, onSelect, multiSelect, size, focusColor, sz.px, colors.panelDivider, colors.panelText],
|
|
405
435
|
);
|
|
406
436
|
|
|
407
437
|
const keyExtractor = useCallback(
|
|
@@ -427,10 +457,10 @@ const ListPanel: React.FC<ListPanelProps> = ({
|
|
|
427
457
|
left={position.left}
|
|
428
458
|
width={position.width}
|
|
429
459
|
maxHeight={maxHeight}
|
|
430
|
-
backgroundColor={
|
|
460
|
+
backgroundColor={colors.panelBackground}
|
|
431
461
|
borderRadius={10}
|
|
432
462
|
borderWidth={1}
|
|
433
|
-
borderColor={
|
|
463
|
+
borderColor={colors.panelBorder}
|
|
434
464
|
shadowColor={theme.colors.gray[900]}
|
|
435
465
|
shadowOffset={{
|
|
436
466
|
width: 0,
|
|
@@ -545,7 +575,7 @@ const ListPanel: React.FC<ListPanelProps> = ({
|
|
|
545
575
|
renderItem={renderItem}
|
|
546
576
|
ItemSeparatorComponent={() => (
|
|
547
577
|
<StyledDivider
|
|
548
|
-
backgroundColor={
|
|
578
|
+
backgroundColor={colors.panelDivider}
|
|
549
579
|
height={1}
|
|
550
580
|
/>
|
|
551
581
|
)}
|
|
@@ -634,6 +664,7 @@ const Trigger: React.FC<{
|
|
|
634
664
|
hasError: boolean;
|
|
635
665
|
focusColor: string;
|
|
636
666
|
leftIcon?: React.ReactNode;
|
|
667
|
+
colors: Required<StyledDropdownColors>;
|
|
637
668
|
}> = ({
|
|
638
669
|
triggerRef,
|
|
639
670
|
onPress,
|
|
@@ -648,24 +679,25 @@ const Trigger: React.FC<{
|
|
|
648
679
|
hasError,
|
|
649
680
|
focusColor,
|
|
650
681
|
leftIcon,
|
|
682
|
+
colors,
|
|
651
683
|
}) => {
|
|
652
684
|
const sz = SZ[size];
|
|
653
685
|
const opacity = disabled ? 0.5 : 1;
|
|
654
|
-
const textColor = isPlaceholder ? placeholderColor :
|
|
686
|
+
const textColor = isPlaceholder ? placeholderColor : colors.text;
|
|
655
687
|
|
|
656
688
|
// Border colour logic
|
|
657
689
|
const borderColor = hasError
|
|
658
690
|
? theme.colors.red[500]
|
|
659
691
|
: open
|
|
660
692
|
? focusColor
|
|
661
|
-
:
|
|
693
|
+
: colors.border;
|
|
662
694
|
|
|
663
695
|
// Variant-specific styles
|
|
664
696
|
const variantStyle: ViewStyle = (() => {
|
|
665
697
|
switch (variant) {
|
|
666
698
|
case "filled":
|
|
667
699
|
return {
|
|
668
|
-
backgroundColor:
|
|
700
|
+
backgroundColor: colors.background,
|
|
669
701
|
borderWidth: 0,
|
|
670
702
|
borderBottomWidth: open ? 2 : 0,
|
|
671
703
|
borderBottomColor: borderColor,
|
|
@@ -686,7 +718,7 @@ const Trigger: React.FC<{
|
|
|
686
718
|
};
|
|
687
719
|
default: // outline
|
|
688
720
|
return {
|
|
689
|
-
backgroundColor:
|
|
721
|
+
backgroundColor: colors.background,
|
|
690
722
|
borderWidth: open ? 1.5 : 1,
|
|
691
723
|
borderColor: borderColor,
|
|
692
724
|
borderRadius: 8,
|
|
@@ -810,6 +842,7 @@ export const StyledDropdown = (
|
|
|
810
842
|
emptyText = "No options found",
|
|
811
843
|
focusColor = theme.colors.indigo?.[500] ?? "#6366f1",
|
|
812
844
|
groupBy,
|
|
845
|
+
colors: colorsProp,
|
|
813
846
|
ref,
|
|
814
847
|
...rest
|
|
815
848
|
}: StyledDropdownProps & { ref?: React.Ref<any> },
|
|
@@ -819,6 +852,18 @@ export const StyledDropdown = (
|
|
|
819
852
|
const { triggerRef, pos, measure, updatePanelHeight } =
|
|
820
853
|
useMeasure(maxHeight);
|
|
821
854
|
|
|
855
|
+
// PATCHED: resolved once here so both the closed Trigger and the open
|
|
856
|
+
// ListPanel share one themed palette instead of each hard-coding white.
|
|
857
|
+
const RC: Required<StyledDropdownColors> = {
|
|
858
|
+
background: colorsProp?.background ?? theme.colors.white,
|
|
859
|
+
border: colorsProp?.border ?? theme.colors.gray[200],
|
|
860
|
+
text: colorsProp?.text ?? theme.colors.gray[800],
|
|
861
|
+
panelBackground: colorsProp?.panelBackground ?? theme.colors.white,
|
|
862
|
+
panelBorder: colorsProp?.panelBorder ?? theme.colors.gray[200],
|
|
863
|
+
panelText: colorsProp?.panelText ?? theme.colors.gray[800],
|
|
864
|
+
panelDivider: colorsProp?.panelDivider ?? theme.colors.gray[100],
|
|
865
|
+
};
|
|
866
|
+
|
|
822
867
|
const selected = value ?? internalValue;
|
|
823
868
|
const hasError = error || !!errorMessage;
|
|
824
869
|
const selectedItem = useMemo(
|
|
@@ -885,6 +930,7 @@ export const StyledDropdown = (
|
|
|
885
930
|
hasError={hasError}
|
|
886
931
|
focusColor={focusColor}
|
|
887
932
|
leftIcon={leftIcon}
|
|
933
|
+
colors={RC}
|
|
888
934
|
/>
|
|
889
935
|
{open && (
|
|
890
936
|
<ListPanel
|
|
@@ -897,6 +943,7 @@ export const StyledDropdown = (
|
|
|
897
943
|
multiSelect={false}
|
|
898
944
|
searchable={searchable}
|
|
899
945
|
searchPlaceholder={searchPlaceholder}
|
|
946
|
+
colors={RC}
|
|
900
947
|
clearable={clearable}
|
|
901
948
|
onClear={handleClear}
|
|
902
949
|
emptyText={emptyText}
|
|
@@ -943,6 +990,7 @@ export const StyledMultiSelectDropdown = (
|
|
|
943
990
|
separator = ", ",
|
|
944
991
|
maxDisplay = 3,
|
|
945
992
|
selectAll = false,
|
|
993
|
+
colors: colorsProp,
|
|
946
994
|
ref,
|
|
947
995
|
...rest
|
|
948
996
|
}: StyledMultiSelectDropdownProps & { ref?: React.Ref<any> },
|
|
@@ -951,6 +999,17 @@ export const StyledMultiSelectDropdown = (
|
|
|
951
999
|
const [internalKeys, setInternalKeys] = useState<string[]>(
|
|
952
1000
|
defaultValue ?? [],
|
|
953
1001
|
);
|
|
1002
|
+
|
|
1003
|
+
// PATCHED: see StyledDropdown above — same shared-palette rationale.
|
|
1004
|
+
const RC: Required<StyledDropdownColors> = {
|
|
1005
|
+
background: colorsProp?.background ?? theme.colors.white,
|
|
1006
|
+
border: colorsProp?.border ?? theme.colors.gray[200],
|
|
1007
|
+
text: colorsProp?.text ?? theme.colors.gray[800],
|
|
1008
|
+
panelBackground: colorsProp?.panelBackground ?? theme.colors.white,
|
|
1009
|
+
panelBorder: colorsProp?.panelBorder ?? theme.colors.gray[200],
|
|
1010
|
+
panelText: colorsProp?.panelText ?? theme.colors.gray[800],
|
|
1011
|
+
panelDivider: colorsProp?.panelDivider ?? theme.colors.gray[100],
|
|
1012
|
+
};
|
|
954
1013
|
const { triggerRef, pos, measure, updatePanelHeight } = useMeasure(maxHeight);
|
|
955
1014
|
|
|
956
1015
|
const selectedKeys = useMemo(
|
|
@@ -1042,9 +1101,11 @@ export const StyledMultiSelectDropdown = (
|
|
|
1042
1101
|
hasError={hasError}
|
|
1043
1102
|
focusColor={focusColor}
|
|
1044
1103
|
leftIcon={leftIcon}
|
|
1104
|
+
colors={RC}
|
|
1045
1105
|
/>
|
|
1046
1106
|
{open && (
|
|
1047
1107
|
<ListPanel
|
|
1108
|
+
colors={RC}
|
|
1048
1109
|
data={data}
|
|
1049
1110
|
selectedKeys={selectedKeys}
|
|
1050
1111
|
onSelect={handleSelect}
|
package/src/input/index.tsx
CHANGED
|
@@ -126,7 +126,29 @@ export interface StyledTextInputProps
|
|
|
126
126
|
// ── Pass-through style props (from original) ───────────────────────────
|
|
127
127
|
fontSize?: number
|
|
128
128
|
fontWeight?: TextStyle['fontWeight']
|
|
129
|
-
|
|
129
|
+
|
|
130
|
+
// ── Theme override ──────────────────────────────────────────────────────
|
|
131
|
+
/**
|
|
132
|
+
* Resting-state surface colours. Lets a consumer theme this field (e.g.
|
|
133
|
+
* for dark mode) without fighting the focus/error border logic below —
|
|
134
|
+
* those stay computed internally and only fall back to `colors.border`
|
|
135
|
+
* when neither focused nor in an error state.
|
|
136
|
+
*/
|
|
137
|
+
colors?: StyledFieldColors
|
|
138
|
+
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export interface StyledFieldColors {
|
|
142
|
+
/** Resting background of the input box. @default '#fff' (outline/filled) */
|
|
143
|
+
background?: string
|
|
144
|
+
/** Resting border colour (overridden by focus/error). @default gray[200] */
|
|
145
|
+
border?: string
|
|
146
|
+
/** Typed text colour. @default gray[800] */
|
|
147
|
+
text?: string
|
|
148
|
+
/** Placeholder text colour. @default gray[300] */
|
|
149
|
+
placeholder?: string
|
|
150
|
+
/** Label text colour — `labelProps.color` still wins if also set. @default gray[700] */
|
|
151
|
+
label?: string
|
|
130
152
|
}
|
|
131
153
|
|
|
132
154
|
// ─── Flat style-prop resolution ────────────────────────────────────────────────
|
|
@@ -138,7 +160,13 @@ export interface StyledTextInputProps
|
|
|
138
160
|
// instead of through the shared HOC.
|
|
139
161
|
const BASE_INPUT_STYLE: TextStyle = {
|
|
140
162
|
borderColor: theme.colors.gray[200],
|
|
141
|
-
|
|
163
|
+
// PATCHED: was theme.colors.gray[1] (white) — this style lands on the
|
|
164
|
+
// *inner* native TextInput, layered on top of the wrap View that
|
|
165
|
+
// `variantWrapStyle`/`FC.background` already colour. Nothing downstream
|
|
166
|
+
// ever overrode it, so every input rendered an opaque white rectangle
|
|
167
|
+
// regardless of the wrap's themed colour. Transparent lets the wrap's
|
|
168
|
+
// colour actually show through.
|
|
169
|
+
backgroundColor: 'transparent',
|
|
142
170
|
flex: 1,
|
|
143
171
|
color: theme.colors.gray[800],
|
|
144
172
|
paddingHorizontal: 16,
|
|
@@ -212,7 +240,9 @@ function variantWrapStyle(
|
|
|
212
240
|
switch (variant) {
|
|
213
241
|
case 'filled':
|
|
214
242
|
return {
|
|
215
|
-
|
|
243
|
+
// PATCHED: used to hard-jump to '#fff' on focus, which fought any
|
|
244
|
+
// themed `bg` (e.g. a dark surface would flash white on tap).
|
|
245
|
+
backgroundColor: bg,
|
|
216
246
|
borderWidth: focused ? 1.5 : 0,
|
|
217
247
|
borderColor: bc,
|
|
218
248
|
}
|
|
@@ -229,8 +259,11 @@ function variantWrapStyle(
|
|
|
229
259
|
borderWidth: 0,
|
|
230
260
|
}
|
|
231
261
|
default: // outline
|
|
262
|
+
// PATCHED: used to hard-code '#fff', ignoring the `bg` param entirely
|
|
263
|
+
// — the one line responsible for every "white input on a dark
|
|
264
|
+
// screen" bug. `bg` now carries the caller's themed surface colour.
|
|
232
265
|
return {
|
|
233
|
-
backgroundColor:
|
|
266
|
+
backgroundColor: bg,
|
|
234
267
|
borderWidth: focused ? 1.5 : 1,
|
|
235
268
|
borderColor: bc,
|
|
236
269
|
}
|
|
@@ -379,6 +412,7 @@ export const StyledTextInput = (
|
|
|
379
412
|
borderColor: borderColorProp,
|
|
380
413
|
focusColor = theme.colors.indigo?.[500] ?? '#6366f1',
|
|
381
414
|
floatLabel = false,
|
|
415
|
+
colors: colorsProp,
|
|
382
416
|
|
|
383
417
|
// Styles
|
|
384
418
|
containerStyle,
|
|
@@ -443,8 +477,20 @@ export const StyledTextInput = (
|
|
|
443
477
|
const hasError = error || !!errorMessage
|
|
444
478
|
const sz = SIZE[size]
|
|
445
479
|
|
|
480
|
+
// PATCHED: `colors` lets a consumer theme the resting surface (e.g. for
|
|
481
|
+
// dark mode) without touching the focus/error logic below — those stay
|
|
482
|
+
// computed here and only fall back to `FC.border` when neither focused
|
|
483
|
+
// nor erroring, so a themed border never masks a validation error.
|
|
484
|
+
const FC = {
|
|
485
|
+
background: colorsProp?.background ?? (theme.colors.gray[50] ?? '#fafafa'),
|
|
486
|
+
border: colorsProp?.border ?? theme.colors.gray[200],
|
|
487
|
+
text: colorsProp?.text ?? theme.colors.gray[800],
|
|
488
|
+
placeholder: colorsProp?.placeholder ?? theme.colors.gray[300],
|
|
489
|
+
label: colorsProp?.label ?? theme.colors.gray[700],
|
|
490
|
+
}
|
|
491
|
+
|
|
446
492
|
const resolvedBorderColor = borderColorProp
|
|
447
|
-
?? (hasError ? theme.colors.red[500] :
|
|
493
|
+
?? (hasError ? theme.colors.red[500] : FC.border)
|
|
448
494
|
|
|
449
495
|
const resolvedFocusColor = hasError
|
|
450
496
|
? theme.colors.red[500]
|
|
@@ -453,7 +499,7 @@ export const StyledTextInput = (
|
|
|
453
499
|
const wrapStyle = variantWrapStyle(
|
|
454
500
|
variant,
|
|
455
501
|
resolvedBorderColor,
|
|
456
|
-
|
|
502
|
+
FC.background,
|
|
457
503
|
focused,
|
|
458
504
|
resolvedFocusColor,
|
|
459
505
|
)
|
|
@@ -492,8 +538,8 @@ export const StyledTextInput = (
|
|
|
492
538
|
<StyledText
|
|
493
539
|
fontSize={theme.fontSize.small}
|
|
494
540
|
fontWeight={theme.fontWeight.semiBold}
|
|
495
|
-
color={
|
|
496
|
-
|
|
541
|
+
color={FC.label}
|
|
542
|
+
|
|
497
543
|
marginBottom={6}
|
|
498
544
|
{...labelProps}
|
|
499
545
|
>
|
|
@@ -559,7 +605,7 @@ export const StyledTextInput = (
|
|
|
559
605
|
onFocus={handleFocus}
|
|
560
606
|
onBlur={handleBlur}
|
|
561
607
|
placeholder={floatLabel ? undefined : placeholder}
|
|
562
|
-
placeholderTextColor={
|
|
608
|
+
placeholderTextColor={FC.placeholder}
|
|
563
609
|
editable={editable && !loading}
|
|
564
610
|
multiline={multiline}
|
|
565
611
|
numberOfLines={numberOfLines}
|
|
@@ -574,7 +620,7 @@ export const StyledTextInput = (
|
|
|
574
620
|
paddingVertical: sz.paddingV,
|
|
575
621
|
minHeight: multiline ? sz.minHeight * 2 : sz.minHeight,
|
|
576
622
|
opacity: editable && !loading ? 1 : 0.55,
|
|
577
|
-
color:
|
|
623
|
+
color: FC.text,
|
|
578
624
|
textAlignVertical: multiline ? 'top' : 'center',
|
|
579
625
|
},
|
|
580
626
|
inputStyle,
|
package/src/page/index.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { StyledSafeAreaView, StyledSafeAreaViewProps } from '../safeAreaView';
|
|
3
|
-
import { StatusBar, StatusBarProps } from 'react-native';
|
|
3
|
+
import { StatusBar, StatusBarProps, Platform, useColorScheme } from 'react-native';
|
|
4
4
|
import { StyledHeader } from '../header';
|
|
5
5
|
|
|
6
6
|
interface StyledPageProps extends StyledSafeAreaViewProps {
|
|
@@ -19,10 +19,43 @@ interface StyledPageType {
|
|
|
19
19
|
displayName?: string;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
// statusBarStyle used to default to a hardcoded 'dark-content' regardless of
|
|
23
|
+
// the active theme — any screen rendered in dark mode that forgot to pass
|
|
24
|
+
// its own statusBarStyle got dark (near-invisible) status bar icons on a
|
|
25
|
+
// dark background. Falls back to the OS color scheme via useColorScheme()
|
|
26
|
+
// instead, the same signal a theme-aware caller would use for its own
|
|
27
|
+
// explicit statusBarStyle.
|
|
28
|
+
//
|
|
29
|
+
// translucentStatusBar now also defaults to true on Android specifically
|
|
30
|
+
// (via Platform.select): with edge-to-edge unavoidable from targetSdk 35+,
|
|
31
|
+
// StatusBar's `backgroundColor` prop is deprecated and silently ignored on
|
|
32
|
+
// Android there, so a non-translucent bar left the *native* window
|
|
33
|
+
// background (white by default) showing behind the status bar instead of
|
|
34
|
+
// the page's own backgroundColor. iOS's status bar is always an overlay, so
|
|
35
|
+
// it's left unaffected (translucentStatusBar stays undefined there unless
|
|
36
|
+
// the caller sets it).
|
|
37
|
+
const Page = ({
|
|
38
|
+
children, statusBarProps, showStatusBar = true,
|
|
39
|
+
statusBarStyle, statusBarBackgroundColor,
|
|
40
|
+
hideStatusBarOnAndroid, hideStatusBarOnIOS,
|
|
41
|
+
translucentStatusBar,
|
|
42
|
+
...props
|
|
43
|
+
}: React.PropsWithChildren<StyledPageProps>) => {
|
|
44
|
+
const colorScheme = useColorScheme();
|
|
45
|
+
const resolvedStatusBarStyle = statusBarStyle ?? (colorScheme === 'dark' ? 'light-content' : 'dark-content');
|
|
46
|
+
const resolvedTranslucent = translucentStatusBar ?? Platform.select({ android: true, default: undefined });
|
|
47
|
+
|
|
23
48
|
return (
|
|
24
49
|
<StyledSafeAreaView {...props}>
|
|
25
|
-
{showStatusBar &&
|
|
50
|
+
{showStatusBar && (
|
|
51
|
+
<StatusBar
|
|
52
|
+
hidden={hideStatusBarOnAndroid || hideStatusBarOnIOS}
|
|
53
|
+
barStyle={resolvedStatusBarStyle}
|
|
54
|
+
backgroundColor={statusBarBackgroundColor}
|
|
55
|
+
translucent={resolvedTranslucent}
|
|
56
|
+
{...statusBarProps}
|
|
57
|
+
/>
|
|
58
|
+
)}
|
|
26
59
|
{children}
|
|
27
60
|
</StyledSafeAreaView>
|
|
28
61
|
)
|
package/src/pressable/index.tsx
CHANGED
|
@@ -2,16 +2,22 @@
|
|
|
2
2
|
import { Pressable, PressableProps } from 'react-native';
|
|
3
3
|
import { styled } from '../utiles/styled';
|
|
4
4
|
import { ViewStyle } from '../utiles/viewStyleProps';
|
|
5
|
-
import { viewStyleStringVariants } from '../utiles/viewStyleVariants';
|
|
5
|
+
import { viewStyleVariants, viewStyleStringVariants } from '../utiles/viewStyleVariants';
|
|
6
6
|
|
|
7
7
|
type StyledPressableProps = PressableProps & ViewStyle;
|
|
8
8
|
|
|
9
|
+
// Same missing-viewStyleVariants gap as StyledSafeAreaView (see that file
|
|
10
|
+
// for the full explanation): width/height/borderRadius/backgroundColor
|
|
11
|
+
// passed to StyledPressable were silently dropped instead of styled —
|
|
12
|
+
// e.g. an icon button built as <StyledPressable width={44} height={44}
|
|
13
|
+
// borderRadius={22} backgroundColor={...}> rendered with none of that.
|
|
9
14
|
const StyledPressable = styled<StyledPressableProps>(Pressable, {
|
|
10
15
|
base: {
|
|
11
16
|
position: 'relative',
|
|
12
17
|
} as ViewStyle,
|
|
13
18
|
variants: {
|
|
14
|
-
...
|
|
19
|
+
...viewStyleVariants,
|
|
20
|
+
...viewStyleStringVariants,
|
|
15
21
|
} as any
|
|
16
22
|
});
|
|
17
23
|
|
|
@@ -4,15 +4,25 @@ import {
|
|
|
4
4
|
} from 'react-native-safe-area-context';
|
|
5
5
|
import { styled } from '../utiles/styled';
|
|
6
6
|
import { ViewStyleProps, ViewStyle } from '../utiles/viewStyleProps';
|
|
7
|
-
import { viewStyleStringVariants } from '../utiles/viewStyleVariants';
|
|
7
|
+
import { viewStyleVariants, viewStyleStringVariants } from '../utiles/viewStyleVariants';
|
|
8
8
|
|
|
9
9
|
type StyledSafeAreaViewProps = SafeAreaViewProps & ViewStyleProps;
|
|
10
10
|
|
|
11
|
+
// This only spread viewStyleStringVariants, so backgroundColor/padding/
|
|
12
|
+
// margin/width/height/borderRadius/etc — everything defined in
|
|
13
|
+
// viewStyleVariants instead — were never registered as variants here. They
|
|
14
|
+
// fell through as raw unhandled props on SafeAreaView instead of landing in
|
|
15
|
+
// `style`, so e.g. <StyledPage backgroundColor="#111"> silently did nothing.
|
|
16
|
+
// Stack already spreads both and works correctly, which is what exposed the
|
|
17
|
+
// gap: on Android specifically, a screen that relied on StyledPage's
|
|
18
|
+
// backgroundColor to paint the safe area showed the native window's default
|
|
19
|
+
// white background through instead.
|
|
11
20
|
const StyledSafeAreaView = styled<StyledSafeAreaViewProps>(SafeAreaView, {
|
|
12
21
|
base: {
|
|
13
22
|
flex: 1,
|
|
14
23
|
} as ViewStyle,
|
|
15
24
|
variants: {
|
|
25
|
+
...viewStyleVariants,
|
|
16
26
|
...viewStyleStringVariants,
|
|
17
27
|
}
|
|
18
28
|
});
|
package/src/utiles/styled.tsx
CHANGED
|
@@ -17,7 +17,16 @@ const styled = <P extends object>(
|
|
|
17
17
|
Component: ComponentType<P>,
|
|
18
18
|
{ base, variants }: StyledOptions = {}
|
|
19
19
|
) => {
|
|
20
|
-
|
|
20
|
+
// `ref` used to be handled via a plain function reading it off props —
|
|
21
|
+
// that only works under React 19's "ref as prop" model. Consumers still
|
|
22
|
+
// on React 18 (the current baseline for RN/Expo) get a plain function
|
|
23
|
+
// component that can never receive a ref at all (React strips it before
|
|
24
|
+
// the function runs), so any ref attached to a styled() component —
|
|
25
|
+
// including this library's own internals, e.g. StyledDropdown's Trigger
|
|
26
|
+
// measuring its own on-screen position — silently no-ops with a
|
|
27
|
+
// "Function components cannot be given refs" warning. forwardRef is the
|
|
28
|
+
// version that works on both React 18 and 19.
|
|
29
|
+
const StyledComponent = React.forwardRef<any, P>((props, ref) => {
|
|
21
30
|
const styles: Style = { ...(base || {}) };
|
|
22
31
|
const options = props as Record<string, any>;
|
|
23
32
|
const incomingStyle = options.style;
|
|
@@ -39,8 +48,8 @@ const styled = <P extends object>(
|
|
|
39
48
|
});
|
|
40
49
|
}
|
|
41
50
|
|
|
42
|
-
return <Component {...(cleanProps as P)} style={[styles, incomingStyle]} />;
|
|
43
|
-
};
|
|
51
|
+
return <Component {...(cleanProps as P)} ref={ref} style={[styles, incomingStyle]} />;
|
|
52
|
+
});
|
|
44
53
|
|
|
45
54
|
StyledComponent.displayName = `Styled(${
|
|
46
55
|
typeof Component === "string" ? Component : Component.displayName ?? Component.name ?? "Component"
|