@coze-arch/cli 0.0.1-beta.6 → 0.0.2

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 (238) hide show
  1. package/README.md +1 -0
  2. package/lib/__templates__/expo/.coze +7 -2
  3. package/lib/__templates__/expo/.cozeproj/scripts/dev_build.sh +46 -0
  4. package/lib/__templates__/expo/.cozeproj/scripts/dev_run.sh +229 -0
  5. package/lib/__templates__/expo/.cozeproj/scripts/prod_build.sh +47 -0
  6. package/lib/__templates__/expo/.cozeproj/scripts/prod_run.sh +34 -0
  7. package/lib/__templates__/expo/.cozeproj/scripts/server_dev_run.sh +46 -0
  8. package/lib/__templates__/expo/README.md +68 -7
  9. package/lib/__templates__/expo/_gitignore +1 -1
  10. package/lib/__templates__/expo/_npmrc +4 -5
  11. package/lib/__templates__/expo/client/app/+not-found.tsx +15 -64
  12. package/lib/__templates__/expo/client/app/_layout.tsx +15 -12
  13. package/lib/__templates__/expo/client/app/index.tsx +1 -0
  14. package/lib/__templates__/expo/client/app.config.ts +76 -0
  15. package/lib/__templates__/expo/client/components/Screen.tsx +3 -19
  16. package/lib/__templates__/expo/client/components/ThemedText.tsx +33 -0
  17. package/lib/__templates__/expo/client/components/ThemedView.tsx +37 -0
  18. package/lib/__templates__/expo/client/constants/theme.ts +117 -58
  19. package/lib/__templates__/expo/client/contexts/AuthContext.tsx +14 -107
  20. package/lib/__templates__/expo/client/declarations.d.ts +5 -0
  21. package/lib/__templates__/expo/{eslint.config.mjs → client/eslint.config.mjs} +40 -10
  22. package/lib/__templates__/expo/client/hooks/useColorScheme.tsx +48 -0
  23. package/lib/__templates__/expo/client/hooks/useSafeRouter.ts +152 -0
  24. package/lib/__templates__/expo/client/hooks/useTheme.ts +26 -6
  25. package/lib/__templates__/expo/client/metro.config.js +124 -0
  26. package/lib/__templates__/expo/client/package.json +95 -0
  27. package/lib/__templates__/expo/client/screens/demo/index.tsx +25 -0
  28. package/lib/__templates__/expo/client/screens/demo/styles.ts +28 -0
  29. package/lib/__templates__/expo/client/scripts/install-missing-deps.js +11 -10
  30. package/lib/__templates__/expo/client/tsconfig.json +24 -0
  31. package/lib/__templates__/expo/client/utils/index.ts +23 -2
  32. package/lib/__templates__/expo/eslint-plugins/fontawesome6/index.js +9 -0
  33. package/lib/__templates__/expo/eslint-plugins/fontawesome6/names.js +1889 -0
  34. package/lib/__templates__/expo/eslint-plugins/fontawesome6/rule.js +174 -0
  35. package/lib/__templates__/expo/eslint-plugins/fontawesome6/v5-only-names.js +388 -0
  36. package/lib/__templates__/expo/eslint-plugins/forbid-emoji/index.js +9 -0
  37. package/lib/__templates__/expo/eslint-plugins/forbid-emoji/rule.js +112 -0
  38. package/lib/__templates__/expo/eslint-plugins/forbid-emoji/tech.md +94 -0
  39. package/lib/__templates__/expo/eslint-plugins/react-native/index.js +9 -0
  40. package/lib/__templates__/expo/eslint-plugins/react-native/rule.js +64 -0
  41. package/lib/__templates__/expo/eslint-plugins/reanimated/index.js +9 -0
  42. package/lib/__templates__/expo/eslint-plugins/reanimated/rule.js +88 -0
  43. package/lib/__templates__/expo/eslint-plugins/restrict-linear-gradient/index.js +9 -0
  44. package/lib/__templates__/expo/eslint-plugins/restrict-linear-gradient/rule.js +120 -0
  45. package/lib/__templates__/expo/eslint-plugins/restrict-linear-gradient/tech.md +58 -0
  46. package/lib/__templates__/expo/package.json +16 -101
  47. package/lib/__templates__/expo/patches/expo@54.0.33.patch +45 -0
  48. package/lib/__templates__/expo/pnpm-lock.yaml +1622 -3274
  49. package/lib/__templates__/expo/pnpm-workspace.yaml +3 -0
  50. package/lib/__templates__/expo/server/build.js +21 -0
  51. package/lib/__templates__/expo/server/package.json +34 -0
  52. package/lib/__templates__/expo/server/src/index.ts +20 -0
  53. package/lib/__templates__/expo/server/tsconfig.json +24 -0
  54. package/lib/__templates__/expo/template.config.js +58 -1
  55. package/lib/__templates__/expo/tsconfig.json +1 -24
  56. package/lib/__templates__/native-static/.coze +11 -0
  57. package/lib/__templates__/native-static/index.html +33 -0
  58. package/lib/__templates__/native-static/styles/main.css +136 -0
  59. package/lib/__templates__/native-static/template.config.js +22 -0
  60. package/lib/__templates__/nextjs/.coze +4 -3
  61. package/lib/__templates__/nextjs/README.md +5 -0
  62. package/lib/__templates__/nextjs/_npmrc +2 -1
  63. package/lib/__templates__/nextjs/eslint.config.mjs +5 -0
  64. package/lib/__templates__/nextjs/next.config.ts +11 -0
  65. package/lib/__templates__/nextjs/package.json +15 -1
  66. package/lib/__templates__/nextjs/pnpm-lock.yaml +7694 -4394
  67. package/lib/__templates__/nextjs/scripts/build.sh +4 -1
  68. package/lib/__templates__/nextjs/scripts/dev.sh +15 -28
  69. package/lib/__templates__/nextjs/scripts/prepare.sh +9 -0
  70. package/lib/__templates__/nextjs/scripts/start.sh +7 -1
  71. package/lib/__templates__/nextjs/src/app/globals.css +109 -89
  72. package/lib/__templates__/nextjs/src/app/layout.tsx +20 -33
  73. package/lib/__templates__/nextjs/src/app/page.tsx +18 -49
  74. package/lib/__templates__/nextjs/src/components/ui/resizable.tsx +29 -22
  75. package/lib/__templates__/nextjs/src/components/ui/sidebar.tsx +228 -230
  76. package/lib/__templates__/nextjs/src/server.ts +35 -0
  77. package/lib/__templates__/nextjs/template.config.js +68 -3
  78. package/lib/__templates__/nextjs/tsconfig.json +1 -1
  79. package/lib/__templates__/nuxt-vue/.coze +12 -0
  80. package/lib/__templates__/nuxt-vue/README.md +73 -0
  81. package/lib/__templates__/nuxt-vue/_gitignore +24 -0
  82. package/lib/__templates__/nuxt-vue/_npmrc +23 -0
  83. package/lib/__templates__/nuxt-vue/app/app.vue +6 -0
  84. package/lib/__templates__/nuxt-vue/app/pages/index.vue +23 -0
  85. package/lib/__templates__/nuxt-vue/assets/css/main.css +24 -0
  86. package/lib/__templates__/nuxt-vue/nuxt.config.ts +116 -0
  87. package/lib/__templates__/nuxt-vue/package.json +35 -0
  88. package/lib/__templates__/nuxt-vue/pnpm-lock.yaml +8759 -0
  89. package/lib/__templates__/nuxt-vue/postcss.config.mjs +8 -0
  90. package/lib/__templates__/nuxt-vue/public/favicon.ico +0 -0
  91. package/lib/__templates__/nuxt-vue/public/robots.txt +2 -0
  92. package/lib/__templates__/nuxt-vue/scripts/build.sh +14 -0
  93. package/lib/__templates__/nuxt-vue/scripts/dev.sh +39 -0
  94. package/lib/__templates__/nuxt-vue/scripts/prepare.sh +14 -0
  95. package/lib/__templates__/nuxt-vue/scripts/start.sh +21 -0
  96. package/lib/__templates__/nuxt-vue/server/api/hello.ts +10 -0
  97. package/lib/__templates__/nuxt-vue/server/middleware/logger.ts +10 -0
  98. package/lib/__templates__/nuxt-vue/server/routes/health.ts +10 -0
  99. package/lib/__templates__/nuxt-vue/tailwind.config.js +13 -0
  100. package/lib/__templates__/nuxt-vue/template.config.js +87 -0
  101. package/lib/__templates__/nuxt-vue/tsconfig.json +18 -0
  102. package/lib/__templates__/taro/.coze +14 -0
  103. package/lib/__templates__/taro/.cozeproj/scripts/deploy_build.sh +19 -0
  104. package/lib/__templates__/taro/.cozeproj/scripts/deploy_run.sh +14 -0
  105. package/lib/__templates__/taro/.cozeproj/scripts/dev_build.sh +2 -0
  106. package/lib/__templates__/taro/.cozeproj/scripts/dev_run.sh +151 -0
  107. package/lib/__templates__/taro/.cozeproj/scripts/init_env.sh +5 -0
  108. package/lib/__templates__/taro/.cozeproj/scripts/pack.sh +24 -0
  109. package/lib/__templates__/taro/README.md +763 -0
  110. package/lib/__templates__/taro/_gitignore +40 -0
  111. package/lib/__templates__/taro/_npmrc +18 -0
  112. package/lib/__templates__/taro/babel.config.js +12 -0
  113. package/lib/__templates__/taro/config/dev.ts +9 -0
  114. package/lib/__templates__/taro/config/index.ts +238 -0
  115. package/lib/__templates__/taro/config/prod.ts +34 -0
  116. package/lib/__templates__/taro/eslint.config.mjs +135 -0
  117. package/lib/__templates__/taro/key/private.appid.key +0 -0
  118. package/lib/__templates__/taro/package.json +112 -0
  119. package/lib/__templates__/taro/patches/@tarojs__plugin-mini-ci@4.1.9.patch +30 -0
  120. package/lib/__templates__/taro/pnpm-lock.yaml +23412 -0
  121. package/lib/__templates__/taro/pnpm-workspace.yaml +2 -0
  122. package/lib/__templates__/taro/project.config.json +15 -0
  123. package/lib/__templates__/taro/server/nest-cli.json +10 -0
  124. package/lib/__templates__/taro/server/package.json +40 -0
  125. package/lib/__templates__/taro/server/src/app.controller.ts +23 -0
  126. package/lib/__templates__/taro/server/src/app.module.ts +10 -0
  127. package/lib/__templates__/taro/server/src/app.service.ts +8 -0
  128. package/lib/__templates__/taro/server/src/interceptors/http-status.interceptor.ts +23 -0
  129. package/lib/__templates__/taro/server/src/main.ts +49 -0
  130. package/lib/__templates__/taro/server/tsconfig.json +24 -0
  131. package/lib/__templates__/taro/src/app.config.ts +11 -0
  132. package/lib/__templates__/taro/src/app.css +156 -0
  133. package/lib/__templates__/taro/src/app.tsx +9 -0
  134. package/lib/__templates__/taro/src/components/ui/accordion.tsx +159 -0
  135. package/lib/__templates__/taro/src/components/ui/alert-dialog.tsx +260 -0
  136. package/lib/__templates__/taro/src/components/ui/alert.tsx +60 -0
  137. package/lib/__templates__/taro/src/components/ui/aspect-ratio.tsx +36 -0
  138. package/lib/__templates__/taro/src/components/ui/avatar.tsx +84 -0
  139. package/lib/__templates__/taro/src/components/ui/badge.tsx +37 -0
  140. package/lib/__templates__/taro/src/components/ui/breadcrumb.tsx +117 -0
  141. package/lib/__templates__/taro/src/components/ui/button-group.tsx +83 -0
  142. package/lib/__templates__/taro/src/components/ui/button.tsx +67 -0
  143. package/lib/__templates__/taro/src/components/ui/calendar.tsx +394 -0
  144. package/lib/__templates__/taro/src/components/ui/card.tsx +108 -0
  145. package/lib/__templates__/taro/src/components/ui/carousel.tsx +228 -0
  146. package/lib/__templates__/taro/src/components/ui/checkbox.tsx +58 -0
  147. package/lib/__templates__/taro/src/components/ui/code-block.tsx +169 -0
  148. package/lib/__templates__/taro/src/components/ui/collapsible.tsx +71 -0
  149. package/lib/__templates__/taro/src/components/ui/command.tsx +385 -0
  150. package/lib/__templates__/taro/src/components/ui/context-menu.tsx +614 -0
  151. package/lib/__templates__/taro/src/components/ui/dialog.tsx +256 -0
  152. package/lib/__templates__/taro/src/components/ui/drawer.tsx +192 -0
  153. package/lib/__templates__/taro/src/components/ui/dropdown-menu.tsx +561 -0
  154. package/lib/__templates__/taro/src/components/ui/field.tsx +228 -0
  155. package/lib/__templates__/taro/src/components/ui/hover-card.tsx +282 -0
  156. package/lib/__templates__/taro/src/components/ui/input-group.tsx +197 -0
  157. package/lib/__templates__/taro/src/components/ui/input-otp.tsx +136 -0
  158. package/lib/__templates__/taro/src/components/ui/input.tsx +56 -0
  159. package/lib/__templates__/taro/src/components/ui/label.tsx +24 -0
  160. package/lib/__templates__/taro/src/components/ui/menubar.tsx +595 -0
  161. package/lib/__templates__/taro/src/components/ui/navigation-menu.tsx +264 -0
  162. package/lib/__templates__/taro/src/components/ui/pagination.tsx +118 -0
  163. package/lib/__templates__/taro/src/components/ui/popover.tsx +291 -0
  164. package/lib/__templates__/taro/src/components/ui/portal.tsx +19 -0
  165. package/lib/__templates__/taro/src/components/ui/progress.tsx +28 -0
  166. package/lib/__templates__/taro/src/components/ui/radio-group.tsx +64 -0
  167. package/lib/__templates__/taro/src/components/ui/resizable.tsx +346 -0
  168. package/lib/__templates__/taro/src/components/ui/scroll-area.tsx +34 -0
  169. package/lib/__templates__/taro/src/components/ui/select.tsx +438 -0
  170. package/lib/__templates__/taro/src/components/ui/separator.tsx +30 -0
  171. package/lib/__templates__/taro/src/components/ui/sheet.tsx +262 -0
  172. package/lib/__templates__/taro/src/components/ui/skeleton.tsx +17 -0
  173. package/lib/__templates__/taro/src/components/ui/slider.tsx +203 -0
  174. package/lib/__templates__/taro/src/components/ui/sonner.tsx +1 -0
  175. package/lib/__templates__/taro/src/components/ui/switch.tsx +55 -0
  176. package/lib/__templates__/taro/src/components/ui/table.tsx +142 -0
  177. package/lib/__templates__/taro/src/components/ui/tabs.tsx +114 -0
  178. package/lib/__templates__/taro/src/components/ui/textarea.tsx +54 -0
  179. package/lib/__templates__/taro/src/components/ui/toast.tsx +517 -0
  180. package/lib/__templates__/taro/src/components/ui/toggle-group.tsx +120 -0
  181. package/lib/__templates__/taro/src/components/ui/toggle.tsx +77 -0
  182. package/lib/__templates__/taro/src/components/ui/tooltip.tsx +455 -0
  183. package/lib/__templates__/taro/src/index.html +39 -0
  184. package/lib/__templates__/taro/src/lib/hooks/use-keyboard-offset.ts +37 -0
  185. package/lib/__templates__/taro/src/lib/measure.ts +115 -0
  186. package/lib/__templates__/taro/src/lib/platform.ts +12 -0
  187. package/lib/__templates__/taro/src/lib/utils.ts +6 -0
  188. package/lib/__templates__/taro/src/network.ts +39 -0
  189. package/lib/__templates__/taro/src/pages/index/index.config.ts +3 -0
  190. package/lib/__templates__/taro/src/pages/index/index.css +1 -0
  191. package/lib/__templates__/taro/src/pages/index/index.tsx +33 -0
  192. package/lib/__templates__/taro/src/presets/dev-debug.ts +23 -0
  193. package/lib/__templates__/taro/src/presets/h5-container.tsx +15 -0
  194. package/lib/__templates__/taro/src/presets/h5-navbar.tsx +238 -0
  195. package/lib/__templates__/taro/src/presets/h5-styles.ts +220 -0
  196. package/lib/__templates__/taro/src/presets/index.tsx +18 -0
  197. package/lib/__templates__/taro/stylelint.config.mjs +4 -0
  198. package/lib/__templates__/taro/template.config.js +68 -0
  199. package/lib/__templates__/taro/tsconfig.json +29 -0
  200. package/lib/__templates__/taro/types/global.d.ts +32 -0
  201. package/lib/__templates__/templates.json +136 -36
  202. package/lib/__templates__/vite/.coze +4 -3
  203. package/lib/__templates__/vite/README.md +383 -26
  204. package/lib/__templates__/vite/_gitignore +1 -0
  205. package/lib/__templates__/vite/_npmrc +2 -1
  206. package/lib/__templates__/vite/eslint.config.mjs +14 -0
  207. package/lib/__templates__/vite/package.json +23 -3
  208. package/lib/__templates__/vite/pnpm-lock.yaml +2509 -293
  209. package/lib/__templates__/vite/scripts/build.sh +4 -1
  210. package/lib/__templates__/vite/scripts/dev.sh +16 -28
  211. package/lib/__templates__/vite/scripts/prepare.sh +9 -0
  212. package/lib/__templates__/vite/scripts/start.sh +9 -3
  213. package/lib/__templates__/vite/server/routes/index.ts +31 -0
  214. package/lib/__templates__/vite/server/server.ts +65 -0
  215. package/lib/__templates__/vite/server/vite.ts +67 -0
  216. package/lib/__templates__/vite/src/main.ts +17 -48
  217. package/lib/__templates__/vite/template.config.js +77 -7
  218. package/lib/__templates__/vite/tsconfig.json +4 -3
  219. package/lib/__templates__/vite/vite.config.ts +8 -3
  220. package/lib/cli.js +1545 -526
  221. package/package.json +17 -6
  222. package/lib/__templates__/expo/.cozeproj/scripts/deploy_build.sh +0 -109
  223. package/lib/__templates__/expo/.cozeproj/scripts/deploy_run.sh +0 -257
  224. package/lib/__templates__/expo/app.json +0 -63
  225. package/lib/__templates__/expo/babel.config.js +0 -9
  226. package/lib/__templates__/expo/client/app/(tabs)/_layout.tsx +0 -43
  227. package/lib/__templates__/expo/client/app/(tabs)/home.tsx +0 -1
  228. package/lib/__templates__/expo/client/app/(tabs)/index.tsx +0 -7
  229. package/lib/__templates__/expo/client/hooks/useColorScheme.ts +0 -1
  230. package/lib/__templates__/expo/client/index.js +0 -12
  231. package/lib/__templates__/expo/client/screens/home/index.tsx +0 -54
  232. package/lib/__templates__/expo/client/screens/home/styles.ts +0 -332
  233. package/lib/__templates__/expo/metro.config.js +0 -53
  234. package/lib/__templates__/expo/src/index.ts +0 -12
  235. package/lib/__templates__/nextjs/.vscode/settings.json +0 -121
  236. package/lib/__templates__/nextjs/server.mjs +0 -50
  237. package/lib/__templates__/vite/.vscode/settings.json +0 -7
  238. /package/lib/__templates__/expo/{eslint-formatter-simple.mjs → client/eslint-formatter-simple.mjs} +0 -0
@@ -0,0 +1,228 @@
1
+ import * as React from "react"
2
+ import { View, Text } from "@tarojs/components"
3
+ import { cva, type VariantProps } from "class-variance-authority"
4
+
5
+ import { cn } from "@/lib/utils"
6
+ import { Label } from "@/components/ui/label"
7
+ import { Separator } from "@/components/ui/separator"
8
+
9
+ function FieldSet({ className, ...props }: React.ComponentPropsWithoutRef<typeof View>) {
10
+ return (
11
+ <View
12
+ data-slot="field-set"
13
+ className={cn(
14
+ "flex flex-col gap-3",
15
+ className
16
+ )}
17
+ {...props}
18
+ />
19
+ )
20
+ }
21
+
22
+ function FieldLegend({
23
+ className,
24
+ variant = "legend",
25
+ ...props
26
+ }: React.ComponentPropsWithoutRef<typeof View> & { variant?: "legend" | "label" }) {
27
+ return (
28
+ <View
29
+ data-slot="field-legend"
30
+ data-variant={variant}
31
+ className={cn(
32
+ "mb-1 font-medium",
33
+ "data-[variant=legend]:text-base",
34
+ "data-[variant=label]:text-sm",
35
+ className
36
+ )}
37
+ {...props}
38
+ />
39
+ )
40
+ }
41
+
42
+ function FieldGroup({ className, ...props }: React.ComponentPropsWithoutRef<typeof View>) {
43
+ return (
44
+ <View
45
+ data-slot="field-group"
46
+ className={cn(
47
+ "flex w-full flex-col gap-3 data-[slot=checkbox-group]:gap-3",
48
+ className
49
+ )}
50
+ {...props}
51
+ />
52
+ )
53
+ }
54
+
55
+ const fieldVariants = cva(
56
+ "data-[invalid=true]:text-destructive flex w-full gap-1",
57
+ {
58
+ variants: {
59
+ orientation: {
60
+ vertical: ["flex-col [&>view]:w-full [&>label]:w-full"],
61
+ horizontal: [
62
+ "flex-row items-center",
63
+ ],
64
+ responsive: ["flex-col [&>view]:w-full [&>label]:w-full"],
65
+ },
66
+ },
67
+ defaultVariants: {
68
+ orientation: "vertical",
69
+ },
70
+ }
71
+ )
72
+
73
+ function Field({
74
+ className,
75
+ orientation = "vertical",
76
+ ...props
77
+ }: React.ComponentPropsWithoutRef<typeof View> & VariantProps<typeof fieldVariants>) {
78
+ return (
79
+ <View
80
+ role="group"
81
+ data-slot="field"
82
+ data-orientation={orientation}
83
+ className={cn(fieldVariants({ orientation }), className)}
84
+ {...props}
85
+ />
86
+ )
87
+ }
88
+
89
+ function FieldContent({ className, ...props }: React.ComponentPropsWithoutRef<typeof View>) {
90
+ return (
91
+ <View
92
+ data-slot="field-content"
93
+ className={cn(
94
+ "flex flex-1 flex-col gap-2 leading-snug",
95
+ className
96
+ )}
97
+ {...props}
98
+ />
99
+ )
100
+ }
101
+
102
+ function FieldLabel({
103
+ className,
104
+ ...props
105
+ }: React.ComponentPropsWithoutRef<typeof Label>) {
106
+ return (
107
+ <Label
108
+ data-slot="field-label"
109
+ className={cn(
110
+ "flex w-fit gap-2 leading-snug",
111
+ "[&>view]:p-1",
112
+ className
113
+ )}
114
+ {...props}
115
+ />
116
+ )
117
+ }
118
+
119
+ function FieldTitle({ className, ...props }: React.ComponentPropsWithoutRef<typeof View>) {
120
+ return (
121
+ <View
122
+ data-slot="field-label"
123
+ className={cn(
124
+ "flex w-fit items-center gap-2 text-sm font-medium leading-snug",
125
+ className
126
+ )}
127
+ {...props}
128
+ />
129
+ )
130
+ }
131
+
132
+ function FieldDescription({ className, ...props }: React.ComponentPropsWithoutRef<typeof View>) {
133
+ return (
134
+ <View
135
+ data-slot="field-description"
136
+ className={cn(
137
+ "text-muted-foreground text-sm font-normal leading-normal",
138
+ // "group-has-[[data-orientation=horizontal]]/field:text-balance", // text-balance not supported in Taro
139
+ className
140
+ )}
141
+ {...props}
142
+ />
143
+ )
144
+ }
145
+
146
+ function FieldSeparator({
147
+ children,
148
+ className,
149
+ ...props
150
+ }: React.ComponentPropsWithoutRef<typeof View> & {
151
+ children?: React.ReactNode
152
+ }) {
153
+ return (
154
+ <View
155
+ data-slot="field-separator"
156
+ data-content={!!children}
157
+ className={cn(
158
+ "relative -my-2 h-5 text-sm",
159
+ className
160
+ )}
161
+ {...props}
162
+ >
163
+ <Separator className="absolute inset-0 top-1/2" />
164
+ {children && (
165
+ <View
166
+ className="bg-background text-muted-foreground relative mx-auto block w-fit px-2"
167
+ data-slot="field-separator-content"
168
+ >
169
+ {children}
170
+ </View>
171
+ )}
172
+ </View>
173
+ )
174
+ }
175
+
176
+ function FieldError({
177
+ className,
178
+ children,
179
+ errors,
180
+ ...props
181
+ }: React.ComponentPropsWithoutRef<typeof View> & {
182
+ errors?: Array<{ message?: string } | undefined>
183
+ }) {
184
+ // Memoize content if needed, or just render.
185
+ let content = children
186
+
187
+ if (!content && errors) {
188
+ if (errors.length === 1 && errors[0]?.message) {
189
+ content = <Text>{errors[0].message}</Text>
190
+ } else if (errors.length > 0) {
191
+ content = (
192
+ <View className="ml-4 flex flex-col gap-1">
193
+ {errors.map((error, index) =>
194
+ error?.message && <Text key={index} className="text-xs">{`\u2022 ${error.message}`}</Text>
195
+ )}
196
+ </View>
197
+ )
198
+ }
199
+ }
200
+
201
+ if (!content) {
202
+ return null
203
+ }
204
+
205
+ return (
206
+ <View
207
+ role="alert"
208
+ data-slot="field-error"
209
+ className={cn("text-destructive text-sm font-normal", className)}
210
+ {...props}
211
+ >
212
+ {content}
213
+ </View>
214
+ )
215
+ }
216
+
217
+ export {
218
+ Field,
219
+ FieldLabel,
220
+ FieldDescription,
221
+ FieldError,
222
+ FieldGroup,
223
+ FieldLegend,
224
+ FieldSeparator,
225
+ FieldSet,
226
+ FieldContent,
227
+ FieldTitle,
228
+ }
@@ -0,0 +1,282 @@
1
+ import * as React from "react"
2
+ import { View } from "@tarojs/components"
3
+ import { cn } from "@/lib/utils"
4
+ import { isH5 } from "@/lib/platform"
5
+ import { getRectById, getViewport } from "@/lib/measure"
6
+ import { Portal } from "@/components/ui/portal"
7
+
8
+ type HoverCardProps = {
9
+ children: React.ReactNode
10
+ open?: boolean
11
+ defaultOpen?: boolean
12
+ onOpenChange?: (open: boolean) => void
13
+ }
14
+
15
+ const HoverCardContext = React.createContext<{
16
+ open?: boolean
17
+ onOpenChange?: (open: boolean) => void
18
+ triggerId: string
19
+ setHoverPart?: (part: "trigger" | "content", hovering: boolean) => void
20
+ } | null>(null)
21
+
22
+ const HoverCard = ({
23
+ open: openProp,
24
+ defaultOpen = false,
25
+ onOpenChange,
26
+ children,
27
+ }: HoverCardProps) => {
28
+ const baseIdRef = React.useRef(
29
+ `hover-card-${Math.random().toString(36).slice(2, 10)}`
30
+ )
31
+ const [openState, setOpenState] = React.useState(defaultOpen)
32
+ const open = openProp !== undefined ? openProp : openState
33
+ const hoverRef = React.useRef({ trigger: false, content: false })
34
+ const closeTimerRef = React.useRef<ReturnType<typeof setTimeout> | null>(null)
35
+
36
+ const handleOpenChange = (newOpen: boolean) => {
37
+ if (openProp === undefined) {
38
+ setOpenState(newOpen)
39
+ }
40
+ onOpenChange?.(newOpen)
41
+ }
42
+
43
+ const setHoverPart = React.useCallback(
44
+ (part: "trigger" | "content", hovering: boolean) => {
45
+ if (!isH5()) return
46
+ hoverRef.current[part] = hovering
47
+ if (hovering) {
48
+ if (closeTimerRef.current) clearTimeout(closeTimerRef.current)
49
+ closeTimerRef.current = null
50
+ handleOpenChange(true)
51
+ return
52
+ }
53
+ if (closeTimerRef.current) clearTimeout(closeTimerRef.current)
54
+ closeTimerRef.current = setTimeout(() => {
55
+ if (!hoverRef.current.trigger && !hoverRef.current.content) {
56
+ handleOpenChange(false)
57
+ }
58
+ }, 80)
59
+ },
60
+ [handleOpenChange]
61
+ )
62
+
63
+ React.useEffect(() => {
64
+ return () => {
65
+ if (closeTimerRef.current) clearTimeout(closeTimerRef.current)
66
+ }
67
+ }, [])
68
+
69
+ return (
70
+ <HoverCardContext.Provider
71
+ value={{
72
+ open,
73
+ onOpenChange: handleOpenChange,
74
+ triggerId: baseIdRef.current,
75
+ setHoverPart,
76
+ }}
77
+ >
78
+ {children}
79
+ </HoverCardContext.Provider>
80
+ )
81
+ }
82
+
83
+ const HoverCardTrigger = React.forwardRef<
84
+ React.ElementRef<typeof View>,
85
+ React.ComponentPropsWithoutRef<typeof View> & {
86
+ onMouseEnter?: (e: any) => void
87
+ onMouseLeave?: (e: any) => void
88
+ }
89
+ >(({ className, children, onClick, onMouseEnter, onMouseLeave, ...props }, ref) => {
90
+ const context = React.useContext(HoverCardContext)
91
+ return (
92
+ <View
93
+ {...props}
94
+ ref={ref}
95
+ id={context?.triggerId}
96
+ className={className}
97
+ onClick={(e) => {
98
+ onClick?.(e)
99
+ e.stopPropagation()
100
+ context?.onOpenChange?.(!context.open)
101
+ }}
102
+ {...(isH5()
103
+ ? ({
104
+ onMouseEnter: (e: any) => {
105
+ onMouseEnter?.(e)
106
+ context?.setHoverPart?.("trigger", true)
107
+ },
108
+ onMouseLeave: (e: any) => {
109
+ onMouseLeave?.(e)
110
+ context?.setHoverPart?.("trigger", false)
111
+ },
112
+ } as any)
113
+ : {})}
114
+ >
115
+ {children}
116
+ </View>
117
+ )
118
+ })
119
+ HoverCardTrigger.displayName = "HoverCardTrigger"
120
+
121
+ const HoverCardContent = React.forwardRef<
122
+ React.ElementRef<typeof View>,
123
+ React.ComponentPropsWithoutRef<typeof View> & {
124
+ align?: "start" | "center" | "end"
125
+ side?: "top" | "bottom" | "left" | "right"
126
+ sideOffset?: number
127
+ onMouseEnter?: (e: any) => void
128
+ onMouseLeave?: (e: any) => void
129
+ }
130
+ >(
131
+ (
132
+ {
133
+ className,
134
+ align = "center",
135
+ side = "bottom",
136
+ sideOffset = 4,
137
+ onMouseEnter,
138
+ onMouseLeave,
139
+ ...props
140
+ },
141
+ ref
142
+ ) => {
143
+ const context = React.useContext(HoverCardContext)
144
+ const contentId = React.useRef(
145
+ `hover-card-content-${Math.random().toString(36).slice(2, 10)}`
146
+ )
147
+ const [position, setPosition] = React.useState<
148
+ | {
149
+ left: number
150
+ top: number
151
+ }
152
+ | null
153
+ >(null)
154
+
155
+ React.useEffect(() => {
156
+ if (!context?.open) {
157
+ setPosition(null)
158
+ return
159
+ }
160
+
161
+ let cancelled = false
162
+
163
+ const compute = async () => {
164
+ const [triggerRect, contentRect] = await Promise.all([
165
+ getRectById(context.triggerId),
166
+ getRectById(contentId.current),
167
+ ])
168
+
169
+ if (cancelled) return
170
+ if (!triggerRect?.width || !contentRect?.width) return
171
+
172
+ const vw = getViewport().width
173
+ const vh = getViewport().height
174
+ const margin = 8
175
+
176
+ const crossStart = (side === "left" || side === "right")
177
+ ? triggerRect.top
178
+ : triggerRect.left
179
+ const crossSize = (side === "left" || side === "right")
180
+ ? triggerRect.height
181
+ : triggerRect.width
182
+ const contentCrossSize = (side === "left" || side === "right")
183
+ ? contentRect.height
184
+ : contentRect.width
185
+
186
+ const cross = (() => {
187
+ if (align === "start") return crossStart
188
+ if (align === "end") return crossStart + crossSize - contentCrossSize
189
+ return crossStart + crossSize / 2 - contentCrossSize / 2
190
+ })()
191
+
192
+ let left = 0
193
+ let top = 0
194
+
195
+ if (side === "bottom" || side === "top") {
196
+ left = cross
197
+ top =
198
+ side === "bottom"
199
+ ? triggerRect.top + triggerRect.height + sideOffset
200
+ : triggerRect.top - contentRect.height - sideOffset
201
+ } else {
202
+ top = cross
203
+ left =
204
+ side === "right"
205
+ ? triggerRect.left + triggerRect.width + sideOffset
206
+ : triggerRect.left - contentRect.width - sideOffset
207
+ }
208
+
209
+ left = Math.min(Math.max(left, margin), vw - contentRect.width - margin)
210
+ top = Math.min(Math.max(top, margin), vh - contentRect.height - margin)
211
+
212
+ setPosition({ left, top })
213
+ }
214
+
215
+ const raf = (() => {
216
+ if (typeof requestAnimationFrame !== "undefined") {
217
+ return requestAnimationFrame(() => compute())
218
+ }
219
+ return setTimeout(() => compute(), 0) as unknown as number
220
+ })()
221
+
222
+ return () => {
223
+ cancelled = true
224
+ if (typeof cancelAnimationFrame !== "undefined") {
225
+ cancelAnimationFrame(raf)
226
+ } else {
227
+ clearTimeout(raf)
228
+ }
229
+ }
230
+ }, [align, context?.open, context?.triggerId, side, sideOffset])
231
+
232
+ if (!context?.open) return null
233
+
234
+ const baseClassName =
235
+ "fixed z-50 w-64 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95"
236
+
237
+ const contentStyle = position
238
+ ? ({ left: position.left, top: position.top } as React.CSSProperties)
239
+ : ({
240
+ left: 0,
241
+ top: 0,
242
+ opacity: 0,
243
+ pointerEvents: "none",
244
+ } as React.CSSProperties)
245
+
246
+ const overlay =
247
+ !isH5() ? (
248
+ <View
249
+ className="fixed inset-0 z-50 bg-transparent"
250
+ onClick={() => context.onOpenChange?.(false)}
251
+ />
252
+ ) : null
253
+
254
+ return (
255
+ <Portal>
256
+ {overlay}
257
+ <View
258
+ {...props}
259
+ ref={ref}
260
+ id={contentId.current}
261
+ className={cn(baseClassName, className)}
262
+ style={contentStyle}
263
+ {...(isH5()
264
+ ? ({
265
+ onMouseEnter: (e: any) => {
266
+ onMouseEnter?.(e)
267
+ context?.setHoverPart?.("content", true)
268
+ },
269
+ onMouseLeave: (e: any) => {
270
+ onMouseLeave?.(e)
271
+ context?.setHoverPart?.("content", false)
272
+ },
273
+ } as any)
274
+ : {})}
275
+ />
276
+ </Portal>
277
+ )
278
+ }
279
+ )
280
+ HoverCardContent.displayName = "HoverCardContent"
281
+
282
+ export { HoverCard, HoverCardTrigger, HoverCardContent }
@@ -0,0 +1,197 @@
1
+ import * as React from "react"
2
+ import { View, Text, Input, Textarea } from "@tarojs/components"
3
+ import { cva, type VariantProps } from "class-variance-authority"
4
+
5
+ import { cn } from "@/lib/utils"
6
+ import { Button } from "@/components/ui/button"
7
+
8
+ interface InputGroupContextValue {
9
+ isFocused: boolean
10
+ setIsFocused: (value: boolean) => void
11
+ disabled?: boolean
12
+ }
13
+
14
+ const InputGroupContext = React.createContext<InputGroupContextValue>({
15
+ isFocused: false,
16
+ setIsFocused: () => {},
17
+ disabled: false,
18
+ })
19
+
20
+ function InputGroup({ className, disabled, ...props }: React.ComponentPropsWithoutRef<typeof View> & { disabled?: boolean }) {
21
+ const [isFocused, setIsFocused] = React.useState(false)
22
+
23
+ return (
24
+ <InputGroupContext.Provider value={{ isFocused, setIsFocused, disabled }}>
25
+ <View
26
+ data-slot="input-group"
27
+ className={cn(
28
+ "border-input dark:bg-input dark:bg-opacity-30 shadow-xs relative flex w-full min-h-9 flex-wrap items-center rounded-md border outline-none transition-[color,box-shadow]",
29
+ isFocused && "ring-2 ring-ring ring-offset-2 ring-offset-background",
30
+ className
31
+ )}
32
+ {...props}
33
+ />
34
+ </InputGroupContext.Provider>
35
+ )
36
+ }
37
+
38
+ const inputGroupAddonVariants = cva(
39
+ "text-muted-foreground flex h-auto cursor-text select-none items-center justify-center gap-2 py-1 text-sm font-medium [&>kbd]:rounded-[calc(var(--radius)-5px)] [&>svg:not([class*='size-'])]:size-4",
40
+ {
41
+ variants: {
42
+ align: {
43
+ "inline-start":
44
+ "order-first pl-3",
45
+ "inline-end":
46
+ "order-last pr-3",
47
+ "block-start":
48
+ "[.border-b]:pb-3 order-first w-full justify-start px-3 pt-3",
49
+ "block-end":
50
+ "[.border-t]:pt-3 order-last w-full justify-start px-3 pb-3",
51
+ },
52
+ },
53
+ defaultVariants: {
54
+ align: "inline-start",
55
+ },
56
+ }
57
+ )
58
+
59
+ function InputGroupAddon({
60
+ className,
61
+ align = "inline-start",
62
+ ...props
63
+ }: React.ComponentPropsWithoutRef<typeof View> & VariantProps<typeof inputGroupAddonVariants>) {
64
+ const { disabled } = React.useContext(InputGroupContext)
65
+ return (
66
+ <View
67
+ data-slot="input-group-addon"
68
+ data-align={align}
69
+ className={cn(inputGroupAddonVariants({ align }), disabled && "opacity-50", className)}
70
+ {...props}
71
+ />
72
+ )
73
+ }
74
+
75
+ const inputGroupButtonVariants = cva(
76
+ "flex items-center gap-2 text-sm shadow-none",
77
+ {
78
+ variants: {
79
+ size: {
80
+ xs: "h-6 gap-1 rounded-[calc(var(--radius)-5px)] px-2 [&>svg:not([class*='size-'])]:size-3",
81
+ sm: "h-8 gap-2 rounded-md px-2",
82
+ "icon-xs":
83
+ "size-6 rounded-[calc(var(--radius)-5px)] p-0",
84
+ "icon-sm": "size-8 p-0",
85
+ },
86
+ },
87
+ defaultVariants: {
88
+ size: "xs",
89
+ },
90
+ }
91
+ )
92
+
93
+ function InputGroupButton({
94
+ className,
95
+ variant = "ghost",
96
+ size = "xs",
97
+ ...props
98
+ }: Omit<React.ComponentProps<typeof Button>, "size"> &
99
+ VariantProps<typeof inputGroupButtonVariants>) {
100
+ return (
101
+ <Button
102
+ data-size={size}
103
+ variant={variant}
104
+ className={cn(inputGroupButtonVariants({ size }), className)}
105
+ {...props}
106
+ />
107
+ )
108
+ }
109
+
110
+ function InputGroupText({ className, ...props }: React.ComponentPropsWithoutRef<typeof Text>) {
111
+ return (
112
+ <Text
113
+ className={cn(
114
+ "text-muted-foreground flex items-center gap-2 text-sm [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none",
115
+ className
116
+ )}
117
+ {...props}
118
+ />
119
+ )
120
+ }
121
+
122
+ function InputGroupInput({
123
+ className,
124
+ onFocus,
125
+ onBlur,
126
+ autoFocus,
127
+ focus,
128
+ ...props
129
+ }: React.ComponentPropsWithoutRef<typeof Input> & { autoFocus?: boolean }) {
130
+ const { setIsFocused } = React.useContext(InputGroupContext)
131
+
132
+ return (
133
+ <View className="flex h-full flex-1 items-center px-2 py-2">
134
+ <Input
135
+ data-slot="input-group-control"
136
+ className={cn(
137
+ "flex-1 bg-transparent text-base text-foreground placeholder:text-muted-foreground focus:outline-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
138
+ className
139
+ )}
140
+ placeholderClass="text-muted-foreground"
141
+ onFocus={(e) => {
142
+ setIsFocused(true)
143
+ onFocus?.(e)
144
+ }}
145
+ onBlur={(e) => {
146
+ setIsFocused(false)
147
+ onBlur?.(e)
148
+ }}
149
+ focus={autoFocus || focus}
150
+ {...props}
151
+ />
152
+ </View>
153
+ )
154
+ }
155
+
156
+ function InputGroupTextarea({
157
+ className,
158
+ onFocus,
159
+ onBlur,
160
+ autoFocus,
161
+ focus,
162
+ ...props
163
+ }: React.ComponentPropsWithoutRef<typeof Textarea> & { autoFocus?: boolean }) {
164
+ const { setIsFocused } = React.useContext(InputGroupContext)
165
+
166
+ return (
167
+ <View className="flex h-full flex-1 min-w-20 m-2">
168
+ <Textarea
169
+ data-slot="input-group-control"
170
+ className={cn(
171
+ "flex-1 w-full h-full bg-transparent text-base text-foreground placeholder:text-muted-foreground focus:outline-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
172
+ className
173
+ )}
174
+ placeholderClass="text-muted-foreground"
175
+ onFocus={(e) => {
176
+ setIsFocused(true)
177
+ onFocus?.(e)
178
+ }}
179
+ onBlur={(e) => {
180
+ setIsFocused(false)
181
+ onBlur?.(e)
182
+ }}
183
+ focus={autoFocus || focus}
184
+ {...props}
185
+ />
186
+ </View>
187
+ )
188
+ }
189
+
190
+ export {
191
+ InputGroup,
192
+ InputGroupAddon,
193
+ InputGroupButton,
194
+ InputGroupText,
195
+ InputGroupInput,
196
+ InputGroupTextarea,
197
+ }