Add interaction link management UI in App.tsx
This commit is contained in:
141
src/app/App.tsx
141
src/app/App.tsx
@@ -2662,6 +2662,147 @@ export function App({ store, initialStatusMessage }: AppProps) {
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="form-section">
|
||||||
|
<div className="label">Links</div>
|
||||||
|
{selectedTriggerVolumeLinks.length === 0 ? (
|
||||||
|
<div className="outliner-empty">No trigger links authored yet.</div>
|
||||||
|
) : (
|
||||||
|
<div className="outliner-list">
|
||||||
|
{selectedTriggerVolumeLinks.map((link, index) => (
|
||||||
|
<div key={link.id} className="outliner-item">
|
||||||
|
<div className="outliner-item__select">
|
||||||
|
<span className="outliner-item__title">{`Link ${index + 1}`}</span>
|
||||||
|
<span className="outliner-item__meta">{getInteractionActionLabel(link)}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="form-section">
|
||||||
|
<div className="vector-inputs vector-inputs--two">
|
||||||
|
<label className="form-field">
|
||||||
|
<span className="label">Trigger</span>
|
||||||
|
<select
|
||||||
|
data-testid={`interaction-link-trigger-${link.id}`}
|
||||||
|
className="text-input"
|
||||||
|
value={link.trigger}
|
||||||
|
onChange={(event) =>
|
||||||
|
updateInteractionLinkTrigger(link, event.currentTarget.value as InteractionTriggerKind)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<option value="enter">On Enter</option>
|
||||||
|
<option value="exit">On Exit</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
<label className="form-field">
|
||||||
|
<span className="label">Action</span>
|
||||||
|
<select
|
||||||
|
data-testid={`interaction-link-action-${link.id}`}
|
||||||
|
className="text-input"
|
||||||
|
value={link.action.type}
|
||||||
|
onChange={(event) =>
|
||||||
|
updateInteractionLinkActionType(link, event.currentTarget.value as InteractionLink["action"]["type"])
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<option value="teleportPlayer">Teleport Player</option>
|
||||||
|
<option value="toggleVisibility">Toggle Visibility</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{link.action.type === "teleportPlayer" ? (
|
||||||
|
<div className="form-section">
|
||||||
|
<label className="form-field">
|
||||||
|
<span className="label">Target</span>
|
||||||
|
<select
|
||||||
|
data-testid={`interaction-link-teleport-target-${link.id}`}
|
||||||
|
className="text-input"
|
||||||
|
value={link.action.targetEntityId}
|
||||||
|
onChange={(event) => updateTeleportInteractionLinkTarget(link, event.currentTarget.value)}
|
||||||
|
>
|
||||||
|
{teleportTargetOptions.map(({ entity, label }) => (
|
||||||
|
<option key={entity.id} value={entity.id}>
|
||||||
|
{label}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="form-section">
|
||||||
|
<div className="vector-inputs vector-inputs--two">
|
||||||
|
<label className="form-field">
|
||||||
|
<span className="label">Brush</span>
|
||||||
|
<select
|
||||||
|
data-testid={`interaction-link-visibility-target-${link.id}`}
|
||||||
|
className="text-input"
|
||||||
|
value={link.action.targetBrushId}
|
||||||
|
onChange={(event) => updateVisibilityInteractionLinkTarget(link, event.currentTarget.value)}
|
||||||
|
>
|
||||||
|
{visibilityBrushOptions.map(({ brush, label }) => (
|
||||||
|
<option key={brush.id} value={brush.id}>
|
||||||
|
{label}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
<label className="form-field">
|
||||||
|
<span className="label">Mode</span>
|
||||||
|
<select
|
||||||
|
data-testid={`interaction-link-visibility-mode-${link.id}`}
|
||||||
|
className="text-input"
|
||||||
|
value={getVisibilityModeSelectValue(link.action.visible)}
|
||||||
|
onChange={(event) =>
|
||||||
|
updateVisibilityInteractionMode(
|
||||||
|
link,
|
||||||
|
event.currentTarget.value as ReturnType<typeof getVisibilityModeSelectValue>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<option value="toggle">Toggle</option>
|
||||||
|
<option value="show">Show</option>
|
||||||
|
<option value="hide">Hide</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="inline-actions">
|
||||||
|
<button
|
||||||
|
className="toolbar__button"
|
||||||
|
type="button"
|
||||||
|
data-testid={`delete-interaction-link-${link.id}`}
|
||||||
|
onClick={() => handleDeleteInteractionLink(link.id)}
|
||||||
|
>
|
||||||
|
Delete Link
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="inline-actions">
|
||||||
|
<button
|
||||||
|
className="toolbar__button"
|
||||||
|
type="button"
|
||||||
|
data-testid="add-trigger-teleport-link"
|
||||||
|
disabled={teleportTargetOptions.length === 0}
|
||||||
|
onClick={handleAddTeleportInteractionLink}
|
||||||
|
>
|
||||||
|
Add Teleport Link
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="toolbar__button"
|
||||||
|
type="button"
|
||||||
|
data-testid="add-trigger-visibility-link"
|
||||||
|
disabled={visibilityBrushOptions.length === 0}
|
||||||
|
onClick={handleAddVisibilityInteractionLink}
|
||||||
|
>
|
||||||
|
Add Visibility Link
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</>
|
</>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user