@coze-arch/cli 0.0.1-alpha.b0f2c2 → 0.0.1-alpha.b41a94

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 (158) hide show
  1. package/README.md +1 -0
  2. package/lib/__templates__/expo/.cozeproj/scripts/dev_run.sh +13 -12
  3. package/lib/__templates__/expo/.cozeproj/scripts/server_dev_run.sh +9 -8
  4. package/lib/__templates__/expo/client/components/Screen.tsx +2 -2
  5. package/lib/__templates__/expo/client/eslint.config.mjs +7 -0
  6. package/lib/__templates__/expo/client/metro.config.js +3 -0
  7. package/lib/__templates__/expo/client/package.json +35 -35
  8. package/lib/__templates__/expo/client/screens/demo/index.tsx +3 -3
  9. package/lib/__templates__/expo/client/scripts/install-missing-deps.js +10 -10
  10. package/lib/__templates__/expo/eslint-plugins/forbid-emoji/index.js +9 -0
  11. package/lib/__templates__/expo/eslint-plugins/forbid-emoji/rule.js +112 -0
  12. package/lib/__templates__/expo/eslint-plugins/forbid-emoji/tech.md +94 -0
  13. package/lib/__templates__/expo/eslint-plugins/restrict-linear-gradient/index.js +9 -0
  14. package/lib/__templates__/expo/eslint-plugins/restrict-linear-gradient/rule.js +120 -0
  15. package/lib/__templates__/expo/eslint-plugins/restrict-linear-gradient/tech.md +58 -0
  16. package/lib/__templates__/expo/package.json +1 -1
  17. package/lib/__templates__/expo/patches/{expo@54.0.32.patch → expo@54.0.33.patch} +3 -2
  18. package/lib/__templates__/expo/pnpm-lock.yaml +340 -1736
  19. package/lib/__templates__/expo/server/package.json +9 -7
  20. package/lib/__templates__/expo/server/src/index.ts +1 -0
  21. package/lib/__templates__/expo/template.config.js +56 -0
  22. package/lib/__templates__/native-static/.coze +11 -0
  23. package/lib/__templates__/native-static/index.html +33 -0
  24. package/lib/__templates__/native-static/styles/main.css +136 -0
  25. package/lib/__templates__/native-static/template.config.js +22 -0
  26. package/lib/__templates__/nextjs/README.md +5 -0
  27. package/lib/__templates__/nextjs/eslint.config.mjs +5 -0
  28. package/lib/__templates__/nextjs/next.config.ts +1 -2
  29. package/lib/__templates__/nextjs/package.json +5 -6
  30. package/lib/__templates__/nextjs/pnpm-lock.yaml +1145 -109
  31. package/lib/__templates__/nextjs/scripts/build.sh +4 -1
  32. package/lib/__templates__/nextjs/scripts/dev.sh +8 -2
  33. package/lib/__templates__/nextjs/scripts/start.sh +7 -1
  34. package/lib/__templates__/nextjs/src/app/layout.tsx +1 -1
  35. package/lib/__templates__/nextjs/src/app/page.tsx +17 -60
  36. package/lib/__templates__/nextjs/src/server.ts +35 -0
  37. package/lib/__templates__/nextjs/template.config.js +49 -14
  38. package/lib/__templates__/nextjs/tsconfig.json +1 -1
  39. package/lib/__templates__/nuxt-vue/.coze +12 -0
  40. package/lib/__templates__/nuxt-vue/README.md +73 -0
  41. package/lib/__templates__/nuxt-vue/_gitignore +24 -0
  42. package/lib/__templates__/nuxt-vue/_npmrc +23 -0
  43. package/lib/__templates__/nuxt-vue/app/app.vue +6 -0
  44. package/lib/__templates__/nuxt-vue/app/pages/index.vue +23 -0
  45. package/lib/__templates__/nuxt-vue/assets/css/main.css +24 -0
  46. package/lib/__templates__/nuxt-vue/nuxt.config.ts +116 -0
  47. package/lib/__templates__/nuxt-vue/package.json +35 -0
  48. package/lib/__templates__/nuxt-vue/pnpm-lock.yaml +8759 -0
  49. package/lib/__templates__/nuxt-vue/postcss.config.mjs +8 -0
  50. package/lib/__templates__/nuxt-vue/public/favicon.ico +0 -0
  51. package/lib/__templates__/nuxt-vue/public/robots.txt +2 -0
  52. package/lib/__templates__/nuxt-vue/scripts/build.sh +14 -0
  53. package/lib/__templates__/nuxt-vue/scripts/dev.sh +39 -0
  54. package/lib/__templates__/nuxt-vue/scripts/prepare.sh +14 -0
  55. package/lib/__templates__/nuxt-vue/scripts/start.sh +21 -0
  56. package/lib/__templates__/nuxt-vue/server/api/hello.ts +10 -0
  57. package/lib/__templates__/nuxt-vue/server/middleware/logger.ts +10 -0
  58. package/lib/__templates__/nuxt-vue/server/routes/health.ts +10 -0
  59. package/lib/__templates__/nuxt-vue/tailwind.config.js +13 -0
  60. package/lib/__templates__/nuxt-vue/template.config.js +87 -0
  61. package/lib/__templates__/nuxt-vue/tsconfig.json +18 -0
  62. package/lib/__templates__/taro/.coze +1 -1
  63. package/lib/__templates__/taro/.cozeproj/scripts/deploy_build.sh +2 -2
  64. package/lib/__templates__/taro/.cozeproj/scripts/deploy_run.sh +4 -3
  65. package/lib/__templates__/taro/.cozeproj/scripts/dev_build.sh +0 -15
  66. package/lib/__templates__/taro/.cozeproj/scripts/dev_run.sh +117 -24
  67. package/lib/__templates__/taro/.cozeproj/scripts/pack.sh +24 -1
  68. package/lib/__templates__/taro/README.md +138 -62
  69. package/lib/__templates__/taro/config/index.ts +105 -41
  70. package/lib/__templates__/taro/config/prod.ts +4 -5
  71. package/lib/__templates__/taro/eslint.config.mjs +82 -4
  72. package/lib/__templates__/taro/package.json +22 -13
  73. package/lib/__templates__/taro/patches/@tarojs__plugin-mini-ci@4.1.9.patch +30 -0
  74. package/lib/__templates__/taro/pnpm-lock.yaml +1307 -423
  75. package/lib/__templates__/taro/server/package.json +3 -1
  76. package/lib/__templates__/taro/server/src/main.ts +14 -2
  77. package/lib/__templates__/taro/src/app.css +141 -37
  78. package/lib/__templates__/taro/src/app.tsx +9 -0
  79. package/lib/__templates__/taro/src/components/ui/accordion.tsx +159 -0
  80. package/lib/__templates__/taro/src/components/ui/alert-dialog.tsx +260 -0
  81. package/lib/__templates__/taro/src/components/ui/alert.tsx +60 -0
  82. package/lib/__templates__/taro/src/components/ui/aspect-ratio.tsx +36 -0
  83. package/lib/__templates__/taro/src/components/ui/avatar.tsx +84 -0
  84. package/lib/__templates__/taro/src/components/ui/badge.tsx +37 -0
  85. package/lib/__templates__/taro/src/components/ui/breadcrumb.tsx +117 -0
  86. package/lib/__templates__/taro/src/components/ui/button-group.tsx +83 -0
  87. package/lib/__templates__/taro/src/components/ui/button.tsx +67 -0
  88. package/lib/__templates__/taro/src/components/ui/calendar.tsx +394 -0
  89. package/lib/__templates__/taro/src/components/ui/card.tsx +108 -0
  90. package/lib/__templates__/taro/src/components/ui/carousel.tsx +228 -0
  91. package/lib/__templates__/taro/src/components/ui/checkbox.tsx +58 -0
  92. package/lib/__templates__/taro/src/components/ui/code-block.tsx +169 -0
  93. package/lib/__templates__/taro/src/components/ui/collapsible.tsx +71 -0
  94. package/lib/__templates__/taro/src/components/ui/command.tsx +385 -0
  95. package/lib/__templates__/taro/src/components/ui/context-menu.tsx +614 -0
  96. package/lib/__templates__/taro/src/components/ui/dialog.tsx +256 -0
  97. package/lib/__templates__/taro/src/components/ui/drawer.tsx +192 -0
  98. package/lib/__templates__/taro/src/components/ui/dropdown-menu.tsx +561 -0
  99. package/lib/__templates__/taro/src/components/ui/field.tsx +228 -0
  100. package/lib/__templates__/taro/src/components/ui/hover-card.tsx +282 -0
  101. package/lib/__templates__/taro/src/components/ui/input-group.tsx +197 -0
  102. package/lib/__templates__/taro/src/components/ui/input-otp.tsx +136 -0
  103. package/lib/__templates__/taro/src/components/ui/input.tsx +56 -0
  104. package/lib/__templates__/taro/src/components/ui/label.tsx +24 -0
  105. package/lib/__templates__/taro/src/components/ui/menubar.tsx +595 -0
  106. package/lib/__templates__/taro/src/components/ui/navigation-menu.tsx +264 -0
  107. package/lib/__templates__/taro/src/components/ui/pagination.tsx +118 -0
  108. package/lib/__templates__/taro/src/components/ui/popover.tsx +291 -0
  109. package/lib/__templates__/taro/src/components/ui/portal.tsx +19 -0
  110. package/lib/__templates__/taro/src/components/ui/progress.tsx +28 -0
  111. package/lib/__templates__/taro/src/components/ui/radio-group.tsx +64 -0
  112. package/lib/__templates__/taro/src/components/ui/resizable.tsx +346 -0
  113. package/lib/__templates__/taro/src/components/ui/scroll-area.tsx +34 -0
  114. package/lib/__templates__/taro/src/components/ui/select.tsx +438 -0
  115. package/lib/__templates__/taro/src/components/ui/separator.tsx +30 -0
  116. package/lib/__templates__/taro/src/components/ui/sheet.tsx +262 -0
  117. package/lib/__templates__/taro/src/components/ui/skeleton.tsx +17 -0
  118. package/lib/__templates__/taro/src/components/ui/slider.tsx +203 -0
  119. package/lib/__templates__/taro/src/components/ui/sonner.tsx +1 -0
  120. package/lib/__templates__/taro/src/components/ui/switch.tsx +55 -0
  121. package/lib/__templates__/taro/src/components/ui/table.tsx +142 -0
  122. package/lib/__templates__/taro/src/components/ui/tabs.tsx +114 -0
  123. package/lib/__templates__/taro/src/components/ui/textarea.tsx +54 -0
  124. package/lib/__templates__/taro/src/components/ui/toast.tsx +517 -0
  125. package/lib/__templates__/taro/src/components/ui/toggle-group.tsx +120 -0
  126. package/lib/__templates__/taro/src/components/ui/toggle.tsx +77 -0
  127. package/lib/__templates__/taro/src/components/ui/tooltip.tsx +455 -0
  128. package/lib/__templates__/taro/src/index.html +20 -1
  129. package/lib/__templates__/taro/src/lib/hooks/use-keyboard-offset.ts +37 -0
  130. package/lib/__templates__/taro/src/lib/measure.ts +115 -0
  131. package/lib/__templates__/taro/src/lib/platform.ts +12 -0
  132. package/lib/__templates__/taro/src/lib/utils.ts +6 -0
  133. package/lib/__templates__/taro/src/presets/dev-debug.ts +23 -0
  134. package/lib/__templates__/taro/src/presets/h5-container.tsx +15 -0
  135. package/lib/__templates__/taro/src/presets/h5-navbar.tsx +238 -0
  136. package/lib/__templates__/taro/src/presets/h5-styles.ts +220 -0
  137. package/lib/__templates__/taro/src/presets/index.tsx +18 -0
  138. package/lib/__templates__/templates.json +28 -22
  139. package/lib/__templates__/vite/README.md +190 -11
  140. package/lib/__templates__/vite/_gitignore +1 -0
  141. package/lib/__templates__/vite/eslint.config.mjs +6 -1
  142. package/lib/__templates__/vite/package.json +14 -3
  143. package/lib/__templates__/vite/pnpm-lock.yaml +820 -1593
  144. package/lib/__templates__/vite/scripts/build.sh +4 -1
  145. package/lib/__templates__/vite/scripts/dev.sh +9 -2
  146. package/lib/__templates__/vite/scripts/start.sh +9 -3
  147. package/lib/__templates__/vite/server/routes/index.ts +31 -0
  148. package/lib/__templates__/vite/server/server.ts +65 -0
  149. package/lib/__templates__/vite/server/vite.ts +67 -0
  150. package/lib/__templates__/vite/src/main.ts +17 -47
  151. package/lib/__templates__/vite/template.config.js +49 -14
  152. package/lib/__templates__/vite/tsconfig.json +4 -3
  153. package/lib/__templates__/vite/vite.config.ts +5 -0
  154. package/lib/cli.js +160 -159
  155. package/package.json +7 -3
  156. package/lib/__templates__/taro/src/app.ts +0 -14
  157. package/lib/__templates__/taro/src/utils/h5-styles.ts +0 -22
  158. 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.3",
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",
@@ -3,6 +3,18 @@ import { AppModule } from '@/app.module';
3
3
  import * as express from 'express';
4
4
  import { HttpStatusInterceptor } from '@/interceptors/http-status.interceptor';
5
5
 
6
+ function parsePort(): number {
7
+ const args = process.argv.slice(2);
8
+ const portIndex = args.indexOf('-p');
9
+ if (portIndex !== -1 && args[portIndex + 1]) {
10
+ const port = parseInt(args[portIndex + 1], 10);
11
+ if (!isNaN(port) && port > 0 && port < 65536) {
12
+ return port;
13
+ }
14
+ }
15
+ return <%= serverPort %>;
16
+ }
17
+
6
18
  async function bootstrap() {
7
19
  const app = await NestFactory.create(AppModule);
8
20
 
@@ -19,8 +31,8 @@ async function bootstrap() {
19
31
  // 1. 开启优雅关闭 Hooks (关键!)
20
32
  app.enableShutdownHooks();
21
33
 
22
- // 2. 增加错误处理,防止端口被占时直接崩溃,而是给出一个清晰的提示
23
- const port = <%= serverPort %>;
34
+ // 2. 解析端口
35
+ const port = parsePort();
24
36
  try {
25
37
  await app.listen(port);
26
38
  console.log(`Server running on http://localhost:${port}`);
@@ -1,52 +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
- height: 100%;
8
+ height: 100%;
15
9
  }
16
10
 
17
- /* H5 端组件默认样式修复 */
18
- taro-view-core {
19
- display: block;
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;
20
61
  }
21
62
 
22
- taro-text-core {
23
- display: inline;
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);
24
98
  }
25
99
 
26
- taro-input-core {
27
- display: block;
28
- width: 100%;
29
- }
100
+ @custom-variant dark (&:is(.dark *));
30
101
 
31
- taro-input-core input {
32
- width: 100%;
33
- background: transparent;
34
- border: none;
35
- outline: 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;
36
139
  }
37
140
 
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;
141
+ page,
142
+ view,
143
+ text,
144
+ button,
145
+ input,
146
+ textarea,
147
+ label,
148
+ scroll-view,
149
+ image {
150
+ border-color: var(--border);
47
151
  }
48
152
 
49
- taro-button-core::after,
50
- button::after {
51
- border: none;
153
+ ::selection {
154
+ background-color: var(--selection);
155
+ color: var(--selection-foreground);
52
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
+ }