mjpic 1.0.0

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 (58) hide show
  1. package/.trae/documents/mjpic-prd.md +111 -0
  2. package/.trae/documents/mjpic-technical-architecture.md +234 -0
  3. package/README.md +57 -0
  4. package/api/app.ts +60 -0
  5. package/api/cli.ts +61 -0
  6. package/api/index.ts +19 -0
  7. package/api/routes/auth.ts +33 -0
  8. package/api/routes/image.ts +27 -0
  9. package/api/server.ts +45 -0
  10. package/dist/cli/app.js +43 -0
  11. package/dist/cli/cli.js +49 -0
  12. package/dist/cli/index.js +13 -0
  13. package/dist/cli/routes/auth.js +28 -0
  14. package/dist/cli/routes/image.js +21 -0
  15. package/dist/cli/server.js +38 -0
  16. package/dist/client/assets/index-BUIYLOn-.js +197 -0
  17. package/dist/client/assets/index-BoiS81Ei.css +1 -0
  18. package/dist/client/favicon.svg +4 -0
  19. package/dist/client/index.html +354 -0
  20. package/eslint.config.js +28 -0
  21. package/index.html +24 -0
  22. package/nodemon.json +10 -0
  23. package/package.json +68 -0
  24. package/postcss.config.js +10 -0
  25. package/public/favicon.svg +4 -0
  26. package/src/App.tsx +13 -0
  27. package/src/assets/react.svg +1 -0
  28. package/src/components/Empty.tsx +8 -0
  29. package/src/components/dialogs/AspectRatioDialog.tsx +218 -0
  30. package/src/components/dialogs/SaveDialog.tsx +150 -0
  31. package/src/components/layout/CanvasArea.tsx +874 -0
  32. package/src/components/layout/Header.tsx +156 -0
  33. package/src/components/layout/RightPanel.tsx +886 -0
  34. package/src/components/layout/Sidebar.tsx +36 -0
  35. package/src/components/layout/StatusBar.tsx +44 -0
  36. package/src/hooks/useDebounce.ts +17 -0
  37. package/src/hooks/useTheme.ts +29 -0
  38. package/src/i18n/index.ts +26 -0
  39. package/src/i18n/locales/en.json +56 -0
  40. package/src/i18n/locales/zh.json +59 -0
  41. package/src/index.css +14 -0
  42. package/src/lib/utils.ts +73 -0
  43. package/src/main.tsx +11 -0
  44. package/src/pages/Home.tsx +72 -0
  45. package/src/store/useImageStore.ts +316 -0
  46. package/src/store/usePresetStore.ts +65 -0
  47. package/src/store/useUIStore.ts +17 -0
  48. package/src/vite-env.d.ts +1 -0
  49. package/tailwind.config.js +13 -0
  50. package/tmp/guangxi.jpg +0 -0
  51. package/tsconfig.json +40 -0
  52. package/tsconfig.server.json +15 -0
  53. package/vercel.json +12 -0
  54. package/vite.config.ts +50 -0
  55. package//345/217/202/350/200/203/345/233/276/347/211/207//346/210/252/345/261/2172026-02-18 16.47.45_/345/233/276/347/211/207/345/260/272/345/257/270/350/260/203/350/212/202_/351/242/204/350/256/276/345/260/272/345/257/270.jpg +0 -0
  56. package//345/217/202/350/200/203/345/233/276/347/211/207//346/210/252/345/261/2172026-02-18 16.47.51_/345/233/276/347/211/207/345/260/272/345/257/270/350/260/203/350/212/202_/346/211/213/345/267/245/350/276/223/345/205/245/345/260/272/345/257/270.jpg +0 -0
  57. package//345/217/202/350/200/203/345/233/276/347/211/207//346/210/252/345/261/2172026-02-18 16.54.56_/345/233/276/347/211/207/345/260/272/345/257/270/350/260/203/350/212/202_/346/267/273/345/212/240/345/270/270/347/224/250/345/260/272/345/257/270.jpg +0 -0
  58. package//345/217/202/350/200/203/345/233/276/347/211/207//346/210/252/345/261/2172026-02-18 16.55.11_/345/233/276/347/211/207/345/260/272/345/257/270/350/260/203/350/212/202_/345/210/240/351/231/244/345/270/270/347/224/250/345/260/272/345/257/270.jpg +0 -0
@@ -0,0 +1 @@
1
+ *,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.pointer-events-none{pointer-events:none}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{top:0;right:0;bottom:0;left:0}.right-3{right:.75rem}.top-1\/2{top:50%}.z-10{z-index:10}.z-20{z-index:20}.z-50{z-index:50}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.ml-auto{margin-left:auto}.mr-2{margin-right:.5rem}.mr-4{margin-right:1rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-4{margin-top:1rem}.mt-6{margin-top:1.5rem}.block{display:block}.flex{display:flex}.grid{display:grid}.h-1{height:.25rem}.h-12{height:3rem}.h-16{height:4rem}.h-6{height:1.5rem}.h-8{height:2rem}.h-full{height:100%}.h-screen{height:100vh}.max-h-\[80vh\]{max-height:80vh}.w-16{width:4rem}.w-32{width:8rem}.w-6{width:1.5rem}.w-8{width:2rem}.w-80{width:20rem}.w-96{width:24rem}.w-\[280px\]{width:280px}.w-\[80px\]{width:80px}.w-full{width:100%}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.-translate-y-1\/2{--tw-translate-y: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-grab{cursor:grab}.cursor-pointer{cursor:pointer}.resize{resize:both}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-6{gap:1.5rem}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.self-end{align-self:flex-end}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-lg{border-radius:.5rem}.border{border-width:1px}.border-0{border-width:0px}.border-b{border-bottom-width:1px}.border-l{border-left-width:1px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-blue-500{--tw-border-opacity: 1;border-color:rgb(59 130 246 / var(--tw-border-opacity, 1))}.border-blue-500\/50{border-color:#3b82f680}.border-transparent{border-color:transparent}.border-zinc-600{--tw-border-opacity: 1;border-color:rgb(82 82 91 / var(--tw-border-opacity, 1))}.border-zinc-700{--tw-border-opacity: 1;border-color:rgb(63 63 70 / var(--tw-border-opacity, 1))}.border-zinc-800{--tw-border-opacity: 1;border-color:rgb(39 39 42 / var(--tw-border-opacity, 1))}.bg-black\/50{background-color:#00000080}.bg-blue-600{--tw-bg-opacity: 1;background-color:rgb(37 99 235 / var(--tw-bg-opacity, 1))}.bg-transparent{background-color:transparent}.bg-zinc-700{--tw-bg-opacity: 1;background-color:rgb(63 63 70 / var(--tw-bg-opacity, 1))}.bg-zinc-800{--tw-bg-opacity: 1;background-color:rgb(39 39 42 / var(--tw-bg-opacity, 1))}.bg-zinc-800\/50{background-color:#27272a80}.bg-zinc-900{--tw-bg-opacity: 1;background-color:rgb(24 24 27 / var(--tw-bg-opacity, 1))}.bg-zinc-950{--tw-bg-opacity: 1;background-color:rgb(9 9 11 / var(--tw-bg-opacity, 1))}.p-0{padding:0}.p-1{padding:.25rem}.p-1\.5{padding:.375rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-4{padding-top:1rem;padding-bottom:1rem}.pb-1{padding-bottom:.25rem}.pr-1{padding-right:.25rem}.text-left{text-align:left}.text-center{text-align:center}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-\[10px\]{font-size:10px}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.capitalize{text-transform:capitalize}.leading-none{line-height:1}.text-blue-500{--tw-text-opacity: 1;color:rgb(59 130 246 / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.text-zinc-100{--tw-text-opacity: 1;color:rgb(244 244 245 / var(--tw-text-opacity, 1))}.text-zinc-200{--tw-text-opacity: 1;color:rgb(228 228 231 / var(--tw-text-opacity, 1))}.text-zinc-300{--tw-text-opacity: 1;color:rgb(212 212 216 / var(--tw-text-opacity, 1))}.text-zinc-400{--tw-text-opacity: 1;color:rgb(161 161 170 / var(--tw-text-opacity, 1))}.text-zinc-500{--tw-text-opacity: 1;color:rgb(113 113 122 / var(--tw-text-opacity, 1))}.text-zinc-600{--tw-text-opacity: 1;color:rgb(82 82 91 / var(--tw-text-opacity, 1))}.accent-blue-500{accent-color:#3b82f6}.opacity-50{opacity:.5}.shadow-xl{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.outline-none{outline:2px solid transparent;outline-offset:2px}.ring-2{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-blue-500{--tw-ring-opacity: 1;--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity, 1))}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-sm{--tw-backdrop-blur: blur(4px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}:root{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Noto Sans,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";line-height:1.5;font-weight:400;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.hover\:bg-blue-500:hover{--tw-bg-opacity: 1;background-color:rgb(59 130 246 / var(--tw-bg-opacity, 1))}.hover\:bg-blue-700:hover{--tw-bg-opacity: 1;background-color:rgb(29 78 216 / var(--tw-bg-opacity, 1))}.hover\:bg-zinc-600:hover{--tw-bg-opacity: 1;background-color:rgb(82 82 91 / var(--tw-bg-opacity, 1))}.hover\:bg-zinc-700:hover{--tw-bg-opacity: 1;background-color:rgb(63 63 70 / var(--tw-bg-opacity, 1))}.hover\:bg-zinc-700\/50:hover{background-color:#3f3f4680}.hover\:bg-zinc-800:hover{--tw-bg-opacity: 1;background-color:rgb(39 39 42 / var(--tw-bg-opacity, 1))}.hover\:text-blue-400:hover{--tw-text-opacity: 1;color:rgb(96 165 250 / var(--tw-text-opacity, 1))}.hover\:text-red-400:hover{--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity, 1))}.hover\:text-white:hover{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.hover\:text-zinc-100:hover{--tw-text-opacity: 1;color:rgb(244 244 245 / var(--tw-text-opacity, 1))}.hover\:text-zinc-200:hover{--tw-text-opacity: 1;color:rgb(228 228 231 / var(--tw-text-opacity, 1))}.hover\:text-zinc-300:hover{--tw-text-opacity: 1;color:rgb(212 212 216 / var(--tw-text-opacity, 1))}.hover\:text-zinc-400:hover{--tw-text-opacity: 1;color:rgb(161 161 170 / var(--tw-text-opacity, 1))}.focus\:border-blue-500:focus{--tw-border-opacity: 1;border-color:rgb(59 130 246 / var(--tw-border-opacity, 1))}.active\:cursor-grabbing:active{cursor:grabbing}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}
@@ -0,0 +1,4 @@
1
+ <svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <rect width="32" height="32" fill="#0A0B0D"/>
3
+ <path d="M26.6677 23.7149H8.38057V20.6496H5.33301V8.38159H26.6677V23.7149ZM8.38057 20.6496H23.6201V11.4482H8.38057V20.6496ZM16.0011 16.0021L13.8461 18.1705L11.6913 16.0021L13.8461 13.8337L16.0011 16.0021ZM22.0963 16.0008L19.9414 18.1691L17.7865 16.0008L19.9414 13.8324L22.0963 16.0008Z" fill="#32F08C"/>
4
+ </svg>
@@ -0,0 +1,354 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>My Trae Project</title>
8
+ <script type="module" crossorigin src="/assets/index-BUIYLOn-.js"></script>
9
+ <link rel="stylesheet" crossorigin href="/assets/index-BoiS81Ei.css">
10
+ </head>
11
+ <body>
12
+ <div id="root"></div>
13
+
14
+ <script>
15
+ (function() {
16
+ 'use strict';
17
+
18
+ if (window.TraeBadgePlugin) return;
19
+
20
+ const css = `
21
+ .trae-badge {
22
+ display: inline-flex;
23
+ align-items: center;
24
+ justify-content: center;
25
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
26
+ font-weight: 500;
27
+ transition: all 0.2s ease;
28
+ cursor: pointer;
29
+ box-sizing: border-box;
30
+ border-radius: 6px;
31
+ position: fixed;
32
+ padding: 8px 8px 8px 10px;
33
+ height: 28px;
34
+ width: 130px;
35
+ z-index: 9999;
36
+ }
37
+
38
+ .trae-badge:hover.trae-badge--light {
39
+ background-color: #EDEFF2;
40
+ }
41
+
42
+ .trae-badge:hover.trae-badge--dark {
43
+ background-color: #2A2D31;
44
+ }
45
+
46
+ .trae-badge-content {
47
+ display: flex;
48
+ align-items: center;
49
+ justify-content: center;
50
+ gap: 4px;
51
+ }
52
+
53
+ .trae-badge-logo {
54
+ flex-shrink: 0;
55
+ }
56
+
57
+ .trae-badge-share {
58
+ flex-shrink: 0;
59
+ color: rgba(78, 82, 87, 1);
60
+ }
61
+
62
+ .trae-badge:hover.trae-badge--light .trae-badge-share {
63
+ color: rgba(38, 41, 44, 1);
64
+ }
65
+
66
+ .trae-badge:hover.trae-badge--dark .trae-badge-share {
67
+ color: #D1D3DB;
68
+ }
69
+
70
+ .trae-badge-cancel {
71
+ position: absolute;
72
+ top: -8px;
73
+ right: -8px;
74
+ width: 16px;
75
+ height: 16px;
76
+ cursor: pointer;
77
+ opacity: 0;
78
+ visibility: hidden;
79
+ z-index: 10001;
80
+ display: flex;
81
+ align-items: center;
82
+ justify-content: center;
83
+ color: #000000;
84
+ }
85
+
86
+ .trae-badge:hover .trae-badge-cancel {
87
+ opacity: 1 !important;
88
+ visibility: visible !important;
89
+ }
90
+
91
+ /* 在移动端设备上始终显示取消按钮 */
92
+ @media (hover: none) and (pointer: coarse) {
93
+ .trae-badge-cancel {
94
+ opacity: 1 !important;
95
+ visibility: visible !important;
96
+ }
97
+ }
98
+
99
+ .trae-badge--light {
100
+ background-color: rgba(255, 255, 255, 1);
101
+ color: #ffffff;
102
+ box-shadow: 0px 0px 0.5px 0px rgba(0, 0, 0, 0.12), 0px 1px 3px 0px rgba(0, 0, 0, 0.08), 0px 4px 8px 0px rgba(0, 0, 0, 0.12);
103
+ }
104
+
105
+ .trae-badge--dark {
106
+ background-color: #000000;
107
+ color: #ffffff;
108
+ box-shadow: 0px 0px 0.5px 0px rgba(0, 0, 0, 0.12), 0px 1px 3px 0px rgba(0, 0, 0, 0.08), 0px 4px 8px 0px rgba(0, 0, 0, 0.12);
109
+ }
110
+
111
+ .trae-badge--bottom-right { bottom: 20px; right: 20px; }
112
+ .trae-badge--bottom-left { bottom: 20px; left: 20px; }
113
+ .trae-badge--top-right { top: 20px; right: 20px; }
114
+ .trae-badge--top-left { top: 20px; left: 20px; }
115
+ `;
116
+ const logos = {"light":"<svg width=\"92\" height=\"12\" viewBox=\"0 0 92 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n<g clip-path=\"url(#clip0_5805_55291)\">\n<g clip-path=\"url(#clip1_5805_55291)\">\n<path d=\"M15.1579 11.2121H2.6478V9.12821H0.562988V0.787872H15.1579V11.2121ZM2.6478 9.12821H13.073V2.87269H2.6478V9.12821ZM7.86092 5.96865L6.38672 7.44275L4.91261 5.96865L6.38672 4.49445L7.86092 5.96865ZM12.0306 5.96775L10.5564 7.44185L9.08233 5.96775L10.5564 4.49355L12.0306 5.96775Z\" fill=\"white\"/>\n</g>\n<g clip-path=\"url(#clip2_5805_55291)\">\n<path d=\"M28.0793 3.37087H25.142V10.6863H23.143V3.37087H20.2048V1.5047H28.0793V3.37087ZM55.4369 3.36808H50.3789V8.81641H55.4369V10.6835H48.3789V1.50092H55.4369V3.36808ZM34.1761 1.50092C36.4528 1.50092 37.1355 2.26109 37.1355 4.43355C37.1355 6.00363 36.6872 6.72417 35.4243 7.14483L37.1466 10.6817H34.9474L33.3569 7.38095H31.2204L31.2222 10.6817V10.6826H29.2583V1.50092H34.1761ZM47.4897 10.6826H45.3993L44.5662 8.50363H40.8449L40.0819 10.6826H37.9048L41.4232 1.5047H44.081L47.4897 10.6826ZM55.436 6.119L53.8697 7.59311L52.3955 6.119L53.8697 4.6448L55.436 6.119ZM41.4547 6.86439H44.0173L42.8578 3.54429H42.5985L41.4547 6.86439ZM31.2222 5.60883H33.8948V5.60793C34.5636 5.60793 35.07 5.38284 35.0701 4.79156V4.14581C35.0701 3.55449 34.5636 3.32934 33.8948 3.32934H31.2222V5.60883Z\" fill=\"white\"/>\n</g>\n</g>\n<path d=\"M65.0407 4.17188C65.0009 3.79972 64.8333 3.50994 64.5379 3.30256C64.2453 3.09517 63.8646 2.99148 63.3958 2.99148C63.0663 2.99148 62.7836 3.04119 62.5478 3.14062C62.312 3.24006 62.1316 3.375 62.0066 3.54545C61.8816 3.71591 61.8177 3.91051 61.8149 4.12926C61.8149 4.31108 61.856 4.46875 61.9384 4.60227C62.0237 4.7358 62.1387 4.84943 62.2836 4.94318C62.4285 5.03409 62.589 5.1108 62.7651 5.1733C62.9413 5.2358 63.1188 5.28835 63.2978 5.33097L64.116 5.53551C64.4455 5.61222 64.7623 5.71591 65.0663 5.84659C65.3731 5.97727 65.6472 6.14205 65.8887 6.34091C66.133 6.53977 66.3262 6.77983 66.4683 7.06108C66.6103 7.34233 66.6813 7.67187 66.6813 8.04972C66.6813 8.56108 66.5506 9.01136 66.2893 9.40057C66.0279 9.78693 65.6501 10.0895 65.1558 10.3082C64.6643 10.5241 64.0691 10.6321 63.3703 10.6321C62.6913 10.6321 62.1018 10.527 61.6018 10.3168C61.1046 10.1065 60.7154 9.79972 60.4342 9.39631C60.1558 8.9929 60.0052 8.50142 59.9825 7.92188H61.5379C61.5606 8.22585 61.6543 8.47869 61.8191 8.6804C61.9839 8.8821 62.1984 9.03267 62.4626 9.1321C62.7296 9.23153 63.0279 9.28125 63.3575 9.28125C63.7012 9.28125 64.0024 9.23011 64.2609 9.12784C64.5222 9.02273 64.7268 8.87784 64.8745 8.69318C65.0222 8.50568 65.0975 8.28693 65.1004 8.03693C65.0975 7.80966 65.0308 7.62216 64.9001 7.47443C64.7694 7.32386 64.5862 7.19886 64.3504 7.09943C64.1174 6.99716 63.8447 6.90625 63.5322 6.8267L62.5393 6.57102C61.8205 6.38636 61.2524 6.10653 60.8347 5.73153C60.42 5.35369 60.2126 4.85227 60.2126 4.22727C60.2126 3.71307 60.3518 3.26278 60.6302 2.87642C60.9114 2.49006 61.2935 2.19034 61.7765 1.97727C62.2595 1.76136 62.8063 1.65341 63.4171 1.65341C64.0364 1.65341 64.5791 1.76136 65.045 1.97727C65.5137 2.19034 65.8816 2.48722 66.1487 2.8679C66.4157 3.24574 66.5535 3.6804 66.562 4.17188H65.0407ZM75.8891 6.13636C75.8891 7.0767 75.7129 7.8821 75.3607 8.55256C75.0112 9.22017 74.534 9.73153 73.9288 10.0866C73.3266 10.4418 72.6433 10.6193 71.8791 10.6193C71.1149 10.6193 70.4303 10.4418 69.8252 10.0866C69.2229 9.72869 68.7456 9.21591 68.3933 8.5483C68.0439 7.87784 67.8692 7.07386 67.8692 6.13636C67.8692 5.19602 68.0439 4.39205 68.3933 3.72443C68.7456 3.05398 69.2229 2.54119 69.8252 2.18608C70.4303 1.83097 71.1149 1.65341 71.8791 1.65341C72.6433 1.65341 73.3266 1.83097 73.9288 2.18608C74.534 2.54119 75.0112 3.05398 75.3607 3.72443C75.7129 4.39205 75.8891 5.19602 75.8891 6.13636ZM74.2996 6.13636C74.2996 5.47443 74.1959 4.91619 73.9885 4.46165C73.784 4.00426 73.4999 3.65909 73.1362 3.42614C72.7726 3.19034 72.3536 3.07244 71.8791 3.07244C71.4047 3.07244 70.9857 3.19034 70.622 3.42614C70.2584 3.65909 69.9729 4.00426 69.7655 4.46165C69.5609 4.91619 69.4587 5.47443 69.4587 6.13636C69.4587 6.7983 69.5609 7.35795 69.7655 7.81534C69.9729 8.26989 70.2584 8.61506 70.622 8.85085C70.9857 9.08381 71.4047 9.20028 71.8791 9.20028C72.3536 9.20028 72.7726 9.08381 73.1362 8.85085C73.4999 8.61506 73.784 8.26989 73.9885 7.81534C74.1959 7.35795 74.2996 6.7983 74.2996 6.13636ZM77.3837 10.5V1.77273H78.9647V9.17472H82.8085V10.5H77.3837ZM91.6391 6.13636C91.6391 7.0767 91.4629 7.8821 91.1107 8.55256C90.7612 9.22017 90.284 9.73153 89.6788 10.0866C89.0766 10.4418 88.3933 10.6193 87.6291 10.6193C86.8649 10.6193 86.1803 10.4418 85.5752 10.0866C84.9729 9.72869 84.4956 9.21591 84.1433 8.5483C83.7939 7.87784 83.6192 7.07386 83.6192 6.13636C83.6192 5.19602 83.7939 4.39205 84.1433 3.72443C84.4956 3.05398 84.9729 2.54119 85.5752 2.18608C86.1803 1.83097 86.8649 1.65341 87.6291 1.65341C88.3933 1.65341 89.0766 1.83097 89.6788 2.18608C90.284 2.54119 90.7612 3.05398 91.1107 3.72443C91.4629 4.39205 91.6391 5.19602 91.6391 6.13636ZM90.0496 6.13636C90.0496 5.47443 89.9459 4.91619 89.7385 4.46165C89.534 4.00426 89.2499 3.65909 88.8862 3.42614C88.5226 3.19034 88.1036 3.07244 87.6291 3.07244C87.1547 3.07244 86.7357 3.19034 86.372 3.42614C86.0084 3.65909 85.7229 4.00426 85.5155 4.46165C85.3109 4.91619 85.2087 5.47443 85.2087 6.13636C85.2087 6.7983 85.3109 7.35795 85.5155 7.81534C85.7229 8.26989 86.0084 8.61506 86.372 8.85085C86.7357 9.08381 87.1547 9.20028 87.6291 9.20028C88.1036 9.20028 88.5226 9.08381 88.8862 8.85085C89.2499 8.61506 89.534 8.26989 89.7385 7.81534C89.9459 7.35795 90.0496 6.7983 90.0496 6.13636Z\" fill=\"#32F08C\"/>\n<defs>\n<clipPath id=\"clip0_5805_55291\">\n<rect width=\"54.874\" height=\"10.4242\" fill=\"white\" transform=\"translate(0.562988 0.787872)\"/>\n</clipPath>\n<clipPath id=\"clip1_5805_55291\">\n<rect width=\"14.5949\" height=\"10.4242\" fill=\"white\" transform=\"translate(0.562988 0.787872)\"/>\n</clipPath>\n<clipPath id=\"clip2_5805_55291\">\n<rect width=\"35.2321\" height=\"9.18536\" fill=\"white\" transform=\"translate(20.2048 1.50092)\"/>\n</clipPath>\n</defs>\n</svg>","dark":"<svg width=\"92\" height=\"12\" viewBox=\"0 0 92 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n<g clip-path=\"url(#clip0_5805_55291)\">\n<g clip-path=\"url(#clip1_5805_55291)\">\n<path d=\"M15.1579 11.2121H2.6478V9.12821H0.562988V0.787872H15.1579V11.2121ZM2.6478 9.12821H13.073V2.87269H2.6478V9.12821ZM7.86092 5.96865L6.38672 7.44275L4.91261 5.96865L6.38672 4.49445L7.86092 5.96865ZM12.0306 5.96775L10.5564 7.44185L9.08233 5.96775L10.5564 4.49355L12.0306 5.96775Z\" fill=\"black\"/>\n</g>\n<g clip-path=\"url(#clip2_5805_55291)\">\n<path d=\"M28.0793 3.37088H25.142V10.6863H23.143V3.37088H20.2048V1.50471H28.0793V3.37088ZM55.4369 3.36808H50.3789V8.81642H55.4369V10.6835H48.3789V1.50092H55.4369V3.36808ZM34.1761 1.50092C36.4528 1.50092 37.1355 2.2611 37.1355 4.43355C37.1355 6.00364 36.6872 6.72418 35.4243 7.14484L37.1466 10.6817H34.9474L33.3569 7.38096H31.2204L31.2222 10.6817V10.6826H29.2583V1.50092H34.1761ZM47.4897 10.6826H45.3993L44.5662 8.50363H40.8449L40.0819 10.6826H37.9048L41.4232 1.50471H44.081L47.4897 10.6826ZM55.436 6.11901L53.8697 7.59312L52.3955 6.11901L53.8697 4.64481L55.436 6.11901ZM41.4547 6.8644H44.0173L42.8578 3.5443H42.5985L41.4547 6.8644ZM31.2222 5.60884H33.8948V5.60794C34.5636 5.60793 35.07 5.38285 35.0701 4.79156V4.14581C35.0701 3.5545 34.5636 3.32935 33.8948 3.32935H31.2222V5.60884Z\" fill=\"black\"/>\n</g>\n</g>\n<path d=\"M65.0407 4.17188C65.0009 3.79972 64.8333 3.50994 64.5379 3.30256C64.2453 3.09517 63.8646 2.99148 63.3958 2.99148C63.0663 2.99148 62.7836 3.04119 62.5478 3.14062C62.312 3.24006 62.1316 3.375 62.0066 3.54545C61.8816 3.71591 61.8177 3.91051 61.8149 4.12926C61.8149 4.31108 61.856 4.46875 61.9384 4.60227C62.0237 4.7358 62.1387 4.84943 62.2836 4.94318C62.4285 5.03409 62.589 5.1108 62.7651 5.1733C62.9413 5.2358 63.1188 5.28835 63.2978 5.33097L64.116 5.53551C64.4455 5.61222 64.7623 5.71591 65.0663 5.84659C65.3731 5.97727 65.6472 6.14205 65.8887 6.34091C66.133 6.53977 66.3262 6.77983 66.4683 7.06108C66.6103 7.34233 66.6813 7.67187 66.6813 8.04972C66.6813 8.56108 66.5506 9.01136 66.2893 9.40057C66.0279 9.78693 65.6501 10.0895 65.1558 10.3082C64.6643 10.5241 64.0691 10.6321 63.3703 10.6321C62.6913 10.6321 62.1018 10.527 61.6018 10.3168C61.1046 10.1065 60.7154 9.79972 60.4342 9.39631C60.1558 8.9929 60.0052 8.50142 59.9825 7.92188H61.5379C61.5606 8.22585 61.6543 8.47869 61.8191 8.6804C61.9839 8.8821 62.1984 9.03267 62.4626 9.1321C62.7296 9.23153 63.0279 9.28125 63.3575 9.28125C63.7012 9.28125 64.0024 9.23011 64.2609 9.12784C64.5222 9.02273 64.7268 8.87784 64.8745 8.69318C65.0222 8.50568 65.0975 8.28693 65.1004 8.03693C65.0975 7.80966 65.0308 7.62216 64.9001 7.47443C64.7694 7.32386 64.5862 7.19886 64.3504 7.09943C64.1174 6.99716 63.8447 6.90625 63.5322 6.8267L62.5393 6.57102C61.8205 6.38636 61.2524 6.10653 60.8347 5.73153C60.42 5.35369 60.2126 4.85227 60.2126 4.22727C60.2126 3.71307 60.3518 3.26278 60.6302 2.87642C60.9114 2.49006 61.2935 2.19034 61.7765 1.97727C62.2595 1.76136 62.8063 1.65341 63.4171 1.65341C64.0364 1.65341 64.5791 1.76136 65.045 1.97727C65.5137 2.19034 65.8816 2.48722 66.1487 2.8679C66.4157 3.24574 66.5535 3.6804 66.562 4.17188H65.0407ZM75.8891 6.13636C75.8891 7.0767 75.7129 7.8821 75.3607 8.55256C75.0112 9.22017 74.534 9.73153 73.9288 10.0866C73.3266 10.4418 72.6433 10.6193 71.8791 10.6193C71.1149 10.6193 70.4303 10.4418 69.8252 10.0866C69.2229 9.72869 68.7456 9.21591 68.3933 8.5483C68.0439 7.87784 67.8692 7.07386 67.8692 6.13636C67.8692 5.19602 68.0439 4.39205 68.3933 3.72443C68.7456 3.05398 69.2229 2.54119 69.8252 2.18608C70.4303 1.83097 71.1149 1.65341 71.8791 1.65341C72.6433 1.65341 73.3266 1.83097 73.9288 2.18608C74.534 2.54119 75.0112 3.05398 75.3607 3.72443C75.7129 4.39205 75.8891 5.19602 75.8891 6.13636ZM74.2996 6.13636C74.2996 5.47443 74.1959 4.91619 73.9885 4.46165C73.784 4.00426 73.4999 3.65909 73.1362 3.42614C72.7726 3.19034 72.3536 3.07244 71.8791 3.07244C71.4047 3.07244 70.9857 3.19034 70.622 3.42614C70.2584 3.65909 69.9729 4.00426 69.7655 4.46165C69.5609 4.91619 69.4587 5.47443 69.4587 6.13636C69.4587 6.7983 69.5609 7.35795 69.7655 7.81534C69.9729 8.26989 70.2584 8.61506 70.622 8.85085C70.9857 9.08381 71.4047 9.20028 71.8791 9.20028C72.3536 9.20028 72.7726 9.08381 73.1362 8.85085C73.4999 8.61506 73.784 8.26989 73.9885 7.81534C74.1959 7.35795 74.2996 6.7983 74.2996 6.13636ZM77.3837 10.5V1.77273H78.9647V9.17472H82.8085V10.5H77.3837ZM91.6391 6.13636C91.6391 7.0767 91.4629 7.8821 91.1107 8.55256C90.7612 9.22017 90.284 9.73153 89.6788 10.0866C89.0766 10.4418 88.3933 10.6193 87.6291 10.6193C86.8649 10.6193 86.1803 10.4418 85.5752 10.0866C84.9729 9.72869 84.4956 9.21591 84.1433 8.5483C83.7939 7.87784 83.6192 7.07386 83.6192 6.13636C83.6192 5.19602 83.7939 4.39205 84.1433 3.72443C84.4956 3.05398 84.9729 2.54119 85.5752 2.18608C86.1803 1.83097 86.8649 1.65341 87.6291 1.65341C88.3933 1.65341 89.0766 1.83097 89.6788 2.18608C90.284 2.54119 90.7612 3.05398 91.1107 3.72443C91.4629 4.39205 91.6391 5.19602 91.6391 6.13636ZM90.0496 6.13636C90.0496 5.47443 89.9459 4.91619 89.7385 4.46165C89.534 4.00426 89.2499 3.65909 88.8862 3.42614C88.5226 3.19034 88.1036 3.07244 87.6291 3.07244C87.1547 3.07244 86.7357 3.19034 86.372 3.42614C86.0084 3.65909 85.7229 4.00426 85.5155 4.46165C85.3109 4.91619 85.2087 5.47443 85.2087 6.13636C85.2087 6.7983 85.3109 7.35795 85.5155 7.81534C85.7229 8.26989 86.0084 8.61506 86.372 8.85085C86.7357 9.08381 87.1547 9.20028 87.6291 9.20028C88.1036 9.20028 88.5226 9.08381 88.8862 8.85085C89.2499 8.61506 89.534 8.26989 89.7385 7.81534C89.9459 7.35795 90.0496 6.7983 90.0496 6.13636Z\" fill=\"#0AB861\"/>\n<defs>\n<clipPath id=\"clip0_5805_55291\">\n<rect width=\"54.874\" height=\"10.4242\" fill=\"white\" transform=\"translate(0.562988 0.787872)\"/>\n</clipPath>\n<clipPath id=\"clip1_5805_55291\">\n<rect width=\"14.5949\" height=\"10.4242\" fill=\"white\" transform=\"translate(0.562988 0.787872)\"/>\n</clipPath>\n<clipPath id=\"clip2_5805_55291\">\n<rect width=\"35.2321\" height=\"9.18536\" fill=\"white\" transform=\"translate(20.2048 1.50092)\"/>\n</clipPath>\n</defs>\n</svg>"};
117
+ const cancelDark = `<svg width="16" height="15" viewBox="0 0 16 15" fill="none" xmlns="http://www.w3.org/2000/svg">
118
+ <g clip-path="url(#clip0_5993_243)">
119
+ <path d="M0.437012 7.5C0.437012 3.35786 3.79488 0 7.93701 0C12.0791 0 15.437 3.35786 15.437 7.5C15.437 11.6421 12.0791 15 7.93701 15C3.79488 15 0.437012 11.6421 0.437012 7.5Z" fill="#EDEFF2"/>
120
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M7.93698 1.34036C11.3391 1.34036 14.0966 4.09792 14.0966 7.5C14.0966 10.9021 11.3391 13.6596 7.93698 13.6596C4.53491 13.6596 1.77734 10.9021 1.77734 7.5C1.77734 4.09792 4.53491 1.34036 7.93698 1.34036Z" fill="#111214"/>
121
+ <path d="M7.93717 6.70886L9.40826 5.23776L9.80383 4.84128L10.5959 5.63334L10.1994 6.02891L8.72831 7.5L10.1994 8.9711L10.5959 9.36667L9.80383 10.1587L9.40826 9.76224L7.93717 8.29115L6.46607 9.76224L6.0705 10.1587L5.27844 9.36667L5.67493 8.9711L7.14602 7.5L5.67493 6.02891L5.27844 5.63334L6.0705 4.84128L6.46607 5.23776L7.93717 6.70886Z" fill="white"/>
122
+ </g>
123
+ <defs>
124
+ <clipPath id="clip0_5993_243">
125
+ <path d="M0.437012 7.5C0.437012 3.35786 3.79488 0 7.93701 0C12.0791 0 15.437 3.35786 15.437 7.5C15.437 11.6421 12.0791 15 7.93701 15C3.79488 15 0.437012 11.6421 0.437012 7.5Z" fill="white"/>
126
+ </clipPath>
127
+ </defs>
128
+ </svg>`;
129
+ const cancelLight = `<svg width="16" height="15" viewBox="0 0 16 15" fill="none" xmlns="http://www.w3.org/2000/svg">
130
+ <g clip-path="url(#clip0_5993_279)">
131
+ <path d="M0.437012 7.5C0.437012 3.35786 3.79488 0 7.93701 0C12.0791 0 15.437 3.35786 15.437 7.5C15.437 11.6421 12.0791 15 7.93701 15C3.79488 15 0.437012 11.6421 0.437012 7.5Z" fill="#2A2D31"/>
132
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M7.93698 1.34036C11.3391 1.34036 14.0966 4.09792 14.0966 7.5C14.0966 10.9021 11.3391 13.6596 7.93698 13.6596C4.53491 13.6596 1.77734 10.9021 1.77734 7.5C1.77734 4.09792 4.53491 1.34036 7.93698 1.34036Z" fill="white"/>
133
+ <path d="M7.93717 6.70886L9.40826 5.23776L9.80383 4.84128L10.5959 5.63334L10.1994 6.02891L8.72831 7.5L10.1994 8.9711L10.5959 9.36667L9.80383 10.1587L9.40826 9.76224L7.93717 8.29115L6.46607 9.76224L6.0705 10.1587L5.27844 9.36667L5.67493 8.9711L7.14602 7.5L5.67493 6.02891L5.27844 5.63334L6.0705 4.84128L6.46607 5.23776L7.93717 6.70886Z" fill="black"/>
134
+ </g>
135
+ <defs>
136
+ <clipPath id="clip0_5993_279">
137
+ <path d="M0.437012 7.5C0.437012 3.35786 3.79488 0 7.93701 0C12.0791 0 15.437 3.35786 15.437 7.5C15.437 11.6421 12.0791 15 7.93701 15C3.79488 15 0.437012 11.6421 0.437012 7.5Z" fill="white"/>
138
+ </clipPath>
139
+ </defs>
140
+ </svg>`;
141
+ const shareIcon = `<svg width="15" height="14" viewBox="0 0 15 14" fill="none" xmlns="http://www.w3.org/2000/svg">
142
+ <path d="M5.68693 2.33333H2.77026V11.6667H12.1036V8.75M8.6036 2.33333H12.1036V5.83333M6.8536 7.58333L11.5203 2.91666"
143
+ stroke="currentColor" stroke-width="1.05" stroke-linecap="square"/>
144
+ </svg>`;
145
+
146
+
147
+ // 主题选择函数 (复用自 theme.ts)
148
+ function getLuminance(r, g, b) {
149
+ return 0.299 * r + 0.587 * g + 0.114 * b;
150
+ }
151
+
152
+ function parseColor(color) {
153
+ const rgbaMatch = color.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*[\d.]+)?\)/);
154
+ if (rgbaMatch) {
155
+ return [parseInt(rgbaMatch[1]), parseInt(rgbaMatch[2]), parseInt(rgbaMatch[3])];
156
+ }
157
+
158
+ const hexMatch = color.match(/^#([0-9a-f]{6})$/i);
159
+ if (hexMatch) {
160
+ const hex = hexMatch[1];
161
+ return [
162
+ parseInt(hex.substr(0, 2), 16),
163
+ parseInt(hex.substr(2, 2), 16),
164
+ parseInt(hex.substr(4, 2), 16)
165
+ ];
166
+ }
167
+
168
+ const hexShortMatch = color.match(/^#([0-9a-f]{3})$/i);
169
+ if (hexShortMatch) {
170
+ const hex = hexShortMatch[1];
171
+ return [
172
+ parseInt(hex[0] + hex[0], 16),
173
+ parseInt(hex[1] + hex[1], 16),
174
+ parseInt(hex[2] + hex[2], 16)
175
+ ];
176
+ }
177
+
178
+ return null;
179
+ }
180
+
181
+ function detectBackgroundColor(element) {
182
+ let targetElement;
183
+
184
+ if (typeof element === 'string') {
185
+ const found = document.querySelector(element);
186
+ console.debug('Target element found:', found);
187
+ if (!found) return 'rgb(255, 255, 255)';
188
+ targetElement = found;
189
+ } else if (element) {
190
+ targetElement = element;
191
+ } else {
192
+ targetElement = document.body;
193
+ }
194
+
195
+ let currentElement = targetElement;
196
+
197
+ while (currentElement && currentElement !== document.documentElement) {
198
+ const computedStyle = window.getComputedStyle(currentElement);
199
+ const backgroundColor = computedStyle.backgroundColor;
200
+
201
+ console.debug('Checking element:', currentElement.tagName, currentElement.id, currentElement.className);
202
+ console.debug('Background color:', backgroundColor);
203
+
204
+ if (backgroundColor && backgroundColor !== 'rgba(0, 0, 0, 0)' && backgroundColor !== 'transparent') {
205
+ console.debug('Found background color:', backgroundColor, 'on element:', currentElement);
206
+ return backgroundColor;
207
+ }
208
+
209
+ currentElement = currentElement.parentElement;
210
+ }
211
+
212
+ const bodyStyle = window.getComputedStyle(document.body);
213
+ const bodyBackground = bodyStyle.backgroundColor;
214
+ console.debug('Body background:', bodyBackground);
215
+ if (bodyBackground && bodyBackground !== 'rgba(0, 0, 0, 0)' && bodyBackground !== 'transparent') {
216
+ return bodyBackground;
217
+ }
218
+
219
+ const htmlStyle = window.getComputedStyle(document.documentElement);
220
+ const htmlBackground = htmlStyle.backgroundColor;
221
+ console.debug('HTML background:', htmlBackground);
222
+ if (htmlBackground && htmlBackground !== 'rgba(0, 0, 0, 0)' && htmlBackground !== 'transparent') {
223
+ return htmlBackground;
224
+ }
225
+
226
+ console.debug('No background found, returning default white');
227
+ return 'rgb(255, 255, 255)';
228
+ }
229
+
230
+ function autoSelectTheme(container) {
231
+ const backgroundColor = detectBackgroundColor(container);
232
+ const rgb = parseColor(backgroundColor);
233
+
234
+ console.debug('TRAE Badge Plugin - Background detection:', {
235
+ container,
236
+ backgroundColor,
237
+ rgb
238
+ });
239
+
240
+ if (!rgb) {
241
+ console.debug('TRAE Badge Plugin - No RGB found, using dark theme');
242
+ return 'dark';
243
+ }
244
+
245
+ const [r, g, b] = rgb;
246
+ const luminance = getLuminance(r, g, b);
247
+ const selectedTheme = luminance > 128 ? 'dark' : 'light';
248
+
249
+ console.debug('TRAE Badge Plugin - Theme selection:', {
250
+ luminance,
251
+ selectedTheme,
252
+ reason: luminance > 128 ? 'Light background -> Dark badge' : 'Dark background -> Light badge'
253
+ });
254
+
255
+ return selectedTheme;
256
+ }
257
+
258
+
259
+ // 注入样式
260
+ const style = document.createElement('style');
261
+ style.id = 'trae-badge-plugin-styles';
262
+ style.textContent = css;
263
+ document.head.appendChild(style);
264
+
265
+ // 创建 Badge 函数
266
+ function createBadge() {
267
+ // 移除已存在的 badge
268
+ const existingBadge = document.getElementById('trae-badge-plugin');
269
+ if (existingBadge) {
270
+ existingBadge.remove();
271
+ }
272
+
273
+ // 确定主题
274
+ let variant = 'dark';
275
+ if (true) {
276
+ variant = autoSelectTheme('#root');
277
+ }
278
+
279
+ const isDarkBackground = variant === 'dark';
280
+ const logoType = isDarkBackground ? 'light' : 'dark';
281
+ const cancelIcon = isDarkBackground ? cancelLight : cancelDark;
282
+
283
+ const badge = document.createElement('div');
284
+ badge.id = 'trae-badge-plugin';
285
+ badge.className = `trae-badge trae-badge--${variant} trae-badge--bottom-right`;
286
+ badge.innerHTML = `
287
+ <div class="trae-badge-content">
288
+ <div class="trae-badge-logo">${logos[logoType]}</div>
289
+ <div class="trae-badge-share">${shareIcon}</div>
290
+ </div>
291
+ <div class="trae-badge-cancel">${cancelIcon}</div>
292
+ `;
293
+
294
+ // 添加点击事件
295
+
296
+ badge.style.cursor = 'pointer';
297
+ badge.addEventListener('click', (e) => {
298
+ if (e.target.closest('.trae-badge-cancel')) return;
299
+ window.open('https://www.trae.ai/solo?showJoin=1', '_blank');
300
+ });
301
+
302
+
303
+ // 添加取消按钮事件
304
+ const cancelButton = badge.querySelector('.trae-badge-cancel');
305
+ if (cancelButton) {
306
+ cancelButton.addEventListener('click', (e) => {
307
+ e.stopPropagation();
308
+ badge.remove();
309
+ });
310
+ }
311
+
312
+ document.body.appendChild(badge);
313
+ return badge;
314
+ }
315
+
316
+ // 初始创建 badge
317
+ // 等待 React 组件渲染完成后再创建 badge
318
+ function initBadge() {
319
+ // 使用 requestAnimationFrame 等待渲染完成
320
+ requestAnimationFrame(() => {
321
+ // 再次检查目标元素是否存在
322
+ const targetElement = document.querySelector('#root');
323
+ if (targetElement) {
324
+ const badge = createBadge();
325
+ } else {
326
+ // 如果还没有找到,等待一段时间再试
327
+ setTimeout(() => {
328
+ const badge = createBadge();
329
+ }, 500);
330
+ }
331
+ });
332
+ }
333
+
334
+ if (document.readyState === 'loading') {
335
+ document.addEventListener('DOMContentLoaded', initBadge);
336
+ } else {
337
+ // DOM 已经加载完成,但 React 可能还没渲染
338
+ initBadge();
339
+ }
340
+
341
+ window.TraeBadgePlugin = {
342
+ destroy: () => {
343
+ const badge = document.getElementById('trae-badge-plugin');
344
+ if (badge) badge.remove();
345
+ style.remove();
346
+ delete window.TraeBadgePlugin;
347
+ },
348
+ recreate: createBadge
349
+ };
350
+ })();
351
+ </script>
352
+
353
+ </body>
354
+ </html>
@@ -0,0 +1,28 @@
1
+ import js from '@eslint/js'
2
+ import globals from 'globals'
3
+ import reactHooks from 'eslint-plugin-react-hooks'
4
+ import reactRefresh from 'eslint-plugin-react-refresh'
5
+ import tseslint from 'typescript-eslint'
6
+
7
+ export default tseslint.config(
8
+ { ignores: ['dist'] },
9
+ {
10
+ extends: [js.configs.recommended, ...tseslint.configs.recommended],
11
+ files: ['**/*.{ts,tsx}'],
12
+ languageOptions: {
13
+ ecmaVersion: 2020,
14
+ globals: globals.browser,
15
+ },
16
+ plugins: {
17
+ 'react-hooks': reactHooks,
18
+ 'react-refresh': reactRefresh,
19
+ },
20
+ rules: {
21
+ ...reactHooks.configs.recommended.rules,
22
+ 'react-refresh/only-export-components': [
23
+ 'warn',
24
+ { allowConstantExport: true },
25
+ ],
26
+ },
27
+ },
28
+ )
package/index.html ADDED
@@ -0,0 +1,24 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>My Trae Project</title>
8
+ <script type="module">
9
+ if (import.meta.hot?.on) {
10
+ import.meta.hot.on('vite:error', (error) => {
11
+ if (error.err) {
12
+ console.error(
13
+ [error.err.message, error.err.frame].filter(Boolean).join('\n'),
14
+ )
15
+ }
16
+ })
17
+ }
18
+ </script>
19
+ </head>
20
+ <body>
21
+ <div id="root"></div>
22
+ <script type="module" src="/src/main.tsx"></script>
23
+ </body>
24
+ </html>
package/nodemon.json ADDED
@@ -0,0 +1,10 @@
1
+ {
2
+ "watch": ["api"],
3
+ "ext": "ts,mts,js,json",
4
+ "ignore": ["api/dist/*"],
5
+ "exec": "tsx api/server.ts",
6
+ "env": {
7
+ "NODE_ENV": "development"
8
+ },
9
+ "delay": 1000
10
+ }
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "mjpic",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "bin": {
6
+ "mjpic": "./dist/cli/cli.js"
7
+ },
8
+ "scripts": {
9
+ "client:dev": "vite",
10
+ "build:client": "vite build",
11
+ "build:server": "tsc -p tsconfig.server.json",
12
+ "build": "npm run build:client && npm run build:server",
13
+ "lint": "eslint .",
14
+ "preview": "vite preview",
15
+ "check": "tsc --noEmit",
16
+ "server:dev": "nodemon",
17
+ "dev": "concurrently \"npm run client:dev\" \"npm run server:dev\""
18
+ },
19
+ "dependencies": {
20
+ "@dnd-kit/core": "^6.3.1",
21
+ "@dnd-kit/sortable": "^10.0.0",
22
+ "@dnd-kit/utilities": "^3.2.2",
23
+ "clsx": "^2.1.1",
24
+ "commander": "^14.0.3",
25
+ "cors": "^2.8.5",
26
+ "dotenv": "^17.2.1",
27
+ "express": "^4.21.2",
28
+ "i18next": "^25.8.8",
29
+ "i18next-browser-languagedetector": "^8.2.1",
30
+ "konva": "^9.3.16",
31
+ "lucide-react": "^0.511.0",
32
+ "open": "^11.0.0",
33
+ "react": "^18.3.1",
34
+ "react-dom": "^18.3.1",
35
+ "react-i18next": "^16.5.4",
36
+ "react-konva": "^18.2.10",
37
+ "react-router-dom": "^7.3.0",
38
+ "tailwind-merge": "^3.0.2",
39
+ "use-image": "^1.1.4",
40
+ "zustand": "^5.0.3"
41
+ },
42
+ "devDependencies": {
43
+ "@eslint/js": "^9.25.0",
44
+ "@types/cors": "^2.8.19",
45
+ "@types/express": "^4.17.21",
46
+ "@types/node": "^22.15.30",
47
+ "@types/react": "^18.3.12",
48
+ "@types/react-dom": "^18.3.1",
49
+ "@vercel/node": "^5.3.6",
50
+ "@vitejs/plugin-react": "^4.4.1",
51
+ "autoprefixer": "^10.4.21",
52
+ "babel-plugin-react-dev-locator": "^1.0.0",
53
+ "concurrently": "^9.2.0",
54
+ "eslint": "^9.25.0",
55
+ "eslint-plugin-react-hooks": "^5.2.0",
56
+ "eslint-plugin-react-refresh": "^0.4.19",
57
+ "globals": "^16.0.0",
58
+ "nodemon": "^3.1.10",
59
+ "postcss": "^8.5.3",
60
+ "tailwindcss": "^3.4.17",
61
+ "tsx": "^4.20.3",
62
+ "typescript": "~5.8.3",
63
+ "typescript-eslint": "^8.30.1",
64
+ "vite": "^6.3.5",
65
+ "vite-plugin-trae-solo-badge": "^1.0.0",
66
+ "vite-tsconfig-paths": "^5.1.4"
67
+ }
68
+ }
@@ -0,0 +1,10 @@
1
+ /** WARNING: DON'T EDIT THIS FILE */
2
+ /** WARNING: DON'T EDIT THIS FILE */
3
+ /** WARNING: DON'T EDIT THIS FILE */
4
+
5
+ export default {
6
+ plugins: {
7
+ tailwindcss: {},
8
+ autoprefixer: {},
9
+ },
10
+ };
@@ -0,0 +1,4 @@
1
+ <svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <rect width="32" height="32" fill="#0A0B0D"/>
3
+ <path d="M26.6677 23.7149H8.38057V20.6496H5.33301V8.38159H26.6677V23.7149ZM8.38057 20.6496H23.6201V11.4482H8.38057V20.6496ZM16.0011 16.0021L13.8461 18.1705L11.6913 16.0021L13.8461 13.8337L16.0011 16.0021ZM22.0963 16.0008L19.9414 18.1691L17.7865 16.0008L19.9414 13.8324L22.0963 16.0008Z" fill="#32F08C"/>
4
+ </svg>
package/src/App.tsx ADDED
@@ -0,0 +1,13 @@
1
+ import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
2
+ import Home from "@/pages/Home";
3
+
4
+ export default function App() {
5
+ return (
6
+ <Router>
7
+ <Routes>
8
+ <Route path="/" element={<Home />} />
9
+ <Route path="/other" element={<div className="text-center text-xl">Other Page - Coming Soon</div>} />
10
+ </Routes>
11
+ </Router>
12
+ );
13
+ }
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="35.93" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 228"><path fill="#00D8FF" d="M210.483 73.824a171.49 171.49 0 0 0-8.24-2.597c.465-1.9.893-3.777 1.273-5.621c6.238-30.281 2.16-54.676-11.769-62.708c-13.355-7.7-35.196.329-57.254 19.526a171.23 171.23 0 0 0-6.375 5.848a155.866 155.866 0 0 0-4.241-3.917C100.759 3.829 77.587-4.822 63.673 3.233C50.33 10.957 46.379 33.89 51.995 62.588a170.974 170.974 0 0 0 1.892 8.48c-3.28.932-6.445 1.924-9.474 2.98C17.309 83.498 0 98.307 0 113.668c0 15.865 18.582 31.778 46.812 41.427a145.52 145.52 0 0 0 6.921 2.165a167.467 167.467 0 0 0-2.01 9.138c-5.354 28.2-1.173 50.591 12.134 58.266c13.744 7.926 36.812-.22 59.273-19.855a145.567 145.567 0 0 0 5.342-4.923a168.064 168.064 0 0 0 6.92 6.314c21.758 18.722 43.246 26.282 56.54 18.586c13.731-7.949 18.194-32.003 12.4-61.268a145.016 145.016 0 0 0-1.535-6.842c1.62-.48 3.21-.974 4.76-1.488c29.348-9.723 48.443-25.443 48.443-41.52c0-15.417-17.868-30.326-45.517-39.844Zm-6.365 70.984c-1.4.463-2.836.91-4.3 1.345c-3.24-10.257-7.612-21.163-12.963-32.432c5.106-11 9.31-21.767 12.459-31.957c2.619.758 5.16 1.557 7.61 2.4c23.69 8.156 38.14 20.213 38.14 29.504c0 9.896-15.606 22.743-40.946 31.14Zm-10.514 20.834c2.562 12.94 2.927 24.64 1.23 33.787c-1.524 8.219-4.59 13.698-8.382 15.893c-8.067 4.67-25.32-1.4-43.927-17.412a156.726 156.726 0 0 1-6.437-5.87c7.214-7.889 14.423-17.06 21.459-27.246c12.376-1.098 24.068-2.894 34.671-5.345a134.17 134.17 0 0 1 1.386 6.193ZM87.276 214.515c-7.882 2.783-14.16 2.863-17.955.675c-8.075-4.657-11.432-22.636-6.853-46.752a156.923 156.923 0 0 1 1.869-8.499c10.486 2.32 22.093 3.988 34.498 4.994c7.084 9.967 14.501 19.128 21.976 27.15a134.668 134.668 0 0 1-4.877 4.492c-9.933 8.682-19.886 14.842-28.658 17.94ZM50.35 144.747c-12.483-4.267-22.792-9.812-29.858-15.863c-6.35-5.437-9.555-10.836-9.555-15.216c0-9.322 13.897-21.212 37.076-29.293c2.813-.98 5.757-1.905 8.812-2.773c3.204 10.42 7.406 21.315 12.477 32.332c-5.137 11.18-9.399 22.249-12.634 32.792a134.718 134.718 0 0 1-6.318-1.979Zm12.378-84.26c-4.811-24.587-1.616-43.134 6.425-47.789c8.564-4.958 27.502 2.111 47.463 19.835a144.318 144.318 0 0 1 3.841 3.545c-7.438 7.987-14.787 17.08-21.808 26.988c-12.04 1.116-23.565 2.908-34.161 5.309a160.342 160.342 0 0 1-1.76-7.887Zm110.427 27.268a347.8 347.8 0 0 0-7.785-12.803c8.168 1.033 15.994 2.404 23.343 4.08c-2.206 7.072-4.956 14.465-8.193 22.045a381.151 381.151 0 0 0-7.365-13.322Zm-45.032-43.861c5.044 5.465 10.096 11.566 15.065 18.186a322.04 322.04 0 0 0-30.257-.006c4.974-6.559 10.069-12.652 15.192-18.18ZM82.802 87.83a323.167 323.167 0 0 0-7.227 13.238c-3.184-7.553-5.909-14.98-8.134-22.152c7.304-1.634 15.093-2.97 23.209-3.984a321.524 321.524 0 0 0-7.848 12.897Zm8.081 65.352c-8.385-.936-16.291-2.203-23.593-3.793c2.26-7.3 5.045-14.885 8.298-22.6a321.187 321.187 0 0 0 7.257 13.246c2.594 4.48 5.28 8.868 8.038 13.147Zm37.542 31.03c-5.184-5.592-10.354-11.779-15.403-18.433c4.902.192 9.899.29 14.978.29c5.218 0 10.376-.117 15.453-.343c-4.985 6.774-10.018 12.97-15.028 18.486Zm52.198-57.817c3.422 7.8 6.306 15.345 8.596 22.52c-7.422 1.694-15.436 3.058-23.88 4.071a382.417 382.417 0 0 0 7.859-13.026a347.403 347.403 0 0 0 7.425-13.565Zm-16.898 8.101a358.557 358.557 0 0 1-12.281 19.815a329.4 329.4 0 0 1-23.444.823c-7.967 0-15.716-.248-23.178-.732a310.202 310.202 0 0 1-12.513-19.846h.001a307.41 307.41 0 0 1-10.923-20.627a310.278 310.278 0 0 1 10.89-20.637l-.001.001a307.318 307.318 0 0 1 12.413-19.761c7.613-.576 15.42-.876 23.31-.876H128c7.926 0 15.743.303 23.354.883a329.357 329.357 0 0 1 12.335 19.695a358.489 358.489 0 0 1 11.036 20.54a329.472 329.472 0 0 1-11 20.722Zm22.56-122.124c8.572 4.944 11.906 24.881 6.52 51.026c-.344 1.668-.73 3.367-1.15 5.09c-10.622-2.452-22.155-4.275-34.23-5.408c-7.034-10.017-14.323-19.124-21.64-27.008a160.789 160.789 0 0 1 5.888-5.4c18.9-16.447 36.564-22.941 44.612-18.3ZM128 90.808c12.625 0 22.86 10.235 22.86 22.86s-10.235 22.86-22.86 22.86s-22.86-10.235-22.86-22.86s10.235-22.86 22.86-22.86Z"></path></svg>
@@ -0,0 +1,8 @@
1
+ import { cn } from '@/lib/utils'
2
+
3
+ // Empty component
4
+ export default function Empty() {
5
+ return (
6
+ <div className={cn('flex h-full items-center justify-center')}>Empty</div>
7
+ )
8
+ }