@korsolutions/ui 0.0.3 → 0.0.5
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/components/index.d.mts +84 -0
- package/dist/components/index.mjs +288 -0
- package/dist/index-Dafk8ZGv.d.mts +265 -0
- package/dist/index.d.mts +45 -0
- package/dist/index.mjs +11 -0
- package/dist/portal-DoPaAohb.mjs +61 -0
- package/dist/primitives/index.d.mts +2 -0
- package/dist/primitives/index.mjs +4 -0
- package/dist/primitives-BYUlEz2_.mjs +442 -0
- package/dist/themes-BrLbh9h6.mjs +86 -0
- package/package.json +20 -8
- package/src/components/button/button.tsx +24 -0
- package/src/components/button/variants/default.tsx +52 -0
- package/src/components/button/variants/index.ts +5 -0
- package/src/components/card/card.tsx +26 -0
- package/src/components/card/variants/default.tsx +38 -0
- package/src/components/card/variants/index.ts +5 -0
- package/src/components/field/field.tsx +27 -0
- package/src/components/field/variants/default.tsx +29 -0
- package/src/components/field/variants/index.ts +5 -0
- package/src/components/index.ts +5 -0
- package/src/components/input/input.tsx +14 -0
- package/src/components/input/variants/default.tsx +34 -0
- package/src/components/input/variants/index.ts +5 -0
- package/src/components/select/select.tsx +35 -0
- package/src/components/select/variants/default.tsx +81 -0
- package/src/components/select/variants/index.ts +5 -0
- package/src/index.tsx +13 -0
- package/src/primitives/button/button-context.tsx +5 -5
- package/src/primitives/button/button-label.tsx +7 -5
- package/src/primitives/button/button-root.tsx +12 -8
- package/src/primitives/button/button-spinner.tsx +14 -0
- package/src/primitives/button/index.ts +5 -3
- package/src/primitives/button/types.ts +6 -5
- package/src/primitives/card/{card-content.tsx → card-body.tsx} +5 -5
- package/src/primitives/card/card-footer.tsx +1 -1
- package/src/primitives/card/card-header.tsx +1 -1
- package/src/primitives/card/card-root.tsx +1 -1
- package/src/primitives/card/card-title.tsx +1 -1
- package/src/primitives/card/index.ts +4 -4
- package/src/primitives/card/types.ts +2 -2
- package/src/primitives/field/context.ts +5 -19
- package/src/primitives/field/field-description.tsx +17 -0
- package/src/primitives/field/field-error.tsx +17 -0
- package/src/primitives/field/field-label.tsx +7 -3
- package/src/primitives/field/field-root.tsx +13 -59
- package/src/primitives/field/index.ts +9 -6
- package/src/primitives/field/types.ts +8 -7
- package/src/primitives/index.ts +5 -0
- package/src/primitives/input/index.ts +1 -1
- package/src/primitives/input/input.tsx +48 -13
- package/src/primitives/input/types.ts +2 -4
- package/src/primitives/select/context.ts +3 -3
- package/src/primitives/select/index.ts +2 -2
- package/src/primitives/select/select-content.tsx +2 -2
- package/src/primitives/select/select-option.tsx +27 -4
- package/src/primitives/select/select-overlay.tsx +1 -1
- package/src/primitives/select/select-root.tsx +13 -11
- package/src/primitives/select/select-trigger.tsx +3 -2
- package/src/primitives/select/select-value.tsx +4 -1
- package/src/primitives/select/types.ts +3 -1
- package/src/themes/default/colors.ts +45 -0
- package/src/themes/default/index.ts +11 -0
- package/src/themes/index.ts +2 -0
- package/src/themes/provider.tsx +56 -0
- package/src/themes/themes.ts +6 -0
- package/src/themes/types.ts +30 -0
- package/src/utils/hsla-utils.ts +10 -0
- package/src/utils/use-themed-styles.ts +13 -0
- package/tsconfig.json +8 -0
- package/tsdown.config.ts +8 -0
- package/src/index.ts +0 -7
- package/src/primitives/field/field-control.tsx +0 -29
- package/src/primitives/provider.tsx +0 -10
|
@@ -1,30 +1,16 @@
|
|
|
1
1
|
import { createContext, useContext } from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { FieldStyles } from "./types";
|
|
3
3
|
|
|
4
|
-
export interface FieldContext
|
|
5
|
-
|
|
6
|
-
onChange: (value: string) => void;
|
|
7
|
-
|
|
8
|
-
focused: boolean;
|
|
9
|
-
setFocused: React.Dispatch<React.SetStateAction<boolean>>;
|
|
10
|
-
|
|
11
|
-
hovered: boolean;
|
|
12
|
-
setHovered: React.Dispatch<React.SetStateAction<boolean>>;
|
|
13
|
-
|
|
14
|
-
disabled?: boolean;
|
|
15
|
-
required?: boolean;
|
|
16
|
-
error?: string | null;
|
|
17
|
-
|
|
18
|
-
state: FieldState;
|
|
19
|
-
styles?: FieldStyles<TControlStyles>;
|
|
4
|
+
export interface FieldContext {
|
|
5
|
+
styles?: FieldStyles;
|
|
20
6
|
}
|
|
21
7
|
|
|
22
8
|
export const FieldContext = createContext<FieldContext | undefined>(undefined);
|
|
23
9
|
|
|
24
|
-
export const useField =
|
|
10
|
+
export const useField = () => {
|
|
25
11
|
const context = useContext(FieldContext);
|
|
26
12
|
if (!context) {
|
|
27
13
|
throw new Error("useField must be used within a FieldProvider");
|
|
28
14
|
}
|
|
29
|
-
return context
|
|
15
|
+
return context;
|
|
30
16
|
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { StyleProp, Text, TextStyle } from "react-native";
|
|
3
|
+
import { useField } from "./context";
|
|
4
|
+
|
|
5
|
+
export interface FieldDescriptionProps {
|
|
6
|
+
children: string;
|
|
7
|
+
|
|
8
|
+
render?: (props: FieldDescriptionProps) => React.ReactNode;
|
|
9
|
+
|
|
10
|
+
style?: StyleProp<TextStyle>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function FieldDescription(props: FieldDescriptionProps) {
|
|
14
|
+
const field = useField();
|
|
15
|
+
const Component = props.render ?? Text;
|
|
16
|
+
return <Component {...props} style={[field.styles?.description, props.style]} />;
|
|
17
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { StyleProp, Text, TextStyle } from "react-native";
|
|
3
|
+
import { useField } from "./context";
|
|
4
|
+
|
|
5
|
+
export interface FieldErrorProps {
|
|
6
|
+
children: string;
|
|
7
|
+
|
|
8
|
+
render?: (props: FieldErrorProps) => React.ReactNode;
|
|
9
|
+
|
|
10
|
+
style?: StyleProp<TextStyle>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function FieldError(props: FieldErrorProps) {
|
|
14
|
+
const field = useField();
|
|
15
|
+
const Component = props.render ?? Text;
|
|
16
|
+
return <Component {...props} style={[field.styles?.error, props.style]} />;
|
|
17
|
+
}
|
|
@@ -4,13 +4,17 @@ import { Text, TextProps } from "react-native";
|
|
|
4
4
|
|
|
5
5
|
export interface FieldLabelProps {
|
|
6
6
|
children: string;
|
|
7
|
-
|
|
7
|
+
|
|
8
|
+
htmlFor?: string;
|
|
9
|
+
|
|
8
10
|
render?: (props: FieldLabelProps) => React.ReactNode;
|
|
11
|
+
|
|
12
|
+
style?: TextProps["style"];
|
|
9
13
|
}
|
|
10
14
|
|
|
11
15
|
export function FieldLabel(props: FieldLabelProps) {
|
|
12
16
|
const field = useField();
|
|
13
|
-
const calculatedStyle = [field.styles?.label?.default, field.styles?.label?.[field.state], props.style];
|
|
14
17
|
|
|
15
|
-
|
|
18
|
+
const Component = props.render ?? Text;
|
|
19
|
+
return <Component {...props} htmlFor={props.htmlFor} style={[field.styles?.label, props.style]} />;
|
|
16
20
|
}
|
|
@@ -1,69 +1,23 @@
|
|
|
1
|
-
import React
|
|
2
|
-
import {
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { StyleProp, View, ViewStyle } from "react-native";
|
|
3
3
|
import { FieldContext } from "./context";
|
|
4
|
-
import {
|
|
4
|
+
import { FieldStyles } from "./types";
|
|
5
5
|
|
|
6
|
-
export interface
|
|
7
|
-
value: string | null;
|
|
8
|
-
onChange: (value: string) => void;
|
|
9
|
-
|
|
10
|
-
required?: boolean;
|
|
11
|
-
disabled?: boolean;
|
|
12
|
-
error?: string | null;
|
|
6
|
+
export interface FieldPrimitiveRootProps {
|
|
13
7
|
children?: React.ReactNode;
|
|
14
|
-
style?: StyleProp<ViewStyle>;
|
|
15
|
-
|
|
16
|
-
styles?: FieldStyles<TControlStyles>;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const calculateState = (props: FieldRootProps, focused: boolean, hovered: boolean): FieldState => {
|
|
20
|
-
if (props.disabled) {
|
|
21
|
-
return "disabled";
|
|
22
|
-
}
|
|
23
|
-
if (props.error) {
|
|
24
|
-
return "error";
|
|
25
|
-
}
|
|
26
|
-
if (focused) {
|
|
27
|
-
return "focused";
|
|
28
|
-
}
|
|
29
|
-
if (hovered) {
|
|
30
|
-
return "hovered";
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return "default";
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
export function FieldRoot<TControlStyles = unknown>(props: FieldRootProps<TControlStyles>) {
|
|
37
|
-
const [focused, setFocused] = useState(false);
|
|
38
|
-
const [hovered, setHovered] = useState(false);
|
|
39
8
|
|
|
40
|
-
|
|
9
|
+
render?: (props: FieldPrimitiveRootProps) => React.ReactNode;
|
|
41
10
|
|
|
42
|
-
|
|
11
|
+
style?: StyleProp<ViewStyle>;
|
|
12
|
+
styles?: FieldStyles;
|
|
13
|
+
}
|
|
43
14
|
|
|
15
|
+
export function FieldRoot(props: FieldPrimitiveRootProps) {
|
|
16
|
+
const composedStyles = [props.styles?.root, props.style];
|
|
17
|
+
const Component = props.render ?? View;
|
|
44
18
|
return (
|
|
45
|
-
<FieldContext.Provider
|
|
46
|
-
|
|
47
|
-
value: props.value,
|
|
48
|
-
onChange: props.onChange,
|
|
49
|
-
|
|
50
|
-
focused,
|
|
51
|
-
setFocused,
|
|
52
|
-
|
|
53
|
-
hovered,
|
|
54
|
-
setHovered,
|
|
55
|
-
|
|
56
|
-
required: props.required,
|
|
57
|
-
disabled: props.disabled,
|
|
58
|
-
error: props.error ?? null,
|
|
59
|
-
|
|
60
|
-
state: state,
|
|
61
|
-
styles: props.styles,
|
|
62
|
-
}}
|
|
63
|
-
>
|
|
64
|
-
<Pressable onHoverIn={() => setHovered(true)} onHoverOut={() => setHovered(false)} style={calculatedStyle}>
|
|
65
|
-
{props.children}
|
|
66
|
-
</Pressable>
|
|
19
|
+
<FieldContext.Provider value={{ styles: props.styles }}>
|
|
20
|
+
<Component {...props} style={composedStyles} />
|
|
67
21
|
</FieldContext.Provider>
|
|
68
22
|
);
|
|
69
23
|
}
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import { FieldRoot } from "./field-root";
|
|
2
2
|
import { FieldLabel } from "./field-label";
|
|
3
|
-
import {
|
|
3
|
+
import { FieldDescription } from "./field-description";
|
|
4
|
+
import { FieldError } from "./field-error";
|
|
4
5
|
|
|
5
|
-
export const
|
|
6
|
+
export const FieldPrimitive = {
|
|
6
7
|
Root: FieldRoot,
|
|
7
8
|
Label: FieldLabel,
|
|
8
|
-
|
|
9
|
+
Description: FieldDescription,
|
|
10
|
+
Error: FieldError,
|
|
9
11
|
};
|
|
10
12
|
|
|
11
|
-
export type {
|
|
13
|
+
export type { FieldPrimitiveRootProps } from "./field-root";
|
|
12
14
|
export type { FieldLabelProps } from "./field-label";
|
|
13
|
-
export type {
|
|
14
|
-
export
|
|
15
|
+
export type { FieldDescriptionProps } from "./field-description";
|
|
16
|
+
export type { FieldErrorProps } from "./field-error";
|
|
17
|
+
export type { FieldStyles } from "./types";
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import { FieldPrimitiveRootProps } from "./field-root";
|
|
1
2
|
import { FieldLabelProps } from "./field-label";
|
|
2
|
-
import {
|
|
3
|
+
import { FieldDescriptionProps } from "./field-description";
|
|
4
|
+
import { FieldErrorProps } from "./field-error";
|
|
3
5
|
|
|
4
|
-
export
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
control?: Partial<Record<FieldState, TControlStyles>>;
|
|
6
|
+
export interface FieldStyles {
|
|
7
|
+
root?: FieldPrimitiveRootProps["style"];
|
|
8
|
+
label?: FieldLabelProps["style"];
|
|
9
|
+
description?: FieldDescriptionProps["style"];
|
|
10
|
+
error?: FieldErrorProps["style"];
|
|
10
11
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export * from "./input";
|
|
2
|
-
export { InputStyles } from "./types";
|
|
2
|
+
export type { InputStyles } from "./types";
|
|
@@ -1,20 +1,55 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { InputStyles } from "./types";
|
|
3
|
-
import {
|
|
1
|
+
import { TextInput, TextInputProps } from "react-native";
|
|
2
|
+
import { InputState, InputStyles } from "./types";
|
|
3
|
+
import { useState } from "react";
|
|
4
4
|
|
|
5
|
-
export
|
|
6
|
-
|
|
7
|
-
value: string | null;
|
|
8
|
-
onChange: (value: string) => void;
|
|
5
|
+
export type InputPrimitiveBaseProps = Omit<TextInputProps, "onChange"> & {
|
|
6
|
+
onChange?: TextInputProps["onChangeText"];
|
|
9
7
|
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
isDisabled?: boolean;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export interface InputPrimitiveProps extends InputPrimitiveBaseProps {
|
|
12
|
+
render?: (props: InputPrimitiveProps) => React.ReactNode;
|
|
12
13
|
|
|
13
|
-
style?: StyleProp<TextStyle>;
|
|
14
14
|
styles?: InputStyles;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
const calculateState = (props: InputPrimitiveProps, isFocused: boolean): InputState => {
|
|
18
|
+
if (props.isDisabled) {
|
|
19
|
+
return "disabled";
|
|
20
|
+
}
|
|
21
|
+
if (isFocused) {
|
|
22
|
+
return "focused";
|
|
23
|
+
}
|
|
24
|
+
return "default";
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export function InputPrimitive(props: InputPrimitiveProps) {
|
|
28
|
+
const [isFocused, setIsFocused] = useState(false);
|
|
29
|
+
const state = calculateState(props, isFocused);
|
|
30
|
+
|
|
31
|
+
const composedStyles = [props.styles?.default?.style, props.styles?.[state]?.style, props.style];
|
|
32
|
+
const composedProps = {
|
|
33
|
+
...props.styles?.default,
|
|
34
|
+
...props.styles?.[state],
|
|
35
|
+
...props,
|
|
36
|
+
};
|
|
37
|
+
const Component = props.render ?? TextInput;
|
|
38
|
+
return (
|
|
39
|
+
<Component
|
|
40
|
+
{...composedProps}
|
|
41
|
+
onChange={undefined}
|
|
42
|
+
onChangeText={props.onChange}
|
|
43
|
+
onFocus={(e) => {
|
|
44
|
+
setIsFocused(true);
|
|
45
|
+
props.onFocus?.(e);
|
|
46
|
+
}}
|
|
47
|
+
onBlur={(e) => {
|
|
48
|
+
setIsFocused(false);
|
|
49
|
+
props.onBlur?.(e);
|
|
50
|
+
}}
|
|
51
|
+
readOnly={props.isDisabled || props.readOnly}
|
|
52
|
+
style={composedStyles}
|
|
53
|
+
/>
|
|
54
|
+
);
|
|
20
55
|
}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { InputPrimitiveBaseProps } from "./input";
|
|
2
2
|
|
|
3
3
|
export type InputState = "default" | "focused" | "disabled";
|
|
4
4
|
|
|
5
|
-
export
|
|
6
|
-
root: Partial<Record<InputState, InputProps["style"]>>;
|
|
7
|
-
}
|
|
5
|
+
export type InputStyles = Partial<Record<InputState, InputPrimitiveBaseProps>>;
|
|
@@ -3,9 +3,9 @@ import { SelectOption, SelectState, SelectStyles } from "./types";
|
|
|
3
3
|
import { LayoutRectangle } from "react-native";
|
|
4
4
|
|
|
5
5
|
export interface SelectContext {
|
|
6
|
-
value
|
|
6
|
+
value?: string;
|
|
7
7
|
onChange?: (value: string) => void;
|
|
8
|
-
placeholder
|
|
8
|
+
placeholder?: string;
|
|
9
9
|
|
|
10
10
|
isOpen: boolean;
|
|
11
11
|
setIsOpen: Dispatch<React.SetStateAction<boolean>>;
|
|
@@ -14,7 +14,7 @@ export interface SelectContext {
|
|
|
14
14
|
options: Array<SelectOption>;
|
|
15
15
|
setOptions: Dispatch<React.SetStateAction<Array<SelectOption>>>;
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
isDisabled: boolean;
|
|
18
18
|
|
|
19
19
|
state: SelectState;
|
|
20
20
|
styles: SelectStyles | null;
|
|
@@ -6,7 +6,7 @@ import { SelectOverlay } from "./select-overlay";
|
|
|
6
6
|
import { SelectContent } from "./select-content";
|
|
7
7
|
import { SelectOption } from "./select-option";
|
|
8
8
|
|
|
9
|
-
export const
|
|
9
|
+
export const SelectPrimitive = {
|
|
10
10
|
Root: SelectRoot,
|
|
11
11
|
Trigger: SelectTrigger,
|
|
12
12
|
Value: SelectValue,
|
|
@@ -16,7 +16,7 @@ export const Select = {
|
|
|
16
16
|
Option: SelectOption,
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
export type { SelectRootProps } from "./select-root";
|
|
19
|
+
export type { SelectRootProps, SelectRootBaseProps } from "./select-root";
|
|
20
20
|
export type { SelectTriggerProps } from "./select-trigger";
|
|
21
21
|
export type { SelectValueProps } from "./select-value";
|
|
22
22
|
export type { SelectPortalProps } from "./select-portal";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from "react";
|
|
2
2
|
import { StyleProp, View, ViewStyle } from "react-native";
|
|
3
|
-
import { calculateComposedStyles } from "
|
|
3
|
+
import { calculateComposedStyles } from "@/utils/calculate-styles";
|
|
4
4
|
import { useSelect } from "./context";
|
|
5
5
|
|
|
6
6
|
export interface SelectContentProps {
|
|
@@ -1,20 +1,41 @@
|
|
|
1
1
|
import { StyleProp, Text, TextStyle } from "react-native";
|
|
2
|
-
import { calculateComposedStyles } from "
|
|
2
|
+
import { calculateComposedStyles } from "@/utils/calculate-styles";
|
|
3
3
|
import { useSelect } from "./context";
|
|
4
|
-
import { useEffect } from "react";
|
|
4
|
+
import { useEffect, useState } from "react";
|
|
5
|
+
import { SelectOptionState, SelectState } from "./types";
|
|
5
6
|
|
|
6
7
|
export interface SelectOptionProps {
|
|
7
8
|
children: string;
|
|
8
9
|
value: string;
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
onMouseEnter?: () => void;
|
|
12
|
+
onMouseLeave?: () => void;
|
|
11
13
|
|
|
12
14
|
render?: (props: SelectOptionProps) => React.ReactElement;
|
|
15
|
+
|
|
16
|
+
style?: StyleProp<TextStyle>;
|
|
13
17
|
}
|
|
14
18
|
|
|
19
|
+
const calculateState = (selectState: SelectState, hovered: boolean, selected: boolean): SelectOptionState => {
|
|
20
|
+
if (selectState === "disabled") {
|
|
21
|
+
return "disabled";
|
|
22
|
+
}
|
|
23
|
+
if (selected) {
|
|
24
|
+
return "selected";
|
|
25
|
+
}
|
|
26
|
+
if (hovered) {
|
|
27
|
+
return "hovered";
|
|
28
|
+
}
|
|
29
|
+
return "default";
|
|
30
|
+
};
|
|
31
|
+
|
|
15
32
|
export function SelectOption(props: SelectOptionProps) {
|
|
33
|
+
const [isHovered, setIsHovered] = useState(false);
|
|
16
34
|
const select = useSelect();
|
|
17
|
-
const
|
|
35
|
+
const isSelected = select.value === props.value;
|
|
36
|
+
|
|
37
|
+
const optionState = calculateState(select.state, isHovered, isSelected);
|
|
38
|
+
const composedStyles = calculateComposedStyles(select.styles, optionState, "option", props.style);
|
|
18
39
|
|
|
19
40
|
useEffect(() => {
|
|
20
41
|
select.setOptions((prev) => {
|
|
@@ -33,6 +54,8 @@ export function SelectOption(props: SelectOptionProps) {
|
|
|
33
54
|
select.onChange?.(props.value);
|
|
34
55
|
select.setIsOpen(false);
|
|
35
56
|
}}
|
|
57
|
+
onMouseEnter={() => setIsHovered(true)}
|
|
58
|
+
onMouseLeave={() => setIsHovered(false)}
|
|
36
59
|
style={composedStyles}
|
|
37
60
|
>
|
|
38
61
|
{props.children}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { useSelect } from "./context";
|
|
3
3
|
import { Pressable, StyleProp, StyleSheet, ViewStyle } from "react-native";
|
|
4
|
-
import { calculateComposedStyles } from "
|
|
4
|
+
import { calculateComposedStyles } from "@/utils/calculate-styles";
|
|
5
5
|
|
|
6
6
|
export interface SelectOverlayProps {
|
|
7
7
|
children?: React.ReactNode;
|
|
@@ -2,20 +2,22 @@ import React, { useState } from "react";
|
|
|
2
2
|
import { LayoutRectangle, StyleProp, View, ViewStyle } from "react-native";
|
|
3
3
|
import { SelectContext } from "./context";
|
|
4
4
|
import { SelectOption, SelectState, SelectStyles } from "./types";
|
|
5
|
-
import { calculateComposedStyles } from "
|
|
5
|
+
import { calculateComposedStyles } from "@/utils/calculate-styles";
|
|
6
6
|
|
|
7
7
|
interface SelectRootInjectedProps {
|
|
8
8
|
style?: StyleProp<ViewStyle>;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
export interface
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
value: string | null;
|
|
15
|
-
onChange: (value: string) => void;
|
|
11
|
+
export interface SelectRootBaseProps {
|
|
12
|
+
value?: string;
|
|
13
|
+
onChange?: (value: string) => void;
|
|
16
14
|
placeholder?: string;
|
|
17
15
|
|
|
18
|
-
|
|
16
|
+
isDisabled?: boolean;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface SelectRootProps extends SelectRootBaseProps {
|
|
20
|
+
children?: React.ReactNode;
|
|
19
21
|
|
|
20
22
|
render?: (props: SelectRootInjectedProps) => React.ReactElement;
|
|
21
23
|
|
|
@@ -24,7 +26,7 @@ export interface SelectRootProps {
|
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
const calculateState = (props: SelectRootProps): SelectState => {
|
|
27
|
-
if (props.
|
|
29
|
+
if (props.isDisabled) {
|
|
28
30
|
return "disabled";
|
|
29
31
|
}
|
|
30
32
|
return "default";
|
|
@@ -42,9 +44,9 @@ export function SelectRoot(props: SelectRootProps) {
|
|
|
42
44
|
return (
|
|
43
45
|
<SelectContext.Provider
|
|
44
46
|
value={{
|
|
45
|
-
value: props.value
|
|
47
|
+
value: props.value,
|
|
46
48
|
onChange: props.onChange,
|
|
47
|
-
placeholder: props.placeholder
|
|
49
|
+
placeholder: props.placeholder,
|
|
48
50
|
isOpen,
|
|
49
51
|
setIsOpen,
|
|
50
52
|
triggerLayout,
|
|
@@ -52,7 +54,7 @@ export function SelectRoot(props: SelectRootProps) {
|
|
|
52
54
|
options,
|
|
53
55
|
setOptions,
|
|
54
56
|
state,
|
|
55
|
-
|
|
57
|
+
isDisabled: props.isDisabled ?? false,
|
|
56
58
|
styles: props.styles ?? null,
|
|
57
59
|
}}
|
|
58
60
|
>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { Pressable, StyleProp, ViewStyle } from "react-native";
|
|
3
3
|
import { useSelect } from "./context";
|
|
4
|
-
import { calculateComposedStyles } from "
|
|
5
|
-
import { normalizeLayout } from "
|
|
4
|
+
import { calculateComposedStyles } from "@/utils/calculate-styles";
|
|
5
|
+
import { normalizeLayout } from "@/utils/normalize-layout";
|
|
6
6
|
|
|
7
7
|
interface SelectTriggerInjectionProps {
|
|
8
8
|
onPress?: () => void;
|
|
@@ -29,6 +29,7 @@ export function SelectTrigger(props: SelectTriggerProps) {
|
|
|
29
29
|
const layout = normalizeLayout(e.nativeEvent.layout);
|
|
30
30
|
select.setTriggerLayout(layout);
|
|
31
31
|
}}
|
|
32
|
+
disabled={select.isDisabled}
|
|
32
33
|
style={composedStyles}
|
|
33
34
|
>
|
|
34
35
|
{props.children}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { StyleProp, Text, TextStyle } from "react-native";
|
|
3
3
|
import { useSelect } from "./context";
|
|
4
|
+
import { calculateComposedStyles } from "@/utils/calculate-styles";
|
|
4
5
|
|
|
5
6
|
export interface SelectValueProps {
|
|
6
7
|
style?: StyleProp<TextStyle>;
|
|
@@ -12,7 +13,9 @@ export function SelectValue(props: SelectValueProps) {
|
|
|
12
13
|
const select = useSelect();
|
|
13
14
|
|
|
14
15
|
const selectedOption = select.options.find((option) => option.value === select.value);
|
|
16
|
+
const selectedOptionLabel = selectedOption?.label;
|
|
15
17
|
|
|
18
|
+
const composedStyles = calculateComposedStyles(select.styles, select.state, selectedOptionLabel ? "value" : "placeholder", props.style);
|
|
16
19
|
const Component = props.render ?? Text;
|
|
17
|
-
return <Component style={
|
|
20
|
+
return <Component style={composedStyles}>{selectedOption?.label ?? select.placeholder}</Component>;
|
|
18
21
|
}
|
|
@@ -6,14 +6,16 @@ import { SelectContentProps } from "./select-content";
|
|
|
6
6
|
import { SelectOptionProps } from "./select-option";
|
|
7
7
|
|
|
8
8
|
export type SelectState = "default" | "disabled";
|
|
9
|
+
export type SelectOptionState = SelectState | "hovered" | "selected";
|
|
9
10
|
|
|
10
11
|
export interface SelectStyles {
|
|
11
12
|
root?: Partial<Record<SelectState, SelectRootProps["style"]>>;
|
|
12
13
|
trigger?: Partial<Record<SelectState, SelectTriggerProps["style"]>>;
|
|
13
14
|
value?: Partial<Record<SelectState, SelectValueProps["style"]>>;
|
|
15
|
+
placeholder?: Partial<Record<SelectState, SelectValueProps["style"]>>;
|
|
14
16
|
overlay?: Partial<Record<SelectState, SelectOverlayProps["style"]>>;
|
|
15
17
|
content?: Partial<Record<SelectState, SelectContentProps["style"]>>;
|
|
16
|
-
option?: Partial<Record<
|
|
18
|
+
option?: Partial<Record<SelectOptionState, SelectOptionProps["style"]>>;
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
export interface SelectOption {
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Colors } from "../types";
|
|
2
|
+
|
|
3
|
+
export const lightColors: Colors = {
|
|
4
|
+
background: "hsla(223.81, 100%, 100%, 1)",
|
|
5
|
+
foreground: "hsla(223.81, 0%, 3.94%, 1)",
|
|
6
|
+
|
|
7
|
+
primary: "hsla(223.81, 0%, 9.05%, 1)",
|
|
8
|
+
primaryForeground: "hsla(223.81, 0%, 98.03%, 1)",
|
|
9
|
+
|
|
10
|
+
secondary: "hsla(223.81, 0%, 96.06%, 1)",
|
|
11
|
+
secondaryForeground: "hsla(223.81, 0%, 9.05%, 1)",
|
|
12
|
+
|
|
13
|
+
muted: "hsla(223.81, 0%, 96.06%, 1)",
|
|
14
|
+
mutedForeground: "hsla(223.81, 0%, 45.15%, 1)",
|
|
15
|
+
|
|
16
|
+
border: "hsla(223.81, 0%, 89.82%, 1)",
|
|
17
|
+
surface: "hsla(223.81, 100%, 100%, 1)",
|
|
18
|
+
|
|
19
|
+
danger: "hsla(0, 84.2%, 60.2%, 1)",
|
|
20
|
+
success: "hsla(173, 58%, 39%, 1)",
|
|
21
|
+
warning: "hsla(43, 74%, 66%, 1)",
|
|
22
|
+
info: "hsla(197, 37%, 24%, 1)",
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const darkColors: Colors = {
|
|
26
|
+
background: "hsla(223.81, 0%, 3.94%, 1)",
|
|
27
|
+
foreground: "hsla(223.81, 0%, 98.03%, 1)",
|
|
28
|
+
|
|
29
|
+
primary: "hsla(223.81, 0%, 89.82%, 1)",
|
|
30
|
+
primaryForeground: "hsla(223.81, 0%, 9.05%, 1)",
|
|
31
|
+
|
|
32
|
+
secondary: "hsla(223.81, 0%, 14.94%, 1)",
|
|
33
|
+
secondaryForeground: "hsla(223.81, 0%, 98.03%, 1)",
|
|
34
|
+
|
|
35
|
+
muted: "hsla(223.81, 0%, 14.94%, 1)",
|
|
36
|
+
mutedForeground: "hsla(223.81, 0%, 63.02%, 1)",
|
|
37
|
+
|
|
38
|
+
border: "hsla(223.81, 0%, 15.51%, 1)",
|
|
39
|
+
surface: "hsla(223.81, 0%, 9.05%, 1)",
|
|
40
|
+
|
|
41
|
+
danger: "hsla(0, 62.8%, 30.6%, 1)",
|
|
42
|
+
success: "hsla(160, 60%, 45%, 1)",
|
|
43
|
+
warning: "hsla(30, 80%, 55%, 1)",
|
|
44
|
+
info: "hsla(220, 70%, 50%, 1)",
|
|
45
|
+
};
|