@tallyui/components 1.0.0 → 2.0.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.
Files changed (136) hide show
  1. package/LICENSE +21 -0
  2. package/dist/index.d.ts +1076 -76
  3. package/dist/index.js +4662 -355
  4. package/package.json +27 -5
  5. package/src/cart/cart-line-actions.tsx +40 -0
  6. package/src/cart/cart-line.tsx +18 -32
  7. package/src/cart/cart-note-input.tsx +46 -0
  8. package/src/cart/cart-panel.tsx +39 -26
  9. package/src/cart/cart-total.tsx +43 -47
  10. package/src/cart/discount-badge.tsx +19 -0
  11. package/src/cart/index.ts +4 -1
  12. package/src/checkout/cash-tendered.tsx +101 -0
  13. package/src/checkout/change-display.tsx +19 -0
  14. package/src/checkout/index.ts +3 -0
  15. package/src/checkout/order-summary-line.tsx +7 -8
  16. package/src/checkout/order-summary.tsx +8 -7
  17. package/src/checkout/payment-method-card.tsx +10 -9
  18. package/src/checkout/payment-selector.tsx +5 -5
  19. package/src/checkout/receipt-preview.tsx +78 -0
  20. package/src/customer/customer-card.tsx +8 -9
  21. package/src/customer/customer-form.tsx +70 -0
  22. package/src/customer/customer-order-history.tsx +34 -0
  23. package/src/customer/customer-select.tsx +63 -24
  24. package/src/customer/index.ts +2 -0
  25. package/src/index.ts +112 -1
  26. package/src/input/filter-chip.tsx +85 -27
  27. package/src/input/index.ts +1 -0
  28. package/src/input/quantity-stepper.tsx +64 -0
  29. package/src/input/search-input.tsx +30 -7
  30. package/src/layout/checkout-layout.tsx +46 -0
  31. package/src/layout/index.ts +5 -0
  32. package/src/layout/live-tab-screen.tsx +54 -0
  33. package/src/layout/pos-layout.tsx +64 -0
  34. package/src/layout/settings-layout.tsx +58 -0
  35. package/src/layout/store-settings-choice-screen.tsx +142 -0
  36. package/src/order/index.ts +4 -0
  37. package/src/order/order-card.tsx +48 -0
  38. package/src/order/order-detail.tsx +82 -0
  39. package/src/order/order-list.tsx +39 -0
  40. package/src/order/order-status-badge.tsx +32 -0
  41. package/src/product/category-nav.tsx +70 -0
  42. package/src/product/index.ts +3 -0
  43. package/src/product/product-card.tsx +36 -8
  44. package/src/product/product-grid.tsx +25 -6
  45. package/src/product/product-image.tsx +28 -7
  46. package/src/product/product-list.tsx +44 -0
  47. package/src/product/product-price.tsx +77 -22
  48. package/src/product/product-sku.tsx +5 -5
  49. package/src/product/product-stock-badge.tsx +41 -28
  50. package/src/product/product-title.tsx +2 -3
  51. package/src/product/product-variant-picker.tsx +61 -0
  52. package/src/register/cash-count-input.tsx +85 -0
  53. package/src/register/closure-sheet.tsx +155 -0
  54. package/src/register/index.ts +12 -0
  55. package/src/register/movement-sheet.tsx +118 -0
  56. package/src/register/open-register-card.tsx +109 -0
  57. package/src/register/register-bar.helpers.ts +57 -0
  58. package/src/register/register-bar.tsx +85 -0
  59. package/src/register/register-column.tsx +117 -0
  60. package/src/register/register-count.tsx +330 -0
  61. package/src/register/register-open-close.tsx +52 -0
  62. package/src/register/register-panel.tsx +151 -0
  63. package/src/register/register-picker.tsx +60 -0
  64. package/src/register/register-summary.tsx +72 -0
  65. package/src/sale/cart-bar.tsx +18 -0
  66. package/src/sale/cart.tsx +66 -0
  67. package/src/sale/catalogue.tsx +131 -0
  68. package/src/sale/discount-form.tsx +85 -0
  69. package/src/sale/index.ts +9 -0
  70. package/src/sale/orders-list.tsx +66 -0
  71. package/src/sale/print-style.ts +11 -0
  72. package/src/sale/receipt.tsx +61 -0
  73. package/src/sale/sync-status.tsx +20 -0
  74. package/src/sale/tender.tsx +35 -0
  75. package/src/settings/connector-status.tsx +65 -0
  76. package/src/settings/index.ts +3 -0
  77. package/src/settings/settings-group.tsx +23 -0
  78. package/src/settings/settings-row.tsx +23 -0
  79. package/src/ui/accordion/index.tsx +59 -0
  80. package/src/ui/alert-dialog/index.tsx +91 -0
  81. package/src/ui/avatar/index.tsx +50 -0
  82. package/src/ui/badge/index.tsx +60 -0
  83. package/src/ui/button/index.tsx +90 -0
  84. package/src/ui/card/index.tsx +60 -0
  85. package/src/ui/checkbox/index.tsx +29 -0
  86. package/src/ui/collapsible/index.tsx +24 -0
  87. package/src/ui/combobox/index.tsx +98 -0
  88. package/src/ui/context-menu/index.tsx +159 -0
  89. package/src/ui/dialog/index.tsx +92 -0
  90. package/src/ui/dropdown-menu/index.tsx +161 -0
  91. package/src/ui/hover-card/index.tsx +31 -0
  92. package/src/ui/hstack/index.tsx +43 -0
  93. package/src/ui/icon/index.tsx +44 -0
  94. package/src/ui/icon/search-icon.tsx +9 -0
  95. package/src/ui/icon/svg-icon.tsx +36 -0
  96. package/src/ui/icon-button/index.tsx +58 -0
  97. package/src/ui/index.ts +99 -0
  98. package/src/ui/input/index.tsx +100 -0
  99. package/src/ui/label/index.tsx +26 -0
  100. package/src/ui/loader/index.tsx +37 -0
  101. package/src/ui/popover/index.tsx +31 -0
  102. package/src/ui/progress/index.tsx +28 -0
  103. package/src/ui/radio-group/index.tsx +38 -0
  104. package/src/ui/select/index.tsx +96 -0
  105. package/src/ui/separator/index.tsx +29 -0
  106. package/src/ui/slider/index.tsx +28 -0
  107. package/src/ui/switch/index.tsx +31 -0
  108. package/src/ui/table/index.tsx +59 -0
  109. package/src/ui/tabs/index.tsx +53 -0
  110. package/src/ui/text/index.tsx +36 -0
  111. package/src/ui/textarea/index.tsx +29 -0
  112. package/src/ui/toast/index.tsx +52 -0
  113. package/src/ui/toggle/index.tsx +69 -0
  114. package/src/ui/toggle-group/index.tsx +66 -0
  115. package/src/ui/tooltip/index.tsx +30 -0
  116. package/src/ui/vstack/index.tsx +43 -0
  117. package/src/uniwind-env.d.ts +9 -1
  118. package/src/__tests__/cart-line.test.tsx +0 -53
  119. package/src/__tests__/cart-panel.test.tsx +0 -55
  120. package/src/__tests__/cart-total.test.tsx +0 -60
  121. package/src/__tests__/customer-card.test.tsx +0 -47
  122. package/src/__tests__/customer-select.test.tsx +0 -33
  123. package/src/__tests__/filter-chip.test.tsx +0 -40
  124. package/src/__tests__/helpers.ts +0 -111
  125. package/src/__tests__/order-summary-line.test.tsx +0 -18
  126. package/src/__tests__/order-summary.test.tsx +0 -32
  127. package/src/__tests__/payment-method-card.test.tsx +0 -24
  128. package/src/__tests__/payment-selector.test.tsx +0 -23
  129. package/src/__tests__/product-card.test.tsx +0 -31
  130. package/src/__tests__/product-grid.test.tsx +0 -37
  131. package/src/__tests__/product-image.test.tsx +0 -54
  132. package/src/__tests__/product-price.test.tsx +0 -68
  133. package/src/__tests__/product-sku.test.tsx +0 -47
  134. package/src/__tests__/product-stock-badge.test.tsx +0 -58
  135. package/src/__tests__/product-title.test.tsx +0 -38
  136. package/src/__tests__/search-input.test.tsx +0 -22
@@ -0,0 +1,23 @@
1
+ import type { ReactNode } from 'react';
2
+ import { Text, View, type ViewProps } from 'react-native';
3
+
4
+ import { cn } from '@tallyui/theme';
5
+
6
+ export interface SettingsRowProps extends Omit<ViewProps, 'children'> {
7
+ label: string;
8
+ description?: string;
9
+ action?: ReactNode;
10
+ className?: string;
11
+ }
12
+
13
+ export function SettingsRow({ label, description, action, className, ...viewProps }: SettingsRowProps) {
14
+ return (
15
+ <View className={cn('flex-row items-center gap-3 px-4 py-3', className)} {...viewProps}>
16
+ <View className="flex-1 gap-0.5">
17
+ <Text className="text-sm font-medium text-foreground">{label}</Text>
18
+ {description && <Text className="text-xs text-muted-foreground">{description}</Text>}
19
+ </View>
20
+ {action && <View>{action}</View>}
21
+ </View>
22
+ );
23
+ }
@@ -0,0 +1,59 @@
1
+ import * as React from 'react';
2
+ import { View } from 'react-native';
3
+ import { Accordion as AccordionPrimitive, TextClassContext } from '@tallyui/primitives';
4
+ import { cn } from '@tallyui/theme';
5
+
6
+ const Accordion = AccordionPrimitive.Root;
7
+
8
+ const AccordionItem = React.forwardRef<
9
+ React.ComponentRef<typeof AccordionPrimitive.Item>,
10
+ React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
11
+ >(function AccordionItem({ className, ...props }, ref) {
12
+ return (
13
+ <AccordionPrimitive.Item ref={ref} className={cn('border-b border-border', className)} {...props} />
14
+ );
15
+ });
16
+ AccordionItem.displayName = 'AccordionItem';
17
+
18
+ const AccordionTrigger = React.forwardRef<
19
+ React.ComponentRef<typeof AccordionPrimitive.Trigger>,
20
+ React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
21
+ >(function AccordionTrigger({ className, children, ...props }, ref) {
22
+ return (
23
+ <AccordionPrimitive.Header className="flex">
24
+ <TextClassContext.Provider value="text-sm font-medium">
25
+ <AccordionPrimitive.Trigger
26
+ ref={ref}
27
+ className={cn(
28
+ 'flex flex-1 flex-row items-center justify-between py-4 font-medium web:transition-all web:hover:underline',
29
+ className,
30
+ )}
31
+ {...props}
32
+ >
33
+ {children}
34
+ </AccordionPrimitive.Trigger>
35
+ </TextClassContext.Provider>
36
+ </AccordionPrimitive.Header>
37
+ );
38
+ });
39
+ AccordionTrigger.displayName = 'AccordionTrigger';
40
+
41
+ const AccordionContent = React.forwardRef<
42
+ React.ComponentRef<typeof AccordionPrimitive.Content>,
43
+ React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
44
+ >(function AccordionContent({ className, children, ...props }, ref) {
45
+ return (
46
+ <TextClassContext.Provider value="text-sm">
47
+ <AccordionPrimitive.Content
48
+ ref={ref}
49
+ className={cn('overflow-hidden text-sm web:transition-all', className)}
50
+ {...props}
51
+ >
52
+ <View className="pb-4 pt-0">{children}</View>
53
+ </AccordionPrimitive.Content>
54
+ </TextClassContext.Provider>
55
+ );
56
+ });
57
+ AccordionContent.displayName = 'AccordionContent';
58
+
59
+ export { Accordion, AccordionItem, AccordionTrigger, AccordionContent };
@@ -0,0 +1,91 @@
1
+ import * as React from 'react';
2
+ import { View } from 'react-native';
3
+ import { AlertDialog as AlertDialogPrimitive, TextClassContext } from '@tallyui/primitives';
4
+ import { cn } from '@tallyui/theme';
5
+
6
+ const AlertDialog = AlertDialogPrimitive.Root;
7
+ const AlertDialogTrigger = AlertDialogPrimitive.Trigger;
8
+ const AlertDialogPortal = AlertDialogPrimitive.Portal;
9
+
10
+ const AlertDialogOverlay = React.forwardRef<
11
+ React.ComponentRef<typeof AlertDialogPrimitive.Overlay>,
12
+ React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>
13
+ >(function AlertDialogOverlay({ className, ...props }, ref) {
14
+ return (
15
+ <AlertDialogPrimitive.Overlay
16
+ ref={ref}
17
+ className={cn('fixed inset-0 z-50 bg-black/80', className)}
18
+ {...props}
19
+ />
20
+ );
21
+ });
22
+ AlertDialogOverlay.displayName = 'AlertDialogOverlay';
23
+
24
+ const AlertDialogContent = React.forwardRef<
25
+ React.ComponentRef<typeof AlertDialogPrimitive.Content>,
26
+ React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content>
27
+ >(function AlertDialogContent({ className, children, ...props }, ref) {
28
+ return (
29
+ <AlertDialogPortal>
30
+ <AlertDialogOverlay />
31
+ <AlertDialogPrimitive.Content
32
+ ref={ref}
33
+ className={cn(
34
+ 'fixed left-1/2 top-1/2 z-50 w-full max-w-lg -translate-x-1/2 -translate-y-1/2 gap-4 rounded-lg border border-border bg-background p-6 shadow-lg',
35
+ className,
36
+ )}
37
+ {...props}
38
+ >
39
+ {children}
40
+ </AlertDialogPrimitive.Content>
41
+ </AlertDialogPortal>
42
+ );
43
+ });
44
+ AlertDialogContent.displayName = 'AlertDialogContent';
45
+
46
+ function AlertDialogHeader({ className, ...props }: React.ComponentPropsWithoutRef<typeof View>) {
47
+ return <View className={cn('flex flex-col gap-2', className)} {...props} />;
48
+ }
49
+
50
+ function AlertDialogFooter({ className, ...props }: React.ComponentPropsWithoutRef<typeof View>) {
51
+ return <View className={cn('flex flex-col-reverse sm:flex-row sm:justify-end sm:gap-2', className)} {...props} />;
52
+ }
53
+
54
+ const AlertDialogTitle = React.forwardRef<
55
+ React.ComponentRef<typeof AlertDialogPrimitive.Title>,
56
+ React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>
57
+ >(function AlertDialogTitle({ className, ...props }, ref) {
58
+ return (
59
+ <TextClassContext.Provider value="text-lg font-semibold text-foreground">
60
+ <AlertDialogPrimitive.Title ref={ref} className={cn('text-lg font-semibold text-foreground', className)} {...props} />
61
+ </TextClassContext.Provider>
62
+ );
63
+ });
64
+ AlertDialogTitle.displayName = 'AlertDialogTitle';
65
+
66
+ const AlertDialogDescription = React.forwardRef<
67
+ React.ComponentRef<typeof AlertDialogPrimitive.Description>,
68
+ React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>
69
+ >(function AlertDialogDescription({ className, ...props }, ref) {
70
+ return (
71
+ <AlertDialogPrimitive.Description ref={ref} className={cn('text-sm text-muted-foreground', className)} {...props} />
72
+ );
73
+ });
74
+ AlertDialogDescription.displayName = 'AlertDialogDescription';
75
+
76
+ const AlertDialogAction = AlertDialogPrimitive.Action;
77
+ const AlertDialogCancel = AlertDialogPrimitive.Cancel;
78
+
79
+ export {
80
+ AlertDialog,
81
+ AlertDialogTrigger,
82
+ AlertDialogPortal,
83
+ AlertDialogOverlay,
84
+ AlertDialogContent,
85
+ AlertDialogHeader,
86
+ AlertDialogFooter,
87
+ AlertDialogTitle,
88
+ AlertDialogDescription,
89
+ AlertDialogAction,
90
+ AlertDialogCancel,
91
+ };
@@ -0,0 +1,50 @@
1
+ import * as React from 'react';
2
+ import { Image, View, Text, type ViewProps } from 'react-native';
3
+ import { cn } from '@tallyui/theme';
4
+ import { cva, type VariantProps } from 'class-variance-authority';
5
+
6
+ const avatarVariants = cva('relative overflow-hidden rounded-full', {
7
+ variants: {
8
+ size: {
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
+ defaultVariants: {
16
+ size: 'md',
17
+ },
18
+ });
19
+
20
+ type AvatarProps = ViewProps & VariantProps<typeof avatarVariants> & {
21
+ src?: string;
22
+ alt?: string;
23
+ fallback?: string;
24
+ };
25
+
26
+ function Avatar({ className, size, src, alt, fallback, ...props }: AvatarProps) {
27
+ const [hasError, setHasError] = React.useState(false);
28
+
29
+ return (
30
+ <View className={cn(avatarVariants({ size }), className)} {...props}>
31
+ {src && !hasError ? (
32
+ <Image
33
+ source={{ uri: src }}
34
+ accessibilityLabel={alt}
35
+ onError={() => setHasError(true)}
36
+ className="h-full w-full"
37
+ />
38
+ ) : (
39
+ <View className="flex h-full w-full items-center justify-center bg-muted">
40
+ <Text className="text-sm font-medium text-muted-foreground">
41
+ {fallback ?? alt?.charAt(0)?.toUpperCase() ?? '?'}
42
+ </Text>
43
+ </View>
44
+ )}
45
+ </View>
46
+ );
47
+ }
48
+
49
+ export { Avatar, avatarVariants };
50
+ export type { AvatarProps };
@@ -0,0 +1,60 @@
1
+ import * as React from 'react';
2
+ import { Text, View, type ViewProps } from 'react-native';
3
+ import { cn } from '@tallyui/theme';
4
+ import { cva, type VariantProps } from 'class-variance-authority';
5
+
6
+ const badgeVariants = cva(
7
+ 'inline-flex items-center rounded-full border px-2.5 py-0.5',
8
+ {
9
+ variants: {
10
+ variant: {
11
+ default: 'border-transparent bg-primary',
12
+ secondary: 'border-transparent bg-secondary',
13
+ destructive: 'border-transparent bg-destructive',
14
+ outline: 'border-border',
15
+ success: 'border-transparent bg-success',
16
+ warning: 'border-transparent bg-warning',
17
+ info: 'border-transparent bg-info',
18
+ },
19
+ },
20
+ defaultVariants: {
21
+ variant: 'default',
22
+ },
23
+ }
24
+ );
25
+
26
+ const badgeTextVariants = cva('text-xs font-semibold', {
27
+ variants: {
28
+ variant: {
29
+ default: 'text-primary-foreground',
30
+ secondary: 'text-secondary-foreground',
31
+ destructive: 'text-destructive-foreground',
32
+ outline: 'text-foreground',
33
+ success: 'text-success-foreground',
34
+ warning: 'text-warning-foreground',
35
+ info: 'text-info-foreground',
36
+ },
37
+ },
38
+ defaultVariants: {
39
+ variant: 'default',
40
+ },
41
+ });
42
+
43
+ type BadgeProps = ViewProps & VariantProps<typeof badgeVariants> & {
44
+ label?: string;
45
+ };
46
+
47
+ function Badge({ className, variant, label, children, ...props }: BadgeProps) {
48
+ return (
49
+ <View className={cn(badgeVariants({ variant }), className)} {...props}>
50
+ {label ? (
51
+ <Text className={badgeTextVariants({ variant })}>{label}</Text>
52
+ ) : (
53
+ children
54
+ )}
55
+ </View>
56
+ );
57
+ }
58
+
59
+ export { Badge, badgeVariants, badgeTextVariants };
60
+ export type { BadgeProps };
@@ -0,0 +1,90 @@
1
+ import * as React from 'react';
2
+ import { Pressable, type PressableProps } from 'react-native';
3
+ import { TextClassContext, Slot } from '@tallyui/primitives';
4
+ import { cn } from '@tallyui/theme';
5
+ import { cva, type VariantProps } from 'class-variance-authority';
6
+
7
+ const buttonVariants = cva(
8
+ 'inline-flex flex-row items-center justify-center gap-2 rounded-md web:ring-offset-background web:transition-colors web:focus-visible:outline-none web:focus-visible:ring-2 web:focus-visible:ring-ring web:focus-visible:ring-offset-2',
9
+ {
10
+ variants: {
11
+ variant: {
12
+ default: 'bg-primary active:opacity-90',
13
+ destructive: 'bg-destructive active:opacity-90',
14
+ outline: 'border border-input bg-background active:bg-accent',
15
+ secondary: 'bg-secondary active:opacity-80',
16
+ ghost: 'active:bg-accent',
17
+ link: 'web:underline-offset-4 web:hover:underline',
18
+ },
19
+ size: {
20
+ default: 'h-10 px-4 py-2',
21
+ sm: 'h-9 rounded-md px-3',
22
+ lg: 'h-11 rounded-md px-8',
23
+ icon: 'h-10 w-10',
24
+ },
25
+ },
26
+ defaultVariants: {
27
+ variant: 'default',
28
+ size: 'default',
29
+ },
30
+ }
31
+ );
32
+
33
+ const buttonTextVariants = cva(
34
+ 'web:whitespace-nowrap text-sm font-medium',
35
+ {
36
+ variants: {
37
+ variant: {
38
+ default: 'text-primary-foreground',
39
+ destructive: 'text-destructive-foreground',
40
+ outline: 'text-foreground',
41
+ secondary: 'text-secondary-foreground',
42
+ ghost: 'text-foreground',
43
+ link: 'text-primary',
44
+ },
45
+ size: {
46
+ default: '',
47
+ sm: '',
48
+ lg: 'text-base',
49
+ icon: '',
50
+ },
51
+ },
52
+ defaultVariants: {
53
+ variant: 'default',
54
+ size: 'default',
55
+ },
56
+ }
57
+ );
58
+
59
+ type ButtonProps = PressableProps & VariantProps<typeof buttonVariants> & {
60
+ asChild?: boolean;
61
+ };
62
+
63
+ const Button = React.forwardRef<React.ComponentRef<typeof Pressable>, ButtonProps>(
64
+ function Button({ className, variant, size, asChild = false, disabled, ...props }, ref) {
65
+ const Component = asChild ? Slot : Pressable;
66
+
67
+ return (
68
+ <TextClassContext.Provider
69
+ value={buttonTextVariants({ variant, size })}
70
+ >
71
+ <Component
72
+ ref={ref}
73
+ role="button"
74
+ disabled={disabled}
75
+ className={cn(
76
+ buttonVariants({ variant, size }),
77
+ disabled && 'opacity-50 web:pointer-events-none',
78
+ className,
79
+ )}
80
+ {...props}
81
+ />
82
+ </TextClassContext.Provider>
83
+ );
84
+ }
85
+ );
86
+
87
+ Button.displayName = 'Button';
88
+
89
+ export { Button, buttonVariants, buttonTextVariants };
90
+ export type { ButtonProps };
@@ -0,0 +1,60 @@
1
+ import * as React from 'react';
2
+ import { Text, View, type TextProps, type ViewProps } from 'react-native';
3
+ import { TextClassContext } from '@tallyui/primitives';
4
+ import { cn } from '@tallyui/theme';
5
+
6
+ const Card = React.forwardRef<View, ViewProps>(function Card({ className, ...props }, ref) {
7
+ return (
8
+ <View
9
+ ref={ref}
10
+ className={cn('rounded-lg border border-border bg-card shadow-sm', className)}
11
+ {...props}
12
+ />
13
+ );
14
+ });
15
+ Card.displayName = 'Card';
16
+
17
+ const CardHeader = React.forwardRef<View, ViewProps>(function CardHeader({ className, ...props }, ref) {
18
+ return (
19
+ <View ref={ref} className={cn('flex flex-col gap-1.5 p-6', className)} {...props} />
20
+ );
21
+ });
22
+ CardHeader.displayName = 'CardHeader';
23
+
24
+ const CardTitle = React.forwardRef<Text, TextProps>(function CardTitle({ className, ...props }, ref) {
25
+ return (
26
+ <Text
27
+ ref={ref}
28
+ role="heading"
29
+ aria-level={3}
30
+ className={cn('text-2xl font-semibold leading-none text-card-foreground', className)}
31
+ {...props}
32
+ />
33
+ );
34
+ });
35
+ CardTitle.displayName = 'CardTitle';
36
+
37
+ const CardDescription = React.forwardRef<Text, TextProps>(function CardDescription({ className, ...props }, ref) {
38
+ return (
39
+ <Text ref={ref} className={cn('text-sm text-muted-foreground', className)} {...props} />
40
+ );
41
+ });
42
+ CardDescription.displayName = 'CardDescription';
43
+
44
+ const CardContent = React.forwardRef<View, ViewProps>(function CardContent({ className, ...props }, ref) {
45
+ return (
46
+ <TextClassContext.Provider value="text-card-foreground">
47
+ <View ref={ref} className={cn('p-6 pt-0', className)} {...props} />
48
+ </TextClassContext.Provider>
49
+ );
50
+ });
51
+ CardContent.displayName = 'CardContent';
52
+
53
+ const CardFooter = React.forwardRef<View, ViewProps>(function CardFooter({ className, ...props }, ref) {
54
+ return (
55
+ <View ref={ref} className={cn('flex flex-row items-center p-6 pt-0', className)} {...props} />
56
+ );
57
+ });
58
+ CardFooter.displayName = 'CardFooter';
59
+
60
+ export { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter };
@@ -0,0 +1,29 @@
1
+ import * as React from 'react';
2
+ import { View, Text } from 'react-native';
3
+ import { Checkbox as CheckboxPrimitive } from '@tallyui/primitives';
4
+ import { cn } from '@tallyui/theme';
5
+
6
+ const Checkbox = React.forwardRef<
7
+ React.ComponentRef<typeof CheckboxPrimitive.Root>,
8
+ React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>
9
+ >(function Checkbox({ className, ...props }, ref) {
10
+ return (
11
+ <CheckboxPrimitive.Root
12
+ ref={ref}
13
+ className={cn(
14
+ 'h-4 w-4 shrink-0 rounded-sm border border-primary web:ring-offset-background web:focus-visible:outline-none web:focus-visible:ring-2 web:focus-visible:ring-ring web:focus-visible:ring-offset-2',
15
+ props.checked && 'bg-primary',
16
+ props.disabled && 'web:cursor-not-allowed opacity-50',
17
+ className,
18
+ )}
19
+ {...props}
20
+ >
21
+ <CheckboxPrimitive.Indicator className="flex items-center justify-center text-current">
22
+ <Text className="text-xs text-primary-foreground">{'\u2713'}</Text>
23
+ </CheckboxPrimitive.Indicator>
24
+ </CheckboxPrimitive.Root>
25
+ );
26
+ });
27
+ Checkbox.displayName = 'Checkbox';
28
+
29
+ export { Checkbox };
@@ -0,0 +1,24 @@
1
+ import * as React from 'react';
2
+ import { Collapsible as CollapsiblePrimitive, TextClassContext } from '@tallyui/primitives';
3
+ import { cn } from '@tallyui/theme';
4
+
5
+ const Collapsible = CollapsiblePrimitive.Root;
6
+ const CollapsibleTrigger = CollapsiblePrimitive.Trigger;
7
+
8
+ const CollapsibleContent = React.forwardRef<
9
+ React.ComponentRef<typeof CollapsiblePrimitive.Content>,
10
+ React.ComponentPropsWithoutRef<typeof CollapsiblePrimitive.Content>
11
+ >(function CollapsibleContent({ className, ...props }, ref) {
12
+ return (
13
+ <TextClassContext.Provider value="text-sm">
14
+ <CollapsiblePrimitive.Content
15
+ ref={ref}
16
+ className={cn('overflow-hidden web:transition-all', className)}
17
+ {...props}
18
+ />
19
+ </TextClassContext.Provider>
20
+ );
21
+ });
22
+ CollapsibleContent.displayName = 'CollapsibleContent';
23
+
24
+ export { Collapsible, CollapsibleTrigger, CollapsibleContent };
@@ -0,0 +1,98 @@
1
+ import * as React from 'react';
2
+ import { View, TextInput, Pressable, Text, ScrollView } from 'react-native';
3
+ import { Combobox as ComboboxPrimitive, TextClassContext } from '@tallyui/primitives';
4
+ import { cn } from '@tallyui/theme';
5
+
6
+ const Combobox = ComboboxPrimitive.Root;
7
+
8
+ const ComboboxTrigger = React.forwardRef<
9
+ React.ComponentRef<typeof ComboboxPrimitive.Trigger>,
10
+ React.ComponentPropsWithoutRef<typeof ComboboxPrimitive.Trigger>
11
+ >(function ComboboxTrigger({ className, children, ...props }, ref) {
12
+ return (
13
+ <ComboboxPrimitive.Trigger
14
+ ref={ref}
15
+ className={cn(
16
+ 'flex h-10 w-full flex-row items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm web:ring-offset-background web:focus:outline-none web:focus:ring-2 web:focus:ring-ring web:focus:ring-offset-2',
17
+ className,
18
+ )}
19
+ {...props}
20
+ >
21
+ {children}
22
+ </ComboboxPrimitive.Trigger>
23
+ );
24
+ });
25
+ ComboboxTrigger.displayName = 'ComboboxTrigger';
26
+
27
+ const ComboboxInput = React.forwardRef<
28
+ React.ComponentRef<typeof ComboboxPrimitive.Input>,
29
+ React.ComponentPropsWithoutRef<typeof ComboboxPrimitive.Input>
30
+ >(function ComboboxInput({ className, ...props }, ref) {
31
+ return (
32
+ <ComboboxPrimitive.Input
33
+ ref={ref}
34
+ className={cn(
35
+ 'flex-1 text-sm text-foreground web:outline-none placeholder:text-muted-foreground',
36
+ className,
37
+ )}
38
+ {...props}
39
+ />
40
+ );
41
+ });
42
+ ComboboxInput.displayName = 'ComboboxInput';
43
+
44
+ const ComboboxContent = React.forwardRef<
45
+ React.ComponentRef<typeof ComboboxPrimitive.Content>,
46
+ React.ComponentPropsWithoutRef<typeof ComboboxPrimitive.Content>
47
+ >(function ComboboxContent({ className, children, ...props }, ref) {
48
+ return (
49
+ <ComboboxPrimitive.Portal>
50
+ <TextClassContext.Provider value="text-popover-foreground">
51
+ <ComboboxPrimitive.Content
52
+ ref={ref}
53
+ className={cn(
54
+ 'z-50 min-w-[8rem] overflow-hidden rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md',
55
+ className,
56
+ )}
57
+ {...props}
58
+ >
59
+ {children}
60
+ </ComboboxPrimitive.Content>
61
+ </TextClassContext.Provider>
62
+ </ComboboxPrimitive.Portal>
63
+ );
64
+ });
65
+ ComboboxContent.displayName = 'ComboboxContent';
66
+
67
+ const ComboboxItem = React.forwardRef<
68
+ React.ComponentRef<typeof ComboboxPrimitive.Item>,
69
+ React.ComponentPropsWithoutRef<typeof ComboboxPrimitive.Item>
70
+ >(function ComboboxItem({ className, ...props }, ref) {
71
+ return (
72
+ <ComboboxPrimitive.Item
73
+ ref={ref}
74
+ className={cn(
75
+ 'relative flex cursor-default select-none flex-row items-center rounded-sm px-2 py-1.5 text-sm outline-none web:focus:bg-accent web:focus:text-accent-foreground',
76
+ className,
77
+ )}
78
+ {...props}
79
+ />
80
+ );
81
+ });
82
+ ComboboxItem.displayName = 'ComboboxItem';
83
+
84
+ const ComboboxEmpty = React.forwardRef<
85
+ View,
86
+ React.ComponentPropsWithoutRef<typeof View>
87
+ >(function ComboboxEmpty({ className, ...props }, ref) {
88
+ return (
89
+ <View ref={ref} className={cn('py-6 text-center', className)} {...props}>
90
+ <Text className="text-sm text-muted-foreground">No results found.</Text>
91
+ </View>
92
+ );
93
+ });
94
+ ComboboxEmpty.displayName = 'ComboboxEmpty';
95
+
96
+ export {
97
+ Combobox, ComboboxTrigger, ComboboxInput, ComboboxContent, ComboboxItem, ComboboxEmpty,
98
+ };