@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
@@ -16,8 +16,10 @@
16
16
  "@nestjs/common": "^10.4.15",
17
17
  "@nestjs/core": "^10.4.15",
18
18
  "@nestjs/platform-express": "^10.4.15",
19
+ "@supabase/supabase-js": "2.95.3",
19
20
  "better-sqlite3": "^11.9.1",
20
- "coze-coding-dev-sdk": "^0.7.15",
21
+ "coze-coding-dev-sdk": "^0.7.16",
22
+ "dotenv": "^17.2.3",
21
23
  "drizzle-kit": "^0.31.8",
22
24
  "drizzle-orm": "^0.45.1",
23
25
  "drizzle-zod": "^0.8.3",
@@ -1,63 +1,156 @@
1
- @import url('tailwindcss');
2
-
3
- /*
4
- * H5 端 rem 适配:与小程序 rpx 缩放一致
5
- * 375px 屏幕:1rem = 16px,小程序 32rpx = 16px
6
- */
7
- html {
8
- font-size: 4vw !important;
9
- }
1
+ /* stylelint-disable selector-type-no-unknown */
2
+ /* stylelint-disable at-rule-no-unknown */
3
+ /* stylelint-disable number-max-precision */
4
+ @import url('weapp-tailwindcss');
10
5
 
11
6
  /* 小程序页面容器高度设置,确保垂直居中生效 */
12
- /* stylelint-disable-next-line selector-type-no-unknown */
13
7
  page {
14
8
  height: 100%;
15
9
  }
16
10
 
17
- /* H5 端组件默认样式修复 */
18
- taro-view-core {
19
- display: block;
20
- }
21
-
22
- taro-text-core {
23
- display: inline;
11
+ :root,
12
+ page,
13
+ root-portal {
14
+ --background: lab(100% 0 0);
15
+ --foreground: lab(2.75381% 0 0);
16
+ --card: lab(100% 0 0);
17
+ --card-foreground: lab(2.75381% 0 0);
18
+ --popover: lab(100% 0 0);
19
+ --popover-foreground: lab(2.75381% 0 0);
20
+ --primary: lab(7.78201% -0.0000149012 0);
21
+ --primary-foreground: lab(98.26% 0 0);
22
+ --secondary: lab(96.52% -0.0000298023 0.0000119209);
23
+ --secondary-foreground: lab(7.78201% -0.0000149012 0);
24
+ --muted: lab(96.52% -0.0000298023 0.0000119209);
25
+ --muted-foreground: lab(48.496% 0 0);
26
+ --accent: lab(96.52% -0.0000298023 0.0000119209);
27
+ --accent-foreground: lab(7.78201% -0.0000149012 0);
28
+ --destructive: lab(48.4493% 77.4328 61.5452);
29
+ --destructive-foreground: lab(96.4152% 3.22586 1.14673);
30
+ --border: lab(90.952% 0 -0.0000119209);
31
+ --input: lab(90.952% 0 -0.0000119209);
32
+ --ring: lab(66.128% -0.0000298023 0.0000119209);
33
+ --sidebar: lab(98.26% 0 0);
34
+ --sidebar-foreground: lab(2.75381% 0 0);
35
+ --sidebar-primary: lab(7.78201% -0.0000149012 0);
36
+ --sidebar-primary-foreground: lab(98.26% 0 0);
37
+ --sidebar-accent: lab(96.52% -0.0000298023 0.0000119209);
38
+ --sidebar-accent-foreground: lab(7.78201% -0.0000149012 0);
39
+ --sidebar-border: lab(90.952% 0 -0.0000119209);
40
+ --sidebar-ring: lab(66.128% -0.0000298023 0.0000119209);
41
+ --surface: lab(97.68% -0.0000298023 0.0000119209);
42
+ --code: var(--surface);
43
+ --code-highlight: lab(95.36% 0 0);
44
+ --code-number: lab(48.96% 0 0);
45
+ --selection: lab(2.75381% 0 0);
46
+ --selection-foreground: lab(100% 0 0);
47
+ --tw-shadow: 0 0 #0000;
48
+ --tw-shadow-color: initial;
49
+ --tw-shadow-alpha: 100%;
50
+ --tw-inset-shadow: 0 0 #0000;
51
+ --tw-inset-shadow-color: initial;
52
+ --tw-inset-shadow-alpha: 100%;
53
+ --tw-ring-color: initial;
54
+ --tw-ring-shadow: 0 0 #0000;
55
+ --tw-inset-ring-color: initial;
56
+ --tw-inset-ring-shadow: 0 0 #0000;
57
+ --tw-ring-inset: initial;
58
+ --tw-ring-offset-width: 0px;
59
+ --tw-ring-offset-color: #fff;
60
+ --tw-ring-offset-shadow: 0 0 #0000;
24
61
  }
25
62
 
26
- taro-input-core {
27
- display: block;
28
- width: 100%;
63
+ .dark {
64
+ --background: lab(2.75381% 0 0);
65
+ --foreground: lab(98.26% 0 0);
66
+ --card: lab(7.78201% -0.0000149012 0);
67
+ --card-foreground: lab(98.26% 0 0);
68
+ --popover: lab(7.78201% -0.0000149012 0);
69
+ --popover-foreground: lab(98.26% 0 0);
70
+ --primary: lab(90.952% 0 -0.0000119209);
71
+ --primary-foreground: lab(7.78201% -0.0000149012 0);
72
+ --secondary: lab(15.204% 0 -0.00000596046);
73
+ --secondary-foreground: lab(98.26% 0 0);
74
+ --muted: lab(15.204% 0 -0.00000596046);
75
+ --muted-foreground: lab(66.128% -0.0000298023 0.0000119209);
76
+ --accent: lab(27.036% 0 0);
77
+ --accent-foreground: lab(98.26% 0 0);
78
+ --destructive: lab(63.7053% 60.745 31.3109);
79
+ --destructive-foreground: lab(49.0747% 69.3434 49.6251);
80
+ --border: lab(100% 0 0 / 10%);
81
+ --input: lab(100% 0 0 / 15%);
82
+ --ring: lab(48.496% 0 0);
83
+ --sidebar: lab(7.78201% -0.0000149012 0);
84
+ --sidebar-foreground: lab(98.26% 0 0);
85
+ --sidebar-primary: lab(36.9089% 35.0961 -85.6872);
86
+ --sidebar-primary-foreground: lab(98.26% 0 0);
87
+ --sidebar-accent: lab(15.204% 0 -0.00000596046);
88
+ --sidebar-accent-foreground: lab(98.26% 0 0);
89
+ --sidebar-border: lab(100% 0 0 / 10%);
90
+ --sidebar-ring: lab(34.924% 0 0);
91
+ --surface: lab(7.22637% -0.0000149012 0);
92
+ --surface-foreground: lab(66.128% -0.0000298023 0.0000119209);
93
+ --code: var(--surface);
94
+ --code-highlight: lab(15.32% 0 0);
95
+ --code-number: lab(67.52% -0.0000298023 0);
96
+ --selection: lab(90.952% 0 -0.0000119209);
97
+ --selection-foreground: lab(7.78201% -0.0000149012 0);
29
98
  }
30
99
 
31
- taro-input-core input {
32
- width: 100%;
33
- background: transparent;
34
- border: none;
35
- outline: none;
36
- }
37
-
38
- /* 全局按钮样式重置 */
39
- taro-button-core,
40
- button {
41
- margin: 0 !important;
42
- padding: 0 !important;
43
- line-height: inherit;
44
- display: flex;
45
- align-items: center;
46
- justify-content: center;
47
- }
100
+ @custom-variant dark (&:is(.dark *));
48
101
 
49
- taro-button-core::after,
50
- button::after {
51
- border: none;
102
+ @theme inline {
103
+ --color-sidebar: var(--sidebar);
104
+ --color-sidebar-foreground: var(--sidebar-foreground);
105
+ --color-sidebar-primary: var(--sidebar-primary);
106
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
107
+ --color-sidebar-accent: var(--sidebar-accent);
108
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
109
+ --color-sidebar-border: var(--sidebar-border);
110
+ --color-sidebar-ring: var(--sidebar-ring);
111
+ --color-chart-5: var(--chart-5);
112
+ --color-chart-4: var(--chart-4);
113
+ --color-chart-3: var(--chart-3);
114
+ --color-chart-2: var(--chart-2);
115
+ --color-chart-1: var(--chart-1);
116
+ --color-ring: var(--ring);
117
+ --color-input: var(--input);
118
+ --color-border: var(--border);
119
+ --color-popover-foreground: var(--popover-foreground);
120
+ --color-popover: var(--popover);
121
+ --color-card-foreground: var(--card-foreground);
122
+ --color-card: var(--card);
123
+ --color-muted-foreground: var(--muted-foreground);
124
+ --color-muted: var(--muted);
125
+ --color-destructive-foreground: var(--destructive-foreground);
126
+ --color-destructive: var(--destructive);
127
+ --color-accent-foreground: var(--accent-foreground);
128
+ --color-accent: var(--accent);
129
+ --color-secondary-foreground: var(--secondary-foreground);
130
+ --color-secondary: var(--secondary);
131
+ --color-primary-foreground: var(--primary-foreground);
132
+ --color-primary: var(--primary);
133
+ --color-foreground: var(--foreground);
134
+ --color-background: var(--background);
135
+ --color-selection: var(--selection);
136
+ --color-selection-foreground: var(--selection-foreground);
137
+ --color-code: var(--code);
138
+ --radius-full: 9999px;
52
139
  }
53
140
 
54
- /* Vite 错误覆盖层无法选择文本的问题 */
55
- vite-error-overlay {
56
- /* stylelint-disable-next-line property-no-vendor-prefix */
57
- -webkit-user-select: text !important;
141
+ page,
142
+ view,
143
+ text,
144
+ button,
145
+ input,
146
+ textarea,
147
+ label,
148
+ scroll-view,
149
+ image {
150
+ border-color: var(--border);
58
151
  }
59
152
 
60
- vite-error-overlay::part(window) {
61
- max-width: 90vw;
62
- padding: 10px;
153
+ ::selection {
154
+ background-color: var(--selection);
155
+ color: var(--selection-foreground);
63
156
  }
@@ -0,0 +1,9 @@
1
+ import { PropsWithChildren } from 'react';
2
+ import '@/app.css';
3
+ import { Preset } from './presets';
4
+
5
+ const App = ({ children }: PropsWithChildren) => {
6
+ return <Preset>{children}</Preset>;
7
+ };
8
+
9
+ export default App;
@@ -0,0 +1,159 @@
1
+ import * as React from "react"
2
+ import { View } from "@tarojs/components"
3
+ import { ChevronsUpDown } from "lucide-react-taro"
4
+ import { cn } from "@/lib/utils"
5
+
6
+ const AccordionContext = React.createContext<{
7
+ value?: string | string[]
8
+ onValueChange?: (value: string | string[]) => void
9
+ type?: "single" | "multiple"
10
+ } | null>(null)
11
+
12
+ const Accordion = React.forwardRef<
13
+ React.ElementRef<typeof View>,
14
+ React.ComponentPropsWithoutRef<typeof View> & {
15
+ type?: "single" | "multiple"
16
+ value?: string | string[]
17
+ defaultValue?: string | string[]
18
+ onValueChange?: (value: string | string[]) => void
19
+ collapsible?: boolean
20
+ }
21
+ >(({ className, type = "single", value: valueProp, defaultValue, onValueChange, collapsible = false, ...props }, ref) => {
22
+ const [valueState, setValueState] = React.useState<string | string[]>(
23
+ defaultValue || (type === "multiple" ? [] : "")
24
+ )
25
+ const value = valueProp !== undefined ? valueProp : valueState
26
+
27
+ const handleValueChange = (itemValue: string) => {
28
+ let newValue: string | string[]
29
+ if (type === "multiple") {
30
+ const current = Array.isArray(value) ? value : []
31
+ if (current.includes(itemValue)) {
32
+ newValue = current.filter(v => v !== itemValue)
33
+ } else {
34
+ newValue = [...current, itemValue]
35
+ }
36
+ } else {
37
+ if (value === itemValue && collapsible) {
38
+ newValue = ""
39
+ } else {
40
+ newValue = itemValue
41
+ }
42
+ }
43
+
44
+ if (valueProp === undefined) {
45
+ setValueState(newValue)
46
+ }
47
+ onValueChange?.(newValue)
48
+ }
49
+
50
+ return (
51
+ <AccordionContext.Provider value={{ value, onValueChange: handleValueChange, type }}>
52
+ <View ref={ref} className={className} {...props} />
53
+ </AccordionContext.Provider>
54
+ )
55
+ })
56
+ Accordion.displayName = "Accordion"
57
+
58
+ const AccordionItem = React.forwardRef<
59
+ React.ElementRef<typeof View>,
60
+ React.ComponentPropsWithoutRef<typeof View> & { value: string }
61
+ >(({ className, value, ...props }, ref) => (
62
+ <View ref={ref} className={cn("border-b", className)} {...props} data-value={value} />
63
+ ))
64
+ AccordionItem.displayName = "AccordionItem"
65
+
66
+ const AccordionTrigger = React.forwardRef<
67
+ React.ElementRef<typeof View>,
68
+ React.ComponentPropsWithoutRef<typeof View>
69
+ >(({ className, children, ...props }, ref) => {
70
+ // Need to find the parent AccordionItem's value.
71
+ // In React Native/Taro we can't easily traverse up DOM.
72
+ // So we assume AccordionItem passes context or we need to explicitly pass value?
73
+ // Radix does this via context nesting.
74
+ // Let's create a context for Item.
75
+ return (
76
+ <AccordionItemContext.Consumer>
77
+ {(itemValue) => <AccordionTriggerInternal itemValue={itemValue} className={className} ref={ref} {...props}>{children}</AccordionTriggerInternal>}
78
+ </AccordionItemContext.Consumer>
79
+ )
80
+ })
81
+ AccordionTrigger.displayName = "AccordionTrigger"
82
+
83
+ // Helper context for Item
84
+ const AccordionItemContext = React.createContext<string>("")
85
+
86
+ // Update AccordionItem to provide context
87
+ const AccordionItemWithContext = React.forwardRef<
88
+ React.ElementRef<typeof View>,
89
+ React.ComponentPropsWithoutRef<typeof View> & { value: string }
90
+ >(({ className, value, children, ...props }, ref) => (
91
+ <AccordionItemContext.Provider value={value}>
92
+ <View ref={ref} className={cn("border-b", className)} {...props}>
93
+ {children}
94
+ </View>
95
+ </AccordionItemContext.Provider>
96
+ ))
97
+ AccordionItemWithContext.displayName = "AccordionItem"
98
+
99
+
100
+ const AccordionTriggerInternal = React.forwardRef<
101
+ React.ElementRef<typeof View>,
102
+ React.ComponentPropsWithoutRef<typeof View> & { itemValue: string }
103
+ >(({ className, children, itemValue, ...props }, ref) => {
104
+ const context = React.useContext(AccordionContext)
105
+ const isOpen = Array.isArray(context?.value)
106
+ ? context?.value.includes(itemValue)
107
+ : context?.value === itemValue
108
+
109
+ return (
110
+ <View className="flex">
111
+ <View
112
+ ref={ref}
113
+ className={cn(
114
+ "flex flex-1 items-center justify-between py-4 font-medium transition-all",
115
+ className
116
+ )}
117
+ onClick={() => context?.onValueChange?.(itemValue)}
118
+ {...props}
119
+ >
120
+ {children}
121
+ <ChevronsUpDown className={cn("shrink-0 transition-transform duration-200", isOpen && "rotate-180")} size={16} />
122
+ </View>
123
+ </View>
124
+ )
125
+ })
126
+
127
+ const AccordionContent = React.forwardRef<
128
+ React.ElementRef<typeof View>,
129
+ React.ComponentPropsWithoutRef<typeof View>
130
+ >(({ className, children, ...props }, ref) => (
131
+ <AccordionItemContext.Consumer>
132
+ {(itemValue) => <AccordionContentInternal itemValue={itemValue} className={className} ref={ref} {...props}>{children}</AccordionContentInternal>}
133
+ </AccordionItemContext.Consumer>
134
+ ))
135
+ AccordionContent.displayName = "AccordionContent"
136
+
137
+ const AccordionContentInternal = React.forwardRef<
138
+ React.ElementRef<typeof View>,
139
+ React.ComponentPropsWithoutRef<typeof View> & { itemValue: string }
140
+ >(({ className, children, itemValue, ...props }, ref) => {
141
+ const context = React.useContext(AccordionContext)
142
+ const isOpen = Array.isArray(context?.value)
143
+ ? context?.value.includes(itemValue)
144
+ : context?.value === itemValue
145
+
146
+ if (!isOpen) return null
147
+
148
+ return (
149
+ <View
150
+ ref={ref}
151
+ className="overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
152
+ {...props}
153
+ >
154
+ <View className={cn("pb-4 pt-0", className)}>{children}</View>
155
+ </View>
156
+ )
157
+ })
158
+
159
+ export { Accordion, AccordionItemWithContext as AccordionItem, AccordionTrigger, AccordionContent }
@@ -0,0 +1,260 @@
1
+ import * as React from "react"
2
+ import { View } from "@tarojs/components"
3
+ import { type VariantProps } from "class-variance-authority"
4
+ import { cn } from "@/lib/utils"
5
+ import { buttonVariants } from "@/components/ui/button"
6
+ import { Portal } from "@/components/ui/portal"
7
+ import { useKeyboardOffset } from "@/lib/hooks/use-keyboard-offset"
8
+
9
+ const AlertDialogContext = React.createContext<{
10
+ open?: boolean
11
+ onOpenChange?: (open: boolean) => void
12
+ } | null>(null)
13
+
14
+ const usePresence = (open: boolean | undefined, durationMs: number) => {
15
+ const [present, setPresent] = React.useState(!!open)
16
+ const timeoutRef = React.useRef<ReturnType<typeof setTimeout> | null>(null)
17
+
18
+ React.useEffect(() => {
19
+ if (open) {
20
+ if (timeoutRef.current) clearTimeout(timeoutRef.current)
21
+ timeoutRef.current = null
22
+ setPresent(true)
23
+ return
24
+ }
25
+
26
+ timeoutRef.current = setTimeout(() => setPresent(false), durationMs)
27
+ return () => {
28
+ if (timeoutRef.current) clearTimeout(timeoutRef.current)
29
+ timeoutRef.current = null
30
+ }
31
+ }, [open, durationMs])
32
+
33
+ return present
34
+ }
35
+
36
+ const AlertDialog = ({
37
+ children,
38
+ open: openProp,
39
+ defaultOpen = false,
40
+ onOpenChange
41
+ }: {
42
+ children: React.ReactNode,
43
+ open?: boolean,
44
+ defaultOpen?: boolean,
45
+ onOpenChange?: (open: boolean) => void
46
+ }) => {
47
+ const [openState, setOpenState] = React.useState(defaultOpen || false)
48
+ const open = openProp !== undefined ? openProp : openState
49
+
50
+ const handleOpenChange = (newOpen: boolean) => {
51
+ if (openProp === undefined) {
52
+ setOpenState(newOpen)
53
+ }
54
+ onOpenChange?.(newOpen)
55
+ }
56
+
57
+ return (
58
+ <AlertDialogContext.Provider value={{ open, onOpenChange: handleOpenChange }}>
59
+ {children}
60
+ </AlertDialogContext.Provider>
61
+ )
62
+ }
63
+
64
+ const AlertDialogTrigger = React.forwardRef<
65
+ React.ElementRef<typeof View>,
66
+ React.ComponentPropsWithoutRef<typeof View>
67
+ >(({ className, children, ...props }, ref) => {
68
+ const context = React.useContext(AlertDialogContext)
69
+ return (
70
+ <View
71
+ ref={ref}
72
+ className={className}
73
+ onClick={(e) => {
74
+ e.stopPropagation()
75
+ context?.onOpenChange?.(true)
76
+ }}
77
+ {...props}
78
+ >
79
+ {children}
80
+ </View>
81
+ )
82
+ })
83
+ AlertDialogTrigger.displayName = "AlertDialogTrigger"
84
+
85
+ const AlertDialogPortal = ({ children }) => {
86
+ const context = React.useContext(AlertDialogContext)
87
+ const present = usePresence(context?.open, 200)
88
+ if (!present) return null
89
+ return <Portal>{children}</Portal>
90
+ }
91
+
92
+ const AlertDialogOverlay = React.forwardRef<
93
+ React.ElementRef<typeof View>,
94
+ React.ComponentPropsWithoutRef<typeof View>
95
+ >(({ className, ...props }, ref) => {
96
+ const context = React.useContext(AlertDialogContext)
97
+ const state = context?.open ? "open" : "closed"
98
+ return (
99
+ <View
100
+ ref={ref}
101
+ data-state={state}
102
+ className={cn(
103
+ "fixed inset-0 isolate z-50 bg-black bg-opacity-10 transition-opacity duration-100 supports-[backdrop-filter]:backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
104
+ className
105
+ )}
106
+ onClick={(e) => {
107
+ e.stopPropagation()
108
+ // Unlike Dialog, AlertDialog typically forces explicit action/cancel.
109
+ // But user might want it to close on overlay click.
110
+ // Standard shadcn/radix alert dialog usually does NOT close on overlay click?
111
+ // Radix Alert Dialog does NOT close on overlay click by default.
112
+ // We will leave it as is (no close on click) or optional?
113
+ // For now, let's follow standard pattern: it blocks interaction.
114
+ }}
115
+ {...props}
116
+ />
117
+ )
118
+ })
119
+ AlertDialogOverlay.displayName = "AlertDialogOverlay"
120
+
121
+ const AlertDialogContent = React.forwardRef<
122
+ React.ElementRef<typeof View>,
123
+ React.ComponentPropsWithoutRef<typeof View>
124
+ >(({ className, children, style, ...props }, ref) => {
125
+ const context = React.useContext(AlertDialogContext)
126
+ const offset = useKeyboardOffset()
127
+ const state = context?.open ? "open" : "closed"
128
+ return (
129
+ <AlertDialogPortal>
130
+ <View className="fixed inset-0 z-50">
131
+ <AlertDialogOverlay />
132
+ <View
133
+ ref={ref}
134
+ data-state={state}
135
+ className={cn(
136
+ "fixed left-[50%] top-[50%] z-50 grid w-[calc(100%-2rem)] max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 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 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] rounded-xl",
137
+ className
138
+ )}
139
+ style={{
140
+ ...(style as object),
141
+ top: offset > 0 ? `calc(50% - ${offset / 2}px)` : undefined
142
+ }}
143
+ onClick={(e) => e.stopPropagation()}
144
+ {...props}
145
+ >
146
+ {children}
147
+ </View>
148
+ </View>
149
+ </AlertDialogPortal>
150
+ )
151
+ })
152
+ AlertDialogContent.displayName = "AlertDialogContent"
153
+
154
+ const AlertDialogHeader = ({
155
+ className,
156
+ ...props
157
+ }: React.ComponentPropsWithoutRef<typeof View>) => (
158
+ <View
159
+ className={cn(
160
+ "flex flex-col space-y-2 text-center sm:text-left",
161
+ className
162
+ )}
163
+ {...props}
164
+ />
165
+ )
166
+ AlertDialogHeader.displayName = "AlertDialogHeader"
167
+
168
+ const AlertDialogFooter = ({
169
+ className,
170
+ ...props
171
+ }: React.ComponentPropsWithoutRef<typeof View>) => (
172
+ <View
173
+ className={cn(
174
+ "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
175
+ className
176
+ )}
177
+ {...props}
178
+ />
179
+ )
180
+ AlertDialogFooter.displayName = "AlertDialogFooter"
181
+
182
+ const AlertDialogTitle = React.forwardRef<
183
+ React.ElementRef<typeof View>,
184
+ React.ComponentPropsWithoutRef<typeof View>
185
+ >(({ className, ...props }, ref) => (
186
+ <View
187
+ ref={ref}
188
+ className={cn("text-lg font-semibold", className)}
189
+ {...props}
190
+ />
191
+ ))
192
+ AlertDialogTitle.displayName = "AlertDialogTitle"
193
+
194
+ const AlertDialogDescription = React.forwardRef<
195
+ React.ElementRef<typeof View>,
196
+ React.ComponentPropsWithoutRef<typeof View>
197
+ >(({ className, ...props }, ref) => (
198
+ <View
199
+ ref={ref}
200
+ className={cn("text-sm text-muted-foreground", className)}
201
+ {...props}
202
+ />
203
+ ))
204
+ AlertDialogDescription.displayName = "AlertDialogDescription"
205
+
206
+ const AlertDialogAction = React.forwardRef<
207
+ React.ElementRef<typeof View>,
208
+ React.ComponentPropsWithoutRef<typeof View> & VariantProps<typeof buttonVariants>
209
+ >(({ className, variant, size, onClick, ...props }, ref) => {
210
+ const context = React.useContext(AlertDialogContext)
211
+ return (
212
+ <View
213
+ ref={ref}
214
+ className={cn(buttonVariants({ variant, size }), "w-full sm:w-auto", className)}
215
+ onClick={(e) => {
216
+ context?.onOpenChange?.(false)
217
+ onClick?.(e)
218
+ }}
219
+ {...props}
220
+ />
221
+ )
222
+ })
223
+ AlertDialogAction.displayName = "AlertDialogAction"
224
+
225
+ const AlertDialogCancel = React.forwardRef<
226
+ React.ElementRef<typeof View>,
227
+ React.ComponentPropsWithoutRef<typeof View> & VariantProps<typeof buttonVariants>
228
+ >(({ className, variant = "outline", size, onClick, ...props }, ref) => {
229
+ const context = React.useContext(AlertDialogContext)
230
+ return (
231
+ <View
232
+ ref={ref}
233
+ className={cn(
234
+ buttonVariants({ variant, size }),
235
+ "mt-2 sm:mt-0 w-full sm:w-auto",
236
+ className
237
+ )}
238
+ onClick={(e) => {
239
+ context?.onOpenChange?.(false)
240
+ onClick?.(e)
241
+ }}
242
+ {...props}
243
+ />
244
+ )
245
+ })
246
+ AlertDialogCancel.displayName = "AlertDialogCancel"
247
+
248
+ export {
249
+ AlertDialog,
250
+ AlertDialogPortal,
251
+ AlertDialogOverlay,
252
+ AlertDialogTrigger,
253
+ AlertDialogContent,
254
+ AlertDialogHeader,
255
+ AlertDialogFooter,
256
+ AlertDialogTitle,
257
+ AlertDialogDescription,
258
+ AlertDialogAction,
259
+ AlertDialogCancel,
260
+ }