ferns-ui 1.10.0 → 1.12.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/dist/Accordion.js +1 -1
- package/dist/Accordion.js.map +1 -1
- package/dist/Accordion.test.d.ts +1 -0
- package/dist/Accordion.test.js +71 -0
- package/dist/Accordion.test.js.map +1 -0
- package/dist/AddressField.test.d.ts +1 -0
- package/dist/AddressField.test.js +65 -0
- package/dist/AddressField.test.js.map +1 -0
- package/dist/Avatar.js +2 -2
- package/dist/Avatar.js.map +1 -1
- package/dist/Avatar.test.d.ts +1 -0
- package/dist/Avatar.test.js +131 -0
- package/dist/Avatar.test.js.map +1 -0
- package/dist/Badge.d.ts +1 -1
- package/dist/Badge.js +3 -3
- package/dist/Badge.js.map +1 -1
- package/dist/Badge.test.d.ts +1 -0
- package/dist/Badge.test.js +76 -0
- package/dist/Badge.test.js.map +1 -0
- package/dist/Box.test.d.ts +1 -0
- package/dist/Box.test.js +528 -0
- package/dist/Box.test.js.map +1 -0
- package/dist/Common.d.ts +101 -2
- package/dist/Common.js.map +1 -1
- package/dist/DateTimeField.js +15 -2
- package/dist/DateTimeField.js.map +1 -1
- package/dist/Heading.js +2 -0
- package/dist/Heading.js.map +1 -1
- package/dist/InfoModalIcon.js +1 -1
- package/dist/InfoModalIcon.js.map +1 -1
- package/dist/MarkdownView.d.ts +5 -0
- package/dist/MarkdownView.js +44 -0
- package/dist/MarkdownView.js.map +1 -0
- package/dist/Slider.d.ts +3 -0
- package/dist/Slider.js +94 -0
- package/dist/Slider.js.map +1 -0
- package/dist/Text.js +2 -0
- package/dist/Text.js.map +1 -1
- package/dist/TextField.test.js +9 -9
- package/dist/TextField.test.js.map +1 -1
- package/dist/Tooltip.js +2 -0
- package/dist/Tooltip.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/setupTests.js +40 -2
- package/dist/setupTests.js.map +1 -1
- package/dist/test-utils.js.map +1 -1
- package/package.json +2 -47
- package/src/Accordion.test.tsx +104 -0
- package/src/Accordion.tsx +1 -0
- package/src/AddressField.test.tsx +89 -0
- package/src/Avatar.test.tsx +163 -0
- package/src/Avatar.tsx +2 -0
- package/src/Badge.test.tsx +116 -0
- package/src/Badge.tsx +3 -1
- package/src/Box.test.tsx +665 -0
- package/src/Common.ts +115 -2
- package/src/DateTimeField.tsx +15 -2
- package/src/Heading.tsx +2 -0
- package/src/InfoModalIcon.tsx +1 -0
- package/src/MarkdownView.tsx +67 -0
- package/src/Slider.tsx +205 -0
- package/src/Text.tsx +2 -0
- package/src/TextField.test.tsx +59 -71
- package/src/Tooltip.tsx +2 -0
- package/src/__snapshots__/Accordion.test.tsx.snap +120 -0
- package/src/__snapshots__/AddressField.test.tsx.snap +464 -0
- package/src/__snapshots__/Avatar.test.tsx.snap +78 -0
- package/src/__snapshots__/Badge.test.tsx.snap +44 -0
- package/src/__snapshots__/Box.test.tsx.snap +159 -0
- package/src/__snapshots__/TextArea.test.tsx.snap +12 -0
- package/src/__snapshots__/TextField.test.tsx.snap +38 -1
- package/src/index.tsx +2 -0
- package/src/setupTests.ts +45 -2
- package/src/test-utils.tsx +1 -0
package/src/Common.ts
CHANGED
|
@@ -430,7 +430,13 @@ export const iconSizeToNumber = (size?: IconSize) => {
|
|
|
430
430
|
}[size || "md"];
|
|
431
431
|
};
|
|
432
432
|
|
|
433
|
-
export type TextSize = "sm" | "md" | "lg" | "xl";
|
|
433
|
+
export type TextSize = "sm" | "md" | "lg" | "xl" | "2xl";
|
|
434
|
+
|
|
435
|
+
export type ValueMappingItem = {
|
|
436
|
+
value: number;
|
|
437
|
+
label: string;
|
|
438
|
+
size?: IconSize;
|
|
439
|
+
};
|
|
434
440
|
|
|
435
441
|
export type IconPrefix = "far" | "fas";
|
|
436
442
|
|
|
@@ -732,7 +738,7 @@ export interface HeadingProps {
|
|
|
732
738
|
children?: React.ReactNode;
|
|
733
739
|
color?: TextColor;
|
|
734
740
|
overflow?: "normal" | "breakWord"; // default "breakWord"
|
|
735
|
-
size?: "sm" | "md" | "lg" | "xl"; // default "sm"
|
|
741
|
+
size?: "sm" | "md" | "lg" | "xl" | "2xl"; // default "sm"
|
|
736
742
|
truncate?: boolean; // default false
|
|
737
743
|
testID?: string;
|
|
738
744
|
}
|
|
@@ -1305,6 +1311,10 @@ export interface AvatarProps {
|
|
|
1305
1311
|
* Accessibility label for the avatar image.
|
|
1306
1312
|
*/
|
|
1307
1313
|
accessibilityLabel?: string;
|
|
1314
|
+
/**
|
|
1315
|
+
* Test ID for unit testing
|
|
1316
|
+
*/
|
|
1317
|
+
testID?: string;
|
|
1308
1318
|
}
|
|
1309
1319
|
|
|
1310
1320
|
export interface BadgeProps {
|
|
@@ -1354,6 +1364,11 @@ export interface BadgeProps {
|
|
|
1354
1364
|
*/
|
|
1355
1365
|
status?: "info" | "error" | "warning" | "success" | "neutral" | "custom";
|
|
1356
1366
|
|
|
1367
|
+
/**
|
|
1368
|
+
* Test ID for unit testing
|
|
1369
|
+
*/
|
|
1370
|
+
testID?: string;
|
|
1371
|
+
|
|
1357
1372
|
/**
|
|
1358
1373
|
* The text or number to display inside the badge.
|
|
1359
1374
|
*/
|
|
@@ -2678,3 +2693,101 @@ export interface TableNumberProps {
|
|
|
2678
2693
|
*/
|
|
2679
2694
|
align?: "left" | "right";
|
|
2680
2695
|
}
|
|
2696
|
+
|
|
2697
|
+
export interface SliderProps extends HelperTextProps, ErrorTextProps {
|
|
2698
|
+
/**
|
|
2699
|
+
* The title of the slider field.
|
|
2700
|
+
*/
|
|
2701
|
+
title?: string;
|
|
2702
|
+
|
|
2703
|
+
/**
|
|
2704
|
+
* The current value of the slider.
|
|
2705
|
+
*/
|
|
2706
|
+
value: number;
|
|
2707
|
+
|
|
2708
|
+
/**
|
|
2709
|
+
* The function to call when the slider value changes.
|
|
2710
|
+
*/
|
|
2711
|
+
onChange: (value: number) => void;
|
|
2712
|
+
|
|
2713
|
+
/**
|
|
2714
|
+
* The minimum value of the slider.
|
|
2715
|
+
* @default 0
|
|
2716
|
+
*/
|
|
2717
|
+
minimumValue?: number;
|
|
2718
|
+
|
|
2719
|
+
/**
|
|
2720
|
+
* The maximum value of the slider.
|
|
2721
|
+
* @default 1
|
|
2722
|
+
*/
|
|
2723
|
+
maximumValue?: number;
|
|
2724
|
+
|
|
2725
|
+
/**
|
|
2726
|
+
* The step value of the slider.
|
|
2727
|
+
* @default 0
|
|
2728
|
+
*/
|
|
2729
|
+
step?: number;
|
|
2730
|
+
|
|
2731
|
+
/**
|
|
2732
|
+
* If true, the slider will be disabled.
|
|
2733
|
+
* @default false
|
|
2734
|
+
*/
|
|
2735
|
+
disabled?: boolean;
|
|
2736
|
+
|
|
2737
|
+
/**
|
|
2738
|
+
* The color of the track to the left of the thumb.
|
|
2739
|
+
*/
|
|
2740
|
+
minimumTrackTintColor?: string;
|
|
2741
|
+
|
|
2742
|
+
/**
|
|
2743
|
+
* The color of the track to the right of the thumb.
|
|
2744
|
+
*/
|
|
2745
|
+
maximumTrackTintColor?: string;
|
|
2746
|
+
|
|
2747
|
+
/**
|
|
2748
|
+
* The color of the thumb.
|
|
2749
|
+
*/
|
|
2750
|
+
thumbTintColor?: string;
|
|
2751
|
+
|
|
2752
|
+
/**
|
|
2753
|
+
* If true, the slider will show the current value as text.
|
|
2754
|
+
* @default false
|
|
2755
|
+
*/
|
|
2756
|
+
showSelection?: boolean;
|
|
2757
|
+
|
|
2758
|
+
/**
|
|
2759
|
+
* Labels to show below the slider track.
|
|
2760
|
+
*/
|
|
2761
|
+
labels?: {
|
|
2762
|
+
/**
|
|
2763
|
+
* The minimum value label.
|
|
2764
|
+
*/
|
|
2765
|
+
min?: string;
|
|
2766
|
+
/**
|
|
2767
|
+
* The maximum value label.
|
|
2768
|
+
*/
|
|
2769
|
+
max?: string;
|
|
2770
|
+
/**
|
|
2771
|
+
* Additional labels with their positions (0-1 range).
|
|
2772
|
+
*/
|
|
2773
|
+
custom?: Array<{index: number; label: string}>;
|
|
2774
|
+
};
|
|
2775
|
+
|
|
2776
|
+
/**
|
|
2777
|
+
* If true, displays min and max labels inline on both ends of the track.
|
|
2778
|
+
* @default false
|
|
2779
|
+
*/
|
|
2780
|
+
inlineLabels?: boolean;
|
|
2781
|
+
|
|
2782
|
+
/**
|
|
2783
|
+
* If true, icons will be displayed instead of numeric values when valueMapping is provided.
|
|
2784
|
+
* @default false
|
|
2785
|
+
*/
|
|
2786
|
+
useIcons?: boolean;
|
|
2787
|
+
|
|
2788
|
+
/**
|
|
2789
|
+
* Graphics/icons to display instead of numeric values.
|
|
2790
|
+
* Maps slider values to icon names or any string.
|
|
2791
|
+
*/
|
|
2792
|
+
valueMapping?: ValueMappingItem[];
|
|
2793
|
+
}
|
package/src/DateTimeField.tsx
CHANGED
|
@@ -336,6 +336,8 @@ export const DateTimeField: FC<DateTimeFieldProps> = ({
|
|
|
336
336
|
day: parseInt(dayVal),
|
|
337
337
|
hour: hourNum,
|
|
338
338
|
minute: parseInt(minuteVal),
|
|
339
|
+
second: 0,
|
|
340
|
+
millisecond: 0,
|
|
339
341
|
},
|
|
340
342
|
{
|
|
341
343
|
zone: override?.timezone ?? timezone,
|
|
@@ -350,6 +352,10 @@ export const DateTimeField: FC<DateTimeFieldProps> = ({
|
|
|
350
352
|
year: parseInt(yearVal),
|
|
351
353
|
month: parseInt(monthVal),
|
|
352
354
|
day: parseInt(dayVal),
|
|
355
|
+
hour: 0,
|
|
356
|
+
minute: 0,
|
|
357
|
+
second: 0,
|
|
358
|
+
millisecond: 0,
|
|
353
359
|
},
|
|
354
360
|
{
|
|
355
361
|
zone: "UTC",
|
|
@@ -369,6 +375,8 @@ export const DateTimeField: FC<DateTimeFieldProps> = ({
|
|
|
369
375
|
{
|
|
370
376
|
hour: hourNum,
|
|
371
377
|
minute: parseInt(minuteVal),
|
|
378
|
+
second: 0,
|
|
379
|
+
millisecond: 0,
|
|
372
380
|
},
|
|
373
381
|
{
|
|
374
382
|
zone: override?.timezone ?? timezone,
|
|
@@ -527,8 +535,13 @@ export const DateTimeField: FC<DateTimeFieldProps> = ({
|
|
|
527
535
|
// Normalize emitted value to ISO (UTC for date-only)
|
|
528
536
|
const normalized =
|
|
529
537
|
type === "date"
|
|
530
|
-
? parsedDate
|
|
531
|
-
|
|
538
|
+
? parsedDate
|
|
539
|
+
.setZone("UTC")
|
|
540
|
+
.startOf("day")
|
|
541
|
+
.set({second: 0, millisecond: 0})
|
|
542
|
+
.toUTC()
|
|
543
|
+
.toISO()
|
|
544
|
+
: parsedDate.set({second: 0, millisecond: 0}).toUTC().toISO();
|
|
532
545
|
if (!normalized) {
|
|
533
546
|
console.warn("Invalid date passed to DateTimeField", parsedDate);
|
|
534
547
|
return;
|
package/src/Heading.tsx
CHANGED
|
@@ -14,6 +14,7 @@ const fontSizeAndWeightWeb = {
|
|
|
14
14
|
md: {size: 18, weight: "bold"},
|
|
15
15
|
lg: {size: 24, weight: "bold"},
|
|
16
16
|
xl: {size: 32, weight: "bold"},
|
|
17
|
+
"2xl": {size: 48, weight: "bold"},
|
|
17
18
|
};
|
|
18
19
|
|
|
19
20
|
const fontSizeAndWeighMobile = {
|
|
@@ -21,6 +22,7 @@ const fontSizeAndWeighMobile = {
|
|
|
21
22
|
md: {size: 16, weight: "bold"},
|
|
22
23
|
lg: {size: 20, weight: "bold"},
|
|
23
24
|
xl: {size: 28, weight: "bold"},
|
|
25
|
+
"2xl": {size: 32, weight: "bold"},
|
|
24
26
|
};
|
|
25
27
|
|
|
26
28
|
const fontSizes = Platform.OS === "web" ? fontSizeAndWeightWeb : fontSizeAndWeighMobile;
|
package/src/InfoModalIcon.tsx
CHANGED
|
@@ -30,6 +30,7 @@ export const InfoModalIcon: FC<InfoModalIconProps> = ({
|
|
|
30
30
|
aria-role="button"
|
|
31
31
|
hitSlop={{top: 10, bottom: 10, left: 10, right: 10}}
|
|
32
32
|
style={{marginLeft: 8}}
|
|
33
|
+
testID="info-icon"
|
|
33
34
|
onPress={() => setInfoModalVisibleState(true)}
|
|
34
35
|
>
|
|
35
36
|
<Heading color="secondaryLight" size="sm">
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Nunito_400Regular,
|
|
3
|
+
Nunito_500Medium,
|
|
4
|
+
Nunito_700Bold,
|
|
5
|
+
useFonts as useTextFonts,
|
|
6
|
+
} from "@expo-google-fonts/nunito";
|
|
7
|
+
import {
|
|
8
|
+
TitilliumWeb_600SemiBold,
|
|
9
|
+
TitilliumWeb_700Bold,
|
|
10
|
+
useFonts as useHeadingFonts,
|
|
11
|
+
} from "@expo-google-fonts/titillium-web";
|
|
12
|
+
import React from "react";
|
|
13
|
+
import {Platform} from "react-native";
|
|
14
|
+
import Markdown from "react-native-markdown-display";
|
|
15
|
+
|
|
16
|
+
import {useTheme} from "./Theme";
|
|
17
|
+
|
|
18
|
+
// Takes markdown and renders it with our theme. We should open source this component.
|
|
19
|
+
export const MarkdownView: React.FC<{children: React.ReactNode; inverted?: boolean}> = ({
|
|
20
|
+
children,
|
|
21
|
+
inverted,
|
|
22
|
+
}) => {
|
|
23
|
+
const {theme} = useTheme();
|
|
24
|
+
|
|
25
|
+
const color = {color: inverted ? theme.text.inverted : theme.text.primary};
|
|
26
|
+
|
|
27
|
+
// Match Heading font sizes to Heading component
|
|
28
|
+
// Web sizes (see src/Heading.tsx): sm:16, md:18, lg:24, xl:32
|
|
29
|
+
// Mobile sizes: sm:14, md:16, lg:20, xl:28
|
|
30
|
+
const isWeb = Platform.OS === "web";
|
|
31
|
+
const sizes = {
|
|
32
|
+
sm: isWeb ? 16 : 14,
|
|
33
|
+
md: isWeb ? 18 : 16,
|
|
34
|
+
lg: isWeb ? 24 : 20,
|
|
35
|
+
xl: isWeb ? 32 : 28,
|
|
36
|
+
} as const;
|
|
37
|
+
|
|
38
|
+
// Load fonts similar to Heading/Text components so fontFamily names resolve
|
|
39
|
+
useHeadingFonts({
|
|
40
|
+
heading: TitilliumWeb_600SemiBold,
|
|
41
|
+
"heading-bold": TitilliumWeb_700Bold,
|
|
42
|
+
"heading-semibold": TitilliumWeb_600SemiBold,
|
|
43
|
+
});
|
|
44
|
+
useTextFonts({
|
|
45
|
+
text: Nunito_400Regular,
|
|
46
|
+
"text-regular": Nunito_400Regular,
|
|
47
|
+
"text-medium": Nunito_500Medium,
|
|
48
|
+
"text-bold": Nunito_700Bold,
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<Markdown
|
|
53
|
+
style={{
|
|
54
|
+
body: {fontFamily: "text", ...color},
|
|
55
|
+
heading1: {fontFamily: "heading-bold", fontSize: sizes.xl, ...color},
|
|
56
|
+
heading2: {fontFamily: "heading-bold", fontSize: sizes.lg, ...color},
|
|
57
|
+
heading3: {fontFamily: "heading-bold", fontSize: sizes.md, ...color},
|
|
58
|
+
heading4: {fontFamily: "heading-semibold", fontSize: sizes.sm, ...color},
|
|
59
|
+
// h5/h6 map to small as well for consistency, slightly smaller visually handled by weight
|
|
60
|
+
heading5: {fontFamily: "heading-semibold", fontSize: sizes.sm, ...color},
|
|
61
|
+
heading6: {fontFamily: "heading-semibold", fontSize: sizes.sm, ...color},
|
|
62
|
+
}}
|
|
63
|
+
>
|
|
64
|
+
{children}
|
|
65
|
+
</Markdown>
|
|
66
|
+
);
|
|
67
|
+
};
|
package/src/Slider.tsx
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import SliderComponent from "@react-native-community/slider";
|
|
2
|
+
import React, {FC} from "react";
|
|
3
|
+
import {View} from "react-native";
|
|
4
|
+
|
|
5
|
+
import {Box} from "./Box";
|
|
6
|
+
import {IconName, SliderProps, ValueMappingItem} from "./Common";
|
|
7
|
+
import {FieldError} from "./fieldElements/FieldError";
|
|
8
|
+
import {FieldHelperText} from "./fieldElements/FieldHelperText";
|
|
9
|
+
import {FieldTitle} from "./fieldElements/FieldTitle";
|
|
10
|
+
import {Icon} from "./Icon";
|
|
11
|
+
import {Text} from "./Text";
|
|
12
|
+
import {useTheme} from "./Theme";
|
|
13
|
+
|
|
14
|
+
// Find the closest option for the current value
|
|
15
|
+
const getCurrentMapping = (map: ValueMappingItem[], value: number) => {
|
|
16
|
+
if (!map || map.length === 0) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Find the option with the closest value
|
|
21
|
+
let closestOption = map[0];
|
|
22
|
+
let closestDistance = Math.abs(value - closestOption.value);
|
|
23
|
+
|
|
24
|
+
for (const option of map) {
|
|
25
|
+
const distance = Math.abs(value - option.value);
|
|
26
|
+
if (distance < closestDistance) {
|
|
27
|
+
closestDistance = distance;
|
|
28
|
+
closestOption = option;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return closestOption;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const getCenterContent = (
|
|
36
|
+
valueMapping: ValueMappingItem[] | undefined,
|
|
37
|
+
value: number,
|
|
38
|
+
step: number,
|
|
39
|
+
disabled: boolean,
|
|
40
|
+
useIcons: boolean
|
|
41
|
+
): React.ReactElement => {
|
|
42
|
+
if (!valueMapping || valueMapping.length === 0) {
|
|
43
|
+
const formattedValue = value.toFixed(
|
|
44
|
+
step > 0 && step < 1 ? String(step).split(".")[1]?.length || 0 : 0
|
|
45
|
+
);
|
|
46
|
+
return (
|
|
47
|
+
<Text align="center" color={disabled ? "secondaryLight" : "primary"} size="lg">
|
|
48
|
+
{formattedValue}
|
|
49
|
+
</Text>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const currentOption = getCurrentMapping(valueMapping, value);
|
|
54
|
+
|
|
55
|
+
if (useIcons) {
|
|
56
|
+
return (
|
|
57
|
+
<Icon
|
|
58
|
+
color={disabled ? "secondaryLight" : "primary"}
|
|
59
|
+
iconName={currentOption!.label as IconName}
|
|
60
|
+
size={currentOption!.size || "md"}
|
|
61
|
+
/>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return (
|
|
66
|
+
<Text align="center" color={disabled ? "secondaryLight" : "primary"} size="2xl">
|
|
67
|
+
{currentOption?.label}
|
|
68
|
+
</Text>
|
|
69
|
+
);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const getSliderContent = (
|
|
73
|
+
slider: React.ReactElement,
|
|
74
|
+
inlineLabels: boolean,
|
|
75
|
+
labels?: SliderProps['labels']
|
|
76
|
+
): React.ReactElement => {
|
|
77
|
+
if (inlineLabels && labels?.min && labels?.max) {
|
|
78
|
+
return (
|
|
79
|
+
<Box alignItems="center" direction="row" gap={2}>
|
|
80
|
+
<Box flex="shrink" minWidth={30}>
|
|
81
|
+
<Text color="secondaryDark" size="md">
|
|
82
|
+
{labels.min}
|
|
83
|
+
</Text>
|
|
84
|
+
</Box>
|
|
85
|
+
<Box flex="grow">{slider}</Box>
|
|
86
|
+
<Box alignItems="end" flex="shrink" minWidth={30}>
|
|
87
|
+
<Text color="secondaryDark" size="md">
|
|
88
|
+
{labels.max}
|
|
89
|
+
</Text>
|
|
90
|
+
</Box>
|
|
91
|
+
</Box>
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return (
|
|
96
|
+
<>
|
|
97
|
+
{slider}
|
|
98
|
+
{labels && (
|
|
99
|
+
<Box direction="row" justifyContent="between" marginTop={2}>
|
|
100
|
+
{labels.min && (
|
|
101
|
+
<Text color="secondaryDark" size="sm">
|
|
102
|
+
{labels.min}
|
|
103
|
+
</Text>
|
|
104
|
+
)}
|
|
105
|
+
{labels.custom?.map((customLabel, index) => (
|
|
106
|
+
<Text key={index} color="secondaryDark" size="sm">
|
|
107
|
+
{customLabel.label}
|
|
108
|
+
</Text>
|
|
109
|
+
))}
|
|
110
|
+
{labels.max && (
|
|
111
|
+
<Text color="secondaryDark" size="sm">
|
|
112
|
+
{labels.max}
|
|
113
|
+
</Text>
|
|
114
|
+
)}
|
|
115
|
+
</Box>
|
|
116
|
+
)}
|
|
117
|
+
</>
|
|
118
|
+
);
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
export const Slider: FC<SliderProps> = ({
|
|
122
|
+
disabled = false,
|
|
123
|
+
errorText,
|
|
124
|
+
helperText,
|
|
125
|
+
inlineLabels = false,
|
|
126
|
+
labels,
|
|
127
|
+
maximumTrackTintColor,
|
|
128
|
+
maximumValue = 1,
|
|
129
|
+
minimumTrackTintColor,
|
|
130
|
+
minimumValue = 0,
|
|
131
|
+
step = 0,
|
|
132
|
+
thumbTintColor,
|
|
133
|
+
title,
|
|
134
|
+
showSelection = false,
|
|
135
|
+
useIcons = false,
|
|
136
|
+
value,
|
|
137
|
+
valueMapping,
|
|
138
|
+
onChange,
|
|
139
|
+
}) => {
|
|
140
|
+
const {theme} = useTheme();
|
|
141
|
+
|
|
142
|
+
if (!theme) {
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const minTrackColor = minimumTrackTintColor || theme.surface.primary;
|
|
147
|
+
const maxTrackColor = maximumTrackTintColor || theme.border.default;
|
|
148
|
+
const thumbColor = thumbTintColor || theme.surface.primary;
|
|
149
|
+
|
|
150
|
+
const sliderStyles = {
|
|
151
|
+
trackStyle: {
|
|
152
|
+
height: 10,
|
|
153
|
+
},
|
|
154
|
+
thumbStyle: {
|
|
155
|
+
width: 48,
|
|
156
|
+
height: 48,
|
|
157
|
+
backgroundColor: 'white',
|
|
158
|
+
borderRadius: 24,
|
|
159
|
+
shadowColor: '#000',
|
|
160
|
+
shadowOffset: {
|
|
161
|
+
width: 0,
|
|
162
|
+
height: 2,
|
|
163
|
+
},
|
|
164
|
+
shadowOpacity: 0.25,
|
|
165
|
+
shadowRadius: 3.84,
|
|
166
|
+
elevation: 5,
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
const sliderElement = (
|
|
171
|
+
<SliderComponent
|
|
172
|
+
disabled={disabled}
|
|
173
|
+
maximumTrackTintColor={maxTrackColor}
|
|
174
|
+
maximumValue={maximumValue}
|
|
175
|
+
minimumTrackTintColor={minTrackColor}
|
|
176
|
+
minimumValue={minimumValue}
|
|
177
|
+
step={step}
|
|
178
|
+
thumbTintColor={thumbColor}
|
|
179
|
+
value={value}
|
|
180
|
+
onValueChange={onChange}
|
|
181
|
+
{...sliderStyles}
|
|
182
|
+
/>
|
|
183
|
+
);
|
|
184
|
+
|
|
185
|
+
const centerContent = getCenterContent(valueMapping, value, step, disabled, useIcons);
|
|
186
|
+
const sliderContent = getSliderContent(sliderElement, inlineLabels, labels);
|
|
187
|
+
|
|
188
|
+
return (
|
|
189
|
+
<Box>
|
|
190
|
+
{Boolean(title) && <FieldTitle text={title!} />}
|
|
191
|
+
<Box direction="column" gap={showSelection ? 2 : 0}>
|
|
192
|
+
{showSelection && (
|
|
193
|
+
<Box alignItems="center">
|
|
194
|
+
{centerContent}
|
|
195
|
+
</Box>
|
|
196
|
+
)}
|
|
197
|
+
{sliderContent}
|
|
198
|
+
</Box>
|
|
199
|
+
{Boolean(helperText && !errorText) && <FieldHelperText text={helperText!} />}
|
|
200
|
+
{Boolean(errorText) && <FieldError text={errorText!} />}
|
|
201
|
+
</Box>
|
|
202
|
+
);
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
|
package/src/Text.tsx
CHANGED
|
@@ -19,6 +19,7 @@ const fontSizeAndWeightWeb = {
|
|
|
19
19
|
md: {size: 16, weight: "regular"},
|
|
20
20
|
lg: {size: 18, weight: "medium"},
|
|
21
21
|
xl: {size: 20, weight: "medium"},
|
|
22
|
+
"2xl": {size: 48, weight: "medium"},
|
|
22
23
|
};
|
|
23
24
|
|
|
24
25
|
const fontSizeAndWeighMobile = {
|
|
@@ -26,6 +27,7 @@ const fontSizeAndWeighMobile = {
|
|
|
26
27
|
md: {size: 14, weight: "regular"},
|
|
27
28
|
lg: {size: 16, weight: "medium"},
|
|
28
29
|
xl: {size: 18, weight: "medium"},
|
|
30
|
+
"2xl": {size: 40, weight: "medium"},
|
|
29
31
|
};
|
|
30
32
|
|
|
31
33
|
const fontSizes = Platform.OS === "web" ? fontSizeAndWeightWeb : fontSizeAndWeighMobile;
|