3DSL Viewer DOM Contract

version: 2026-01-09

この文書は Viewer UI(public/viewer/ui/*)が依存する DOM の契約である。 Tailwind の class / レイアウト構造は自由だが、以下の アンカー属性は固定する:

  • id
  • data-role(推奨:将来 id 依存を減らすため)
  • input/select の type(range / select など)

原則

  • UI layer は state を読む → DOM 更新のみ行う
  • state 書き込みは hub/core の公開 API 経由のみ(single-writer)
  • DOM が欠けても落とさず、該当機能だけ disable し warn を出す(robust)

例外(fail-fast)

  • prod_full / devHarness_full は「フレーム+フィルタ必須」固定
  • 必須 DOM が欠けている場合、UI 初期化は 即エラーで停止する
    • “半分だけ動いて原因不明” を避けるため

Profiles

  • prod_minimal: 最小UI(gizmo 等のみ)
  • prod_full: 通常UI(picker/keyboard/timeline/controls)
  • devHarness_full: 開発用(prod_full + メタ/ログ/デバッグ要素)

共通(全 profile)必須

roleselector (preferred)selector (fallback)requiredtype/attrs
+viewerCanvas[data-role="viewer-canvas"]#viewer-canvasYES
hudToast[data-role="viewer-hud"]#viewer-hudNO<div>(toast表示)
orbitHint[data-role="orbit-hint"]#orbit-hintNO<div>(Orbit操作ヒント)
perfHud[data-role="perf-hud"]#perf-hudNO<div>(debug/perf表示。dev限定で使用)

prod_minimal 必須

roleselector (preferred)selector (fallback)requiredtype/attrs
gizmoSlot[data-role="gizmo-slot"]#gizmo-slotYESgizmo canvas が差し込まれる枠
gizmoModeLabel[data-role="gizmo-mode-label"]#gizmo-mode-labelNO<span>(結果モード表示)

(任意)

  • world axes toggle / preset view / auto orbit はページ側が用意してれば動く、無ければ黙って無効

prod_full 必須(prod_minimal + 追加)

Filters

rolepreferredfallbackrequiredtype/attrs
filterLines[data-role="filter-lines"]#filter-linesYES<button>
filterPoints[data-role="filter-points"]#filter-pointsYES<button>
filterAux[data-role="filter-aux"]#filter-auxYES<button>

Frame controls

rolepreferredfallbackrequiredtype/attrs
btnPlay[data-role="btn-play"]#btn-playYES<button>
btnRew[data-role="btn-rew"]#btn-rewYES<button>
btnFf[data-role="btn-ff"]#btn-ffYES<button>
btnStepBack[data-role="btn-step-back"]#btn-step-backYES<button>
btnStepForward[data-role="btn-step-forward"]#btn-step-forwardYES<button>
frameSlider[data-role="frame-slider"]#frame-sliderYES<input type="range">
frameLabelMin[data-role="frame-label-min"]#frame-label-minYES<span/div>
frameLabelMax[data-role="frame-label-max"]#frame-label-maxYES<span/div>
frameLabelZero[data-role="frame-label-zero"]#frame-label-zeroNO<span/div>
frameLabelCurrent[data-role="frame-label-current"]#frame-label-currentYES<span/div>
frameZeroLine[data-role="frame-zero-line"]#frame-zero-lineNO<div>

Viewer settings

rolepreferredfallbackrequiredtype/attrs
vsLineWidthMode[data-role="vs-linewidth-mode"]#vs-linewidth-modeNO<select>
vsMicroProfile[data-role="vs-micro-profile"]#vs-micro-profileNO<select>

Gizmo extras / Camera

rolepreferredfallbackrequiredtype/attrs
worldAxesToggle[data-role="world-axes-toggle"]#world-axes-toggleNO<button aria-pressed>
presetViewToggle[data-role="gizmo-presets-toggle"]#gizmo-presets-toggleNO<button>
autoOrbitSlot[data-role="auto-orbit-slot"]#auto-orbit-slotNO<div>
autoOrbitToggle[data-role="auto-orbit-toggle"]#auto-orbit-toggleNO<button>
autoOrbitSpeedDown[data-role="auto-orbit-speed-down"]#auto-orbit-speed-downNO<button>
autoOrbitCW.auto-orbit-btn-dir[data-dir="cw"]同左NO<button data-dir="cw">
autoOrbitCCW.auto-orbit-btn-dir[data-dir="ccw"]同左NO<button data-dir="ccw">
autoOrbitSpeedUp[data-role="auto-orbit-speed-up"]#auto-orbit-speed-upNO<button>

Detail view

rolepreferredfallbackrequiredtype/attrs
detailRoot[data-role="viewer-detail"]#viewer-detailNOdetailView の挿入先

devHarness_full 必須(prod_full + 追加)

Meta panels(viewerDevHarness のみ)

rolepreferredfallbackrequiredtype/attrs
metaFile[data-role="meta-file"]#meta-fileYES<section/div>
metaModel[data-role="meta-model"]#meta-modelYES<section/div>
metaModelLog[data-role="meta-model-log"]#meta-model-logYES<div>

Document caption(右上カード)

rolepreferredfallbackrequiredtype/attrs
docCaptionTitle[data-role="doc-caption-title"]#doc-caption-titleNO<div>
docCaptionBody[data-role="doc-caption-body"]#doc-caption-bodyNO<div>

注意:mode表示は「要求」ではなく「結果」を表示する

UI は原則 hub.core.uiState.runtime.status.effective.mode を表示する。 debug のみ、要求(req)とブロック要因(blockedBy)を補助表示してよい。