@korsolutions/ui 0.0.2 → 0.0.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@korsolutions/ui",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "license": "MIT",
5
5
  "main": ".src/index.ts",
6
6
  "types": ".src/index.ts",
package/src/index.ts CHANGED
@@ -4,3 +4,4 @@ export * from "./primitives/field";
4
4
  export * from "./primitives/input";
5
5
  export * from "./primitives/button";
6
6
  export * from "./primitives/select";
7
+ export * from "./primitives/card";
@@ -0,0 +1,21 @@
1
+ import React from "react";
2
+ import { StyleProp, View, ViewStyle } from "react-native";
3
+ import { useCard } from "./context";
4
+ import { calculateComposedStyles } from "../../utils/calculate-styles";
5
+
6
+ export interface CardContentProps {
7
+ children?: React.ReactNode;
8
+
9
+ render?: (props: CardContentProps) => React.ReactNode;
10
+
11
+ style?: StyleProp<ViewStyle>;
12
+ }
13
+
14
+ export function CardContent(props: CardContentProps) {
15
+ const card = useCard();
16
+
17
+ const composedStyle = calculateComposedStyles(card.styles, card.state, "content", props.style);
18
+
19
+ const Component = props.render ?? View;
20
+ return <Component {...props} style={composedStyle} />;
21
+ }
@@ -0,0 +1,21 @@
1
+ import React from "react";
2
+ import { StyleProp, View, ViewStyle } from "react-native";
3
+ import { useCard } from "./context";
4
+ import { calculateComposedStyles } from "../../utils/calculate-styles";
5
+
6
+ export interface CardFooterProps {
7
+ children?: React.ReactNode;
8
+
9
+ render?: (props: CardFooterProps) => React.ReactNode;
10
+
11
+ style?: StyleProp<ViewStyle>;
12
+ }
13
+
14
+ export function CardFooter(props: CardFooterProps) {
15
+ const card = useCard();
16
+
17
+ const composedStyle = calculateComposedStyles(card.styles, card.state, "footer", props.style);
18
+
19
+ const Component = props.render ?? View;
20
+ return <Component {...props} style={composedStyle} />;
21
+ }
@@ -0,0 +1,21 @@
1
+ import React from "react";
2
+ import { StyleProp, View, ViewStyle } from "react-native";
3
+ import { useCard } from "./context";
4
+ import { calculateComposedStyles } from "../../utils/calculate-styles";
5
+
6
+ export interface CardHeaderProps {
7
+ children?: React.ReactNode;
8
+
9
+ render?: (props: CardHeaderProps) => React.ReactNode;
10
+
11
+ style?: StyleProp<ViewStyle>;
12
+ }
13
+
14
+ export function CardHeader(props: CardHeaderProps) {
15
+ const card = useCard();
16
+
17
+ const composedStyle = calculateComposedStyles(card.styles, card.state, "header", props.style);
18
+
19
+ const Component = props.render ?? View;
20
+ return <Component {...props} style={composedStyle} />;
21
+ }
@@ -0,0 +1,30 @@
1
+ import React from "react";
2
+ import { StyleProp, View, ViewStyle } from "react-native";
3
+ import { CardStyles } from "./types";
4
+ import { calculateComposedStyles } from "../../utils/calculate-styles";
5
+ import { CardContext } from "./context";
6
+
7
+ export interface CardRootProps {
8
+ children?: React.ReactNode;
9
+
10
+ render?: (props: CardRootProps) => React.ReactNode;
11
+
12
+ style?: StyleProp<ViewStyle>;
13
+ styles?: CardStyles;
14
+ }
15
+
16
+ export function CardRoot(props: CardRootProps) {
17
+ const composedStyle = calculateComposedStyles(props.styles, "default", "root", props.style);
18
+
19
+ const Component = props.render ?? View;
20
+ return (
21
+ <CardContext.Provider
22
+ value={{
23
+ state: "default",
24
+ styles: props.styles,
25
+ }}
26
+ >
27
+ <Component {...props} style={composedStyle} />
28
+ </CardContext.Provider>
29
+ );
30
+ }
@@ -0,0 +1,21 @@
1
+ import React from "react";
2
+ import { StyleProp, Text, TextStyle } from "react-native";
3
+ import { useCard } from "./context";
4
+ import { calculateComposedStyles } from "../../utils/calculate-styles";
5
+
6
+ export interface CardTitleProps {
7
+ children?: string;
8
+
9
+ render?: (props: CardTitleProps) => React.ReactNode;
10
+
11
+ style?: StyleProp<TextStyle>;
12
+ }
13
+
14
+ export function CardTitle(props: CardTitleProps) {
15
+ const card = useCard();
16
+
17
+ const composedStyle = calculateComposedStyles(card.styles, card.state, "title", props.style);
18
+
19
+ const Component = props.render ?? Text;
20
+ return <Component {...props} style={composedStyle} />;
21
+ }
@@ -0,0 +1,17 @@
1
+ import { createContext, useContext } from "react";
2
+ import { CardState, CardStyles } from "./types";
3
+
4
+ export interface CardContext {
5
+ state: CardState;
6
+ styles?: CardStyles;
7
+ }
8
+
9
+ export const CardContext = createContext<CardContext | undefined>(undefined);
10
+
11
+ export const useCard = () => {
12
+ const context = useContext(CardContext);
13
+ if (!context) {
14
+ throw new Error("useCard must be used within a CardProvider");
15
+ }
16
+ return context;
17
+ };
@@ -0,0 +1,20 @@
1
+ import { CardRoot } from "./card-root";
2
+ import { CardHeader } from "./card-header";
3
+ import { CardTitle } from "./card-title";
4
+ import { CardContent } from "./card-content";
5
+ import { CardFooter } from "./card-footer";
6
+
7
+ export const Card = {
8
+ Root: CardRoot,
9
+ Header: CardHeader,
10
+ Title: CardTitle,
11
+ Content: CardContent,
12
+ Footer: CardFooter,
13
+ };
14
+
15
+ export type { CardRootProps } from "./card-root";
16
+ export type { CardHeaderProps } from "./card-header";
17
+ export type { CardTitleProps } from "./card-title";
18
+ export type { CardContentProps } from "./card-content";
19
+ export type { CardFooterProps } from "./card-footer";
20
+ export type { CardStyles } from "./types";
@@ -0,0 +1,15 @@
1
+ import { CardRootProps } from "./card-root";
2
+ import { CardHeaderProps } from "./card-header";
3
+ import { CardTitleProps } from "./card-title";
4
+ import { CardContentProps } from "./card-content";
5
+ import { CardFooterProps } from "./card-footer";
6
+
7
+ export type CardState = "default";
8
+
9
+ export interface CardStyles {
10
+ root?: Partial<Record<CardState, CardRootProps["style"]>>;
11
+ header?: Partial<Record<CardState, CardHeaderProps["style"]>>;
12
+ title?: Partial<Record<CardState, CardTitleProps["style"]>>;
13
+ content?: Partial<Record<CardState, CardContentProps["style"]>>;
14
+ footer?: Partial<Record<CardState, CardFooterProps["style"]>>;
15
+ }
@@ -1,9 +1,9 @@
1
1
  import { createContext, useContext } from "react";
2
2
  import { FieldState, FieldStyles } from "./types";
3
3
 
4
- export interface FieldContext {
4
+ export interface FieldContext<TControlStyles = unknown> {
5
5
  value: string | null;
6
- onChange?: (value: string) => void;
6
+ onChange: (value: string) => void;
7
7
 
8
8
  focused: boolean;
9
9
  setFocused: React.Dispatch<React.SetStateAction<boolean>>;
@@ -16,15 +16,15 @@ export interface FieldContext {
16
16
  error?: string | null;
17
17
 
18
18
  state: FieldState;
19
- styles?: FieldStyles<unknown>;
19
+ styles?: FieldStyles<TControlStyles>;
20
20
  }
21
21
 
22
22
  export const FieldContext = createContext<FieldContext | undefined>(undefined);
23
23
 
24
- export const useField = () => {
24
+ export const useField = <TControlStyles = unknown>() => {
25
25
  const context = useContext(FieldContext);
26
26
  if (!context) {
27
27
  throw new Error("useField must be used within a FieldProvider");
28
28
  }
29
- return context;
29
+ return context as FieldContext<TControlStyles>;
30
30
  };
@@ -1,28 +1,29 @@
1
1
  import React from "react";
2
2
  import { useField } from "./context";
3
- import { StyleProp, TextStyle } from "react-native";
4
- import { calculateComposedStyles } from "../../utils/calculate-styles";
3
+ import { FieldRootProps } from "./field-root";
5
4
 
6
- interface FieldControlInjectedProps<Style> {
7
- value?: string;
8
- onChange?: (value: string) => void;
5
+ interface FieldControlInjectedProps<TControlStyles> {
6
+ value: FieldRootProps["value"];
7
+ onChange: FieldRootProps["onChange"];
9
8
 
10
9
  onFocus?: () => void;
11
10
  onBlur?: () => void;
12
11
 
13
- style?: StyleProp<Style>;
12
+ styles?: TControlStyles;
14
13
  }
15
14
 
16
- export interface FieldControlProps<Style = TextStyle> {
17
- style?: StyleProp<Style>;
18
- render: (props: FieldControlInjectedProps<Style>) => React.ReactElement;
19
- }
15
+ export type FieldControlProps<T> = {
16
+ render: (props: FieldControlInjectedProps<T>) => React.ReactElement;
17
+ };
20
18
 
21
- export function FieldControl<Style = TextStyle>(props: FieldControlProps<Style>) {
22
- const { value, onChange, setFocused, ...field } = useField();
19
+ export function FieldControl<T>(props: FieldControlProps<T>) {
20
+ const { value, onChange, setFocused, state, styles } = useField<T>();
23
21
 
24
- const calculatedStyle = calculateComposedStyles(field.styles, field.state, "control", props.style) as StyleProp<Style>;
22
+ const controlStyles = styles?.control;
23
+ const composedStyles = controlStyles ? { ...controlStyles.default, ...controlStyles[state] } : undefined;
25
24
 
26
25
  const Component = props.render;
27
- return <Component value={value} onChange={onChange} onBlur={() => setFocused(false)} onFocus={() => setFocused(true)} style={calculatedStyle} />;
26
+ return (
27
+ <Component value={value} onChange={onChange} onBlur={() => setFocused(false)} onFocus={() => setFocused(true)} styles={composedStyles as T} />
28
+ );
28
29
  }
@@ -3,9 +3,9 @@ import { Pressable, StyleProp, View, ViewStyle } from "react-native";
3
3
  import { FieldContext } from "./context";
4
4
  import { FieldState, FieldStyles } from "./types";
5
5
 
6
- export interface FieldRootProps {
7
- value?: string | null;
8
- onChange?: (value: string) => void;
6
+ export interface FieldRootProps<TControlStyles = unknown> {
7
+ value: string | null;
8
+ onChange: (value: string) => void;
9
9
 
10
10
  required?: boolean;
11
11
  disabled?: boolean;
@@ -13,7 +13,7 @@ export interface FieldRootProps {
13
13
  children?: React.ReactNode;
14
14
  style?: StyleProp<ViewStyle>;
15
15
 
16
- styles?: FieldStyles<unknown>;
16
+ styles?: FieldStyles<TControlStyles>;
17
17
  }
18
18
 
19
19
  const calculateState = (props: FieldRootProps, focused: boolean, hovered: boolean): FieldState => {
@@ -33,7 +33,7 @@ const calculateState = (props: FieldRootProps, focused: boolean, hovered: boolea
33
33
  return "default";
34
34
  };
35
35
 
36
- export function FieldRoot(props: FieldRootProps) {
36
+ export function FieldRoot<TControlStyles = unknown>(props: FieldRootProps<TControlStyles>) {
37
37
  const [focused, setFocused] = useState(false);
38
38
  const [hovered, setHovered] = useState(false);
39
39
 
@@ -44,7 +44,7 @@ export function FieldRoot(props: FieldRootProps) {
44
44
  return (
45
45
  <FieldContext.Provider
46
46
  value={{
47
- value: props.value ?? null,
47
+ value: props.value,
48
48
  onChange: props.onChange,
49
49
 
50
50
  focused,
@@ -3,8 +3,8 @@ import { FieldRootProps } from "./field-root";
3
3
 
4
4
  export type FieldState = "default" | "disabled" | "error" | "focused" | "hovered";
5
5
 
6
- export interface FieldStyles<TControlStyle> {
6
+ export interface FieldStyles<TControlStyles = unknown> {
7
7
  root?: Partial<Record<FieldState, FieldRootProps["style"]>>;
8
8
  label?: Partial<Record<FieldState, FieldLabelProps["style"]>>;
9
- control?: Partial<Record<FieldState, TControlStyle>>;
9
+ control?: Partial<Record<FieldState, TControlStyles>>;
10
10
  }
@@ -1 +1,2 @@
1
1
  export * from "./input";
2
+ export { InputStyles } from "./types";
@@ -1,16 +1,20 @@
1
- import { TextInput, TextInputProps } from "react-native";
1
+ import { StyleProp, TextInput, TextInputProps, TextStyle } from "react-native";
2
+ import { InputStyles } from "./types";
3
+ import { calculateComposedStyles } from "../../utils/calculate-styles";
2
4
 
3
5
  export interface InputProps {
4
6
  defaultValue?: TextInputProps["defaultValue"];
5
- value?: TextInputProps["value"];
6
- onChange?: TextInputProps["onChangeText"];
7
+ value: string | null;
8
+ onChange: (value: string) => void;
7
9
 
8
10
  onFocus?: TextInputProps["onFocus"];
9
11
  onBlur?: TextInputProps["onBlur"];
10
12
 
11
- style?: TextInputProps["style"];
13
+ style?: StyleProp<TextStyle>;
14
+ styles?: InputStyles;
12
15
  }
13
16
 
14
17
  export function Input(props: InputProps) {
15
- return <TextInput {...props} onChange={undefined} onChangeText={props.onChange} />;
18
+ const composedStyles = calculateComposedStyles(props.styles, "default", "root", props.style);
19
+ return <TextInput {...props} value={props.value ?? ""} onChange={undefined} onChangeText={props.onChange} style={composedStyles} />;
16
20
  }
@@ -0,0 +1,7 @@
1
+ import { InputProps } from "./input";
2
+
3
+ export type InputState = "default" | "focused" | "disabled";
4
+
5
+ export interface InputStyles {
6
+ root: Partial<Record<InputState, InputProps["style"]>>;
7
+ }
@@ -4,16 +4,20 @@ import { SelectContext } from "./context";
4
4
  import { SelectOption, SelectState, SelectStyles } from "./types";
5
5
  import { calculateComposedStyles } from "../../utils/calculate-styles";
6
6
 
7
+ interface SelectRootInjectedProps {
8
+ style?: StyleProp<ViewStyle>;
9
+ }
10
+
7
11
  export interface SelectRootProps {
8
12
  children?: React.ReactNode;
9
13
 
10
- value?: string;
11
- onChange?: (value: string) => void;
14
+ value: string | null;
15
+ onChange: (value: string) => void;
12
16
  placeholder?: string;
13
17
 
14
18
  disabled?: boolean;
15
19
 
16
- render?: (props: SelectRootProps) => React.ReactElement;
20
+ render?: (props: SelectRootInjectedProps) => React.ReactElement;
17
21
 
18
22
  styles?: SelectStyles;
19
23
  style?: StyleProp<ViewStyle>;