@sibipro/sprinkles-native 0.1.8 → 0.1.17

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,9 +1,13 @@
1
1
  {
2
2
  "name": "@sibipro/sprinkles-native",
3
- "version": "0.1.8",
3
+ "version": "0.1.17",
4
4
  "description": "React Native UI component library with Tailwind theming",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/sibipro/sprinkles-react-native.git"
10
+ },
7
11
  "packageManager": "pnpm@10.6.2",
8
12
  "main": "dist/index.js",
9
13
  "types": "dist/index.d.ts",
package/README.md DELETED
@@ -1,101 +0,0 @@
1
- # @sibipro/sprinkles-native
2
-
3
- A React Native component library with Tailwind-style theming via [Uniwind](https://github.com/nickshanks347/uniwind).
4
-
5
- ## Install
6
-
7
- ```bash
8
- pnpm add @sibipro/sprinkles-native
9
- ```
10
-
11
- Peer dependencies: `react >= 18`, `react-native >= 0.74`, and optionally `uniwind >= 1.0.0`.
12
-
13
- ## Components
14
-
15
- ### Layout & Containers
16
-
17
- - **Card** — `variant: "default" | "outline"`
18
- - **Banner** — `variant: "info" | "warn" | "danger" | "success"`
19
- - **Separator** — horizontal or vertical divider
20
- - **EmptyState** — centered placeholder with title, description, icon, and action slot
21
-
22
- ### Text & Typography
23
-
24
- - **Text** — `variant: "body" | "caption" | "label" | "heading"`, `size: "xs" | "sm" | "md" | "lg" | "xl" | "2xl"`, `weight: "normal" | "medium" | "semibold" | "bold"`
25
-
26
- ### Form Controls
27
-
28
- - **Input** — `variant: "default" | "search" | "ghost"`, `girth: "sm" | "md" | "lg"`
29
- - **InputWithExtras** — Input with leading/trailing adornments
30
- - **InputWithLabel** — Input with an attached label
31
- - **Checkbox** — custom checkbox with label and disabled state
32
- - **Switch** — toggle with `checked` / `onCheckedChange`
33
- - **Label** — semantic label wrapper
34
-
35
- ### Buttons & Actions
36
-
37
- - **Button** — `variant: "primary" | "secondary" | "tertiary" | "tertiary-brand" | "tertiary-danger" | "danger" | "ghost" | "link"`, `size: "sm" | "md" | "lg"`
38
- - **Chip** — dismissible chip with optional `onDismiss`
39
-
40
- ### Data Display
41
-
42
- - **Badge** — `variant: "default" | "brand" | "danger" | "success" | "warn" | "info" | "outline"`
43
- - **Avatar** — auto-generates initials from `name`, `size: "sm" | "md" | "lg" | "xl"`
44
- - **ProgressBar** — `value` / `max` progress indicator
45
- - **Skeleton** — animated loading placeholder
46
-
47
- ## Usage
48
-
49
- ```tsx
50
- import { Button, Card, Text, Badge } from "@sibipro/sprinkles-native"
51
-
52
- const Example = () => (
53
- <Card variant="outline">
54
- <Text variant="heading" size="lg">Order #1234</Text>
55
- <Badge variant="success">Delivered</Badge>
56
- <Button variant="primary" size="md" onPress={() => {}}>
57
- View Details
58
- </Button>
59
- </Card>
60
- )
61
- ```
62
-
63
- All components accept a `className` prop for Tailwind-style overrides (requires Uniwind):
64
-
65
- ```tsx
66
- <Button className="mt-4 w-full" variant="primary">Submit</Button>
67
- ```
68
-
69
- ## Theming
70
-
71
- Import the global stylesheet in your app entry:
72
-
73
- ```tsx
74
- import "@sibipro/sprinkles-native/styles.css"
75
- ```
76
-
77
- This provides color tokens, font definitions, and light/dark mode support via CSS custom properties.
78
-
79
- ### Color Palettes
80
-
81
- | Palette | Usage |
82
- |-----------|--------------------------------|
83
- | Neutral | Backgrounds, borders, text |
84
- | Purple | Brand / primary actions |
85
- | Emerald | Success states |
86
- | Amber | Warnings |
87
- | Blue | Informational |
88
- | Magenta | Danger / destructive actions |
89
-
90
- ## Development
91
-
92
- ```bash
93
- pnpm install
94
- pnpm build # compile TypeScript to dist/
95
- pnpm test # type-check with tsc --noEmit
96
- pnpm release # bump patch, tag, and push
97
- ```
98
-
99
- ### Kitchen Sink
100
-
101
- An Expo app lives in `kitchen-sink/` for previewing components during development.
@@ -1,58 +0,0 @@
1
- import React from 'react';
2
- import { View, type ViewProps } from 'react-native';
3
- import { cn } from '../utils/cn';
4
- import { Text } from './Text';
5
-
6
- export type AvatarSize = 'sm' | 'md' | 'lg' | 'xl';
7
-
8
- const sizeClasses: Record<AvatarSize, string> = {
9
- sm: 'h-8 w-8',
10
- md: 'h-10 w-10',
11
- lg: 'h-12 w-12',
12
- xl: 'h-16 w-16',
13
- };
14
-
15
- const textSizeClasses: Record<AvatarSize, string> = {
16
- sm: 'text-xs',
17
- md: 'text-sm',
18
- lg: 'text-base',
19
- xl: 'text-xl',
20
- };
21
-
22
- function getInitials(name: string): string {
23
- const parts = name.trim().split(/\s+/);
24
- if (parts.length === 1) return parts[0][0]?.toUpperCase() ?? '';
25
- return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
26
- }
27
-
28
- export interface AvatarProps extends ViewProps {
29
- name: string;
30
- size?: AvatarSize;
31
- className?: string;
32
- }
33
-
34
- export function Avatar({
35
- name,
36
- size = 'md',
37
- className,
38
- ...props
39
- }: AvatarProps) {
40
- const initials = getInitials(name);
41
-
42
- return (
43
- <View
44
- className={cn(
45
- 'rounded-full bg-brand-100 items-center justify-center',
46
- sizeClasses[size],
47
- className,
48
- )}
49
- accessibilityRole="image"
50
- accessibilityLabel={name}
51
- {...props}
52
- >
53
- <Text weight="semibold" className={cn('text-brand-700', textSizeClasses[size])}>
54
- {initials}
55
- </Text>
56
- </View>
57
- );
58
- }
@@ -1,70 +0,0 @@
1
- import React from 'react';
2
- import { View, type ViewProps } from 'react-native';
3
- import { cn } from '../utils/cn';
4
- import { Text } from './Text';
5
-
6
- export type BadgeVariant =
7
- | 'default'
8
- | 'brand'
9
- | 'danger'
10
- | 'success'
11
- | 'warn'
12
- | 'info'
13
- | 'outline';
14
-
15
- const variantClasses: Record<BadgeVariant, string> = {
16
- default: 'bg-background-tertiary',
17
- brand: 'bg-brand-50 dark:bg-brand-900',
18
- danger: 'bg-danger-50 dark:bg-danger-900',
19
- success: 'bg-success-50 dark:bg-success-900',
20
- warn: 'bg-warn-50 dark:bg-warn-900',
21
- info: 'bg-info-50 dark:bg-info-900',
22
- outline: 'border border-border',
23
- };
24
-
25
- const textClasses: Record<BadgeVariant, string> = {
26
- default: 'text-foreground',
27
- brand: 'text-brand-700',
28
- danger: 'text-danger-700',
29
- success: 'text-success-700',
30
- warn: 'text-warn-700',
31
- info: 'text-info-700',
32
- outline: 'text-foreground',
33
- };
34
-
35
- export interface BadgeProps extends ViewProps {
36
- variant?: BadgeVariant;
37
- className?: string;
38
- children: React.ReactNode;
39
- }
40
-
41
- export function Badge({
42
- variant = 'default',
43
- className,
44
- children,
45
- ...props
46
- }: BadgeProps) {
47
- return (
48
- <View
49
- className={cn(
50
- 'rounded-lg py-1.5 px-2.5 flex-row items-center gap-1.5',
51
- variantClasses[variant],
52
- className,
53
- )}
54
- {...props}
55
- >
56
- {typeof children === 'string' ? (
57
- <Text
58
- size="xs"
59
- weight="semibold"
60
- className={textClasses[variant]}
61
- numberOfLines={1}
62
- >
63
- {children}
64
- </Text>
65
- ) : (
66
- children
67
- )}
68
- </View>
69
- );
70
- }
@@ -1,34 +0,0 @@
1
- import React from 'react';
2
- import { View, type ViewProps } from 'react-native';
3
- import { cn } from '../utils/cn';
4
-
5
- export type BannerVariant = 'info' | 'warn' | 'danger' | 'success';
6
-
7
- const variantClasses: Record<BannerVariant, string> = {
8
- info: 'bg-info-50 dark:bg-info-900',
9
- warn: 'bg-warn-50 dark:bg-warn-900',
10
- danger: 'bg-danger-50 dark:bg-danger-900',
11
- success: 'bg-success-50 dark:bg-success-900',
12
- };
13
-
14
- export interface BannerProps extends ViewProps {
15
- variant?: BannerVariant;
16
- className?: string;
17
- }
18
-
19
- export function Banner({
20
- variant = 'info',
21
- className,
22
- ...props
23
- }: BannerProps) {
24
- return (
25
- <View
26
- className={cn(
27
- 'rounded-2xl p-4 flex-row items-start gap-2.5',
28
- variantClasses[variant],
29
- className,
30
- )}
31
- {...props}
32
- />
33
- );
34
- }
@@ -1,96 +0,0 @@
1
- import React from 'react';
2
- import { Pressable, type PressableProps } from 'react-native';
3
- import { cn } from '../utils/cn';
4
- import { Text } from './Text';
5
-
6
- export type ButtonVariant =
7
- | 'primary'
8
- | 'secondary'
9
- | 'tertiary'
10
- | 'tertiary-brand'
11
- | 'tertiary-danger'
12
- | 'danger'
13
- | 'ghost'
14
- | 'link';
15
-
16
- export type ButtonSize = 'sm' | 'md' | 'lg';
17
-
18
- const variantClasses: Record<ButtonVariant, string> = {
19
- primary: 'bg-button-primary',
20
- secondary: 'bg-button-secondary border border-border',
21
- tertiary: 'bg-transparent',
22
- 'tertiary-brand': 'bg-transparent',
23
- 'tertiary-danger': 'bg-transparent',
24
- danger: 'bg-danger-500',
25
- ghost: 'bg-transparent',
26
- link: 'bg-transparent',
27
- };
28
-
29
- const pressedClasses: Record<ButtonVariant, string> = {
30
- primary: 'bg-button-primary-hover',
31
- secondary: 'bg-button-secondary-hover',
32
- tertiary: 'bg-button-tertiary-hover',
33
- 'tertiary-brand': 'bg-brand-25',
34
- 'tertiary-danger': 'bg-danger-25',
35
- danger: 'bg-danger-600',
36
- ghost: 'bg-accent',
37
- link: 'opacity-70',
38
- };
39
-
40
- const textClasses: Record<ButtonVariant, string> = {
41
- primary: 'text-button-primary-foreground',
42
- secondary: 'text-button-secondary-foreground',
43
- tertiary: 'text-button-tertiary-foreground',
44
- 'tertiary-brand': 'text-brand-500',
45
- 'tertiary-danger': 'text-danger-500',
46
- danger: 'text-white',
47
- ghost: 'text-foreground',
48
- link: 'text-brand-500 underline',
49
- };
50
-
51
- const sizeClasses: Record<ButtonSize, string> = {
52
- sm: 'h-8 px-3',
53
- md: 'h-10 px-4',
54
- lg: 'h-12 px-5',
55
- };
56
-
57
- export interface ButtonProps extends Omit<PressableProps, 'children'> {
58
- variant?: ButtonVariant;
59
- size?: ButtonSize;
60
- className?: string;
61
- children: React.ReactNode;
62
- }
63
-
64
- export function Button({
65
- variant = 'secondary',
66
- size = 'md',
67
- className,
68
- disabled,
69
- children,
70
- ...props
71
- }: ButtonProps) {
72
- return (
73
- <Pressable
74
- className={({ pressed }) =>
75
- cn(
76
- 'rounded-lg flex-row items-center justify-center gap-2',
77
- variantClasses[variant],
78
- sizeClasses[size],
79
- pressed && pressedClasses[variant],
80
- disabled && 'opacity-50',
81
- className,
82
- )
83
- }
84
- disabled={disabled}
85
- {...props}
86
- >
87
- {typeof children === 'string' ? (
88
- <Text size="sm" weight="bold" className={textClasses[variant]}>
89
- {children}
90
- </Text>
91
- ) : (
92
- children
93
- )}
94
- </Pressable>
95
- );
96
- }
@@ -1,28 +0,0 @@
1
- import React from 'react';
2
- import { View, type ViewProps } from 'react-native';
3
- import { cn } from '../utils/cn';
4
-
5
- export type CardVariant = 'default' | 'outline';
6
-
7
- const variantClasses: Record<CardVariant, string> = {
8
- default: 'bg-background shadow-md',
9
- outline: 'bg-background border border-border',
10
- };
11
-
12
- export interface CardProps extends ViewProps {
13
- variant?: CardVariant;
14
- className?: string;
15
- }
16
-
17
- export function Card({
18
- variant = 'default',
19
- className,
20
- ...props
21
- }: CardProps) {
22
- return (
23
- <View
24
- className={cn('rounded-xl p-4', variantClasses[variant], className)}
25
- {...props}
26
- />
27
- );
28
- }
@@ -1,43 +0,0 @@
1
- import React from 'react';
2
- import { Pressable, View } from 'react-native';
3
- import { cn } from '../utils/cn';
4
- import { Text } from './Text';
5
-
6
- export interface CheckboxProps {
7
- checked?: boolean;
8
- onCheckedChange?: (checked: boolean) => void;
9
- disabled?: boolean;
10
- label?: string;
11
- className?: string;
12
- }
13
-
14
- export function Checkbox({
15
- checked = false,
16
- onCheckedChange,
17
- disabled,
18
- label,
19
- className,
20
- }: CheckboxProps) {
21
- return (
22
- <Pressable
23
- onPress={() => !disabled && onCheckedChange?.(!checked)}
24
- className={cn('flex-row items-center gap-2', disabled && 'opacity-50', className)}
25
- accessibilityRole="checkbox"
26
- accessibilityState={{ checked, disabled }}
27
- >
28
- <View
29
- className={cn(
30
- 'h-5 w-5 rounded border items-center justify-center',
31
- checked
32
- ? 'bg-brand-500 border-brand-500'
33
- : 'bg-background border-border',
34
- )}
35
- >
36
- {checked && (
37
- <Text className="text-white text-xs">✓</Text>
38
- )}
39
- </View>
40
- {label && <Text className="text-foreground">{label}</Text>}
41
- </Pressable>
42
- );
43
- }
@@ -1,38 +0,0 @@
1
- import React from 'react';
2
- import { View, Pressable, type ViewProps } from 'react-native';
3
- import { cn } from '../utils/cn';
4
- import { Text } from './Text';
5
-
6
- export interface ChipProps extends ViewProps {
7
- label: string;
8
- onDismiss?: () => void;
9
- className?: string;
10
- }
11
-
12
- export function Chip({ label, onDismiss, className, ...props }: ChipProps) {
13
- return (
14
- <View
15
- className={cn(
16
- 'h-7 rounded-full bg-background-tertiary px-2.5 flex-row items-center gap-1',
17
- className,
18
- )}
19
- {...props}
20
- >
21
- <Text size="sm" className="text-foreground">
22
- {label}
23
- </Text>
24
- {onDismiss && (
25
- <Pressable
26
- onPress={onDismiss}
27
- className="ml-0.5"
28
- accessibilityRole="button"
29
- accessibilityLabel={`Remove ${label}`}
30
- >
31
- <Text size="sm" className="text-foreground-label">
32
-
33
- </Text>
34
- </Pressable>
35
- )}
36
- </View>
37
- );
38
- }
@@ -1,41 +0,0 @@
1
- import React from 'react';
2
- import { View, type ViewProps } from 'react-native';
3
- import { cn } from '../utils/cn';
4
- import { Text } from './Text';
5
-
6
- export interface EmptyStateProps extends ViewProps {
7
- title: string;
8
- description?: string;
9
- icon?: React.ReactNode;
10
- action?: React.ReactNode;
11
- className?: string;
12
- }
13
-
14
- export function EmptyState({
15
- title,
16
- description,
17
- icon,
18
- action,
19
- className,
20
- ...props
21
- }: EmptyStateProps) {
22
- return (
23
- <View
24
- className={cn('items-center py-12 px-4 gap-3', className)}
25
- {...props}
26
- >
27
- {icon}
28
- <View className="items-center gap-1">
29
- <Text variant="heading" className="text-2xl text-center">
30
- {title}
31
- </Text>
32
- {description && (
33
- <Text className="text-lg text-foreground text-center">
34
- {description}
35
- </Text>
36
- )}
37
- </View>
38
- {action}
39
- </View>
40
- );
41
- }
@@ -1,123 +0,0 @@
1
- import React, { useRef } from 'react';
2
- import {
3
- TextInput,
4
- View,
5
- Pressable,
6
- type TextInputProps,
7
- type ViewProps,
8
- } from 'react-native';
9
- import { cn } from '../utils/cn';
10
- import { Text } from './Text';
11
-
12
- export type InputVariant = 'default' | 'search' | 'ghost';
13
- export type InputGirth = 'sm' | 'md' | 'lg';
14
-
15
- const variantClasses: Record<InputVariant, string> = {
16
- default: 'border border-border bg-background',
17
- search: 'border-0 bg-background-secondary',
18
- ghost: 'border-0 bg-transparent',
19
- };
20
-
21
- const girthClasses: Record<InputGirth, string> = {
22
- sm: 'h-8',
23
- md: 'h-10',
24
- lg: 'min-h-[48px] py-3',
25
- };
26
-
27
- export interface InputProps extends TextInputProps {
28
- variant?: InputVariant;
29
- girth?: InputGirth;
30
- error?: boolean;
31
- className?: string;
32
- }
33
-
34
- export const Input = React.forwardRef<TextInput, InputProps>(
35
- ({ variant = 'default', girth = 'md', error, className, ...props }, ref) => {
36
- return (
37
- <TextInput
38
- ref={ref}
39
- className={cn(
40
- 'w-full rounded-xl px-4 text-base text-foreground',
41
- variantClasses[variant],
42
- girthClasses[girth],
43
- error && 'border-2 border-danger-500',
44
- props.editable === false && 'opacity-60',
45
- className,
46
- )}
47
- {...props}
48
- />
49
- );
50
- },
51
- );
52
-
53
- export interface InputWithExtrasProps extends InputProps {
54
- before?: React.ReactNode;
55
- after?: React.ReactNode;
56
- containerClassName?: string;
57
- }
58
-
59
- export const InputWithExtras = React.forwardRef<TextInput, InputWithExtrasProps>(
60
- ({ before, after, containerClassName, variant = 'default', girth = 'md', error, className, ...props }, ref) => {
61
- const innerRef = useRef<TextInput>(null);
62
- const inputRef = (ref as React.RefObject<TextInput>) ?? innerRef;
63
-
64
- return (
65
- <Pressable onPress={() => inputRef.current?.focus()}>
66
- <View
67
- className={cn(
68
- 'flex-row items-center gap-1',
69
- variantClasses[variant],
70
- girthClasses[girth],
71
- 'rounded-xl px-4',
72
- error && 'border-2 border-danger-500',
73
- containerClassName,
74
- )}
75
- >
76
- {before}
77
- <Input
78
- ref={inputRef}
79
- variant="ghost"
80
- girth={girth}
81
- className={cn('flex-1 h-full px-0', className)}
82
- {...props}
83
- />
84
- {after}
85
- </View>
86
- </Pressable>
87
- );
88
- },
89
- );
90
-
91
- export interface InputWithLabelProps extends InputProps {
92
- label?: string;
93
- description?: string;
94
- errorMessage?: string;
95
- containerClassName?: string;
96
- }
97
-
98
- export const InputWithLabel = React.forwardRef<TextInput, InputWithLabelProps>(
99
- ({ label, description, errorMessage, containerClassName, error, ...props }, ref) => {
100
- const hasError = error || !!errorMessage;
101
-
102
- return (
103
- <View className={cn('gap-1 w-full', containerClassName)}>
104
- {label && (
105
- <Text size="sm" weight="semibold" className="text-foreground">
106
- {label}
107
- </Text>
108
- )}
109
- <Input ref={ref} error={hasError} {...props} />
110
- {description && !errorMessage && (
111
- <Text size="xs" className="text-foreground-label">
112
- {description}
113
- </Text>
114
- )}
115
- {errorMessage && (
116
- <Text size="xs" weight="semibold" className="text-danger-700">
117
- {errorMessage}
118
- </Text>
119
- )}
120
- </View>
121
- );
122
- },
123
- );
@@ -1,16 +0,0 @@
1
- import React from 'react';
2
- import { Text as RNText, type TextProps } from 'react-native';
3
- import { cn } from '../utils/cn';
4
-
5
- export interface LabelProps extends TextProps {
6
- className?: string;
7
- }
8
-
9
- export function Label({ className, ...props }: LabelProps) {
10
- return (
11
- <RNText
12
- className={cn('text-sm font-semibold text-foreground', className)}
13
- {...props}
14
- />
15
- );
16
- }
@@ -1,32 +0,0 @@
1
- import React from 'react';
2
- import { View, type ViewProps } from 'react-native';
3
- import { cn } from '../utils/cn';
4
-
5
- export interface ProgressBarProps extends ViewProps {
6
- value: number;
7
- max?: number;
8
- className?: string;
9
- }
10
-
11
- export function ProgressBar({
12
- value,
13
- max = 100,
14
- className,
15
- ...props
16
- }: ProgressBarProps) {
17
- const percentage = Math.min(100, Math.max(0, (value / max) * 100));
18
-
19
- return (
20
- <View
21
- className={cn('h-2 w-full rounded-full bg-background-tertiary', className)}
22
- accessibilityRole="progressbar"
23
- accessibilityValue={{ min: 0, max, now: value }}
24
- {...props}
25
- >
26
- <View
27
- className="h-full rounded-full bg-brand-500"
28
- style={{ width: `${percentage}%` }}
29
- />
30
- </View>
31
- );
32
- }
@@ -1,25 +0,0 @@
1
- import React from 'react';
2
- import { View, type ViewProps } from 'react-native';
3
- import { cn } from '../utils/cn';
4
-
5
- export interface SeparatorProps extends ViewProps {
6
- orientation?: 'horizontal' | 'vertical';
7
- className?: string;
8
- }
9
-
10
- export function Separator({
11
- orientation = 'horizontal',
12
- className,
13
- ...props
14
- }: SeparatorProps) {
15
- return (
16
- <View
17
- className={cn(
18
- 'bg-border',
19
- orientation === 'horizontal' ? 'h-px w-full' : 'w-px h-full',
20
- className,
21
- )}
22
- {...props}
23
- />
24
- );
25
- }
@@ -1,38 +0,0 @@
1
- import React, { useEffect, useRef } from 'react';
2
- import { Animated, View, type ViewProps } from 'react-native';
3
- import { cn } from '../utils/cn';
4
-
5
- export interface SkeletonProps extends ViewProps {
6
- className?: string;
7
- }
8
-
9
- export function Skeleton({ className, style, ...props }: SkeletonProps) {
10
- const opacity = useRef(new Animated.Value(1)).current;
11
-
12
- useEffect(() => {
13
- const animation = Animated.loop(
14
- Animated.sequence([
15
- Animated.timing(opacity, {
16
- toValue: 0.5,
17
- duration: 1000,
18
- useNativeDriver: true,
19
- }),
20
- Animated.timing(opacity, {
21
- toValue: 1,
22
- duration: 1000,
23
- useNativeDriver: true,
24
- }),
25
- ]),
26
- );
27
- animation.start();
28
- return () => animation.stop();
29
- }, [opacity]);
30
-
31
- return (
32
- <Animated.View
33
- className={cn('rounded-md bg-background-tertiary', className)}
34
- style={[{ opacity }, style]}
35
- {...props}
36
- />
37
- );
38
- }
@@ -1,32 +0,0 @@
1
- import React from 'react';
2
- import {
3
- Switch as RNSwitch,
4
- type SwitchProps as RNSwitchProps,
5
- } from 'react-native';
6
- import { palettes } from '../theming/color-palettes';
7
-
8
- export interface SwitchProps extends RNSwitchProps {
9
- checked?: boolean;
10
- onCheckedChange?: (value: boolean) => void;
11
- }
12
-
13
- export function Switch({
14
- checked,
15
- onCheckedChange,
16
- value,
17
- onValueChange,
18
- ...props
19
- }: SwitchProps) {
20
- return (
21
- <RNSwitch
22
- value={checked ?? value}
23
- onValueChange={onCheckedChange ?? onValueChange}
24
- trackColor={{
25
- false: palettes.neutral[300],
26
- true: palettes.purple[500],
27
- }}
28
- thumbColor={palettes.white}
29
- {...props}
30
- />
31
- );
32
- }
@@ -1,57 +0,0 @@
1
- import React from 'react';
2
- import { Text as RNText, type TextProps as RNTextProps } from 'react-native';
3
- import { cn } from '../utils/cn';
4
-
5
- export type TextVariant = 'body' | 'caption' | 'label' | 'heading';
6
- export type TextSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl';
7
- export type TextWeight = 'normal' | 'medium' | 'semibold' | 'bold';
8
-
9
- const variantClasses: Record<TextVariant, string> = {
10
- body: 'text-base text-foreground',
11
- caption: 'text-xs text-foreground-label',
12
- label: 'text-sm text-foreground-label',
13
- heading: 'text-lg font-bold text-foreground-heading',
14
- };
15
-
16
- const sizeClasses: Record<TextSize, string> = {
17
- xs: 'text-xs',
18
- sm: 'text-sm',
19
- md: 'text-base',
20
- lg: 'text-lg',
21
- xl: 'text-xl',
22
- '2xl': 'text-2xl',
23
- };
24
-
25
- const weightClasses: Record<TextWeight, string> = {
26
- normal: 'font-normal',
27
- medium: 'font-medium',
28
- semibold: 'font-semibold',
29
- bold: 'font-bold',
30
- };
31
-
32
- export interface TextProps extends RNTextProps {
33
- variant?: TextVariant;
34
- size?: TextSize;
35
- weight?: TextWeight;
36
- className?: string;
37
- }
38
-
39
- export function Text({
40
- variant = 'body',
41
- size,
42
- weight,
43
- className,
44
- ...props
45
- }: TextProps) {
46
- return (
47
- <RNText
48
- className={cn(
49
- variantClasses[variant],
50
- size && sizeClasses[size],
51
- weight && weightClasses[weight],
52
- className,
53
- )}
54
- {...props}
55
- />
56
- );
57
- }
package/src/index.ts DELETED
@@ -1,52 +0,0 @@
1
- // Components
2
- export { Text } from './components/Text';
3
- export type { TextProps, TextVariant, TextSize, TextWeight } from './components/Text';
4
-
5
- export { Badge } from './components/Badge';
6
- export type { BadgeProps, BadgeVariant } from './components/Badge';
7
-
8
- export { Button } from './components/Button';
9
- export type { ButtonProps, ButtonVariant, ButtonSize } from './components/Button';
10
-
11
- export { Input, InputWithExtras, InputWithLabel } from './components/Input';
12
- export type { InputProps, InputWithExtrasProps, InputWithLabelProps, InputVariant, InputGirth } from './components/Input';
13
-
14
- export { Card } from './components/Card';
15
- export type { CardProps, CardVariant } from './components/Card';
16
-
17
- export { Banner } from './components/Banner';
18
- export type { BannerProps, BannerVariant } from './components/Banner';
19
-
20
- export { Separator } from './components/Separator';
21
- export type { SeparatorProps } from './components/Separator';
22
-
23
- export { Skeleton } from './components/Skeleton';
24
- export type { SkeletonProps } from './components/Skeleton';
25
-
26
- export { ProgressBar } from './components/ProgressBar';
27
- export type { ProgressBarProps } from './components/ProgressBar';
28
-
29
- export { Chip } from './components/Chip';
30
- export type { ChipProps } from './components/Chip';
31
-
32
- export { EmptyState } from './components/EmptyState';
33
- export type { EmptyStateProps } from './components/EmptyState';
34
-
35
- export { Avatar } from './components/Avatar';
36
- export type { AvatarProps, AvatarSize } from './components/Avatar';
37
-
38
- export { Switch } from './components/Switch';
39
- export type { SwitchProps } from './components/Switch';
40
-
41
- export { Checkbox } from './components/Checkbox';
42
- export type { CheckboxProps } from './components/Checkbox';
43
-
44
- export { Label } from './components/Label';
45
- export type { LabelProps } from './components/Label';
46
-
47
- // Utilities
48
- export { cn } from './utils/cn';
49
-
50
- // Theming
51
- export { palettes } from './theming/color-palettes';
52
- export type { SprinklesTheme, SprinklesColorPalette, Tone } from './theming/types';
@@ -1,81 +0,0 @@
1
- export const palettes = {
2
- white: '#ffffff',
3
- neutral: {
4
- 25: '#fcfcff',
5
- 50: '#f8f9ff',
6
- 100: '#f1f5f9',
7
- 200: '#e2e8f0',
8
- 300: '#cbd5e1',
9
- 400: '#a9b6c9',
10
- 500: '#64748b',
11
- 600: '#475569',
12
- 700: '#334155',
13
- 800: '#1e293b',
14
- 900: '#0f172a',
15
- },
16
- purple: {
17
- 25: '#f0f1fd',
18
- 50: '#dddff9',
19
- 100: '#c1c4ee',
20
- 200: '#a2a6e5',
21
- 300: '#8388dd',
22
- 400: '#646bd4',
23
- 500: '#454dcc',
24
- 600: '#3a40aa',
25
- 700: '#2e3388',
26
- 800: '#232766',
27
- 900: '#171a44',
28
- },
29
- magenta: {
30
- 25: '#ffe7f1',
31
- 50: '#fbd5e5',
32
- 100: '#f9b9d4',
33
- 200: '#f696be',
34
- 300: '#f374a9',
35
- 400: '#f05193',
36
- 500: '#ef3f89',
37
- 600: '#cf4880',
38
- 700: '#a1285b',
39
- 800: '#791e44',
40
- 900: '#51142d',
41
- },
42
- emerald: {
43
- 25: '#e4f9f2',
44
- 50: '#d3f4e9',
45
- 100: '#b5ecda',
46
- 200: '#90e2c7',
47
- 300: '#6bd9b4',
48
- 400: '#46d0a2',
49
- 500: '#21c68f',
50
- 600: '#1ca577',
51
- 700: '#16845f',
52
- 800: '#106347',
53
- 900: '#0b4230',
54
- },
55
- amber: {
56
- 25: '#fff7eb',
57
- 50: '#fef1db',
58
- 100: '#fee7c2',
59
- 200: '#ffe1b1',
60
- 300: '#ffd797',
61
- 400: '#ffcd7d',
62
- 500: '#ffc363',
63
- 600: '#D29D49',
64
- 700: '#806131',
65
- 800: '#6C4B15',
66
- 900: '#554121',
67
- },
68
- blue: {
69
- 25: '#ebf2ff',
70
- 50: '#d8e6fd',
71
- 100: '#bed5fc',
72
- 200: '#9dc0fb',
73
- 300: '#7cacf9',
74
- 400: '#5c97f8',
75
- 500: '#3b82f6',
76
- 600: '#316ccd',
77
- 700: '#2757a4',
78
- 800: '#1d417b',
79
- 900: '#142b52',
80
- },
81
- };
@@ -1,82 +0,0 @@
1
- export interface SprinklesColorPalette {
2
- DEFAULT: string;
3
- background: {
4
- DEFAULT: string;
5
- hover: string;
6
- alt: string;
7
- };
8
- foreground: {
9
- DEFAULT: string;
10
- heading: string;
11
- label: string;
12
- inverted: string;
13
- };
14
- outline: string;
15
- }
16
-
17
- export interface SprinklesTheme {
18
- background: {
19
- DEFAULT: string;
20
- secondary: string;
21
- tertiary: string;
22
- quaternary: string;
23
- };
24
- foreground: {
25
- DEFAULT: string;
26
- heading: string;
27
- label: string;
28
- };
29
- border: {
30
- DEFAULT: string;
31
- alt: string;
32
- secondary: string;
33
- tertiary: string;
34
- };
35
- popover: {
36
- DEFAULT: string;
37
- foreground: string;
38
- };
39
- tooltip: {
40
- DEFAULT: string;
41
- foreground: string;
42
- };
43
- toast: {
44
- DEFAULT: string;
45
- foreground: string;
46
- danger: {
47
- DEFAULT: string;
48
- foreground: string;
49
- };
50
- };
51
- actionbar: {
52
- DEFAULT: string;
53
- foreground: string;
54
- };
55
- dialog: {
56
- DEFAULT: string;
57
- foreground: string;
58
- backdrop: string;
59
- };
60
- ring: string;
61
- shadow: string;
62
- outline: string;
63
- accent: {
64
- DEFAULT: string;
65
- foreground: string;
66
- };
67
- primary: SprinklesColorPalette;
68
- brand: SprinklesColorPalette;
69
- success: SprinklesColorPalette;
70
- info: SprinklesColorPalette;
71
- warn: SprinklesColorPalette;
72
- danger: SprinklesColorPalette;
73
- stock: {
74
- available: string;
75
- substitution: string;
76
- unavailable: string;
77
- unknown: string;
78
- };
79
- }
80
-
81
- export const TONES = [25, 50, 100, 200, 300, 400, 500, 600, 700, 800, 900] as const;
82
- export type Tone = (typeof TONES)[number];
@@ -1,31 +0,0 @@
1
- /**
2
- * Augment React Native component props with className support.
3
- * At build time, uniwind resolves className to style objects via its metro plugin.
4
- * This declaration ensures TypeScript accepts className on RN primitives
5
- * even when building this library without a metro/uniwind context.
6
- */
7
- import 'react-native';
8
-
9
- declare module 'react-native' {
10
- interface ViewProps {
11
- className?: string;
12
- }
13
- interface TextProps {
14
- className?: string;
15
- }
16
- interface TextInputProps {
17
- className?: string;
18
- }
19
- interface PressableProps {
20
- className?: string | ((state: { pressed: boolean }) => string);
21
- }
22
- interface ImageProps {
23
- className?: string;
24
- }
25
- interface ScrollViewProps {
26
- className?: string;
27
- }
28
- interface FlatListProps<ItemT> {
29
- className?: string;
30
- }
31
- }
package/src/utils/cn.ts DELETED
@@ -1,6 +0,0 @@
1
- import { clsx, type ClassValue } from 'clsx';
2
- import { twMerge } from 'tailwind-merge';
3
-
4
- export function cn(...inputs: ClassValue[]) {
5
- return twMerge(clsx(inputs));
6
- }
@@ -1 +0,0 @@
1
- export { cn } from './cn';