@coze-arch/cli 0.0.1-alpha.de5a13 → 0.0.1-alpha.deaedf

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 (143) hide show
  1. package/README.md +1 -0
  2. package/lib/__templates__/expo/.cozeproj/scripts/server_dev_run.sh +1 -1
  3. package/lib/__templates__/expo/client/components/Screen.tsx +2 -2
  4. package/lib/__templates__/expo/client/eslint.config.mjs +7 -0
  5. package/lib/__templates__/expo/client/metro.config.js +3 -0
  6. package/lib/__templates__/expo/client/scripts/install-missing-deps.js +10 -10
  7. package/lib/__templates__/expo/eslint-plugins/forbid-emoji/index.js +9 -0
  8. package/lib/__templates__/expo/eslint-plugins/forbid-emoji/rule.js +112 -0
  9. package/lib/__templates__/expo/eslint-plugins/forbid-emoji/tech.md +94 -0
  10. package/lib/__templates__/expo/eslint-plugins/restrict-linear-gradient/index.js +9 -0
  11. package/lib/__templates__/expo/eslint-plugins/restrict-linear-gradient/rule.js +120 -0
  12. package/lib/__templates__/expo/eslint-plugins/restrict-linear-gradient/tech.md +58 -0
  13. package/lib/__templates__/expo/pnpm-lock.yaml +8 -5
  14. package/lib/__templates__/expo/server/package.json +1 -1
  15. package/lib/__templates__/native-static/.coze +11 -0
  16. package/lib/__templates__/native-static/index.html +33 -0
  17. package/lib/__templates__/native-static/styles/main.css +136 -0
  18. package/lib/__templates__/native-static/template.config.js +22 -0
  19. package/lib/__templates__/nextjs/.babelrc +3 -0
  20. package/lib/__templates__/nextjs/README.md +5 -0
  21. package/lib/__templates__/nextjs/eslint.config.mjs +5 -0
  22. package/lib/__templates__/nextjs/next.config.ts +1 -2
  23. package/lib/__templates__/nextjs/package.json +3 -6
  24. package/lib/__templates__/nextjs/pnpm-lock.yaml +1036 -10
  25. package/lib/__templates__/nextjs/scripts/build.sh +4 -1
  26. package/lib/__templates__/nextjs/scripts/dev.sh +8 -2
  27. package/lib/__templates__/nextjs/scripts/start.sh +7 -1
  28. package/lib/__templates__/nextjs/src/app/layout.tsx +1 -1
  29. package/lib/__templates__/nextjs/src/app/page.tsx +1 -2
  30. package/lib/__templates__/nextjs/src/server.ts +35 -0
  31. package/lib/__templates__/nextjs/tsconfig.json +1 -1
  32. package/lib/__templates__/nuxt-vue/.coze +12 -0
  33. package/lib/__templates__/nuxt-vue/README.md +73 -0
  34. package/lib/__templates__/nuxt-vue/_gitignore +24 -0
  35. package/lib/__templates__/nuxt-vue/_npmrc +23 -0
  36. package/lib/__templates__/nuxt-vue/app/app.vue +6 -0
  37. package/lib/__templates__/nuxt-vue/app/pages/index.vue +23 -0
  38. package/lib/__templates__/nuxt-vue/assets/css/main.css +24 -0
  39. package/lib/__templates__/nuxt-vue/nuxt.config.ts +116 -0
  40. package/lib/__templates__/nuxt-vue/package.json +35 -0
  41. package/lib/__templates__/nuxt-vue/pnpm-lock.yaml +8759 -0
  42. package/lib/__templates__/nuxt-vue/postcss.config.mjs +8 -0
  43. package/lib/__templates__/nuxt-vue/public/favicon.ico +0 -0
  44. package/lib/__templates__/nuxt-vue/public/robots.txt +2 -0
  45. package/lib/__templates__/nuxt-vue/scripts/build.sh +14 -0
  46. package/lib/__templates__/nuxt-vue/scripts/dev.sh +39 -0
  47. package/lib/__templates__/nuxt-vue/scripts/prepare.sh +14 -0
  48. package/lib/__templates__/nuxt-vue/scripts/start.sh +21 -0
  49. package/lib/__templates__/nuxt-vue/server/api/hello.ts +10 -0
  50. package/lib/__templates__/nuxt-vue/server/middleware/logger.ts +10 -0
  51. package/lib/__templates__/nuxt-vue/server/routes/health.ts +10 -0
  52. package/lib/__templates__/nuxt-vue/tailwind.config.js +13 -0
  53. package/lib/__templates__/nuxt-vue/template.config.js +87 -0
  54. package/lib/__templates__/nuxt-vue/tsconfig.json +18 -0
  55. package/lib/__templates__/taro/.cozeproj/scripts/dev_run.sh +107 -37
  56. package/lib/__templates__/taro/.cozeproj/scripts/pack.sh +24 -1
  57. package/lib/__templates__/taro/README.md +138 -62
  58. package/lib/__templates__/taro/config/index.ts +105 -41
  59. package/lib/__templates__/taro/config/prod.ts +4 -5
  60. package/lib/__templates__/taro/eslint.config.mjs +82 -4
  61. package/lib/__templates__/taro/package.json +23 -7
  62. package/lib/__templates__/taro/patches/@tarojs__plugin-mini-ci@4.1.9.patch +30 -0
  63. package/lib/__templates__/taro/pnpm-lock.yaml +1198 -214
  64. package/lib/__templates__/taro/server/package.json +3 -1
  65. package/lib/__templates__/taro/src/app.css +140 -47
  66. package/lib/__templates__/taro/src/app.tsx +9 -0
  67. package/lib/__templates__/taro/src/components/ui/accordion.tsx +159 -0
  68. package/lib/__templates__/taro/src/components/ui/alert-dialog.tsx +260 -0
  69. package/lib/__templates__/taro/src/components/ui/alert.tsx +60 -0
  70. package/lib/__templates__/taro/src/components/ui/aspect-ratio.tsx +36 -0
  71. package/lib/__templates__/taro/src/components/ui/avatar.tsx +84 -0
  72. package/lib/__templates__/taro/src/components/ui/badge.tsx +37 -0
  73. package/lib/__templates__/taro/src/components/ui/breadcrumb.tsx +117 -0
  74. package/lib/__templates__/taro/src/components/ui/button-group.tsx +83 -0
  75. package/lib/__templates__/taro/src/components/ui/button.tsx +67 -0
  76. package/lib/__templates__/taro/src/components/ui/calendar.tsx +394 -0
  77. package/lib/__templates__/taro/src/components/ui/card.tsx +108 -0
  78. package/lib/__templates__/taro/src/components/ui/carousel.tsx +228 -0
  79. package/lib/__templates__/taro/src/components/ui/checkbox.tsx +58 -0
  80. package/lib/__templates__/taro/src/components/ui/code-block.tsx +169 -0
  81. package/lib/__templates__/taro/src/components/ui/collapsible.tsx +71 -0
  82. package/lib/__templates__/taro/src/components/ui/command.tsx +385 -0
  83. package/lib/__templates__/taro/src/components/ui/context-menu.tsx +614 -0
  84. package/lib/__templates__/taro/src/components/ui/dialog.tsx +256 -0
  85. package/lib/__templates__/taro/src/components/ui/drawer.tsx +192 -0
  86. package/lib/__templates__/taro/src/components/ui/dropdown-menu.tsx +561 -0
  87. package/lib/__templates__/taro/src/components/ui/field.tsx +228 -0
  88. package/lib/__templates__/taro/src/components/ui/hover-card.tsx +282 -0
  89. package/lib/__templates__/taro/src/components/ui/input-group.tsx +197 -0
  90. package/lib/__templates__/taro/src/components/ui/input-otp.tsx +136 -0
  91. package/lib/__templates__/taro/src/components/ui/input.tsx +56 -0
  92. package/lib/__templates__/taro/src/components/ui/label.tsx +24 -0
  93. package/lib/__templates__/taro/src/components/ui/menubar.tsx +595 -0
  94. package/lib/__templates__/taro/src/components/ui/navigation-menu.tsx +264 -0
  95. package/lib/__templates__/taro/src/components/ui/pagination.tsx +118 -0
  96. package/lib/__templates__/taro/src/components/ui/popover.tsx +291 -0
  97. package/lib/__templates__/taro/src/components/ui/portal.tsx +19 -0
  98. package/lib/__templates__/taro/src/components/ui/progress.tsx +28 -0
  99. package/lib/__templates__/taro/src/components/ui/radio-group.tsx +64 -0
  100. package/lib/__templates__/taro/src/components/ui/resizable.tsx +346 -0
  101. package/lib/__templates__/taro/src/components/ui/scroll-area.tsx +34 -0
  102. package/lib/__templates__/taro/src/components/ui/select.tsx +438 -0
  103. package/lib/__templates__/taro/src/components/ui/separator.tsx +30 -0
  104. package/lib/__templates__/taro/src/components/ui/sheet.tsx +262 -0
  105. package/lib/__templates__/taro/src/components/ui/skeleton.tsx +17 -0
  106. package/lib/__templates__/taro/src/components/ui/slider.tsx +203 -0
  107. package/lib/__templates__/taro/src/components/ui/sonner.tsx +1 -0
  108. package/lib/__templates__/taro/src/components/ui/switch.tsx +55 -0
  109. package/lib/__templates__/taro/src/components/ui/table.tsx +142 -0
  110. package/lib/__templates__/taro/src/components/ui/tabs.tsx +114 -0
  111. package/lib/__templates__/taro/src/components/ui/textarea.tsx +54 -0
  112. package/lib/__templates__/taro/src/components/ui/toast.tsx +517 -0
  113. package/lib/__templates__/taro/src/components/ui/toggle-group.tsx +120 -0
  114. package/lib/__templates__/taro/src/components/ui/toggle.tsx +77 -0
  115. package/lib/__templates__/taro/src/components/ui/tooltip.tsx +455 -0
  116. package/lib/__templates__/taro/src/lib/hooks/use-keyboard-offset.ts +37 -0
  117. package/lib/__templates__/taro/src/lib/measure.ts +115 -0
  118. package/lib/__templates__/taro/src/lib/platform.ts +12 -0
  119. package/lib/__templates__/taro/src/lib/utils.ts +6 -0
  120. package/lib/__templates__/taro/src/presets/dev-debug.ts +23 -0
  121. package/lib/__templates__/taro/src/presets/h5-container.tsx +15 -0
  122. package/lib/__templates__/taro/src/presets/h5-navbar.tsx +238 -0
  123. package/lib/__templates__/taro/src/presets/h5-styles.ts +220 -0
  124. package/lib/__templates__/taro/src/presets/index.tsx +18 -0
  125. package/lib/__templates__/templates.json +43 -0
  126. package/lib/__templates__/vite/README.md +190 -11
  127. package/lib/__templates__/vite/_gitignore +1 -0
  128. package/lib/__templates__/vite/eslint.config.mjs +6 -1
  129. package/lib/__templates__/vite/package.json +14 -5
  130. package/lib/__templates__/vite/pnpm-lock.yaml +768 -24
  131. package/lib/__templates__/vite/scripts/build.sh +4 -1
  132. package/lib/__templates__/vite/scripts/dev.sh +9 -2
  133. package/lib/__templates__/vite/scripts/start.sh +9 -3
  134. package/lib/__templates__/vite/server/routes/index.ts +31 -0
  135. package/lib/__templates__/vite/server/server.ts +65 -0
  136. package/lib/__templates__/vite/server/vite.ts +67 -0
  137. package/lib/__templates__/vite/tsconfig.json +4 -3
  138. package/lib/__templates__/vite/vite.config.ts +5 -0
  139. package/lib/cli.js +124 -103
  140. package/package.json +7 -3
  141. package/lib/__templates__/taro/src/app.ts +0 -14
  142. package/lib/__templates__/taro/src/utils/h5-styles.ts +0 -22
  143. package/lib/__templates__/taro/src/utils/wx-debug.ts +0 -23
@@ -0,0 +1,385 @@
1
+ import * as React from "react"
2
+ import { View, Input, ScrollView } from "@tarojs/components"
3
+ import Taro from "@tarojs/taro"
4
+ import { Search } from "lucide-react-taro"
5
+ import { cn } from "@/lib/utils"
6
+ import { Dialog, DialogContent } from "@/components/ui/dialog"
7
+
8
+ const CommandContext = React.createContext<{
9
+ search: string
10
+ deferredSearch: string
11
+ setSearch: (search: string) => void
12
+ } | null>(null)
13
+
14
+ const CommandItemsContext = React.createContext<{
15
+ setItemState: (id: string, state: ItemState) => void
16
+ removeItem: (id: string) => void
17
+ hasAnyMatch: () => boolean
18
+ groupHasAnyMatch: (groupId: string) => boolean
19
+ itemsSize: number
20
+ } | null>(null)
21
+
22
+ type ItemState = { match: boolean; groupId?: string }
23
+
24
+ const GroupContext = React.createContext<{ groupId?: string } | null>(null)
25
+
26
+ function getNodeText(node: React.ReactNode): string {
27
+ if (node == null || typeof node === "boolean") return ""
28
+ if (typeof node === "string" || typeof node === "number") return String(node)
29
+ if (Array.isArray(node)) return node.map(getNodeText).join(" ")
30
+ if (React.isValidElement(node)) return getNodeText(node.props?.children)
31
+ return ""
32
+ }
33
+
34
+ const Command = React.forwardRef<
35
+ React.ElementRef<typeof View>,
36
+ React.ComponentPropsWithoutRef<typeof View>
37
+ >(({ className, children, ...props }, ref) => {
38
+ const [search, setSearch] = React.useState("")
39
+ // 使用 deferredSearch 来延迟搜索过滤逻辑,确保输入框在输入时保持响应,解决微信小程序中的输入抖动和文字消失问题
40
+ const deferredSearch = React.useDeferredValue(search)
41
+ const [, setItemsTick] = React.useState(0)
42
+ const itemsRef = React.useRef<Map<string, ItemState>>(new Map())
43
+ const tickRef = React.useRef<ReturnType<typeof setTimeout> | null>(null)
44
+
45
+ React.useEffect(() => {
46
+ return () => {
47
+ if (tickRef.current) clearTimeout(tickRef.current)
48
+ }
49
+ }, [])
50
+
51
+ const triggerItemsUpdate = React.useCallback(() => {
52
+ if (tickRef.current) return
53
+ // 使用短延时批处理项目状态更新,减少重绘频率
54
+ tickRef.current = setTimeout(() => {
55
+ setItemsTick((v) => v + 1)
56
+ tickRef.current = null
57
+ }, 16)
58
+ }, [])
59
+
60
+ const setItemState = React.useCallback((id: string, state: ItemState) => {
61
+ const prev = itemsRef.current.get(id)
62
+ if (prev?.match === state.match && prev?.groupId === state.groupId) return
63
+ itemsRef.current.set(id, state)
64
+ triggerItemsUpdate()
65
+ }, [triggerItemsUpdate])
66
+
67
+ const removeItem = React.useCallback((id: string) => {
68
+ if (!itemsRef.current.has(id)) return
69
+ itemsRef.current.delete(id)
70
+ triggerItemsUpdate()
71
+ }, [triggerItemsUpdate])
72
+
73
+ const hasAnyMatch = React.useCallback(() => {
74
+ for (const s of itemsRef.current.values()) {
75
+ if (s.match) return true
76
+ }
77
+ return false
78
+ }, [])
79
+
80
+ const groupHasAnyMatch = React.useCallback((groupId: string) => {
81
+ for (const s of itemsRef.current.values()) {
82
+ if (s.groupId === groupId && s.match) return true
83
+ }
84
+ return false
85
+ }, [])
86
+
87
+ const searchContextValue = React.useMemo(() => ({
88
+ search,
89
+ deferredSearch,
90
+ setSearch,
91
+ }), [search, deferredSearch])
92
+
93
+ const itemsContextValue = React.useMemo(() => ({
94
+ setItemState,
95
+ removeItem,
96
+ hasAnyMatch,
97
+ groupHasAnyMatch,
98
+ itemsSize: itemsRef.current.size,
99
+ }), [setItemState, removeItem, hasAnyMatch, groupHasAnyMatch])
100
+
101
+ return (
102
+ <CommandContext.Provider value={searchContextValue}>
103
+ <CommandItemsContext.Provider value={itemsContextValue}>
104
+ <View
105
+ ref={ref}
106
+ className={cn(
107
+ "flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground",
108
+ className
109
+ )}
110
+ {...props}
111
+ >
112
+ {children}
113
+ </View>
114
+ </CommandItemsContext.Provider>
115
+ </CommandContext.Provider>
116
+ )
117
+ })
118
+ Command.displayName = "Command"
119
+
120
+ const CommandDialog = ({ children, ...props }) => {
121
+ const { open: openProp, defaultOpen, onOpenChange, ...rest } = props as any
122
+ const [openState, setOpenState] = React.useState(defaultOpen || false)
123
+ const open = openProp !== undefined ? openProp : openState
124
+
125
+ const handleOpenChange = (newOpen: boolean) => {
126
+ if (openProp === undefined) setOpenState(newOpen)
127
+ onOpenChange?.(newOpen)
128
+ }
129
+
130
+ const enhancedChildren = React.useMemo(() => {
131
+ const enhance = (node: React.ReactNode): React.ReactNode =>
132
+ React.Children.map(node, (child) => {
133
+ if (!React.isValidElement(child)) return child
134
+ if (child.type === CommandInput) {
135
+ if (child.props?.focus === false) return child
136
+ return React.cloneElement(child as any, {
137
+ focus: open,
138
+ className: cn(child.props?.className, "pr-11")
139
+ })
140
+ }
141
+ if (!child.props?.children) return child
142
+ return React.cloneElement(child as any, undefined, enhance(child.props.children))
143
+ })
144
+
145
+ return enhance(children)
146
+ }, [children, open])
147
+
148
+ return (
149
+ <Dialog open={open} onOpenChange={handleOpenChange} {...rest}>
150
+ <DialogContent
151
+ className="overflow-hidden p-0 shadow-lg"
152
+ closeClassName="top-3"
153
+ >
154
+ <Command>{enhancedChildren}</Command>
155
+ </DialogContent>
156
+ </Dialog>
157
+ )
158
+ }
159
+
160
+ const CommandInput = React.forwardRef<
161
+ React.ElementRef<typeof Input>,
162
+ React.ComponentPropsWithoutRef<typeof Input> & { focus?: boolean }
163
+ >(({ className, placeholderClass, focus = true, ...props }, ref) => {
164
+ const context = React.useContext(CommandContext)
165
+ const [localValue, setLocalValue] = React.useState(context?.search ?? "")
166
+ const lastSyncedSearchRef = React.useRef(context?.search ?? "")
167
+ const [inputFocus, setInputFocus] = React.useState(false)
168
+ const focusTimerRef = React.useRef<ReturnType<typeof setTimeout> | null>(null)
169
+
170
+ React.useEffect(() => {
171
+ // 只有当 context.search 与上次同步的值不同,且与当前输入值也不同时,才进行强制同步(通常是外部重置了搜索内容)
172
+ if (context?.search !== lastSyncedSearchRef.current && context?.search !== localValue) {
173
+ setLocalValue(context?.search ?? "")
174
+ lastSyncedSearchRef.current = context?.search ?? ""
175
+ }
176
+ }, [context?.search, localValue])
177
+
178
+ React.useEffect(() => {
179
+ if (focusTimerRef.current) clearTimeout(focusTimerRef.current)
180
+ focusTimerRef.current = null
181
+
182
+ if (!focus) {
183
+ setInputFocus(false)
184
+ return
185
+ }
186
+
187
+ setInputFocus(false)
188
+
189
+ const schedule = () => {
190
+ focusTimerRef.current = setTimeout(() => {
191
+ setInputFocus(true)
192
+ focusTimerRef.current = null
193
+ }, 0)
194
+ }
195
+
196
+ if (typeof (Taro as any)?.nextTick === "function") {
197
+ ;(Taro as any).nextTick(schedule)
198
+ } else {
199
+ schedule()
200
+ }
201
+
202
+ return () => {
203
+ if (focusTimerRef.current) clearTimeout(focusTimerRef.current)
204
+ focusTimerRef.current = null
205
+ }
206
+ }, [focus])
207
+
208
+ return (
209
+ <View
210
+ className="flex h-11 items-center border-b px-3"
211
+ data-slot="command-input-wrapper"
212
+ >
213
+ <Search className="mr-2 shrink-0 opacity-50" size={16} />
214
+ <Input
215
+ ref={ref}
216
+ className={cn(
217
+ "min-w-0 flex-1 rounded-md bg-transparent text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
218
+ className
219
+ )}
220
+ placeholderClass={cn("text-muted-foreground", placeholderClass)}
221
+ value={localValue}
222
+ onInput={(e) => {
223
+ const v = e.detail.value
224
+ setLocalValue(v)
225
+ lastSyncedSearchRef.current = v
226
+ context?.setSearch(v)
227
+ }}
228
+ focus={inputFocus}
229
+ {...props}
230
+ />
231
+ </View>
232
+ )
233
+ })
234
+ CommandInput.displayName = "CommandInput"
235
+
236
+ const CommandList = React.forwardRef<
237
+ React.ElementRef<typeof ScrollView>,
238
+ React.ComponentPropsWithoutRef<typeof ScrollView>
239
+ >(({ className, ...props }, ref) => (
240
+ <ScrollView
241
+ scrollY
242
+ ref={ref}
243
+ className={cn("overflow-y-auto overflow-x-hidden", className)}
244
+ {...props}
245
+ />
246
+ ))
247
+ CommandList.displayName = "CommandList"
248
+
249
+ const CommandEmpty = React.forwardRef<
250
+ React.ElementRef<typeof View>,
251
+ React.ComponentPropsWithoutRef<typeof View>
252
+ >(({ className, ...props }, ref) => {
253
+ const context = React.useContext(CommandItemsContext)
254
+
255
+ const show = context ? context.itemsSize > 0 && !context.hasAnyMatch() : false
256
+ if (!show) return null
257
+
258
+ return (
259
+ <View
260
+ ref={ref}
261
+ className={cn("py-6 text-center text-sm", className)}
262
+ {...props}
263
+ />
264
+ )
265
+ })
266
+ CommandEmpty.displayName = "CommandEmpty"
267
+
268
+ const CommandGroup = React.forwardRef<
269
+ React.ElementRef<typeof View>,
270
+ React.ComponentPropsWithoutRef<typeof View> & { heading?: React.ReactNode }
271
+ >(({ className, heading, children, ...props }, ref) => {
272
+ const context = React.useContext(CommandItemsContext)
273
+ const groupId = React.useId()
274
+
275
+ const show =
276
+ !context || context.itemsSize === 0 || context.groupHasAnyMatch(groupId)
277
+
278
+ return (
279
+ <GroupContext.Provider value={{ groupId }}>
280
+ <View
281
+ ref={ref}
282
+ data-slot="command-group"
283
+ className={cn("overflow-hidden p-1 text-foreground", className)}
284
+ style={!show ? ({ display: "none" } as any) : undefined}
285
+ {...props}
286
+ >
287
+ {heading && (
288
+ <View
289
+ data-slot="command-group-heading"
290
+ className="px-2 py-2 text-xs font-medium text-muted-foreground"
291
+ >
292
+ {heading}
293
+ </View>
294
+ )}
295
+ {children}
296
+ </View>
297
+ </GroupContext.Provider>
298
+ )
299
+ })
300
+ CommandGroup.displayName = "CommandGroup"
301
+
302
+ const CommandSeparator = React.forwardRef<
303
+ React.ElementRef<typeof View>,
304
+ React.ComponentPropsWithoutRef<typeof View>
305
+ >(({ className, ...props }, ref) => (
306
+ <View
307
+ ref={ref}
308
+ className={cn("-mx-1 h-px bg-border", className)}
309
+ {...props}
310
+ />
311
+ ))
312
+ CommandSeparator.displayName = "CommandSeparator"
313
+
314
+ const CommandItem = React.forwardRef<
315
+ React.ElementRef<typeof View>,
316
+ React.ComponentPropsWithoutRef<typeof View> & {
317
+ value?: string
318
+ onSelect?: (value: string) => void
319
+ disabled?: boolean
320
+ }
321
+ >(({ className, value, onSelect, disabled, children, ...props }, ref) => {
322
+ const context = React.useContext(CommandContext)
323
+ const itemsContext = React.useContext(CommandItemsContext)
324
+ const group = React.useContext(GroupContext)
325
+ const id = React.useId()
326
+
327
+ const computedValue = React.useMemo(() => (value ?? getNodeText(children)).trim(), [value, children])
328
+ const search = (context?.deferredSearch ?? "").trim().toLowerCase()
329
+
330
+ const match = React.useMemo(() =>
331
+ !search || (!!computedValue && computedValue.toLowerCase().includes(search))
332
+ , [search, computedValue])
333
+
334
+ React.useEffect(() => {
335
+ if (!itemsContext) return
336
+ itemsContext.setItemState(id, { match, groupId: group?.groupId })
337
+ return () => itemsContext.removeItem(id)
338
+ }, [itemsContext, id, match, group?.groupId])
339
+
340
+ return (
341
+ <View
342
+ ref={ref}
343
+ data-slot="command-item"
344
+ className={cn(
345
+ "relative flex cursor-default gap-2 select-none items-center rounded-sm px-2 py-2 text-sm outline-none data-[disabled=true]:pointer-events-none data-[selected='true']:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
346
+ disabled && "opacity-50 pointer-events-none",
347
+ className
348
+ )}
349
+ style={!match ? ({ display: "none" } as any) : undefined}
350
+ onClick={() => !disabled && onSelect?.(computedValue)}
351
+ {...props}
352
+ >
353
+ {children}
354
+ </View>
355
+ )
356
+ })
357
+ CommandItem.displayName = "CommandItem"
358
+
359
+ const CommandShortcut = ({
360
+ className,
361
+ ...props
362
+ }: React.ComponentPropsWithoutRef<typeof View>) => {
363
+ return (
364
+ <View
365
+ className={cn(
366
+ "ml-auto text-xs tracking-widest text-muted-foreground",
367
+ className
368
+ )}
369
+ {...props}
370
+ />
371
+ )
372
+ }
373
+ CommandShortcut.displayName = "CommandShortcut"
374
+
375
+ export {
376
+ Command,
377
+ CommandDialog,
378
+ CommandInput,
379
+ CommandList,
380
+ CommandEmpty,
381
+ CommandGroup,
382
+ CommandItem,
383
+ CommandShortcut,
384
+ CommandSeparator,
385
+ }