@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,438 @@
1
+ import * as React from "react"
2
+ import { View, ScrollView } from "@tarojs/components"
3
+ import { Check, ChevronDown, ChevronUp } from "lucide-react-taro"
4
+ import { cn } from "@/lib/utils"
5
+ import { getRectById, getViewport } from "@/lib/measure"
6
+ import { Portal } from "@/components/ui/portal"
7
+
8
+ type SelectContextValue = {
9
+ value?: string
10
+ onValueChange?: (value: string) => void
11
+ open?: boolean
12
+ onOpenChange?: (open: boolean) => void
13
+ triggerId: string
14
+ selectedLabel?: string
15
+ setSelectedLabel?: (label?: string) => void
16
+ }
17
+
18
+ const SelectContext = React.createContext<SelectContextValue | null>(null)
19
+
20
+ interface SelectProps {
21
+ value?: string
22
+ defaultValue?: string
23
+ onValueChange?: (value: string) => void
24
+ open?: boolean
25
+ defaultOpen?: boolean
26
+ onOpenChange?: (open: boolean) => void
27
+ children?: React.ReactNode
28
+ }
29
+
30
+ const Select: React.FC<SelectProps> = ({
31
+ value: valueProp,
32
+ defaultValue,
33
+ onValueChange,
34
+ open: openProp,
35
+ defaultOpen,
36
+ onOpenChange,
37
+ children,
38
+ }) => {
39
+ const baseIdRef = React.useRef(
40
+ `select-${Math.random().toString(36).slice(2, 10)}`
41
+ )
42
+ const [openState, setOpenState] = React.useState(defaultOpen || false)
43
+ const open = openProp !== undefined ? openProp : openState
44
+ const [valueState, setValueState] = React.useState(defaultValue || "")
45
+ const value = valueProp !== undefined ? valueProp : valueState
46
+ const [selectedLabel, setSelectedLabel] = React.useState<string | undefined>(
47
+ undefined
48
+ )
49
+
50
+ const handleOpenChange = (newOpen: boolean) => {
51
+ if (openProp === undefined) {
52
+ setOpenState(newOpen)
53
+ }
54
+ onOpenChange?.(newOpen)
55
+ }
56
+
57
+ const handleValueChange = (newValue: string) => {
58
+ if (valueProp === undefined) {
59
+ setValueState(newValue)
60
+ }
61
+ onValueChange?.(newValue)
62
+ handleOpenChange(false)
63
+ }
64
+
65
+ return (
66
+ <SelectContext.Provider
67
+ value={{
68
+ value,
69
+ onValueChange: handleValueChange,
70
+ open,
71
+ onOpenChange: handleOpenChange,
72
+ triggerId: baseIdRef.current,
73
+ selectedLabel,
74
+ setSelectedLabel,
75
+ }}
76
+ >
77
+ {children}
78
+ </SelectContext.Provider>
79
+ )
80
+ }
81
+
82
+ const SelectGroup = React.forwardRef<
83
+ React.ElementRef<typeof View>,
84
+ React.ComponentPropsWithoutRef<typeof View>
85
+ >(({ className, ...props }, ref) => (
86
+ <View ref={ref} className={cn("scroll-my-1 p-1", className)} {...props} />
87
+ ))
88
+ SelectGroup.displayName = "SelectGroup"
89
+
90
+ const SelectValue = React.forwardRef<
91
+ React.ElementRef<typeof View>,
92
+ React.ComponentPropsWithoutRef<typeof View> & { placeholder?: string }
93
+ >(({ className, placeholder, children, ...props }, ref) => {
94
+ const context = React.useContext(SelectContext)
95
+ const hasValue = !!context?.value
96
+ const displayValue = children
97
+ ? children
98
+ : context?.selectedLabel || context?.value || placeholder
99
+
100
+ return (
101
+ <View
102
+ ref={ref}
103
+ className={cn(
104
+ "flex flex-1 text-left",
105
+ !hasValue && !children && "text-muted-foreground",
106
+ className
107
+ )}
108
+ {...props}
109
+ >
110
+ {displayValue}
111
+ </View>
112
+ )
113
+ })
114
+ SelectValue.displayName = "SelectValue"
115
+
116
+ const SelectTrigger = React.forwardRef<
117
+ React.ElementRef<typeof View>,
118
+ React.ComponentPropsWithoutRef<typeof View> & {
119
+ size?: "sm" | "default"
120
+ disabled?: boolean
121
+ }
122
+ >(({ className, size = "default", disabled, children, onClick, ...props }, ref) => {
123
+ const context = React.useContext(SelectContext)
124
+ return (
125
+ <View
126
+ ref={ref}
127
+ {...props}
128
+ id={context?.triggerId}
129
+ className={cn(
130
+ "flex w-fit items-center justify-between gap-2 rounded-lg border border-input bg-transparent pr-2 pl-3 text-sm whitespace-nowrap transition-colors outline-none select-none focus:border-ring focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg]:size-4",
131
+ size === "default" && "h-8 py-2",
132
+ size === "sm" && "h-7 py-1 rounded-[10px]",
133
+ context?.open &&
134
+ "border-ring ring-2 ring-ring ring-offset-2 ring-offset-background",
135
+ className
136
+ )}
137
+ hoverClass={
138
+ disabled
139
+ ? undefined
140
+ : "border-ring ring-2 ring-ring ring-offset-2 ring-offset-background"
141
+ }
142
+ onClick={(e) => {
143
+ if (disabled) return
144
+ onClick?.(e)
145
+ e.stopPropagation()
146
+ context?.onOpenChange?.(!context.open)
147
+ }}
148
+ >
149
+ {children}
150
+ <ChevronDown className="text-muted-foreground" size={16} />
151
+ </View>
152
+ )
153
+ })
154
+ SelectTrigger.displayName = "SelectTrigger"
155
+
156
+ const SelectScrollUpButton = ({ className, ...props }: React.ComponentPropsWithoutRef<typeof View>) => (
157
+ <View className={cn("flex cursor-default items-center justify-center py-1", className)} {...props}>
158
+ <ChevronUp size={16} />
159
+ </View>
160
+ )
161
+ SelectScrollUpButton.displayName = "SelectScrollUpButton"
162
+
163
+ const SelectScrollDownButton = ({ className, ...props }: React.ComponentPropsWithoutRef<typeof View>) => (
164
+ <View className={cn("flex cursor-default items-center justify-center py-1", className)} {...props}>
165
+ <ChevronDown size={16} />
166
+ </View>
167
+ )
168
+ SelectScrollDownButton.displayName = "SelectScrollDownButton"
169
+
170
+ const SelectContent = React.forwardRef<
171
+ React.ElementRef<typeof View>,
172
+ React.ComponentPropsWithoutRef<typeof View> &
173
+ Pick<
174
+ {
175
+ align?: "start" | "center" | "end"
176
+ alignOffset?: number
177
+ side?: "top" | "bottom" | "left" | "right"
178
+ sideOffset?: number
179
+ alignItemWithTrigger?: boolean
180
+ },
181
+ "align" | "alignOffset" | "side" | "sideOffset" | "alignItemWithTrigger"
182
+ >
183
+ >(
184
+ (
185
+ {
186
+ className,
187
+ children,
188
+ side = "bottom",
189
+ sideOffset = 4,
190
+ align = "center",
191
+ alignOffset = 0,
192
+ alignItemWithTrigger = true,
193
+ onClick,
194
+ ...props
195
+ },
196
+ ref
197
+ ) => {
198
+ const context = React.useContext(SelectContext)
199
+ const contentId = React.useRef(
200
+ `select-content-${Math.random().toString(36).slice(2, 10)}`
201
+ )
202
+ const [position, setPosition] = React.useState<{
203
+ left: number
204
+ top: number
205
+ } | null>(null)
206
+ const [anchorWidth, setAnchorWidth] = React.useState<number | null>(null)
207
+
208
+ React.useEffect(() => {
209
+ if (!context?.open) {
210
+ setPosition(null)
211
+ setAnchorWidth(null)
212
+ return
213
+ }
214
+
215
+ let cancelled = false
216
+
217
+ const compute = async () => {
218
+ if (!context?.triggerId) return
219
+ const [triggerRect, contentRect] = await Promise.all([
220
+ getRectById(context.triggerId),
221
+ getRectById(contentId.current),
222
+ ])
223
+
224
+ if (cancelled) return
225
+ if (!triggerRect?.width || !contentRect?.width) return
226
+
227
+ const { width: vw, height: vh } = getViewport()
228
+ const margin = 8
229
+
230
+ const contentMainSize =
231
+ alignItemWithTrigger && (side === "bottom" || side === "top")
232
+ ? triggerRect.width
233
+ : side === "left" || side === "right"
234
+ ? contentRect.height
235
+ : contentRect.width
236
+
237
+ const crossStart =
238
+ side === "left" || side === "right" ? triggerRect.top : triggerRect.left
239
+ const crossSize =
240
+ side === "left" || side === "right" ? triggerRect.height : triggerRect.width
241
+ const contentCrossSize = (() => {
242
+ if (side === "left" || side === "right") return contentRect.height
243
+ return alignItemWithTrigger ? triggerRect.width : contentRect.width
244
+ })()
245
+
246
+ const cross = (() => {
247
+ if (align === "start") return crossStart
248
+ if (align === "end") return crossStart + crossSize - contentCrossSize
249
+ return crossStart + crossSize / 2 - contentCrossSize / 2
250
+ })()
251
+
252
+ let left = 0
253
+ let top = 0
254
+
255
+ if (side === "bottom" || side === "top") {
256
+ left = cross + alignOffset
257
+ top =
258
+ side === "bottom"
259
+ ? triggerRect.top + triggerRect.height + sideOffset
260
+ : triggerRect.top - contentRect.height - sideOffset
261
+ } else {
262
+ top = cross + alignOffset
263
+ left =
264
+ side === "right"
265
+ ? triggerRect.left + triggerRect.width + sideOffset
266
+ : triggerRect.left - contentRect.width - sideOffset
267
+ }
268
+
269
+ const clampWidth =
270
+ side === "bottom" || side === "top" ? contentMainSize : contentRect.width
271
+ const clampHeight =
272
+ side === "left" || side === "right" ? contentMainSize : contentRect.height
273
+
274
+ left = Math.min(Math.max(left, margin), vw - clampWidth - margin)
275
+ top = Math.min(Math.max(top, margin), vh - clampHeight - margin)
276
+
277
+ setAnchorWidth(triggerRect.width)
278
+ setPosition({ left, top })
279
+ }
280
+
281
+ const raf = (() => {
282
+ if (typeof requestAnimationFrame !== "undefined") {
283
+ return requestAnimationFrame(() => compute())
284
+ }
285
+ return setTimeout(() => compute(), 0) as unknown as number
286
+ })()
287
+
288
+ return () => {
289
+ cancelled = true
290
+ if (typeof cancelAnimationFrame !== "undefined") {
291
+ cancelAnimationFrame(raf)
292
+ } else {
293
+ clearTimeout(raf)
294
+ }
295
+ }
296
+ }, [
297
+ align,
298
+ alignOffset,
299
+ alignItemWithTrigger,
300
+ context?.open,
301
+ context?.triggerId,
302
+ side,
303
+ sideOffset,
304
+ ])
305
+
306
+ if (!context?.open) return null
307
+
308
+ const contentStyle: React.CSSProperties = position
309
+ ? {
310
+ left: position.left,
311
+ top: position.top,
312
+ width: alignItemWithTrigger && anchorWidth ? anchorWidth : undefined,
313
+ }
314
+ : {
315
+ left: 0,
316
+ top: 0,
317
+ opacity: 0,
318
+ pointerEvents: "none",
319
+ }
320
+
321
+ return (
322
+ <Portal>
323
+ <View
324
+ className="fixed inset-0 z-50 bg-transparent"
325
+ onClick={() => context.onOpenChange?.(false)}
326
+ />
327
+ <View
328
+ ref={ref}
329
+ id={contentId.current}
330
+ className={cn(
331
+ "fixed z-50 min-w-36 overflow-x-hidden overflow-y-auto rounded-lg border bg-popover p-1 text-popover-foreground shadow-md",
332
+ className
333
+ )}
334
+ style={contentStyle}
335
+ onClick={(e) => {
336
+ onClick?.(e)
337
+ e.stopPropagation()
338
+ }}
339
+ {...props}
340
+ >
341
+ <SelectScrollUpButton className="hidden" />
342
+ <ScrollView scrollY className="max-h-[50vh]">
343
+ {children}
344
+ </ScrollView>
345
+ <SelectScrollDownButton className="hidden" />
346
+ </View>
347
+ </Portal>
348
+ )
349
+ })
350
+ SelectContent.displayName = "SelectContent"
351
+
352
+ const SelectLabel = React.forwardRef<
353
+ React.ElementRef<typeof View>,
354
+ React.ComponentPropsWithoutRef<typeof View>
355
+ >(({ className, ...props }, ref) => (
356
+ <View
357
+ ref={ref}
358
+ className={cn("px-2 py-1 text-xs text-muted-foreground", className)}
359
+ {...props}
360
+ />
361
+ ))
362
+ SelectLabel.displayName = "SelectLabel"
363
+
364
+ const SelectItem = React.forwardRef<
365
+ React.ElementRef<typeof View>,
366
+ React.ComponentPropsWithoutRef<typeof View> & { value: string; disabled?: boolean }
367
+ >(({ className, children, value, disabled, onClick, ...props }, ref) => {
368
+ const context = React.useContext(SelectContext)
369
+ const isSelected = context?.value === value
370
+
371
+ const labelText = React.useMemo(() => {
372
+ if (typeof children === "string") return children
373
+ if (Array.isArray(children) && children.every((c) => typeof c === "string")) {
374
+ return children.join("")
375
+ }
376
+ return undefined
377
+ }, [children])
378
+
379
+ React.useEffect(() => {
380
+ if (isSelected && labelText) {
381
+ context?.setSelectedLabel?.(labelText)
382
+ }
383
+ }, [context, isSelected, labelText])
384
+
385
+ return (
386
+ <View
387
+ ref={ref}
388
+ className={cn(
389
+ "relative flex w-full cursor-default items-center gap-2 rounded-md py-1 pr-8 pl-2 text-sm outline-none select-none transition-colors focus:bg-accent focus:text-accent-foreground",
390
+ disabled && "opacity-50 pointer-events-none",
391
+ className
392
+ )}
393
+ onClick={(e) => {
394
+ onClick?.(e)
395
+ if (disabled) return
396
+ e.stopPropagation()
397
+ context?.setSelectedLabel?.(labelText)
398
+ context?.onValueChange?.(value)
399
+ }}
400
+ {...props}
401
+ >
402
+ <View className="flex flex-1 shrink-0 gap-2 whitespace-nowrap">
403
+ {children}
404
+ </View>
405
+ {isSelected ? (
406
+ <View className="pointer-events-none absolute right-2 flex h-4 w-4 items-center justify-center">
407
+ <Check size={16} />
408
+ </View>
409
+ ) : null}
410
+ </View>
411
+ )
412
+ })
413
+ SelectItem.displayName = "SelectItem"
414
+
415
+ const SelectSeparator = React.forwardRef<
416
+ React.ElementRef<typeof View>,
417
+ React.ComponentPropsWithoutRef<typeof View>
418
+ >(({ className, ...props }, ref) => (
419
+ <View
420
+ ref={ref}
421
+ className={cn("pointer-events-none -mx-1 my-1 h-px bg-border", className)}
422
+ {...props}
423
+ />
424
+ ))
425
+ SelectSeparator.displayName = "SelectSeparator"
426
+
427
+ export {
428
+ Select,
429
+ SelectGroup,
430
+ SelectValue,
431
+ SelectTrigger,
432
+ SelectContent,
433
+ SelectLabel,
434
+ SelectItem,
435
+ SelectSeparator,
436
+ SelectScrollUpButton,
437
+ SelectScrollDownButton,
438
+ }
@@ -0,0 +1,30 @@
1
+ import * as React from "react"
2
+ import { View } from "@tarojs/components"
3
+
4
+ import { cn } from "@/lib/utils"
5
+
6
+ const Separator = React.forwardRef<
7
+ React.ElementRef<typeof View>,
8
+ React.ComponentPropsWithoutRef<typeof View> & {
9
+ orientation?: "horizontal" | "vertical"
10
+ decorative?: boolean
11
+ }
12
+ >(
13
+ (
14
+ { className, orientation = "horizontal", decorative = true, ...props },
15
+ ref
16
+ ) => (
17
+ <View
18
+ ref={ref}
19
+ className={cn(
20
+ "shrink-0 bg-border",
21
+ orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
22
+ className
23
+ )}
24
+ {...props}
25
+ />
26
+ )
27
+ )
28
+ Separator.displayName = "Separator"
29
+
30
+ export { Separator }