优化 Inspector 组件:
- 调整输入框样式以提升可读性。 - 新增上下按钮与键盘上下箭头支持,用于调整数值变换。 - 修复数值格式化逻辑,提升输入精度控制。 - 增强只读模式的视觉提示与操作不可用状态。
This commit is contained in:
+53
-26
@@ -1,6 +1,7 @@
|
||||
import {
|
||||
AlertTriangle,
|
||||
ChevronDown,
|
||||
ChevronUp,
|
||||
Crosshair,
|
||||
LockKeyhole,
|
||||
Maximize2,
|
||||
@@ -170,7 +171,7 @@ function formatValue(value: number): string {
|
||||
if (Object.is(value, -0)) {
|
||||
return '0';
|
||||
}
|
||||
return String(Number(value.toFixed(4)));
|
||||
return String(Number(value.toFixed(2)));
|
||||
}
|
||||
|
||||
function VectorInputRow({
|
||||
@@ -234,6 +235,17 @@ function ScalarInput({
|
||||
setDraft(formatValue(next));
|
||||
};
|
||||
|
||||
const adjust = (direction: -1 | 1) => {
|
||||
if (readOnly) {
|
||||
return;
|
||||
}
|
||||
const current = Number(draft);
|
||||
const base = Number.isFinite(current) ? current : value;
|
||||
const next = Number((base + direction * step).toFixed(4));
|
||||
setDraft(formatValue(next));
|
||||
onCommit(next);
|
||||
};
|
||||
|
||||
return (
|
||||
<label className="relative">
|
||||
<span className="pointer-events-none absolute left-2 top-1/2 -translate-y-1/2 text-[9px] font-bold text-(--platform-text-soft)">
|
||||
@@ -246,7 +258,7 @@ function ScalarInput({
|
||||
value={draft}
|
||||
aria-label={ariaLabel}
|
||||
readOnly={readOnly}
|
||||
className="h-9 w-full rounded-lg border border-(--platform-subpanel-border) bg-white/75 pl-6 pr-2 text-xs tabular-nums text-(--platform-text-strong) outline-none transition focus:ring-2 focus:ring-orange-100 read-only:cursor-default"
|
||||
className="h-11 w-full appearance-none rounded-lg border border-(--platform-subpanel-border) bg-white/75 pl-6 pr-8 text-sm tabular-nums text-(--platform-text-strong) outline-none transition focus:ring-2 focus:ring-orange-100 read-only:cursor-default read-only:bg-slate-100 [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none [-moz-appearance:textfield]"
|
||||
onChange={(event) => setDraft(event.target.value)}
|
||||
onBlur={commit}
|
||||
onKeyDown={(event) => {
|
||||
@@ -255,9 +267,34 @@ function ScalarInput({
|
||||
} else if (event.key === 'Escape') {
|
||||
setDraft(formatValue(value));
|
||||
event.currentTarget.blur();
|
||||
} else if (event.key === 'ArrowUp' || event.key === 'ArrowDown') {
|
||||
event.preventDefault();
|
||||
adjust(event.key === 'ArrowUp' ? 1 : -1);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<span className="absolute right-1 top-1/2 flex -translate-y-1/2 flex-col gap-0.5">
|
||||
<button
|
||||
type="button"
|
||||
aria-label={`${ariaLabel} increase`}
|
||||
disabled={readOnly}
|
||||
className="grid size-5 place-items-center rounded text-(--platform-text-soft) transition hover:bg-orange-100 hover:text-orange-700 disabled:cursor-default disabled:opacity-40"
|
||||
onMouseDown={(event) => event.preventDefault()}
|
||||
onClick={() => adjust(1)}
|
||||
>
|
||||
<ChevronUp size={14} aria-hidden="true" />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
aria-label={`${ariaLabel} decrease`}
|
||||
disabled={readOnly}
|
||||
className="grid size-5 place-items-center rounded text-(--platform-text-soft) transition hover:bg-orange-100 hover:text-orange-700 disabled:cursor-default disabled:opacity-40"
|
||||
onMouseDown={(event) => event.preventDefault()}
|
||||
onClick={() => adjust(-1)}
|
||||
>
|
||||
<ChevronDown size={14} aria-hidden="true" />
|
||||
</button>
|
||||
</span>
|
||||
</label>
|
||||
);
|
||||
}
|
||||
@@ -314,7 +351,10 @@ export function TransformEditor({
|
||||
geometry?.invalid;
|
||||
|
||||
return (
|
||||
<section className="w-full min-w-72.5 max-w-90 overflow-visible rounded-2xl border border-(--platform-subpanel-border) bg-(--platform-subpanel-fill) text-(--platform-text-strong) shadow-[0_16px_40px_rgb(91_62_45/10%)]">
|
||||
<section
|
||||
aria-readonly={readOnly}
|
||||
className={`w-full min-w-72.5 max-w-none overflow-visible rounded-2xl border text-(--platform-text-strong) shadow-[0_16px_40px_rgb(91_62_45/10%)] ${readOnly ? 'border-slate-300 bg-slate-100/90' : 'border-(--platform-subpanel-border) bg-(--platform-subpanel-fill)'}`}
|
||||
>
|
||||
<header className="flex items-center justify-between border-b border-(--platform-subpanel-border) px-4 py-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="grid size-8 place-items-center rounded-xl bg-orange-100 text-orange-600">
|
||||
@@ -328,17 +368,15 @@ export function TransformEditor({
|
||||
</div>
|
||||
</div>
|
||||
{readOnly ? (
|
||||
<LockKeyhole
|
||||
size={14}
|
||||
className="text-(--platform-text-soft)"
|
||||
aria-label="Read only"
|
||||
/>
|
||||
<span className="inline-flex items-center gap-1 rounded-full border border-slate-300 bg-slate-200 px-2 py-1 text-[10px] font-semibold text-slate-600">
|
||||
<LockKeyhole size={12} aria-hidden="true" />
|
||||
Read only
|
||||
</span>
|
||||
) : (
|
||||
<Unlock
|
||||
size={14}
|
||||
className="text-emerald-500"
|
||||
aria-label="Editable"
|
||||
/>
|
||||
<span className="inline-flex items-center gap-1 rounded-full border border-emerald-200 bg-emerald-50 px-2 py-1 text-[10px] font-semibold text-emerald-600">
|
||||
<Unlock size={12} aria-hidden="true" />
|
||||
Editable
|
||||
</span>
|
||||
)}
|
||||
</header>
|
||||
|
||||
@@ -374,12 +412,12 @@ export function TransformEditor({
|
||||
|
||||
{presetOpen ? (
|
||||
<div
|
||||
className="absolute inset-x-0 top-[calc(100%+0.5rem)] z-30 rounded-2xl border border-(--platform-subpanel-border) bg-white p-3 shadow-[0_18px_42px_rgb(41_31_24_/_18%)]"
|
||||
className="absolute inset-x-0 top-[calc(100%+0.5rem)] z-30 rounded-2xl border border-(--platform-subpanel-border) bg-white p-3 shadow-[0_18px_42px_rgb(41_31_24/18%)]"
|
||||
role="dialog"
|
||||
aria-label="Anchor presets"
|
||||
>
|
||||
<div className="mb-2 flex items-center justify-between px-1">
|
||||
<span className="text-[10px] font-bold uppercase tracking-[0.1em] text-(--platform-text-soft)">
|
||||
<span className="text-[10px] font-bold uppercase tracking-widest text-(--platform-text-soft)">
|
||||
Anchor
|
||||
</span>
|
||||
<span className="font-mono text-[10px] text-(--platform-text-soft)">
|
||||
@@ -498,17 +536,6 @@ export function TransformEditor({
|
||||
) : null}
|
||||
|
||||
<div className="grid gap-2">
|
||||
<div className="grid grid-cols-[5.6rem_minmax(0,1fr)_minmax(0,1fr)] gap-2 px-0.5">
|
||||
<span />
|
||||
{AXIS_LABELS.map((axis) => (
|
||||
<span
|
||||
key={axis}
|
||||
className="text-[9px] font-bold text-(--platform-text-soft)"
|
||||
>
|
||||
{axis}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
<VectorInputRow
|
||||
label="Offset Min"
|
||||
values={transform.offset_min}
|
||||
|
||||
Reference in New Issue
Block a user