diff --git a/apps/ai-game-creator-shell/src/features/resource-canvas/resourceCanvasChrome.css b/apps/ai-game-creator-shell/src/features/resource-canvas/resourceCanvasChrome.css index 2b63f5113..068b31d02 100644 --- a/apps/ai-game-creator-shell/src/features/resource-canvas/resourceCanvasChrome.css +++ b/apps/ai-game-creator-shell/src/features/resource-canvas/resourceCanvasChrome.css @@ -3,8 +3,10 @@ * 的 AGC 宿主 chrome。 * * 这些 `image-canvas-editor__*` 类名在网页端由全局样式表 src/index.css 提供;AGC 是独立 - * 应用、不引入那张整站样式表,因此在这里按实际用到的类补一套宿主样式:定位、浮层层级、 - * 按钮与面板外观。组件本身与交互语义仍全部复用美术画布的实现。 + * 应用、不引入那张整站样式表,因此在这里按实际用到的类补一套宿主样式。规则**逐条照抄** + * src/index.css 的同名规则(只删掉 AGC 没渲染的兄弟选择器),不再手写近似值: + * 快速编辑面板 / 生成 composer 及其选项区与下拉弹层 / 选中工具条。组件本身与交互语义 + * 仍全部复用美术画布的实现。 */ /* 主题变量:与网页端 .image-canvas-editor 作用域下的一组变量保持一致。 */ @@ -122,130 +124,639 @@ background: var(--image-canvas-brand-border-soft); } -/* 快速编辑浮层面板:锚在资源卡正下方。 */ -.game-resource-canvas-toolbar-host .image-canvas-editor__generation-composer { - position: absolute; - z-index: 70; - display: flex; - width: min(360px, 92vw); - flex-direction: column; - gap: 0.5rem; - padding: 0.75rem; - border: 1px solid var(--image-canvas-brand-border-soft); - border-radius: 0.75rem; - background: #ffffff; - box-shadow: 0 22px 40px rgba(15, 23, 42, 0.22); - transform: translateX(-50%); - pointer-events: auto; -} +/* ========================================================================== + * 以下规则逐条照抄 src/index.css;只保留 AGC 实际渲染到的类。 + * 顺序与源文件一致——有几组选择器权重相同,靠先后顺序定胜负。 + * ========================================================================== */ -.game-resource-canvas-toolbar-host .image-canvas-editor__generation-prompt { - width: 100%; - min-height: 4.5rem; - resize: none; - border: 1px solid var(--image-canvas-brand-border-soft); - border-radius: 0.5rem; - padding: 0.5rem 0.6rem; - background: #fffdfa; +.image-canvas-editor__generation-composer { + position: absolute; + z-index: 13; + display: grid; + grid-template-columns: 3.8rem minmax(0, 1fr); + grid-template-rows: minmax(5.9rem, auto) auto auto; + width: min(38rem, calc(100% - 1.5rem)); + min-height: 10.4rem; + gap: 0.38rem 0.72rem; + border: 1px solid rgba(15, 23, 42, 0.09); + border-radius: 1.45rem; + background: rgba(255, 255, 255, 0.97); + padding: 0.72rem 0.82rem 0.58rem; color: #1f2937; font-size: 0.82rem; - line-height: 1.5; + box-shadow: + 0 22px 60px rgba(15, 23, 42, 0.12), + inset 0 1px 0 rgba(255, 255, 255, 0.94); + transform: translateX(-50%); + backdrop-filter: blur(18px); } -.game-resource-canvas-toolbar-host .image-canvas-editor__reference-strip { - display: flex; - flex-wrap: wrap; - gap: 0.35rem; +.image-canvas-editor__generation-composer--image { + grid-template-columns: 4rem minmax(0, 1fr); + grid-template-rows: auto auto auto; + width: min(42rem, calc(100% - 1.5rem)); + gap: 0.18rem 0.72rem; } -.game-resource-canvas-toolbar-host - .image-canvas-editor__generation-composer-footer { - display: flex; - align-items: center; - justify-content: space-between; - gap: 0.5rem; - flex-wrap: wrap; +.image-canvas-editor__generation-prompt { + --auto-grow-editor-radius: 1.05rem; + --auto-grow-editor-min-height: 3.35rem; + --auto-grow-editor-padding: 0.52rem 0.82rem; + grid-column: 1 / -1; + border: 1px solid rgba(15, 23, 42, 0.08); + border-radius: var(--auto-grow-editor-radius); + background: #f8fafc; + color: #0f172a; + font: inherit; + font-size: 0.82rem; + font-weight: 680; + line-height: 1.48; + outline: none; } -.game-resource-canvas-toolbar-host .image-canvas-editor__option-cluster { - display: inline-flex; - align-items: center; - gap: 0.3rem; - flex-wrap: wrap; -} - -.game-resource-canvas-toolbar-host .image-canvas-editor__option-popover-anchor { - position: relative; - display: inline-flex; -} - -.game-resource-canvas-toolbar-host - .image-canvas-editor__option-popover { - position: absolute; - bottom: calc(100% + 6px); - left: 0; - z-index: 80; - min-width: 12rem; - border: 1px solid var(--image-canvas-brand-border-soft); - border-radius: 0.6rem; +.image-canvas-editor__generation-prompt:focus-within { + border-color: var(--image-canvas-brand-border-strong); background: #ffffff; - padding: 0.5rem; - box-shadow: 0 18px 32px rgba(15, 23, 42, 0.2); + box-shadow: 0 0 0 3px var(--image-canvas-brand-focus-ring); } -.game-resource-canvas-toolbar-host - .image-canvas-editor__option-popover-sections { - display: flex; - flex-direction: column; - gap: 0.4rem; +.image-canvas-editor__generation-prompt .auto-grow-text-area__placeholder { + color: #94a3b8; } -.game-resource-canvas-toolbar-host - .image-canvas-editor__option-popover-items { +.image-canvas-editor__generation-composer-footer { + grid-column: 1 / -1; + display: grid; + grid-template-columns: + max-content minmax(0, 1fr) + max-content max-content max-content; + align-items: center; + gap: 0.1rem; + justify-content: start; + position: relative; + border-top: 1px solid rgba(15, 23, 42, 0.06); + padding-top: 0.44rem; +} + +.image-canvas-editor__generation-composer + .image-canvas-editor__generation-composer-footer { + padding-top: 1.1rem; +} + +.image-canvas-editor__option-cluster { + min-height: 2.25rem; + height: 2.25rem; + width: 100%; + min-width: 0; + border: 1px solid transparent; + border-radius: 999px; + background: transparent; + padding: 0 0.72rem; + color: #0f172a; + box-shadow: none; +} + +.image-canvas-editor__option-cluster .platform-inline-option-button__label { + display: inline-flex; + min-width: 0; + max-width: 100%; + align-items: center; + overflow: hidden; +} + +.image-canvas-editor__option-cluster:hover:not(:disabled), +.image-canvas-editor__option-cluster[aria-expanded='true'] { + border-color: rgba(15, 23, 42, 0.08); + background: #f8fafc; + box-shadow: 0 10px 24px rgba(15, 23, 42, 0.08); +} + +.image-canvas-editor__option-cluster .platform-inline-option-button__trailing { + transition: transform 160ms ease; +} + +.image-canvas-editor__option-cluster[aria-expanded='true'] + .platform-inline-option-button__trailing { + transform: rotate(180deg); +} + +.image-canvas-editor__option-cluster--dimensions { + grid-column: auto; + justify-self: start; + gap: 0.42rem; +} + +.image-canvas-editor__option-cluster--dimensions span { + font-variant-numeric: tabular-nums; +} + +.image-canvas-editor__option-cluster--model { + max-width: 8.5rem; + justify-self: end; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.image-canvas-editor__option-popover-anchor { + position: relative; + min-width: 0; +} + +.image-canvas-editor__option-popover-anchor--dimensions { + grid-column: 1; + justify-self: start; + width: max-content; +} + +.image-canvas-editor__option-popover-anchor--model { + grid-column: 4; + justify-self: end; + width: 8.5rem; +} + +.image-canvas-editor__model-trigger-label { + display: inline-flex; + min-width: 0; + max-width: 100%; + align-items: center; + gap: 0.32rem; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.image-canvas-editor__model-trigger-label svg, +.image-canvas-editor__model-icon svg { + width: 0.88rem; + height: 0.88rem; +} + +.image-canvas-editor__model-trigger-label span:last-child { + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.image-canvas-editor__model-icon { + display: inline-flex; + flex: 0 0 auto; + align-items: center; + justify-content: center; + color: #334155; +} + +.image-canvas-editor__option-popover { + position: absolute; + left: 0; + bottom: calc(100% + 0.45rem); + z-index: 3; + min-width: 16rem; + max-width: min(23rem, calc(100vw - 1.5rem)); + border: 1px solid rgba(15, 23, 42, 0.08); + border-radius: 1.05rem; + background: rgba(255, 255, 255, 0.98); + padding: 1.78rem 0.95rem 0.95rem; + color: #111827; + font-size: 0.82rem; + box-shadow: + 0 22px 56px rgba(15, 23, 42, 0.15), + inset 0 1px 0 rgba(255, 255, 255, 0.96); + backdrop-filter: blur(16px); +} + +.image-canvas-editor__option-popover-anchor--model + .image-canvas-editor__option-popover { + right: 0; + left: auto; +} + +.image-canvas-editor__option-popover-sections { + display: grid; + gap: 1rem; +} + +.image-canvas-editor__option-popover-section { + display: grid; + gap: 0.58rem; +} + +.image-canvas-editor__option-popover-title { + color: #2f2f35; + font-size: 0.82rem; + font-weight: 760; +} + +.image-canvas-editor__option-popover-items { display: flex; flex-wrap: wrap; - gap: 0.3rem; + gap: 0.46rem; } -.game-resource-canvas-toolbar-host +.image-canvas-editor__option-popover-items--card { + gap: 0.62rem; +} + +.image-canvas-editor__option-popover:has( + .image-canvas-editor__option-popover-choice--model + ) { + min-width: 13.5rem; +} + +.image-canvas-editor__option-popover-choice { + display: inline-flex; + min-width: 4.5rem; + min-height: 2.25rem; + align-items: center; + justify-content: center; + border: 1px solid rgba(15, 23, 42, 0.1); + border-radius: 999px; + background: #ffffff; + padding: 0 0.85rem; + color: #111827; + font-size: 0.82rem; + font-weight: 720; +} + +.image-canvas-editor__option-popover-items--card .image-canvas-editor__option-popover-choice { - display: inline-flex; - align-items: center; - gap: 0.3rem; - padding: 0.28rem 0.5rem; - border: 1px solid var(--image-canvas-brand-border-soft); - border-radius: 0.375rem; - background: #fffdfa; - color: #334155; - font-size: 0.74rem; - cursor: pointer; + min-width: 5.25rem; + min-height: 4.6rem; + border-radius: 1rem; + font-size: 0.82rem; } -.game-resource-canvas-toolbar-host - .image-canvas-editor__generation-submit { +.image-canvas-editor__option-popover-choice[aria-pressed='true'] { + border-color: var(--image-canvas-brand-border-strong); + background: var(--image-canvas-brand-soft); + color: var(--image-canvas-brand-accent-strong); + box-shadow: inset 0 0 0 1px var(--image-canvas-brand-border-strong); +} + +.image-canvas-editor__option-popover-choice--model { + display: grid; + width: 100%; + grid-template-columns: 1rem minmax(0, 1fr) 1rem; + justify-content: stretch; + column-gap: 0.44rem; + border-color: transparent; + background: transparent; + padding: 0.18rem 0.2rem; + text-align: left; + white-space: nowrap; +} + +.image-canvas-editor__option-popover-choice--model span:nth-child(2) { + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.image-canvas-editor__option-popover-choice--model + .image-canvas-editor__model-icon { + justify-self: start; +} + +.image-canvas-editor__option-popover-choice--model[aria-pressed='true'] { + border-color: transparent; + box-shadow: none; +} + +.image-canvas-editor__option-popover-choice--model:hover { + background: #f8fafc; +} + +.image-canvas-editor__option-selected-check { + width: 0.92rem; + height: 0.92rem; + justify-self: end; + color: var(--image-canvas-brand-accent-strong); + stroke-width: 3; +} + +.image-canvas-editor__option-selected-check[data-visible='false'] { + opacity: 0; +} + +.image-canvas-editor__option-popover-choice--ratio { + flex-direction: column; + gap: 0.42rem; +} + +.image-canvas-editor__ratio-wireframe { + display: block; + width: 1.65rem; + height: 1.08rem; + border: 2px solid currentColor; + border-radius: 0.24rem; +} + +.image-canvas-editor__ratio-wireframe[data-ratio='21:9'] { + width: 1.9rem; + height: 0.84rem; +} + +.image-canvas-editor__ratio-wireframe[data-ratio='9:16'] { + width: 1.02rem; + height: 1.74rem; +} + +.image-canvas-editor__ratio-wireframe[data-ratio='3:4'], +.image-canvas-editor__ratio-wireframe[data-ratio='2:3'] { + width: 1.12rem; + height: 1.58rem; +} + +.image-canvas-editor__ratio-wireframe[data-ratio='4:3'], +.image-canvas-editor__ratio-wireframe[data-ratio='3:2'] { + width: 1.74rem; + height: 1.16rem; +} + +.image-canvas-editor__ratio-wireframe[data-ratio='1:1'] { + width: 1.36rem; + height: 1.36rem; +} + +.image-canvas-editor__mud-point-inline { display: inline-flex; align-items: center; - gap: 0.35rem; - padding: 0.4rem 0.9rem; - border: 1px solid transparent; - border-radius: 0.5rem; + gap: 0.18rem; + color: currentColor; + font-size: 0.74rem; + font-weight: 850; + line-height: 1; +} + +.image-canvas-editor__mud-point-inline svg { + width: 0.88rem; + height: 0.88rem; +} + +.image-canvas-editor__generation-composer .platform-inline-option-button { + min-height: 2.25rem; + border-color: transparent; + background: transparent; + color: #475569; + font-size: 0.82rem; + font-weight: 760; + box-shadow: none; +} + +.image-canvas-editor__generation-composer + .platform-inline-option-button[aria-pressed='true'], +.image-canvas-editor__generation-composer + .platform-inline-option-button[aria-pressed='true']:hover:not(:disabled) { + border-color: var(--image-canvas-brand-border-strong); + background: var(--image-canvas-brand-soft); + color: var(--image-canvas-brand-accent); +} + +.image-canvas-editor__generation-submit { + grid-column: 5; + min-width: 5.45rem; + height: 2.25rem; + gap: 0.4rem; + border: 0; background: var(--image-canvas-brand-fill); color: var(--image-canvas-brand-text-on-fill); - font-size: 0.78rem; - font-weight: 850; - cursor: pointer; + font-size: 0.82rem; + font-weight: 820; } -.game-resource-canvas-toolbar-host - .image-canvas-editor__generation-submit:disabled { - opacity: 0.55; - cursor: not-allowed; +.image-canvas-editor__generation-submit:not(:disabled) { + color: var(--image-canvas-brand-text-on-fill); } -.game-resource-canvas-toolbar-host .image-canvas-editor__generate-status { +.image-canvas-editor__generation-submit:disabled { + cursor: wait; + background: #e2e8f0; + color: #94a3b8; +} + +.image-canvas-editor__generation-composer + .image-canvas-editor__generate-status { + grid-column: 1 / -1; +} + +.image-canvas-editor__readonly-generation-option + .image-canvas-editor__option-cluster:disabled { + cursor: default; + opacity: 1; + color: #475569; + pointer-events: none; +} + +.image-canvas-editor__readonly-generation-option + .image-canvas-editor__option-cluster:disabled:hover { + border-color: transparent; + background: transparent; + box-shadow: none; +} + +/* 快速编辑浮层面板:锚在资源卡正下方。 + * + * AGC 没有 portal:`renderEditorPortal` 用共享组件默认的就地渲染,下拉弹层挂在 + * 面板内部。所以这里额外把 `overflow` 放开,否则上面那条 `bottom: 100%` 的弹层 + * 会被面板的滚动容器裁掉(网页端弹层 portal 到 body,不存在这个问题)。 */ +.image-canvas-editor__quick-edit-panel { + position: absolute; + z-index: 14; + display: grid; + width: min(24rem, calc(100vw - 1.5rem)); + max-height: min(32rem, calc(100% - 1.5rem)); + gap: 0.58rem; + overflow: visible; + border: 1px solid rgba(148, 163, 184, 0.36); + border-radius: 1.1rem; + background: rgba(255, 255, 255, 0.96); + padding: 0.72rem; + color: #1f2937; + box-shadow: 0 22px 48px rgba(15, 23, 42, 0.22); + transform: translateX(-50%); +} + +.image-canvas-editor__quick-edit-panel.image-canvas-editor__generation-composer { + width: min(42rem, calc(100vw - 1.5rem)); + gap: 0.18rem 0.72rem; + padding-bottom: 0.48rem; +} + +.image-canvas-editor__generation-composer--quick-edit { + min-height: 11.8rem; +} + +.image-canvas-editor__quick-edit-footer { + grid-template-columns: auto minmax(0, 1fr) auto auto; +} + +.image-canvas-editor__quick-edit-panel + .image-canvas-editor__generation-composer-footer { + padding-top: 1rem; +} + +.image-canvas-editor__quick-edit-footer + .image-canvas-editor__option-popover-anchor--model { + grid-column: 3; + width: 9.75rem; +} + +.image-canvas-editor__quick-edit-footer + .image-canvas-editor__option-cluster--model { + width: 100%; + max-width: none; +} + +.image-canvas-editor__quick-edit-footer + .image-canvas-editor__generation-submit { + grid-column: 4; +} + +.image-canvas-editor__quick-edit-prompt { + --auto-grow-editor-min-height: 5.6rem; +} + +.image-canvas-editor__quick-edit-submit { + justify-self: end; + min-width: 6.8rem; +} + +.image-canvas-editor__generate-status { margin: 0; - font-size: 0.74rem; - color: #8c6252; +} + +.image-canvas-editor__portal-menu { + z-index: 70; +} + +/* 提示词输入框是 Lexical 的 auto-grow 编辑器,外观由这一族类名撑开。 */ +.auto-grow-text-area { + position: relative; + display: block; + box-sizing: border-box; + width: 100%; + min-width: 0; + min-height: var(--auto-grow-editor-min-height, 2.5rem); + max-height: var(--auto-grow-editor-max-height, 8rem); + border-radius: var(--auto-grow-editor-radius, 1rem); + overflow: hidden; +} + +.auto-grow-text-area__content { + box-sizing: border-box; + width: 100%; + min-height: calc(var(--auto-grow-editor-min-height, 2.5rem) - 2px); + padding: var(--auto-grow-editor-padding, 0.5rem 0.75rem); + padding-right: 2.25rem; + outline: none; + overflow-wrap: anywhere; + white-space: pre-wrap; + -webkit-user-select: text; + user-select: text; +} + +.auto-grow-text-area__placeholder { + position: absolute; + inset: 0; + box-sizing: border-box; + padding: var(--auto-grow-editor-padding, 0.5rem 0.75rem); + padding-right: 2.25rem; + overflow: hidden; + color: #94a3b8; + pointer-events: none; + text-overflow: ellipsis; + white-space: nowrap; +} + +.auto-grow-text-area__viewport, +.auto-grow-text-area [data-overlayscrollbars-viewport] { + display: block; + height: 100%; + min-height: 0; + overflow-x: hidden !important; + overflow-y: auto !important; + overscroll-behavior: contain; +} + +.auto-grow-text-area__content-root { + box-sizing: border-box; + min-height: calc(var(--auto-grow-editor-min-height, 2.5rem) - 2px); +} + +.auto-grow-text-area[data-disabled='true'] { + cursor: not-allowed; + opacity: 0.6; +} + +.auto-grow-text-area[data-readonly='true'] { + cursor: default; +} + +.auto-grow-text-area + > .os-theme-auto-grow-text-area.os-scrollbar-vertical.os-scrollbar-cornerless { + --os-size: 8px; + --os-padding-axis: 0; + --os-padding-perpendicular: 0; + --os-track-border-radius: 999px; + --os-track-bg: transparent; + --os-track-bg-hover: transparent; + --os-track-bg-active: transparent; + --os-handle-border-radius: 999px; + --os-handle-bg: rgba(98, 98, 98, 0.56); + --os-handle-bg-hover: rgba(98, 98, 98, 0.72); + --os-handle-bg-active: rgba(98, 98, 98, 0.86); + --os-handle-min-size: 24px; + --os-handle-perpendicular-size: 100%; + --os-handle-perpendicular-size-hover: 100%; + --os-handle-perpendicular-size-active: 100%; + box-sizing: border-box; + top: var(--auto-grow-editor-radius, 1rem) !important; + right: 5px; + bottom: var(--auto-grow-editor-radius, 1rem) !important; + width: 8px; + padding: 0; +} + +.auto-grow-text-area + > .os-theme-auto-grow-text-area.os-scrollbar-vertical + .os-scrollbar-track { + width: 8px; + border-radius: 999px; + background: transparent; +} + +.auto-grow-text-area + > .os-theme-auto-grow-text-area.os-scrollbar-vertical + .os-scrollbar-handle { + width: 8px; + min-height: 24px; + border: 0; + border-radius: 999px; + background: rgba(98, 98, 98, 0.56); +} + +.auto-grow-text-area + > .os-theme-auto-grow-text-area.os-scrollbar-vertical:hover + .os-scrollbar-handle { + background: rgba(98, 98, 98, 0.72); +} + +.auto-grow-text-area + > .os-theme-auto-grow-text-area.os-scrollbar-vertical:active + .os-scrollbar-handle { + background: rgba(98, 98, 98, 0.86); +} + +/* AGC 宿主:浮层挂在资源卡上方/下方,层级要高于画布卡片与标题栏。 + * + * 只覆盖美术画布没有的宿主条件(层级、锚点变换、窄屏宽度),其余全部沿用上面的 + * 真实规则;早期那套 `display: flex` + `gap: 0.5rem` + 手写内边距的近似值已删除。 */ +.game-resource-canvas-toolbar-host + .image-canvas-editor__quick-edit-panel { + z-index: 70; + pointer-events: auto; } @media (max-width: 720px) { @@ -253,10 +764,6 @@ .image-canvas-editor__floating-toolbar { max-width: 94vw; } - - .game-resource-canvas-toolbar-host .image-canvas-editor__generation-composer { - width: 94vw; - } } /* 资源面板:独立浮层面板(预览 / 上传 / 下载 / 多选)。 */ @@ -425,4 +932,4 @@ flex-wrap: wrap; justify-content: flex-end; gap: 8px; -} \ No newline at end of file +} diff --git a/apps/ai-game-creator-shell/src/styles.css b/apps/ai-game-creator-shell/src/styles.css index 585e696c5..7a6f4bfe2 100644 --- a/apps/ai-game-creator-shell/src/styles.css +++ b/apps/ai-game-creator-shell/src/styles.css @@ -1,5 +1,10 @@ @import 'tailwindcss'; @source '../../../packages/shared/src/components'; +/* 资源画布直接渲染仓库根 src/components/image-editor 下的共享图片画布组件(它们又用到 + src/components/common)。这两个目录不在 app 根下,Tailwind 自动探测扫不到,缺了组件 + 自带的工具类(h-3 / rounded-full / inline-flex …)就会和网页端美术画布长得不一样。 */ +@source '../../../src/components/image-editor'; +@source '../../../src/components/common'; @import '@genarrative/shared/styles.css'; @import '../../../packages/shared/src/theme.css';