getlotui 0.1.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 (128) hide show
  1. package/README.md +78 -0
  2. package/dist/bin.d.ts +2 -0
  3. package/dist/bin.js +5 -0
  4. package/dist/commands/add.d.ts +1 -0
  5. package/dist/commands/add.js +37 -0
  6. package/dist/commands/init.d.ts +1 -0
  7. package/dist/commands/init.js +93 -0
  8. package/dist/index.d.ts +1 -0
  9. package/dist/index.js +22 -0
  10. package/dist/templates/expo/Accordion.d.ts +14 -0
  11. package/dist/templates/expo/Accordion.js +118 -0
  12. package/dist/templates/expo/Accordion.tsx +152 -0
  13. package/dist/templates/expo/AlertDialog.d.ts +12 -0
  14. package/dist/templates/expo/AlertDialog.js +126 -0
  15. package/dist/templates/expo/AlertDialog.tsx +147 -0
  16. package/dist/templates/expo/Avatar.d.ts +8 -0
  17. package/dist/templates/expo/Avatar.js +81 -0
  18. package/dist/templates/expo/Avatar.tsx +78 -0
  19. package/dist/templates/expo/Badge.d.ts +6 -0
  20. package/dist/templates/expo/Badge.js +60 -0
  21. package/dist/templates/expo/Badge.tsx +67 -0
  22. package/dist/templates/expo/Button.d.ts +9 -0
  23. package/dist/templates/expo/Button.js +37 -0
  24. package/dist/templates/expo/Button.tsx +53 -0
  25. package/dist/templates/expo/Dropdown.d.ts +12 -0
  26. package/dist/templates/expo/Dropdown.js +91 -0
  27. package/dist/templates/expo/Dropdown.tsx +100 -0
  28. package/dist/templates/expo/Input.d.ts +11 -0
  29. package/dist/templates/expo/Input.js +43 -0
  30. package/dist/templates/expo/Input.tsx +67 -0
  31. package/dist/templates/expo/Toast.d.ts +16 -0
  32. package/dist/templates/expo/Toast.js +142 -0
  33. package/dist/templates/expo/Toast.tsx +161 -0
  34. package/dist/templates/expo/utils.d.ts +4 -0
  35. package/dist/templates/expo/utils.js +10 -0
  36. package/dist/templates/expo/utils.ts +8 -0
  37. package/dist/templates/flutter/Accordion.dart +142 -0
  38. package/dist/templates/flutter/Alert.dart +96 -0
  39. package/dist/templates/flutter/AlertDialog.dart +175 -0
  40. package/dist/templates/flutter/Avatar.dart +82 -0
  41. package/dist/templates/flutter/Badge.dart +89 -0
  42. package/dist/templates/flutter/Button.dart +116 -0
  43. package/dist/templates/flutter/Card.dart +91 -0
  44. package/dist/templates/flutter/Input.dart +73 -0
  45. package/dist/templates/flutter/Text.dart +87 -0
  46. package/dist/templates/flutter/utils.dart +13 -0
  47. package/dist/templates/templates/expo/Button.tsx +50 -0
  48. package/dist/templates/templates/expo/Input.tsx +67 -0
  49. package/dist/templates/web/Accordion.d.ts +7 -0
  50. package/dist/templates/web/Accordion.js +59 -0
  51. package/dist/templates/web/Accordion.tsx +64 -0
  52. package/dist/templates/web/Alert.d.ts +9 -0
  53. package/dist/templates/web/Alert.js +64 -0
  54. package/dist/templates/web/Alert.tsx +71 -0
  55. package/dist/templates/web/AlertDialog.d.ts +14 -0
  56. package/dist/templates/web/AlertDialog.js +85 -0
  57. package/dist/templates/web/AlertDialog.tsx +164 -0
  58. package/dist/templates/web/Avatar.d.ts +6 -0
  59. package/dist/templates/web/Avatar.js +50 -0
  60. package/dist/templates/web/Avatar.tsx +51 -0
  61. package/dist/templates/web/Badge.d.ts +9 -0
  62. package/dist/templates/web/Badge.js +59 -0
  63. package/dist/templates/web/Badge.tsx +38 -0
  64. package/dist/templates/web/Button.d.ts +10 -0
  65. package/dist/templates/web/Button.js +70 -0
  66. package/dist/templates/web/Button.tsx +60 -0
  67. package/dist/templates/web/Card.d.ts +9 -0
  68. package/dist/templates/web/Card.js +65 -0
  69. package/dist/templates/web/Card.tsx +92 -0
  70. package/dist/templates/web/Dropdown.d.ts +27 -0
  71. package/dist/templates/web/Dropdown.js +95 -0
  72. package/dist/templates/web/Dropdown.tsx +198 -0
  73. package/dist/templates/web/Input.d.ts +3 -0
  74. package/dist/templates/web/Input.js +41 -0
  75. package/dist/templates/web/Input.tsx +21 -0
  76. package/dist/templates/web/Tabs.d.ts +7 -0
  77. package/dist/templates/web/Tabs.js +55 -0
  78. package/dist/templates/web/Tabs.tsx +66 -0
  79. package/dist/templates/web/Toast.d.ts +15 -0
  80. package/dist/templates/web/Toast.js +75 -0
  81. package/dist/templates/web/Toast.tsx +126 -0
  82. package/dist/templates/web/utils.d.ts +2 -0
  83. package/dist/templates/web/utils.js +8 -0
  84. package/dist/templates/web/utils.ts +6 -0
  85. package/dist/utils/detect.d.ts +19 -0
  86. package/dist/utils/detect.js +90 -0
  87. package/dist/utils/fs.d.ts +5 -0
  88. package/dist/utils/fs.js +35 -0
  89. package/getlotui.config.json +4 -0
  90. package/package.json +31 -0
  91. package/src/bin.ts +5 -0
  92. package/src/commands/add.ts +50 -0
  93. package/src/commands/init.ts +108 -0
  94. package/src/index.ts +23 -0
  95. package/src/templates/expo/Accordion.tsx +152 -0
  96. package/src/templates/expo/AlertDialog.tsx +147 -0
  97. package/src/templates/expo/Avatar.tsx +78 -0
  98. package/src/templates/expo/Badge.tsx +67 -0
  99. package/src/templates/expo/Button.tsx +53 -0
  100. package/src/templates/expo/Dropdown.tsx +100 -0
  101. package/src/templates/expo/Input.tsx +67 -0
  102. package/src/templates/expo/Toast.tsx +161 -0
  103. package/src/templates/expo/utils.ts +8 -0
  104. package/src/templates/flutter/Accordion.dart +142 -0
  105. package/src/templates/flutter/Alert.dart +96 -0
  106. package/src/templates/flutter/AlertDialog.dart +175 -0
  107. package/src/templates/flutter/Avatar.dart +82 -0
  108. package/src/templates/flutter/Badge.dart +89 -0
  109. package/src/templates/flutter/Button.dart +116 -0
  110. package/src/templates/flutter/Card.dart +91 -0
  111. package/src/templates/flutter/Input.dart +73 -0
  112. package/src/templates/flutter/Text.dart +87 -0
  113. package/src/templates/flutter/utils.dart +13 -0
  114. package/src/templates/web/Accordion.tsx +64 -0
  115. package/src/templates/web/Alert.tsx +71 -0
  116. package/src/templates/web/AlertDialog.tsx +164 -0
  117. package/src/templates/web/Avatar.tsx +51 -0
  118. package/src/templates/web/Badge.tsx +38 -0
  119. package/src/templates/web/Button.tsx +60 -0
  120. package/src/templates/web/Card.tsx +92 -0
  121. package/src/templates/web/Dropdown.tsx +198 -0
  122. package/src/templates/web/Input.tsx +21 -0
  123. package/src/templates/web/Tabs.tsx +66 -0
  124. package/src/templates/web/Toast.tsx +126 -0
  125. package/src/templates/web/utils.ts +6 -0
  126. package/src/utils/detect.ts +81 -0
  127. package/src/utils/fs.ts +32 -0
  128. package/tsconfig.json +17 -0
@@ -0,0 +1,89 @@
1
+ import 'package:flutter/material.dart';
2
+
3
+ enum CrossUIBadgeVariant {
4
+ defaultVariant,
5
+ secondary,
6
+ outline,
7
+ destructive,
8
+ success,
9
+ warning,
10
+ }
11
+
12
+ enum CrossUIBadgeSize { sm, md }
13
+
14
+ class CrossUIBadge extends StatelessWidget {
15
+ final String label;
16
+ final CrossUIBadgeVariant variant;
17
+ final CrossUIBadgeSize size;
18
+
19
+ const CrossUIBadge({
20
+ super.key,
21
+ required this.label,
22
+ this.variant = CrossUIBadgeVariant.defaultVariant,
23
+ this.size = CrossUIBadgeSize.md,
24
+ });
25
+
26
+ @override
27
+ Widget build(BuildContext context) {
28
+ Color backgroundColor;
29
+ Color textColor;
30
+ BorderSide borderSide = BorderSide.none;
31
+
32
+ switch (variant) {
33
+ case CrossUIBadgeVariant.secondary:
34
+ backgroundColor = Colors.blue.withValues(alpha: 0.1);
35
+ textColor = Colors.blue;
36
+ break;
37
+ case CrossUIBadgeVariant.outline:
38
+ backgroundColor = Colors.transparent;
39
+ textColor = Colors.blue;
40
+ borderSide = const BorderSide(color: Colors.blue);
41
+ break;
42
+ case CrossUIBadgeVariant.destructive:
43
+ backgroundColor = Colors.red;
44
+ textColor = Colors.white;
45
+ break;
46
+ case CrossUIBadgeVariant.success:
47
+ backgroundColor = Colors.green.withValues(alpha: 0.1);
48
+ textColor = Colors.green;
49
+ break;
50
+ case CrossUIBadgeVariant.warning:
51
+ backgroundColor = Colors.amber.withValues(alpha: 0.1);
52
+ textColor = Colors.amber;
53
+ break;
54
+ case CrossUIBadgeVariant.defaultVariant:
55
+ backgroundColor = Colors.blue;
56
+ textColor = Colors.white;
57
+ break;
58
+ }
59
+
60
+ EdgeInsets padding;
61
+ double fontSize;
62
+
63
+ if (size == CrossUIBadgeSize.sm) {
64
+ padding = const EdgeInsets.symmetric(horizontal: 6, vertical: 2);
65
+ fontSize = 10;
66
+ } else {
67
+ padding = const EdgeInsets.symmetric(horizontal: 10, vertical: 4);
68
+ fontSize = 12;
69
+ }
70
+
71
+ return Container(
72
+ padding: padding,
73
+ decoration: BoxDecoration(
74
+ color: backgroundColor,
75
+ borderRadius: BorderRadius.circular(999),
76
+ border: Border.fromBorderSide(borderSide),
77
+ ),
78
+ child: Text(
79
+ label.toUpperCase(),
80
+ style: TextStyle(
81
+ color: textColor,
82
+ fontSize: fontSize,
83
+ fontWeight: FontWeight.w700,
84
+ letterSpacing: 0.5,
85
+ ),
86
+ ),
87
+ );
88
+ }
89
+ }
@@ -0,0 +1,116 @@
1
+ import 'package:flutter/material.dart';
2
+ import '../theme/config.dart';
3
+
4
+ enum CrossUIButtonVariant {
5
+ defaultVariant,
6
+ secondary,
7
+ outline,
8
+ ghost,
9
+ destructive,
10
+ }
11
+
12
+ enum CrossUIButtonSize { sm, defaultSize, lg }
13
+
14
+ class CrossUIButton extends StatelessWidget {
15
+ final String label;
16
+ final VoidCallback? onPressed;
17
+ final CrossUIButtonVariant variant;
18
+ final CrossUIButtonSize size;
19
+ final bool disabled;
20
+ final Widget? icon;
21
+
22
+ const CrossUIButton({
23
+ Key? key,
24
+ required this.label,
25
+ this.onPressed,
26
+ this.variant = CrossUIButtonVariant.defaultVariant,
27
+ this.size = CrossUIButtonSize.defaultSize,
28
+ this.disabled = false,
29
+ this.icon,
30
+ }) : super(key: key);
31
+
32
+ @override
33
+ Widget build(BuildContext context) {
34
+ Color backgroundColor;
35
+ Color foregroundColor;
36
+ BorderSide borderSide = BorderSide.none;
37
+
38
+ final themeColors = CrossUITheme.colors;
39
+
40
+ switch (variant) {
41
+ case CrossUIButtonVariant.secondary:
42
+ backgroundColor = themeColors['secondary'] ?? Colors.grey;
43
+ foregroundColor = Colors.white;
44
+ break;
45
+ case CrossUIButtonVariant.outline:
46
+ backgroundColor = Colors.transparent;
47
+ foregroundColor = themeColors['primary'] ?? Colors.blue;
48
+ borderSide = BorderSide(color: themeColors['primary'] ?? Colors.blue);
49
+ break;
50
+ case CrossUIButtonVariant.ghost:
51
+ backgroundColor = Colors.transparent;
52
+ foregroundColor = themeColors['primary'] ?? Colors.blue;
53
+ break;
54
+ case CrossUIButtonVariant.destructive:
55
+ backgroundColor = Colors.red;
56
+ foregroundColor = Colors.white;
57
+ break;
58
+ case CrossUIButtonVariant.defaultVariant:
59
+ default:
60
+ backgroundColor = themeColors['primary'] ?? Colors.blue;
61
+ foregroundColor = themeColors['background'] ?? Colors.white;
62
+ break;
63
+ }
64
+
65
+ if (disabled) {
66
+ backgroundColor = backgroundColor.withOpacity(0.5);
67
+ foregroundColor = foregroundColor.withOpacity(0.5);
68
+ }
69
+
70
+ EdgeInsets padding;
71
+ double fontSize;
72
+ switch (size) {
73
+ case CrossUIButtonSize.sm:
74
+ padding = const EdgeInsets.symmetric(horizontal: 12, vertical: 8);
75
+ fontSize = CrossUITokens.fontSizeSm;
76
+ break;
77
+ case CrossUIButtonSize.lg:
78
+ padding = const EdgeInsets.symmetric(horizontal: 24, vertical: 16);
79
+ fontSize = CrossUITokens.fontSizeLg;
80
+ break;
81
+ case CrossUIButtonSize.defaultSize:
82
+ default:
83
+ padding = const EdgeInsets.symmetric(horizontal: 16, vertical: 12);
84
+ fontSize = CrossUITokens.fontSizeBase;
85
+ break;
86
+ }
87
+
88
+ return InkWell(
89
+ onTap: disabled ? null : onPressed,
90
+ borderRadius: BorderRadius.circular(CrossUITokens.radiusMedium),
91
+ child: Container(
92
+ padding: padding,
93
+ decoration: BoxDecoration(
94
+ color: backgroundColor,
95
+ borderRadius: BorderRadius.circular(CrossUITokens.radiusMedium),
96
+ border: Border.fromBorderSide(borderSide),
97
+ ),
98
+ child: Row(
99
+ mainAxisSize: MainAxisSize.min,
100
+ mainAxisAlignment: MainAxisAlignment.center,
101
+ children: [
102
+ if (icon != null) ...[icon!, const SizedBox(width: 8)],
103
+ Text(
104
+ label,
105
+ style: TextStyle(
106
+ color: foregroundColor,
107
+ fontSize: fontSize,
108
+ fontWeight: FontWeight.w600,
109
+ ),
110
+ ),
111
+ ],
112
+ ),
113
+ ),
114
+ );
115
+ }
116
+ }
@@ -0,0 +1,91 @@
1
+ import 'package:flutter/material.dart';
2
+ import '../theme/tokens.dart';
3
+
4
+ class CrossUICard extends StatelessWidget {
5
+ final Widget? header;
6
+ final Widget? title;
7
+ final Widget? description;
8
+ final Widget child;
9
+ final Widget? footer;
10
+ final VoidCallback? onTap;
11
+
12
+ const CrossUICard({
13
+ Key? key,
14
+ required this.child,
15
+ this.header,
16
+ this.title,
17
+ this.description,
18
+ this.footer,
19
+ this.onTap,
20
+ }) : super(key: key);
21
+
22
+ @override
23
+ Widget build(BuildContext context) {
24
+ return InkWell(
25
+ onTap: onTap,
26
+ borderRadius: BorderRadius.circular(CrossUITokens.radiusLarge),
27
+ child: Container(
28
+ decoration: BoxDecoration(
29
+ color: Colors.white,
30
+ borderRadius: BorderRadius.circular(CrossUITokens.radiusLarge),
31
+ border: Border.all(color: CrossUITokens.border),
32
+ boxShadow: [
33
+ BoxShadow(
34
+ color: Colors.black.withOpacity(0.05),
35
+ blurRadius: 10,
36
+ offset: const Offset(0, 4),
37
+ ),
38
+ ],
39
+ ),
40
+ child: Column(
41
+ crossAxisAlignment: CrossAxisAlignment.start,
42
+ children: [
43
+ if (header != null || title != null || description != null)
44
+ Padding(
45
+ padding: const EdgeInsets.all(CrossUITokens.spacingL),
46
+ child: Column(
47
+ crossAxisAlignment: CrossAxisAlignment.start,
48
+ children: [
49
+ if (header != null) header!,
50
+ if (title != null) ...[
51
+ DefaultTextStyle(
52
+ style: const TextStyle(
53
+ fontSize: CrossUITokens.fontSize2xl,
54
+ fontWeight: FontWeight.bold,
55
+ color: CrossUITokens.dark,
56
+ ),
57
+ child: title!,
58
+ ),
59
+ ],
60
+ if (description != null) ...[
61
+ const SizedBox(height: 4),
62
+ DefaultTextStyle(
63
+ style: const TextStyle(
64
+ fontSize: CrossUITokens.fontSizeSm,
65
+ color: Colors.grey,
66
+ ),
67
+ child: description!,
68
+ ),
69
+ ],
70
+ ],
71
+ ),
72
+ ),
73
+ Padding(
74
+ padding: const EdgeInsets.symmetric(horizontal: CrossUITokens.spacingL),
75
+ child: child,
76
+ ),
77
+ if (footer != null) ...[
78
+ const SizedBox(height: CrossUITokens.spacingL),
79
+ const Divider(height: 1),
80
+ Padding(
81
+ padding: const EdgeInsets.all(CrossUITokens.spacingL),
82
+ child: footer!,
83
+ ),
84
+ ] else
85
+ const SizedBox(height: CrossUITokens.spacingL),
86
+ ],
87
+ ),
88
+ ),
89
+ );
90
+ }
91
+ }
@@ -0,0 +1,73 @@
1
+ import 'package:flutter/material.dart';
2
+ import '../theme/tokens.dart';
3
+
4
+ class CrossUIInput extends StatelessWidget {
5
+ final String? placeholder;
6
+ final TextEditingController? controller;
7
+ final bool obscureText;
8
+ final TextInputType? keyboardType;
9
+ final void Function(String)? onChanged;
10
+ final bool disabled;
11
+ final String? label;
12
+
13
+ const CrossUIInput({
14
+ Key? key,
15
+ this.placeholder,
16
+ this.controller,
17
+ this.obscureText = false,
18
+ this.keyboardType,
19
+ this.onChanged,
20
+ this.disabled = false,
21
+ this.label,
22
+ }) : super(key: key);
23
+
24
+ @override
25
+ Widget build(BuildContext context) {
26
+ return Column(
27
+ crossAxisAlignment: CrossAxisAlignment.start,
28
+ children: [
29
+ if (label != null) ...[
30
+ Text(
31
+ label!,
32
+ style: const TextStyle(
33
+ fontSize: CrossUITokens.fontSizeSm,
34
+ fontWeight: FontWeight.w600,
35
+ color: CrossUITokens.dark,
36
+ ),
37
+ ),
38
+ const SizedBox(height: CrossUITokens.spacingXs),
39
+ ],
40
+ TextField(
41
+ controller: controller,
42
+ obscureText: obscureText,
43
+ keyboardType: keyboardType,
44
+ onChanged: onChanged,
45
+ enabled: !disabled,
46
+ style: const TextStyle(fontSize: CrossUITokens.fontSizeBase),
47
+ decoration: InputDecoration(
48
+ hintText: placeholder,
49
+ hintStyle: const TextStyle(color: Color(0xFF94A3B8)),
50
+ contentPadding: const EdgeInsets.symmetric(
51
+ horizontal: CrossUITokens.spacingM,
52
+ vertical: CrossUITokens.spacingM,
53
+ ),
54
+ filled: true,
55
+ fillColor: disabled ? const Color(0xFFF1F5F9) : Colors.white,
56
+ enabledBorder: OutlineInputBorder(
57
+ borderRadius: BorderRadius.circular(CrossUITokens.radiusMedium),
58
+ borderSide: const BorderSide(color: CrossUITokens.border),
59
+ ),
60
+ focusedBorder: OutlineInputBorder(
61
+ borderRadius: BorderRadius.circular(CrossUITokens.radiusMedium),
62
+ borderSide: const BorderSide(color: CrossUITokens.primary, width: 2),
63
+ ),
64
+ disabledBorder: OutlineInputBorder(
65
+ borderRadius: BorderRadius.circular(CrossUITokens.radiusMedium),
66
+ borderSide: const BorderSide(color: CrossUITokens.border),
67
+ ),
68
+ ),
69
+ ),
70
+ ],
71
+ );
72
+ }
73
+ }
@@ -0,0 +1,87 @@
1
+ import 'package:flutter/material.dart';
2
+ import '../theme/tokens.dart';
3
+
4
+ enum CrossUITextVariant { h1, h2, h3, h4, h5, h6, body, subtitle, caption, muted, code }
5
+
6
+ class CrossUIText extends StatelessWidget {
7
+ final String text;
8
+ final CrossUITextVariant variant;
9
+ final Color? color;
10
+ final TextAlign? textAlign;
11
+ final FontWeight? fontWeight;
12
+
13
+ const CrossUIText(
14
+ this.text, {
15
+ Key? key,
16
+ this.variant = CrossUITextVariant.body,
17
+ this.color,
18
+ this.textAlign,
19
+ this.fontWeight,
20
+ }) : super(key: key);
21
+
22
+ @override
23
+ Widget build(BuildContext context) {
24
+ double fontSize;
25
+ FontWeight defaultFontWeight = FontWeight.normal;
26
+ Color defaultColor = color ?? CrossUITokens.dark;
27
+ bool isCode = false;
28
+
29
+ switch (variant) {
30
+ case CrossUITextVariant.h1:
31
+ fontSize = CrossUITokens.fontSize6xl;
32
+ defaultFontWeight = FontWeight.w900;
33
+ break;
34
+ case CrossUITextVariant.h2:
35
+ fontSize = CrossUITokens.fontSize4xl;
36
+ defaultFontWeight = FontWeight.bold;
37
+ break;
38
+ case CrossUITextVariant.h3:
39
+ fontSize = CrossUITokens.fontSize2xl;
40
+ defaultFontWeight = FontWeight.bold;
41
+ break;
42
+ case CrossUITextVariant.h4:
43
+ fontSize = CrossUITokens.fontSizeXl;
44
+ defaultFontWeight = FontWeight.w600;
45
+ break;
46
+ case CrossUITextVariant.h5:
47
+ fontSize = CrossUITokens.fontSizeLg;
48
+ defaultFontWeight = FontWeight.w600;
49
+ break;
50
+ case CrossUITextVariant.h6:
51
+ fontSize = CrossUITokens.fontSizeBase;
52
+ defaultFontWeight = FontWeight.w600;
53
+ break;
54
+ case CrossUITextVariant.subtitle:
55
+ fontSize = CrossUITokens.fontSizeLg;
56
+ defaultColor = color ?? Colors.grey[700]!;
57
+ break;
58
+ case CrossUITextVariant.caption:
59
+ fontSize = CrossUITokens.fontSizeXs;
60
+ defaultColor = color ?? Colors.grey[600]!;
61
+ break;
62
+ case CrossUITextVariant.muted:
63
+ fontSize = CrossUITokens.fontSizeSm;
64
+ defaultColor = color ?? Colors.grey[500]!;
65
+ break;
66
+ case CrossUITextVariant.code:
67
+ fontSize = CrossUITokens.fontSizeSm;
68
+ isCode = true;
69
+ break;
70
+ case CrossUITextVariant.body:
71
+ default:
72
+ fontSize = CrossUITokens.fontSizeBase;
73
+ break;
74
+ }
75
+
76
+ return Text(
77
+ text,
78
+ textAlign: textAlign,
79
+ style: TextStyle(
80
+ fontSize: fontSize,
81
+ fontWeight: fontWeight ?? defaultFontWeight,
82
+ color: defaultColor,
83
+ fontFamily: isCode ? 'monospace' : null,
84
+ ),
85
+ );
86
+ }
87
+ }
@@ -0,0 +1,13 @@
1
+ import 'package:flutter/material.dart';
2
+
3
+ class CrossUIUtils {
4
+ static TextStyle cnText(List<TextStyle?> styles) {
5
+ TextStyle result = const TextStyle();
6
+ for (var style in styles) {
7
+ if (style != null) {
8
+ result = result.merge(style);
9
+ }
10
+ }
11
+ return result;
12
+ }
13
+ }
@@ -0,0 +1,64 @@
1
+ import * as React from "react";
2
+ import * as AccordionPrimitive from "@radix-ui/react-accordion";
3
+ import { ChevronDown } from "lucide-react";
4
+
5
+ import { cn } from "@/lib/utils";
6
+
7
+ function Accordion({
8
+ ...props
9
+ }: React.ComponentProps<typeof AccordionPrimitive.Root>) {
10
+ return <AccordionPrimitive.Root data-slot="accordion" {...props} />;
11
+ }
12
+
13
+ function AccordionItem({
14
+ className,
15
+ ...props
16
+ }: React.ComponentProps<typeof AccordionPrimitive.Item>) {
17
+ return (
18
+ <AccordionPrimitive.Item
19
+ data-slot="accordion-item"
20
+ className={cn("border-b", className)}
21
+ {...props}
22
+ />
23
+ );
24
+ }
25
+
26
+ function AccordionTrigger({
27
+ className,
28
+ children,
29
+ ...props
30
+ }: React.ComponentProps<typeof AccordionPrimitive.Trigger>) {
31
+ return (
32
+ <AccordionPrimitive.Header className="flex">
33
+ <AccordionPrimitive.Trigger
34
+ data-slot="accordion-trigger"
35
+ className={cn(
36
+ "flex flex-1 items-center justify-between py-4 text-left text-sm font-medium transition-all hover:underline [&&[data-state=open]>svg]:rotate-180",
37
+ className
38
+ )}
39
+ {...props}
40
+ >
41
+ {children}
42
+ <ChevronDown className="size-4 shrink-0 transition-transform duration-200" />
43
+ </AccordionPrimitive.Trigger>
44
+ </AccordionPrimitive.Header>
45
+ );
46
+ }
47
+
48
+ function AccordionContent({
49
+ className,
50
+ children,
51
+ ...props
52
+ }: React.ComponentProps<typeof AccordionPrimitive.Content>) {
53
+ return (
54
+ <AccordionPrimitive.Content
55
+ data-slot="accordion-content"
56
+ className="overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
57
+ {...props}
58
+ >
59
+ <div className={cn("pb-4 pt-0", className)}>{children}</div>
60
+ </AccordionPrimitive.Content>
61
+ );
62
+ }
63
+
64
+ export { Accordion, AccordionItem, AccordionTrigger, AccordionContent };
@@ -0,0 +1,71 @@
1
+ import * as React from "react";
2
+ import { cva, type VariantProps } from "class-variance-authority";
3
+
4
+ import { cn } from "@/lib/utils";
5
+
6
+ const alertVariants = cva(
7
+ "relative w-full rounded-lg border px-4 py-3 text-sm grid grid-cols-[auto_1fr] gap-x-3 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current",
8
+ {
9
+ variants: {
10
+ variant: {
11
+ default: "bg-card text-card-foreground",
12
+ destructive:
13
+ "text-destructive border-destructive/50 bg-destructive/5 dark:bg-destructive/10 [&>svg]:text-destructive",
14
+ info: "text-blue-600 border-blue-500/50 bg-blue-50 dark:bg-blue-950/20 dark:text-blue-400 [&>svg]:text-blue-600 dark:[&>svg]:text-blue-400",
15
+ success:
16
+ "text-green-600 border-green-500/50 bg-green-50 dark:bg-green-950/20 dark:text-green-400 [&>svg]:text-green-600 dark:[&>svg]:text-green-400",
17
+ warning:
18
+ "text-yellow-600 border-yellow-500/50 bg-yellow-50 dark:bg-yellow-950/20 dark:text-yellow-400 [&>svg]:text-yellow-600 dark:[&>svg]:text-yellow-400",
19
+ },
20
+ },
21
+ defaultVariants: {
22
+ variant: "default",
23
+ },
24
+ }
25
+ );
26
+
27
+ function Alert({
28
+ className,
29
+ variant,
30
+ ...props
31
+ }: React.ComponentProps<"div"> & VariantProps<typeof alertVariants>) {
32
+ return (
33
+ <div
34
+ data-slot="alert"
35
+ role="alert"
36
+ className={cn(alertVariants({ variant }), className)}
37
+ {...props}
38
+ />
39
+ );
40
+ }
41
+
42
+ function AlertTitle({ className, ...props }: React.ComponentProps<"div">) {
43
+ return (
44
+ <div
45
+ data-slot="alert-title"
46
+ className={cn(
47
+ "col-start-2 line-clamp-1 min-h-4 font-medium tracking-tight",
48
+ className
49
+ )}
50
+ {...props}
51
+ />
52
+ );
53
+ }
54
+
55
+ function AlertDescription({
56
+ className,
57
+ ...props
58
+ }: React.ComponentProps<"div">) {
59
+ return (
60
+ <div
61
+ data-slot="alert-description"
62
+ className={cn(
63
+ "text-muted-foreground col-start-2 grid justify-items-start gap-1 text-sm [&_p]:leading-relaxed",
64
+ className
65
+ )}
66
+ {...props}
67
+ />
68
+ );
69
+ }
70
+
71
+ export { Alert, AlertTitle, AlertDescription };