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.
- package/README.md +78 -0
- package/dist/bin.d.ts +2 -0
- package/dist/bin.js +5 -0
- package/dist/commands/add.d.ts +1 -0
- package/dist/commands/add.js +37 -0
- package/dist/commands/init.d.ts +1 -0
- package/dist/commands/init.js +93 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +22 -0
- package/dist/templates/expo/Accordion.d.ts +14 -0
- package/dist/templates/expo/Accordion.js +118 -0
- package/dist/templates/expo/Accordion.tsx +152 -0
- package/dist/templates/expo/AlertDialog.d.ts +12 -0
- package/dist/templates/expo/AlertDialog.js +126 -0
- package/dist/templates/expo/AlertDialog.tsx +147 -0
- package/dist/templates/expo/Avatar.d.ts +8 -0
- package/dist/templates/expo/Avatar.js +81 -0
- package/dist/templates/expo/Avatar.tsx +78 -0
- package/dist/templates/expo/Badge.d.ts +6 -0
- package/dist/templates/expo/Badge.js +60 -0
- package/dist/templates/expo/Badge.tsx +67 -0
- package/dist/templates/expo/Button.d.ts +9 -0
- package/dist/templates/expo/Button.js +37 -0
- package/dist/templates/expo/Button.tsx +53 -0
- package/dist/templates/expo/Dropdown.d.ts +12 -0
- package/dist/templates/expo/Dropdown.js +91 -0
- package/dist/templates/expo/Dropdown.tsx +100 -0
- package/dist/templates/expo/Input.d.ts +11 -0
- package/dist/templates/expo/Input.js +43 -0
- package/dist/templates/expo/Input.tsx +67 -0
- package/dist/templates/expo/Toast.d.ts +16 -0
- package/dist/templates/expo/Toast.js +142 -0
- package/dist/templates/expo/Toast.tsx +161 -0
- package/dist/templates/expo/utils.d.ts +4 -0
- package/dist/templates/expo/utils.js +10 -0
- package/dist/templates/expo/utils.ts +8 -0
- package/dist/templates/flutter/Accordion.dart +142 -0
- package/dist/templates/flutter/Alert.dart +96 -0
- package/dist/templates/flutter/AlertDialog.dart +175 -0
- package/dist/templates/flutter/Avatar.dart +82 -0
- package/dist/templates/flutter/Badge.dart +89 -0
- package/dist/templates/flutter/Button.dart +116 -0
- package/dist/templates/flutter/Card.dart +91 -0
- package/dist/templates/flutter/Input.dart +73 -0
- package/dist/templates/flutter/Text.dart +87 -0
- package/dist/templates/flutter/utils.dart +13 -0
- package/dist/templates/templates/expo/Button.tsx +50 -0
- package/dist/templates/templates/expo/Input.tsx +67 -0
- package/dist/templates/web/Accordion.d.ts +7 -0
- package/dist/templates/web/Accordion.js +59 -0
- package/dist/templates/web/Accordion.tsx +64 -0
- package/dist/templates/web/Alert.d.ts +9 -0
- package/dist/templates/web/Alert.js +64 -0
- package/dist/templates/web/Alert.tsx +71 -0
- package/dist/templates/web/AlertDialog.d.ts +14 -0
- package/dist/templates/web/AlertDialog.js +85 -0
- package/dist/templates/web/AlertDialog.tsx +164 -0
- package/dist/templates/web/Avatar.d.ts +6 -0
- package/dist/templates/web/Avatar.js +50 -0
- package/dist/templates/web/Avatar.tsx +51 -0
- package/dist/templates/web/Badge.d.ts +9 -0
- package/dist/templates/web/Badge.js +59 -0
- package/dist/templates/web/Badge.tsx +38 -0
- package/dist/templates/web/Button.d.ts +10 -0
- package/dist/templates/web/Button.js +70 -0
- package/dist/templates/web/Button.tsx +60 -0
- package/dist/templates/web/Card.d.ts +9 -0
- package/dist/templates/web/Card.js +65 -0
- package/dist/templates/web/Card.tsx +92 -0
- package/dist/templates/web/Dropdown.d.ts +27 -0
- package/dist/templates/web/Dropdown.js +95 -0
- package/dist/templates/web/Dropdown.tsx +198 -0
- package/dist/templates/web/Input.d.ts +3 -0
- package/dist/templates/web/Input.js +41 -0
- package/dist/templates/web/Input.tsx +21 -0
- package/dist/templates/web/Tabs.d.ts +7 -0
- package/dist/templates/web/Tabs.js +55 -0
- package/dist/templates/web/Tabs.tsx +66 -0
- package/dist/templates/web/Toast.d.ts +15 -0
- package/dist/templates/web/Toast.js +75 -0
- package/dist/templates/web/Toast.tsx +126 -0
- package/dist/templates/web/utils.d.ts +2 -0
- package/dist/templates/web/utils.js +8 -0
- package/dist/templates/web/utils.ts +6 -0
- package/dist/utils/detect.d.ts +19 -0
- package/dist/utils/detect.js +90 -0
- package/dist/utils/fs.d.ts +5 -0
- package/dist/utils/fs.js +35 -0
- package/getlotui.config.json +4 -0
- package/package.json +31 -0
- package/src/bin.ts +5 -0
- package/src/commands/add.ts +50 -0
- package/src/commands/init.ts +108 -0
- package/src/index.ts +23 -0
- package/src/templates/expo/Accordion.tsx +152 -0
- package/src/templates/expo/AlertDialog.tsx +147 -0
- package/src/templates/expo/Avatar.tsx +78 -0
- package/src/templates/expo/Badge.tsx +67 -0
- package/src/templates/expo/Button.tsx +53 -0
- package/src/templates/expo/Dropdown.tsx +100 -0
- package/src/templates/expo/Input.tsx +67 -0
- package/src/templates/expo/Toast.tsx +161 -0
- package/src/templates/expo/utils.ts +8 -0
- package/src/templates/flutter/Accordion.dart +142 -0
- package/src/templates/flutter/Alert.dart +96 -0
- package/src/templates/flutter/AlertDialog.dart +175 -0
- package/src/templates/flutter/Avatar.dart +82 -0
- package/src/templates/flutter/Badge.dart +89 -0
- package/src/templates/flutter/Button.dart +116 -0
- package/src/templates/flutter/Card.dart +91 -0
- package/src/templates/flutter/Input.dart +73 -0
- package/src/templates/flutter/Text.dart +87 -0
- package/src/templates/flutter/utils.dart +13 -0
- package/src/templates/web/Accordion.tsx +64 -0
- package/src/templates/web/Alert.tsx +71 -0
- package/src/templates/web/AlertDialog.tsx +164 -0
- package/src/templates/web/Avatar.tsx +51 -0
- package/src/templates/web/Badge.tsx +38 -0
- package/src/templates/web/Button.tsx +60 -0
- package/src/templates/web/Card.tsx +92 -0
- package/src/templates/web/Dropdown.tsx +198 -0
- package/src/templates/web/Input.tsx +21 -0
- package/src/templates/web/Tabs.tsx +66 -0
- package/src/templates/web/Toast.tsx +126 -0
- package/src/templates/web/utils.ts +6 -0
- package/src/utils/detect.ts +81 -0
- package/src/utils/fs.ts +32 -0
- 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 };
|