From bbf09c2ea9987d8d69bb6ffbb1e5eea208a7637c Mon Sep 17 00:00:00 2001 From: jialin Date: Wed, 7 Jan 2026 11:44:31 +0800 Subject: [PATCH] style: command viewer scroller --- .../highlight-code/code-viewer-dark.tsx | 5 +- .../highlight-code/code-viewer-light.tsx | 5 +- src/components/highlight-code/code-viewer.tsx | 20 ++- src/components/highlight-code/index.tsx | 6 +- src/components/icon-font/index.tsx | 2 +- src/components/tags-wrapper/index.tsx | 3 +- src/layouts/extraRender.tsx | 8 +- src/locales/en-US/clusters.ts | 7 +- src/locales/ja-JP/clusters.ts | 16 +-- src/locales/ru-RU/clusters.ts | 14 ++- src/locales/zh-CN/clusters.ts | 7 +- .../_components/collapse-panel/index.tsx | 13 +- src/pages/_components/yaml-editor/index.tsx | 2 +- .../cluster-management/cluster-create.tsx | 36 +----- .../cluster-management/cluster-modal.tsx | 10 +- .../components/add-worker-command.tsx | 1 + .../components/add-worker/index.tsx | 2 +- .../components/cluster-steps.tsx | 115 ++++++------------ .../components/success-result.tsx | 4 +- .../step-forms/use-step-list.tsx | 8 +- src/pages/llmodels/forms/advance-config.tsx | 5 +- 21 files changed, 136 insertions(+), 153 deletions(-) diff --git a/src/components/highlight-code/code-viewer-dark.tsx b/src/components/highlight-code/code-viewer-dark.tsx index f18bb42c..1d5b8bb0 100644 --- a/src/components/highlight-code/code-viewer-dark.tsx +++ b/src/components/highlight-code/code-viewer-dark.tsx @@ -10,6 +10,7 @@ interface CodeViewerProps { copyable?: boolean; height?: string | number; style?: React.CSSProperties; + xScrollable?: boolean; } const DarkViewer: React.FC = (props) => { const { @@ -19,7 +20,8 @@ const DarkViewer: React.FC = (props) => { autodetect, ignoreIllegals, copyable, - height = 'auto' + height = 'auto', + xScrollable = false } = props || {}; return ( @@ -33,6 +35,7 @@ const DarkViewer: React.FC = (props) => { autodetect={autodetect} ignoreIllegals={ignoreIllegals} copyable={copyable} + xScrollable={xScrollable} > ); }; diff --git a/src/components/highlight-code/code-viewer-light.tsx b/src/components/highlight-code/code-viewer-light.tsx index 821d312c..7de78b8e 100644 --- a/src/components/highlight-code/code-viewer-light.tsx +++ b/src/components/highlight-code/code-viewer-light.tsx @@ -10,6 +10,7 @@ interface CodeViewerProps { copyable?: boolean; height?: string | number; style?: React.CSSProperties; + xScrollable?: boolean; } const LightViewer: React.FC = (props) => { const { @@ -20,7 +21,8 @@ const LightViewer: React.FC = (props) => { ignoreIllegals, copyable, style, - height = 'auto' + height = 'auto', + xScrollable = false } = props || {}; return ( @@ -34,6 +36,7 @@ const LightViewer: React.FC = (props) => { autodetect={autodetect} ignoreIllegals={ignoreIllegals} copyable={copyable} + xScrollable={xScrollable} > ); }; diff --git a/src/components/highlight-code/code-viewer.tsx b/src/components/highlight-code/code-viewer.tsx index 6047afbc..8aa5ec18 100644 --- a/src/components/highlight-code/code-viewer.tsx +++ b/src/components/highlight-code/code-viewer.tsx @@ -15,6 +15,7 @@ interface CodeViewerProps { height?: string | number; theme?: 'light' | 'dark'; style?: React.CSSProperties; + xScrollable?: boolean; } interface CodeHeaderProps { @@ -43,6 +44,14 @@ const CodeHeaderWrapper = styled.div` const Wrapper = styled.div` border-radius: var(--border-radius-mini); + &:hover { + .custome-scrollbar { + &::-webkit-scrollbar-thumb { + background-color: var(--color-scrollbar-thumb); + border-radius: 4px; + } + } + } `; const CodeHeader: React.FC = ({ @@ -80,7 +89,8 @@ const CodeViewer: React.FC = (props) => { ignoreIllegals = true, copyable = true, height = 'auto', - style + style, + xScrollable = false } = props || {}; const highlightedCode = useMemo(() => { @@ -131,7 +141,8 @@ const CodeViewer: React.FC = (props) => { 'code-pre custome-scrollbar custom-scrollbar-horizontal ', { dark: props.theme === 'dark', - light: props.theme === 'light' + light: props.theme === 'light', + 'x-scrollable': xScrollable } )} style={{ @@ -141,7 +152,10 @@ const CodeViewer: React.FC = (props) => { }} > ) : ( @@ -50,6 +53,7 @@ const HighlightCode: React.FC<{ copyValue={copyValue} copyable={copyable} height={height} + xScrollable={xScrollable} /> )} diff --git a/src/components/icon-font/index.tsx b/src/components/icon-font/index.tsx index 666b43f1..98db3a77 100644 --- a/src/components/icon-font/index.tsx +++ b/src/components/icon-font/index.tsx @@ -2,7 +2,7 @@ import { createFromIconfontCN } from '@ant-design/icons'; // import './iconfont/iconfont.js'; const IconFont = createFromIconfontCN({ - scriptUrl: '//at.alicdn.com/t/c/font_4613488_jo5x7z2z718.js' + scriptUrl: '//at.alicdn.com/t/c/font_4613488_rajpu0blzkp.js' }); export default IconFont; diff --git a/src/components/tags-wrapper/index.tsx b/src/components/tags-wrapper/index.tsx index ff6a149c..6c85b653 100644 --- a/src/components/tags-wrapper/index.tsx +++ b/src/components/tags-wrapper/index.tsx @@ -120,6 +120,7 @@ const TagsWrapper: React.FC = (props) => { > @@ -132,4 +133,4 @@ const TagsWrapper: React.FC = (props) => { ); }; -export default React.memo(TagsWrapper); +export default TagsWrapper; diff --git a/src/layouts/extraRender.tsx b/src/layouts/extraRender.tsx index 284e8399..0dcb3829 100644 --- a/src/layouts/extraRender.tsx +++ b/src/layouts/extraRender.tsx @@ -10,9 +10,7 @@ import { DiscordOutlined, GithubOutlined, HomeOutlined, - LogoutOutlined, - ReadOutlined, - SettingOutlined + ReadOutlined } from '@ant-design/icons'; import { history, useIntl, useNavigate } from '@umijs/max'; import { Avatar, Button, Divider, Modal } from 'antd'; @@ -235,7 +233,7 @@ export const ExtraContent = (props: { isDarkTheme?: boolean }) => { key: 'settings', label: ( - + {intl?.formatMessage?.({ id: 'common.button.settings' })} @@ -270,7 +268,7 @@ export const ExtraContent = (props: { isDarkTheme?: boolean }) => { {originNode} - + {intl?.formatMessage?.({ id: 'common.button.logout' })} diff --git a/src/locales/en-US/clusters.ts b/src/locales/en-US/clusters.ts index ca8447bc..99e497d7 100644 --- a/src/locales/en-US/clusters.ts +++ b/src/locales/en-US/clusters.ts @@ -28,7 +28,7 @@ export default { 'clusters.workerpool.volumes.add': 'Add Volume', 'clusters.create.provider.self': 'Self-Hosted', 'clusters.create.provider.cloud': 'Cloud Provider', - 'clusters.create.selectProvider': 'Select Provider', + 'clusters.create.steps.selectProvider': 'Select Provider', 'clusters.create.configBasic': 'Basic Configuration', 'clusters.create.execCommand': 'Execute Command', 'clusters.create.supportedGpu': 'Supported GPUs', @@ -117,8 +117,9 @@ export default { 'clusters.form.setDefault': 'Set as Default', 'clusters.form.setDefault.tips': 'Default for deployment.', 'clusters.addworker.noClusters': 'No available clusters', - 'clusters.create.complete.tips': 'Cluster created successfully!', - 'clusters.create.complete': 'Completed', + 'clusters.create.steps.complete.tips': 'Cluster created successfully!', + 'clusters.create.steps.complete': 'Complete', + 'clusters.create.steps.configure': 'Configure', 'clusters.create.dockerTips1': 'Next, add worker to this cluster.', 'clusters.create.dockerTips2': 'You can also skip this step and add them later from the cluster list.', diff --git a/src/locales/ja-JP/clusters.ts b/src/locales/ja-JP/clusters.ts index 8dd95983..e2051e38 100644 --- a/src/locales/ja-JP/clusters.ts +++ b/src/locales/ja-JP/clusters.ts @@ -28,7 +28,7 @@ export default { 'clusters.workerpool.volumes.add': 'Add Volume', 'clusters.create.provider.self': 'Self-Hosted', 'clusters.create.provider.cloud': 'Cloud Provider', - 'clusters.create.selectProvider': 'Select Provider', + 'clusters.create.steps.selectProvider': 'Select Provider', 'clusters.create.configBasic': 'Basic Configuration', 'clusters.create.execCommand': 'Execute Command', 'clusters.create.supportedGpu': 'Supported GPUs', @@ -117,8 +117,9 @@ export default { 'clusters.form.setDefault': 'Set as Default', 'clusters.form.setDefault.tips': 'Default for deployment.', 'clusters.addworker.noClusters': 'No available clusters', - 'clusters.create.complete.tips': 'Cluster created successfully!', - 'clusters.create.complete': 'Completed', + 'clusters.create.steps.complete.tips': 'Cluster created successfully!', + 'clusters.create.steps.complete': 'Complete', + 'clusters.create.steps.configure': 'Configure', 'clusters.create.dockerTips1': 'Next, add worker to this cluster.', 'clusters.create.dockerTips2': 'You can also skip this step and add them later from the cluster list.', @@ -157,7 +158,7 @@ export default { // 27. 'clusters.workerpool.volumes.add': 'Add Volume' // 28. 'clusters.create.provider.self': 'Self-Hosted', // 29. 'clusters.create.provider.cloud': 'Cloud Provider', -// 30. 'clusters.create.selectProvider': 'Select Provider', +// 30. 'clusters.create.steps.selectProvider': 'Select Provider', // 31. 'clusters.create.configBasic': 'Basic Configuration', // 32. 'clusters.create.execCommand': 'Execute Command', // 33. 'clusters.create.supportedGpu': 'Supported GPUs', @@ -219,10 +220,11 @@ export default { // 85. 'clusters.addworker.enterWorkerAddress': 'Enter worker external address', // 86. 'clusters.addworker.enterWorkerAddress.error': 'Please enter the worker external address.', // 87. 'clusters.addworker.noClusters': 'No available clusters', -// 88. 'clusters.create.complete.tips': 'Cluster created successfully!', -// 89. 'clusters.create.complete': 'Completed', +// 88. 'clusters.create.steps.complete.tips': 'Cluster created successfully!', +// 89. 'clusters.create.steps.complete': 'Complete', // 90. 'clusters.create.dockerTips1': 'Next, add worker to this cluster.', // 91. 'clusters.create.dockerTips2': 'You can also skip this step and add them later from the cluster list.', // 92. 'clusters.create.k8sTips1': 'Next, register existing Kubernetes cluster.', -// 93. 'clusters.create.k8sTips2': 'You can also skip this step and register it later from the cluster list.' +// 93. 'clusters.create.k8sTips2': 'You can also skip this step and register it later from the cluster list.', +// 94. 'clusters.create.steps.configure': 'Configure', // ========== End of To-Do List ========== diff --git a/src/locales/ru-RU/clusters.ts b/src/locales/ru-RU/clusters.ts index 5aacb51c..bad6ab5d 100644 --- a/src/locales/ru-RU/clusters.ts +++ b/src/locales/ru-RU/clusters.ts @@ -28,7 +28,7 @@ export default { 'clusters.workerpool.volumes.add': 'Добавить том', 'clusters.create.provider.self': 'Самостоятельное размещение', 'clusters.create.provider.cloud': 'Облачный провайдер', - 'clusters.create.selectProvider': 'Выберите провайдера', + 'clusters.create.steps.selectProvider': 'Выберите провайдера', 'clusters.create.configBasic': 'Базовая конфигурация', 'clusters.create.execCommand': 'Выполнить команду', 'clusters.create.supportedGpu': 'Поддерживаемые GPU', @@ -118,8 +118,9 @@ export default { 'clusters.form.setDefault.tips': 'Использовать по умолчанию для развертывания.', 'clusters.addworker.noClusters': 'No available clusters', - 'clusters.create.complete.tips': 'Cluster created successfully!', - 'clusters.create.complete': 'Completed', + 'clusters.create.steps.complete.tips': 'Cluster created successfully!', + 'clusters.create.steps.complete': 'Complete', + 'clusters.create.steps.configure': 'Configure', 'clusters.create.dockerTips1': 'Next, add worker to this cluster.', 'clusters.create.dockerTips2': 'You can also skip this step and add them later from the cluster list.', @@ -131,10 +132,11 @@ export default { // ========== To-Do: Translate Keys (Remove After Translation) ========== // 1. 'clusters.addworker.hygonNotes': `If /opt/hyhal or /opt/dtk does not exist, create symbolic links pointing to the corresponding Hygon installation paths, for example: ln -s /path/to/hyhal /opt/hyhal ln -s /path/to/dtk /opt/dtk.`, // 2. 'clusters.addworker.noClusters': 'No available clusters', -// 3. 'clusters.create.complete.tips': 'Cluster created successfully!', -// 4. 'clusters.create.complete': 'Completed', +// 3. 'clusters.create.steps.complete.tips': 'Cluster created successfully!', +// 4. 'clusters.create.steps.complete': 'Complete', // 5. 'clusters.create.dockerTips1': 'Next, add worker to this cluster.', // 6. 'clusters.create.dockerTips2': 'You can also skip this step and add them later from the cluster list.', // 7. 'clusters.create.k8sTips1': 'Next, register existing Kubernetes cluster.', -// 8. 'clusters.create.k8sTips2': 'You can also skip this step and register it later from the cluster list.' +// 8. 'clusters.create.k8sTips2': 'You can also skip this step and register it later from the cluster list.', +// 9. 'clusters.create.steps.configure': 'Configure', // ================================================================ diff --git a/src/locales/zh-CN/clusters.ts b/src/locales/zh-CN/clusters.ts index 45f10a7e..f513da93 100644 --- a/src/locales/zh-CN/clusters.ts +++ b/src/locales/zh-CN/clusters.ts @@ -28,7 +28,7 @@ export default { 'clusters.workerpool.volumes.add': '添加存储卷', 'clusters.create.provider.self': '自建环境', 'clusters.create.provider.cloud': '云环境', - 'clusters.create.selectProvider': '选择环境', + 'clusters.create.steps.selectProvider': '选择环境', 'clusters.create.configBasic': '基本配置', 'clusters.create.execCommand': '执行命令', 'clusters.create.supportedGpu': '支持的 GPU', @@ -114,8 +114,9 @@ export default { 'clusters.form.setDefault': '设为默认', 'clusters.form.setDefault.tips': '部署时的默认集群。', 'clusters.addworker.noClusters': '无可用集群', - 'clusters.create.complete.tips': '集群创建成功!', - 'clusters.create.complete': '完成', + 'clusters.create.steps.complete.tips': '集群创建成功!', + 'clusters.create.steps.complete': '完成', + 'clusters.create.steps.configure': '配置', 'clusters.create.dockerTips1': '接下来,为该集群添加节点。', 'clusters.create.dockerTips2': '你也可以跳过此步骤,稍后在集群列表中添加。', 'clusters.create.k8sTips1': '接下来,注册已有的 Kubernetes 集群。', diff --git a/src/pages/_components/collapse-panel/index.tsx b/src/pages/_components/collapse-panel/index.tsx index d8058f21..c1d7543e 100644 --- a/src/pages/_components/collapse-panel/index.tsx +++ b/src/pages/_components/collapse-panel/index.tsx @@ -13,7 +13,9 @@ const CollapseInner = styled(Collapse)` border-radius: var(--border-radius-base) !important; font-size: 14px !important; font-weight: 600 !important; - background-color: var(--ant-color-fill-tertiary) !important; + &:hover { + background-color: var(--ant-color-fill-tertiary) !important; + } } .ant-collapse-body { @@ -32,7 +34,8 @@ const CollapsePanel: React.FC<{ activeKey: string | string[]; accordion?: boolean; onChange?: (key: string | string[]) => void; -}> = ({ items, activeKey, accordion, onChange }) => { + styles?: Record; +}> = ({ items, activeKey, accordion, onChange, styles }) => { return ( ( void; onClose?: () => void; -}> = ({ onClose }) => { - const intl = useIntl(); +}> = ({ onClose, action, setCurrentTitle }) => { const startStep = 0; const stepList = useStepList(); const { systemConfig } = useSystemConfig(); - const [searchParams] = useSearchParams(); - const action = - (searchParams.get('action') as PageActionType) || PageAction.CREATE; - const [clusterSession, setClusterSession] = useAtom(clusterSessionAtom); + const intl = useIntl(); const [credentialList, setCredentialList] = useState< Global.BaseOption[] >([]); @@ -85,7 +74,6 @@ const ClusterCreate: React.FC<{ const [formValues, setFormValues] = useState>({}); const [submitLoading, setSubmitLoading] = useState(false); const [isAddWorkerStep, setIsAddWorkerStep] = useState(false); - const [isComplete, setIsComplete] = useState(false); const formRefs: Record = { [moduleMap.BasicForm]: useRef(null), @@ -240,6 +228,7 @@ const ClusterCreate: React.FC<{ // add worker or cluster registration step const handleAddWorker = () => { setIsAddWorkerStep(true); + setCurrentTitle?.(intl.formatMessage({ id: 'resources.button.create' })); onNext(); }; @@ -301,7 +290,6 @@ const ClusterCreate: React.FC<{ const res = await createCluster({ data }); const info = await queryClusterToken({ id: res.id }); setSubmitLoading(false); - setIsComplete(true); setRegistrationInfo({ ...info, cluster_id: res.id @@ -320,11 +308,6 @@ const ClusterCreate: React.FC<{ return ( - {/* {!isAddWorkerStep && ( - - - - )} */} } > - {/* {!isComplete && ( -
- - {steps[currentStep]?.subTitle || steps[currentStep]?.title} - -
- )} */} {!isAddWorkerStep && (
= ({ onClose, title }) => { + const [currentTitle, setCurrentTitle] = React.useState(title); const handleCancel = () => { onClose(); }; return ( = ({ }} footer={false} > - + ); }; diff --git a/src/pages/cluster-management/components/add-worker-command.tsx b/src/pages/cluster-management/components/add-worker-command.tsx index 95a0a17f..7ed26bee 100644 --- a/src/pages/cluster-management/components/add-worker-command.tsx +++ b/src/pages/cluster-management/components/add-worker-command.tsx @@ -65,6 +65,7 @@ const AddWorkerCommand: React.FC = ({ code={code} copyValue={code} lang="bash" + xScrollable={true} > ); }; diff --git a/src/pages/cluster-management/components/add-worker/index.tsx b/src/pages/cluster-management/components/add-worker/index.tsx index 5e57f275..a3e187e6 100644 --- a/src/pages/cluster-management/components/add-worker/index.tsx +++ b/src/pages/cluster-management/components/add-worker/index.tsx @@ -131,7 +131,7 @@ const AddWorker: React.FC = (props) => { body: { paddingBlock: 0 }, - wrapper: { width: 865 } + wrapper: { width: 700 } }} footer={false} > diff --git a/src/pages/cluster-management/components/cluster-steps.tsx b/src/pages/cluster-management/components/cluster-steps.tsx index bc1d7984..9b010416 100644 --- a/src/pages/cluster-management/components/cluster-steps.tsx +++ b/src/pages/cluster-management/components/cluster-steps.tsx @@ -1,4 +1,3 @@ -import { CheckCircleFilled, CheckCircleOutlined } from '@ant-design/icons'; import { Steps } from 'antd'; import React from 'react'; import styled from 'styled-components'; @@ -9,6 +8,9 @@ const Wrapper = styled.div` gap: 24px; `; +/** + * --steps-item-base-width: 20px; type="panel" + */ const Box = styled.div` .indicates { color: var(--ant-color-text-tertiary); @@ -16,76 +18,20 @@ const Box = styled.div` margin-bottom: 24px; } .ant-steps { - --steps-title-font-size: 14px; .ant-steps-item { --steps-item-base-width: 20px; } - } -`; - -const StepItemWrapper = styled.div` - display: flex; - align-items: flex-start; - gap: 12px; - padding-bottom: 16px; - // border-bottom: 1px solid var(--ant-color-split); - .description { - display: flex; - flex-direction: column; - gap: 4px; - - .title { - font-weight: 500; - line-height: 20px; - color: var(--ant-color-text-tertiary); + .ant-steps-item-rail-wait { + --steps-item-solid-line-color: var(--ant-color-split); } - .content { - line-height: 22px; - font-size: 14px; - color: var(--ant-color-text-tertiary); - } - } - &.active { - .description { - .title { - color: var(--ant-color-text); - font-weight: 600; - } - .content { - color: var(--ant-color-text); + &:not(.ant-steps-panel) { + .ant-steps-item-finish { + --steps-item-icon-bg-color: var(--ant-color-primary); } } } `; -const StepsItem: React.FC<{ - active: boolean; - item: { - title: string; - content: string; - }; -}> = ({ active, item }) => { - return ( - -
- {active ? ( - - ) : ( - - )} -
-
-
{item.title}
-
{item.content}
-
-
- ); -}; - const ClusterSteps: React.FC<{ currentStep: number; onChange?: (step: number) => void; @@ -94,28 +40,41 @@ const ClusterSteps: React.FC<{ const { steps, currentStep = 0, onChange } = props; const visibleSteps = steps.filter((step) => !step.hideInSteps); + + const styles: Record = { + root: { + '--ant-steps-description-max-width': 'auto' + }, + item: { + paddingBlock: 0 + }, + itemIcon: { + fontSize: 0, + width: 8, + height: 8, + marginInlineStart: 0 + }, + itemWrapper: { + alignItems: 'center' + }, + itemRail: { + borderWidth: 1.5, + borderRadius: 1, + insetInlineStart: 10, + insetInlineEnd: 2, + '--steps-horizontal-rail-margin': '12px' + } + }; + return ( - {/* {visibleSteps.map((item, index) => ( - - ))} */} diff --git a/src/pages/cluster-management/components/success-result.tsx b/src/pages/cluster-management/components/success-result.tsx index 96d8bfa5..edac7fdb 100644 --- a/src/pages/cluster-management/components/success-result.tsx +++ b/src/pages/cluster-management/components/success-result.tsx @@ -35,11 +35,11 @@ const SuccessResult: React.FC<{ }} icon={ } status="success" - title={intl.formatMessage({ id: 'clusters.create.complete.tips' })} + title={intl.formatMessage({ id: 'clusters.create.steps.complete.tips' })} subTitle={provider === ProviderValueMap.Kubernetes ? k8sTips : dockerTips} extra={[ diff --git a/src/pages/cluster-management/step-forms/use-step-list.tsx b/src/pages/cluster-management/step-forms/use-step-list.tsx index 956fc98a..ae35162e 100644 --- a/src/pages/cluster-management/step-forms/use-step-list.tsx +++ b/src/pages/cluster-management/step-forms/use-step-list.tsx @@ -15,7 +15,9 @@ export default function useStepList() { return useMemo( () => [ { - title: intl.formatMessage({ id: 'clusters.create.selectProvider' }), + title: intl.formatMessage({ + id: 'clusters.create.steps.selectProvider' + }), content: '', subTitle: '', description: @@ -35,7 +37,7 @@ export default function useStepList() { providers: [] }, { - title: intl.formatMessage({ id: 'common.title.config' }), + title: intl.formatMessage({ id: 'clusters.create.steps.configure' }), content: '', description: 'Set the cluster name, description, or other essential parameters in advanced settings.', @@ -72,7 +74,7 @@ export default function useStepList() { beforeNext: handleBack }, { - title: intl.formatMessage({ id: 'clusters.create.complete' }), + title: intl.formatMessage({ id: 'clusters.create.steps.complete' }), content: '', description: '', showButtons: (provider?: ProviderType) => { diff --git a/src/pages/llmodels/forms/advance-config.tsx b/src/pages/llmodels/forms/advance-config.tsx index 89283f62..42cfd0c7 100644 --- a/src/pages/llmodels/forms/advance-config.tsx +++ b/src/pages/llmodels/forms/advance-config.tsx @@ -77,9 +77,10 @@ const AdvanceConfig = () => { included={true} max={modelContextData?.scaled || 163840} tooltip={{}} + step={1024} marks={{ - [modelContextData?.native]: 'native', - [modelContextData?.scaled]: 'scaled' + [modelContextData?.scaled]: 'scaled', + [modelContextData?.native]: 'native' }} >