create-next-imagicma 0.0.5 → 0.0.7

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 (104) hide show
  1. package/README.md +30 -14
  2. package/bin/create-next-imagicma.mjs +121 -23
  3. package/package.json +2 -1
  4. package/template/app/globals.css +331 -0
  5. package/template/app/layout.tsx +4 -6
  6. package/template/app/page.tsx +18 -40
  7. package/template/package.json +1 -1
  8. package/template/public/imagicma-picker-bridge.js +374 -0
  9. package/template-hono/.env.example +8 -0
  10. package/template-hono/AGENTS.md +39 -0
  11. package/template-hono/README.md +58 -0
  12. package/template-hono/client/index.html +13 -0
  13. package/template-hono/client/public/favicon.ico +0 -0
  14. package/template-hono/client/public/file.svg +1 -0
  15. package/template-hono/client/public/globe.svg +1 -0
  16. package/template-hono/client/public/imagicma-picker-bridge.js +374 -0
  17. package/template-hono/client/public/next.svg +1 -0
  18. package/template-hono/client/public/vercel.svg +1 -0
  19. package/template-hono/client/public/window.svg +1 -0
  20. package/template-hono/client/src/App.tsx +13 -0
  21. package/template-hono/client/src/components/ErrorBoundary.tsx +74 -0
  22. package/template-hono/client/src/components/HelloClient.tsx +69 -0
  23. package/template-hono/client/src/components/ui/accordion.tsx +58 -0
  24. package/template-hono/client/src/components/ui/alert-dialog.tsx +141 -0
  25. package/template-hono/client/src/components/ui/alert.tsx +61 -0
  26. package/template-hono/client/src/components/ui/aspect-ratio.tsx +7 -0
  27. package/template-hono/client/src/components/ui/avatar.tsx +51 -0
  28. package/template-hono/client/src/components/ui/badge.tsx +40 -0
  29. package/template-hono/client/src/components/ui/breadcrumb.tsx +117 -0
  30. package/template-hono/client/src/components/ui/button.tsx +64 -0
  31. package/template-hono/client/src/components/ui/calendar.tsx +72 -0
  32. package/template-hono/client/src/components/ui/card.tsx +87 -0
  33. package/template-hono/client/src/components/ui/carousel.tsx +262 -0
  34. package/template-hono/client/src/components/ui/chart.tsx +365 -0
  35. package/template-hono/client/src/components/ui/checkbox.tsx +30 -0
  36. package/template-hono/client/src/components/ui/collapsible.tsx +11 -0
  37. package/template-hono/client/src/components/ui/command.tsx +153 -0
  38. package/template-hono/client/src/components/ui/context-menu.tsx +200 -0
  39. package/template-hono/client/src/components/ui/dialog.tsx +122 -0
  40. package/template-hono/client/src/components/ui/drawer.tsx +118 -0
  41. package/template-hono/client/src/components/ui/dropdown-menu.tsx +200 -0
  42. package/template-hono/client/src/components/ui/form.tsx +178 -0
  43. package/template-hono/client/src/components/ui/hover-card.tsx +29 -0
  44. package/template-hono/client/src/components/ui/input-otp.tsx +71 -0
  45. package/template-hono/client/src/components/ui/input.tsx +25 -0
  46. package/template-hono/client/src/components/ui/label.tsx +26 -0
  47. package/template-hono/client/src/components/ui/menubar.tsx +256 -0
  48. package/template-hono/client/src/components/ui/navigation-menu.tsx +130 -0
  49. package/template-hono/client/src/components/ui/pagination.tsx +119 -0
  50. package/template-hono/client/src/components/ui/popover.tsx +31 -0
  51. package/template-hono/client/src/components/ui/progress.tsx +28 -0
  52. package/template-hono/client/src/components/ui/radio-group.tsx +44 -0
  53. package/template-hono/client/src/components/ui/resizable.tsx +45 -0
  54. package/template-hono/client/src/components/ui/scroll-area.tsx +48 -0
  55. package/template-hono/client/src/components/ui/select.tsx +160 -0
  56. package/template-hono/client/src/components/ui/separator.tsx +31 -0
  57. package/template-hono/client/src/components/ui/sheet.tsx +140 -0
  58. package/template-hono/client/src/components/ui/sidebar.tsx +732 -0
  59. package/template-hono/client/src/components/ui/skeleton.tsx +17 -0
  60. package/template-hono/client/src/components/ui/slider.tsx +28 -0
  61. package/template-hono/client/src/components/ui/switch.tsx +29 -0
  62. package/template-hono/client/src/components/ui/table.tsx +119 -0
  63. package/template-hono/client/src/components/ui/tabs.tsx +55 -0
  64. package/template-hono/client/src/components/ui/textarea.tsx +24 -0
  65. package/template-hono/client/src/components/ui/toast.tsx +129 -0
  66. package/template-hono/client/src/components/ui/toaster.tsx +35 -0
  67. package/template-hono/client/src/components/ui/toggle-group.tsx +61 -0
  68. package/template-hono/client/src/components/ui/toggle.tsx +45 -0
  69. package/template-hono/client/src/components/ui/tooltip.tsx +30 -0
  70. package/template-hono/client/src/globals.css +767 -0
  71. package/template-hono/client/src/hooks/use-greeting.ts +15 -0
  72. package/template-hono/client/src/hooks/use-mobile.ts +21 -0
  73. package/template-hono/client/src/hooks/use-toast.ts +194 -0
  74. package/template-hono/client/src/lib/queryClient.ts +59 -0
  75. package/template-hono/client/src/lib/theme/default-theme.ts +11 -0
  76. package/template-hono/client/src/lib/utils.ts +6 -0
  77. package/template-hono/client/src/main.tsx +24 -0
  78. package/template-hono/client/src/pages/HelloPage.tsx +22 -0
  79. package/template-hono/client/src/pages/HomePage.tsx +30 -0
  80. package/template-hono/client/src/providers.tsx +21 -0
  81. package/template-hono/drizzle.config.ts +50 -0
  82. package/template-hono/eslint.config.mjs +13 -0
  83. package/template-hono/gitignore +40 -0
  84. package/template-hono/package.json +83 -0
  85. package/template-hono/pnpm-lock.yaml +5176 -0
  86. package/template-hono/postcss.config.mjs +7 -0
  87. package/template-hono/process-compose.yaml +13 -0
  88. package/template-hono/scripts/imagicma-common.mjs +118 -0
  89. package/template-hono/scripts/imagicma-dev.mjs +29 -0
  90. package/template-hono/scripts/imagicma-guard.mjs +17 -0
  91. package/template-hono/scripts/imagicma-start.mjs +24 -0
  92. package/template-hono/server/app.ts +40 -0
  93. package/template-hono/server/db.ts +22 -0
  94. package/template-hono/server/dev-app.ts +5 -0
  95. package/template-hono/server/index.ts +94 -0
  96. package/template-hono/server/routes/greeting.ts +25 -0
  97. package/template-hono/server/storage.ts +39 -0
  98. package/template-hono/shared/routes.ts +13 -0
  99. package/template-hono/shared/schema.ts +17 -0
  100. package/template-hono/tailwind.config.mjs +94 -0
  101. package/template-hono/tsconfig.json +33 -0
  102. package/template-hono/tsconfig.server.json +15 -0
  103. package/template-hono/types/pg.d.ts +19 -0
  104. package/template-hono/vite.config.ts +126 -0
package/README.md CHANGED
@@ -1,44 +1,60 @@
1
1
  # create-next-imagicma
2
2
 
3
- 一个极简的项目脚手架(类似 `create-next-app`),用于从本仓库模板快速生成新项目。
3
+ 一个极简项目脚手架,用于从本仓库模板快速生成新项目。支持双模板:`hono` `next`。
4
4
 
5
5
  ## 使用
6
6
 
7
7
  ```bash
8
8
  npm install -g create-next-imagicma
9
- create-next-imagicma <project-dir> [--port <1-65535>] [--theme <name>]
9
+ create-next-imagicma <project-dir> [--template <hono|next>] [--port <1-65535>] [--theme <name>]
10
10
  ```
11
11
 
12
12
  本地(未发布)使用示例:
13
13
 
14
14
  ```bash
15
- cd /Users/alexliu/Project/nextjs-app
16
- node ./create-next-imagicma/bin/create-next-imagicma.mjs demo-5001 --port 5001
15
+ cd /Users/alexliu/Project/imagicma-template
16
+ node ./create-next-imagicma/bin/create-next-imagicma.mjs demo-hono --template hono --port 5001
17
+ node ./create-next-imagicma/bin/create-next-imagicma.mjs demo-next --template next --port 5001
17
18
  ```
18
19
 
19
20
  ## 参数
20
21
 
21
- - `--port <number>`:设置新项目 `dev/start` 的默认端口(写入 `next ... -p <port>`)。
22
- - `--theme <name>`:设置新项目默认主题(可选:`quadratic`、`nomad`、`honey`、`zen-garden`、`highlighter`)。
23
- - `-v, --version`:显示当前脚手架版本号。
24
- - 运行时仍可覆盖,例如:`pnpm dev -- -p 6001` `PORT=6001 pnpm start`
22
+ - `--template <hono|next>`:选择模板。默认 `hono`。
23
+ - `--port <number>`:设置新项目默认端口。
24
+ - `next` 模板:写入 `next dev/start -p <port>`
25
+ - `hono` 模板:写入 `/.imagicma/port.json`,并同步 `process-compose.yaml` `PORT`
26
+ - `--theme <name>`:设置默认主题(`quadratic`、`nomad`、`honey`、`zen-garden`、`highlighter`)。
27
+ - `-v, --version`:显示版本号。
25
28
 
26
29
  ## 依赖安装策略
27
30
 
28
- - 优先使用 `pnpm install`
29
- - 如果没有 `pnpm`,会尝试 `corepack pnpm install`
30
- - 如果依然不可用,会自动回退到 `npm install`
31
+ - 优先 `pnpm install`
32
+ - `pnpm` 时尝试 `corepack pnpm install`
33
+ - 仍不可用则回退 `npm install`
31
34
 
32
35
  ## 维护模板
33
36
 
34
- 在脚手架目录执行(默认从同级的 `../nextjs-app` 同步):
37
+ 在脚手架目录执行:
35
38
 
36
39
  ```bash
37
40
  pnpm run sync-template
38
41
  ```
39
42
 
40
- 可通过环境变量自定义源仓库路径:
43
+ 默认同步:
44
+
45
+ - `../nextjs-app` -> `template/`
46
+ - `../hono-app` -> `template-hono/`
47
+
48
+ 可通过环境变量覆盖:
49
+
50
+ ```bash
51
+ SOURCE_REPO_NEXT=/abs/path/to/nextjs-app \
52
+ SOURCE_REPO_HONO=/abs/path/to/hono-app \
53
+ pnpm run sync-template
54
+ ```
55
+
56
+ 兼容旧变量(仅 Next):
41
57
 
42
58
  ```bash
43
- SOURCE_REPO=/abs/path/to/source pnpm run sync-template
59
+ SOURCE_REPO=/abs/path/to/nextjs-app pnpm run sync-template
44
60
  ```
@@ -7,7 +7,12 @@ import { fileURLToPath } from "node:url";
7
7
 
8
8
  const __filename = fileURLToPath(import.meta.url);
9
9
  const __dirname = path.dirname(__filename);
10
- const TEMPLATE_DIR = path.resolve(__dirname, "..", "template");
10
+
11
+ const TEMPLATE_DIR_NEXT = path.resolve(__dirname, "..", "template");
12
+ const TEMPLATE_DIR_HONO = path.resolve(__dirname, "..", "template-hono");
13
+ const TEMPLATE_CHOICES = ["hono", "next"];
14
+ const DEFAULT_TEMPLATE = "hono";
15
+
11
16
  const THEME_STYLES = [
12
17
  "quadratic",
13
18
  "nomad",
@@ -17,6 +22,12 @@ const THEME_STYLES = [
17
22
  ];
18
23
 
19
24
  const PACKAGE_JSON_PATH = path.resolve(__dirname, "..", "package.json");
25
+ const HONO_LOCKED_SCRIPTS = {
26
+ predev: "node ./scripts/imagicma-guard.mjs dev",
27
+ dev: "node ./scripts/imagicma-dev.mjs",
28
+ prestart: "node ./scripts/imagicma-guard.mjs start",
29
+ start: "node ./scripts/imagicma-start.mjs",
30
+ };
20
31
 
21
32
  async function getVersion() {
22
33
  const raw = await fs.readFile(PACKAGE_JSON_PATH, "utf8");
@@ -25,13 +36,14 @@ async function getVersion() {
25
36
  }
26
37
 
27
38
  function printHelp() {
28
- console.log(`create-next-imagicma <project-dir> [--port <1-65535>] [--theme <name>]
39
+ console.log(`create-next-imagicma <project-dir> [--template <hono|next>] [--port <1-65535>] [--theme <name>]
29
40
 
30
41
  参数:
31
- --port <number> 设置新项目 dev/start 的默认端口(next ... -p
32
- --theme <name> 设置默认主题(可选:${THEME_STYLES.join(", ")})
33
- -h, --help 显示帮助
34
- -v, --version 显示版本号
42
+ --template <name> 选择模板(可选:${TEMPLATE_CHOICES.join("、")},默认:${DEFAULT_TEMPLATE}
43
+ --port <number> 设置新项目默认端口
44
+ --theme <name> 设置默认主题(可选:${THEME_STYLES.join(", ")})
45
+ -h, --help 显示帮助
46
+ -v, --version 显示版本号
35
47
  `);
36
48
  }
37
49
 
@@ -64,6 +76,21 @@ function parseTheme(raw) {
64
76
  return normalized;
65
77
  }
66
78
 
79
+ function parseTemplate(raw) {
80
+ const normalized = String(raw ?? "").trim().toLowerCase();
81
+ if (!normalized) {
82
+ throw new Error("--template 缺少值:请使用 --template <hono|next>");
83
+ }
84
+
85
+ if (!TEMPLATE_CHOICES.includes(normalized)) {
86
+ throw new Error(
87
+ `--template 参数不合法:${JSON.stringify(raw)}(可选:${TEMPLATE_CHOICES.join("、")})`,
88
+ );
89
+ }
90
+
91
+ return normalized;
92
+ }
93
+
67
94
  function sanitizePackageName(raw) {
68
95
  const normalized = raw
69
96
  .toLowerCase()
@@ -76,6 +103,7 @@ function parseArgs(argv) {
76
103
  let projectDir;
77
104
  let port;
78
105
  let theme;
106
+ let template = DEFAULT_TEMPLATE;
79
107
 
80
108
  for (let i = 0; i < argv.length; i += 1) {
81
109
  const arg = argv[i];
@@ -118,6 +146,21 @@ function parseArgs(argv) {
118
146
  continue;
119
147
  }
120
148
 
149
+ if (arg === "--template") {
150
+ const value = argv[i + 1];
151
+ if (!value) {
152
+ throw new Error("--template 缺少值:请使用 --template <hono|next>");
153
+ }
154
+ template = parseTemplate(value);
155
+ i += 1;
156
+ continue;
157
+ }
158
+
159
+ if (arg.startsWith("--template=")) {
160
+ template = parseTemplate(arg.slice("--template=".length));
161
+ continue;
162
+ }
163
+
121
164
  if (arg.startsWith("-")) {
122
165
  throw new Error(`未知参数:${arg}`);
123
166
  }
@@ -134,7 +177,14 @@ function parseArgs(argv) {
134
177
  throw new Error("缺少 <project-dir>:请指定要创建的项目目录名/路径");
135
178
  }
136
179
 
137
- return { projectDir, port, theme, help: false, version: false };
180
+ return {
181
+ projectDir,
182
+ port,
183
+ theme,
184
+ template,
185
+ help: false,
186
+ version: false,
187
+ };
138
188
  }
139
189
 
140
190
  async function ensureTargetDirReady(targetDir) {
@@ -152,20 +202,30 @@ async function ensureTargetDirReady(targetDir) {
152
202
  }
153
203
  }
154
204
 
155
- async function updatePackageName(targetDir, port) {
205
+ async function updatePackageName(targetDir, port, template) {
156
206
  const pkgPath = path.join(targetDir, "package.json");
157
207
  const raw = await fs.readFile(pkgPath, "utf8");
158
208
  const pkg = JSON.parse(raw);
159
- const devScript = port === undefined ? "next dev" : `next dev -p ${port}`;
160
- const startScript =
161
- port === undefined ? "next start" : `next start -p ${port}`;
162
209
 
163
210
  pkg.name = sanitizePackageName(path.basename(targetDir));
164
- pkg.scripts = {
165
- ...(pkg.scripts ?? {}),
166
- dev: devScript,
167
- start: startScript,
168
- };
211
+
212
+ if (template === "next") {
213
+ const devScript = port === undefined ? "next dev" : `next dev -p ${port}`;
214
+ const startScript =
215
+ port === undefined ? "next start" : `next start -p ${port}`;
216
+
217
+ pkg.scripts = {
218
+ ...(pkg.scripts ?? {}),
219
+ dev: devScript,
220
+ start: startScript,
221
+ };
222
+ } else {
223
+ pkg.scripts = {
224
+ ...(pkg.scripts ?? {}),
225
+ ...HONO_LOCKED_SCRIPTS,
226
+ };
227
+ }
228
+
169
229
  await fs.writeFile(pkgPath, `${JSON.stringify(pkg, null, 2)}\n`);
170
230
  }
171
231
 
@@ -191,6 +251,34 @@ async function updateProcessComposePort(targetDir, port) {
191
251
  await fs.writeFile(filePath, next);
192
252
  }
193
253
 
254
+ async function updateLockedPortFile(targetDir, port) {
255
+ if (port === undefined) return;
256
+
257
+ const filePath = path.join(targetDir, ".imagicma", "port.json");
258
+
259
+ let current = {};
260
+ try {
261
+ const raw = await fs.readFile(filePath, "utf8");
262
+ const parsed = JSON.parse(raw);
263
+ if (parsed && typeof parsed === "object") {
264
+ current = parsed;
265
+ }
266
+ } catch (error) {
267
+ if (!(error && typeof error === "object" && error.code === "ENOENT")) {
268
+ throw error;
269
+ }
270
+ }
271
+
272
+ const next = {
273
+ ...current,
274
+ port,
275
+ locked: true,
276
+ version: 1,
277
+ };
278
+ await fs.mkdir(path.dirname(filePath), { recursive: true });
279
+ await fs.writeFile(filePath, `${JSON.stringify(next, null, 2)}\n`);
280
+ }
281
+
194
282
  async function updateDefaultTheme(targetDir, theme) {
195
283
  if (theme === undefined) return;
196
284
 
@@ -250,7 +338,6 @@ async function initGit(targetDir) {
250
338
  }
251
339
  return true;
252
340
  } catch (_error) {
253
- // 不存在 git 或其它异常时静默跳过,不报错
254
341
  return false;
255
342
  }
256
343
  }
@@ -293,6 +380,11 @@ async function installDependencies(targetDir) {
293
380
  }
294
381
  }
295
382
 
383
+ function getTemplateDir(template) {
384
+ if (template === "next") return TEMPLATE_DIR_NEXT;
385
+ return TEMPLATE_DIR_HONO;
386
+ }
387
+
296
388
  async function main() {
297
389
  const parsed = parseArgs(process.argv.slice(2));
298
390
  if (parsed.help) {
@@ -305,26 +397,31 @@ async function main() {
305
397
  return;
306
398
  }
307
399
 
308
- const { projectDir, port, theme } = parsed;
400
+ const { projectDir, port, theme, template } = parsed;
309
401
  const targetDir = path.resolve(process.cwd(), projectDir);
402
+ const templateDir = getTemplateDir(template);
310
403
 
311
404
  await ensureTargetDirReady(targetDir);
312
405
 
313
- await fs.cp(TEMPLATE_DIR, targetDir, {
406
+ await fs.cp(templateDir, targetDir, {
314
407
  recursive: true,
315
408
  force: true,
316
409
  errorOnExist: false,
317
410
  });
318
- // npm publish 会默认排除 .gitignore,模板中以 gitignore 发布,此处还原为 .gitignore
411
+
319
412
  const gitignoreSrc = path.join(targetDir, "gitignore");
320
413
  try {
321
414
  await fs.access(gitignoreSrc);
322
415
  await fs.rename(gitignoreSrc, path.join(targetDir, ".gitignore"));
323
416
  } catch {
324
- // 无 gitignore 则跳过(如本地开发时仍保留 .gitignore 的情况)
417
+ // ignore
325
418
  }
326
- await updatePackageName(targetDir, port);
419
+
420
+ await updatePackageName(targetDir, port, template);
327
421
  await updateProcessComposePort(targetDir, port);
422
+ if (template === "hono") {
423
+ await updateLockedPortFile(targetDir, port);
424
+ }
328
425
  await updateDefaultTheme(targetDir, theme);
329
426
 
330
427
  await initGit(targetDir);
@@ -343,8 +440,9 @@ async function main() {
343
440
  }
344
441
 
345
442
  console.log(`\n✅ 项目已创建:${targetDir}`);
443
+ console.log(`模板类型:${template}`);
346
444
  if (port !== undefined) {
347
- console.log(`已设置默认端口:${port}(写入 dev/start 启动命令)`);
445
+ console.log(`已设置默认端口:${port}`);
348
446
  }
349
447
  if (theme !== undefined) {
350
448
  console.log(`已设置默认主题:${theme}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-next-imagicma",
3
- "version": "0.0.5",
3
+ "version": "0.0.7",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "create-next-imagicma": "./bin/create-next-imagicma.mjs"
@@ -8,6 +8,7 @@
8
8
  "files": [
9
9
  "bin/**",
10
10
  "template/**",
11
+ "template-hono/**",
11
12
  "README.md"
12
13
  ],
13
14
  "scripts": {
@@ -428,6 +428,337 @@
428
428
  transform: translateY(0px);
429
429
  box-shadow: 0 6px 18px rgb(0 0 0 / 0.08);
430
430
  }
431
+
432
+ @keyframes aurora-shift-x {
433
+ from {
434
+ background-position: 0% 50%;
435
+ }
436
+ to {
437
+ background-position: 200% 50%;
438
+ }
439
+ }
440
+
441
+ @keyframes aurora-shift-y {
442
+ from {
443
+ background-position: 50% 0%;
444
+ }
445
+ to {
446
+ background-position: 50% 200%;
447
+ }
448
+ }
449
+
450
+ @keyframes aurora-breathe {
451
+ 0%,
452
+ 100% {
453
+ opacity: 0.55;
454
+ }
455
+ 50% {
456
+ opacity: 0.95;
457
+ }
458
+ }
459
+
460
+ @keyframes nebula-float-a {
461
+ 0%,
462
+ 100% {
463
+ transform: translate3d(0, 0, 0) scale(1);
464
+ }
465
+ 50% {
466
+ transform: translate3d(8%, 5%, 0) scale(1.08);
467
+ }
468
+ }
469
+
470
+ @keyframes nebula-float-b {
471
+ 0%,
472
+ 100% {
473
+ transform: translate3d(0, 0, 0) scale(1);
474
+ }
475
+ 50% {
476
+ transform: translate3d(-7%, 6%, 0) scale(1.12);
477
+ }
478
+ }
479
+
480
+ @keyframes nebula-float-c {
481
+ 0%,
482
+ 100% {
483
+ transform: translate3d(0, 0, 0) scale(1);
484
+ }
485
+ 50% {
486
+ transform: translate3d(5%, -6%, 0) scale(1.06);
487
+ }
488
+ }
489
+
490
+ @keyframes grain-shift {
491
+ 0% {
492
+ transform: translate3d(0, 0, 0);
493
+ }
494
+ 25% {
495
+ transform: translate3d(1%, -1%, 0);
496
+ }
497
+ 50% {
498
+ transform: translate3d(-1%, 1%, 0);
499
+ }
500
+ 75% {
501
+ transform: translate3d(0.5%, 1%, 0);
502
+ }
503
+ 100% {
504
+ transform: translate3d(0, 0, 0);
505
+ }
506
+ }
507
+
508
+ @keyframes loader-spin {
509
+ from {
510
+ transform: rotate(0deg);
511
+ }
512
+ to {
513
+ transform: rotate(360deg);
514
+ }
515
+ }
516
+
517
+ @keyframes loader-spin-reverse {
518
+ from {
519
+ transform: rotate(360deg);
520
+ }
521
+ to {
522
+ transform: rotate(0deg);
523
+ }
524
+ }
525
+
526
+ @keyframes loader-core-breathe {
527
+ 0%,
528
+ 100% {
529
+ transform: scale(0.92);
530
+ opacity: 0.85;
531
+ }
532
+ 50% {
533
+ transform: scale(1.04);
534
+ opacity: 1;
535
+ }
536
+ }
537
+
538
+ .nebula-orb {
539
+ position: absolute;
540
+ border-radius: 9999px;
541
+ mix-blend-mode: screen;
542
+ opacity: 0.72;
543
+ filter: blur(72px);
544
+ will-change: transform;
545
+ }
546
+
547
+ .nebula-orb-a {
548
+ left: -11rem;
549
+ top: -8rem;
550
+ height: 34rem;
551
+ width: 34rem;
552
+ background: radial-gradient(
553
+ circle,
554
+ rgba(56, 189, 248, 0.36) 0%,
555
+ rgba(99, 102, 241, 0.2) 45%,
556
+ rgba(255, 255, 255, 0) 72%
557
+ );
558
+ animation: nebula-float-a 16s ease-in-out infinite;
559
+ }
560
+
561
+ .nebula-orb-b {
562
+ right: -13rem;
563
+ top: 14%;
564
+ height: 38rem;
565
+ width: 38rem;
566
+ background: radial-gradient(
567
+ circle,
568
+ rgba(20, 184, 166, 0.33) 0%,
569
+ rgba(59, 130, 246, 0.16) 46%,
570
+ rgba(255, 255, 255, 0) 75%
571
+ );
572
+ animation: nebula-float-b 18s ease-in-out infinite;
573
+ }
574
+
575
+ .nebula-orb-c {
576
+ bottom: -16rem;
577
+ left: 26%;
578
+ height: 36rem;
579
+ width: 36rem;
580
+ background: radial-gradient(
581
+ circle,
582
+ rgba(167, 139, 250, 0.24) 0%,
583
+ rgba(56, 189, 248, 0.12) 45%,
584
+ rgba(255, 255, 255, 0) 74%
585
+ );
586
+ animation: nebula-float-c 15s ease-in-out infinite;
587
+ }
588
+
589
+ .nebula-grain {
590
+ position: absolute;
591
+ inset: -20%;
592
+ background-image: radial-gradient(rgba(15, 23, 42, 0.08) 0.7px, transparent 0.7px);
593
+ background-size: 3px 3px;
594
+ opacity: 0.08;
595
+ animation: grain-shift 8s steps(10) infinite;
596
+ }
597
+
598
+ .luxe-loader {
599
+ position: relative;
600
+ height: 96px;
601
+ width: 96px;
602
+ }
603
+
604
+ .luxe-loader__ring {
605
+ position: absolute;
606
+ border-radius: 9999px;
607
+ border: 2px solid transparent;
608
+ }
609
+
610
+ .luxe-loader__ring--outer {
611
+ inset: 0;
612
+ border-top-color: rgba(56, 189, 248, 0.98);
613
+ border-right-color: rgba(99, 102, 241, 0.94);
614
+ box-shadow:
615
+ 0 0 18px rgba(56, 189, 248, 0.6),
616
+ inset 0 0 12px rgba(59, 130, 246, 0.15);
617
+ animation: loader-spin 1.35s linear infinite;
618
+ }
619
+
620
+ .luxe-loader__ring--inner {
621
+ inset: 13px;
622
+ border-left-color: rgba(20, 184, 166, 0.96);
623
+ border-bottom-color: rgba(56, 189, 248, 0.88);
624
+ box-shadow: 0 0 14px rgba(20, 184, 166, 0.45);
625
+ animation: loader-spin-reverse 1.05s linear infinite;
626
+ }
627
+
628
+ .luxe-loader__core {
629
+ position: absolute;
630
+ inset: 34px;
631
+ border-radius: 9999px;
632
+ background: radial-gradient(
633
+ circle at 35% 30%,
634
+ rgba(255, 255, 255, 1) 0%,
635
+ rgba(210, 237, 255, 0.95) 42%,
636
+ rgba(107, 172, 255, 0.78) 100%
637
+ );
638
+ box-shadow:
639
+ 0 0 24px rgba(56, 189, 248, 0.48),
640
+ 0 0 34px rgba(99, 102, 241, 0.24);
641
+ animation: loader-core-breathe 2.1s ease-in-out infinite;
642
+ }
643
+
644
+ .luxe-loader__orbit {
645
+ position: absolute;
646
+ inset: 0;
647
+ animation: loader-spin 2.5s linear infinite;
648
+ }
649
+
650
+ .luxe-loader__dot {
651
+ position: absolute;
652
+ left: 50%;
653
+ top: 3px;
654
+ height: 9px;
655
+ width: 9px;
656
+ border-radius: 9999px;
657
+ transform: translateX(-50%);
658
+ background: radial-gradient(
659
+ circle at 30% 30%,
660
+ rgba(255, 255, 255, 1) 0%,
661
+ rgba(167, 243, 255, 0.95) 35%,
662
+ rgba(34, 211, 238, 0.95) 100%
663
+ );
664
+ box-shadow:
665
+ 0 0 10px rgba(34, 211, 238, 0.8),
666
+ 0 0 18px rgba(56, 189, 248, 0.5);
667
+ }
668
+
669
+ .aurora-frame {
670
+ pointer-events: none;
671
+ position: absolute;
672
+ inset: 0;
673
+ z-index: 20;
674
+ }
675
+
676
+ .aurora-edge {
677
+ position: absolute;
678
+ opacity: 0.95;
679
+ will-change: background-position, opacity;
680
+ }
681
+
682
+ .aurora-edge.is-glow {
683
+ filter: blur(16px);
684
+ opacity: 0.75;
685
+ }
686
+
687
+ .aurora-edge.top,
688
+ .aurora-edge.bottom {
689
+ left: 0;
690
+ right: 0;
691
+ height: 4px;
692
+ background-image: linear-gradient(
693
+ 90deg,
694
+ rgba(16, 185, 129, 0.2),
695
+ rgba(34, 211, 238, 1),
696
+ rgba(59, 130, 246, 1),
697
+ rgba(16, 185, 129, 0.2)
698
+ );
699
+ background-size: 320% 100%;
700
+ box-shadow:
701
+ 0 0 8px rgba(34, 211, 238, 0.9),
702
+ 0 0 22px rgba(59, 130, 246, 0.65);
703
+ animation:
704
+ aurora-shift-x 5.2s linear infinite,
705
+ aurora-breathe 2.6s ease-in-out infinite;
706
+ }
707
+
708
+ .aurora-edge.top {
709
+ top: 0;
710
+ }
711
+
712
+ .aurora-edge.bottom {
713
+ bottom: 0;
714
+ animation-direction: reverse, normal;
715
+ }
716
+
717
+ .aurora-edge.left,
718
+ .aurora-edge.right {
719
+ top: 0;
720
+ bottom: 0;
721
+ width: 4px;
722
+ background-image: linear-gradient(
723
+ 180deg,
724
+ rgba(16, 185, 129, 0.2),
725
+ rgba(34, 211, 238, 1),
726
+ rgba(59, 130, 246, 1),
727
+ rgba(16, 185, 129, 0.2)
728
+ );
729
+ background-size: 100% 320%;
730
+ box-shadow:
731
+ 0 0 8px rgba(34, 211, 238, 0.85),
732
+ 0 0 20px rgba(59, 130, 246, 0.6);
733
+ animation:
734
+ aurora-shift-y 5.8s linear infinite,
735
+ aurora-breathe 3s ease-in-out infinite;
736
+ }
737
+
738
+ .aurora-edge.left {
739
+ left: 0;
740
+ }
741
+
742
+ .aurora-edge.right {
743
+ right: 0;
744
+ animation-direction: reverse, normal;
745
+ }
746
+
747
+ @media (prefers-reduced-motion: reduce) {
748
+ .nebula-orb,
749
+ .nebula-grain,
750
+ .luxe-loader__ring--outer,
751
+ .luxe-loader__ring--inner,
752
+ .luxe-loader__core,
753
+ .luxe-loader__orbit {
754
+ animation: none;
755
+ }
756
+
757
+ .aurora-edge {
758
+ animation: none;
759
+ opacity: 0.75;
760
+ }
761
+ }
431
762
  }
432
763
 
433
764
  html[data-preview-shield="on"] nextjs-portal,
@@ -1,6 +1,7 @@
1
1
  import type { Metadata } from "next";
2
+ import Script from "next/script";
2
3
  import "./globals.css";
3
- import { DevPreviewShield } from "./_components/DevPreviewShield";
4
+ // import { DevPreviewShield } from "./_components/DevPreviewShield";
4
5
  import { Providers } from "./providers";
5
6
  import { DEFAULT_THEME_STYLE } from "@/lib/theme/default-theme";
6
7
 
@@ -21,12 +22,9 @@ export default function RootLayout({
21
22
  data-theme-style={DEFAULT_THEME_STYLE}
22
23
  >
23
24
  <body className="antialiased">
25
+ <Script src="/imagicma-picker-bridge.js" strategy="beforeInteractive" />
24
26
  <Providers>
25
- {process.env.NODE_ENV === "development" ? (
26
- <DevPreviewShield>{children}</DevPreviewShield>
27
- ) : (
28
- children
29
- )}
27
+ {children}
30
28
  </Providers>
31
29
  </body>
32
30
  </html>