Proposal #5 from docs/ARCHITECTURE.md, first slice: split one of the
three remaining inline tab bodies of WiredCreatorToolsView out into
its own file. Same approach the Settings tab has had for a while
(see WiredToolsSettingsTabView).
What moved
- 113 lines of inline JSX (the `{ activeTab === 'variables' && <div>
... </div> }` block) → src/components/wired-tools/WiredVariablesTabView.tsx
- The new component is a pure presentation function: 12 typed props,
no useState, no useEffect, no event subscriptions. It receives:
* state to render: variablesType, variablePickerDefinitions,
selectedVariableDefinition, canVariableHighlight,
isVariableHighlightActive, variableManageCanOpen,
selectedVariableProperties, selectedVariableTextValues
* actions to call: onVariablesTypeChange, onPickVariable,
onToggleVariableHighlight, onOpenManagePanel
- The parent supplies all of them inline at the call site. The
manage-panel open sequence (request fresh user vars + reset page +
clear selection + show modal) is closed over into a single
onOpenManagePanel callback, so the sub-component doesn't need to
know about its three internal setters.
Impact
- WiredCreatorToolsView.tsx: 3901 → 3809 lines (−92 net). The file
is still large, but one of the three big inline blocks is gone.
Monitor (~176 lines) and Inspection (~138 lines) remain inline as
follow-up PRs.
- The React Compiler now has a smaller file boundary for the
Variables panel; once the other two blocks come out the parent
module should stop being skipped for memoization.
Conscious non-goals
- No state was moved. The shared state (selectedVariableKeys,
isVariableHighlightActive, variableManagePage, etc.) still lives
in the parent's useState. Hoisting them to a Zustand slice would
be a separate PR — premature here.
- No behavior change. Same renders, same handlers, same DOM.
Verification
- yarn eslint on the two touched files: 34 problems baseline,
34 problems after the split (identical: same FC<{}>, same
pre-existing set-state-in-effect, same react-compiler skip
warnings on the parent module).
- yarn test: 49/49 passing.
- yarn tsc on the two files: clean.
Phase 3 of the refactor plan in docs/ARCHITECTURE.md — the foundation
that unblocks every safe refactor below.
Install
- yarn add -D vitest@3 jsdom @testing-library/dom @testing-library/react
@testing-library/jest-dom
Note: pinned to vitest@3 (not the latest 4.x) because yarn 1's peer
resolution breaks on vitest@4's peer link to vite. With vitest@3 the
existing Vite 8 install resolves cleanly.
Configuration
- vitest.config.mts (new): separate from vite.config.mjs because the
dev/build config wires up renderer SDK aliases that point at sibling
working trees (../renderer, ../Nitro_Render_V3). Tests are written
against pure modules that don't pull in the renderer, so the test
runner uses a smaller alias set.
- tests/setup.ts (new): imports @testing-library/jest-dom/vitest so
custom matchers (toBeInTheDocument, etc.) are available without
per-file imports.
- tsconfig.json: include "tests" so eslint stops complaining about
unparseable files; also makes the IDE see the test files.
- package.json scripts: "test" (one-shot) and "test:watch".
Tests
- tests/WiredCreatorTools.helpers.test.ts (18 cases): covers the pure
helpers extracted in 3c68d97 — createEmptyMonitorSnapshot,
formatMonitorLatestOccurrence (5 time-bucket branches),
formatMonitorHistoryOccurrence, formatVariableTimestamp,
formatMonitorSource (4 branches), normalizeMonitorReason. These are
the most boring-but-easy-to-break functions; locking them down first
is high value, near-zero risk.
- tests/navigatorRoomCreatorStore.test.ts (4 cases): exercises the
Zustand store added in the previous commit — initial state, latch
semantics, 5s auto-reset (with fake timers), and the
"second beginCreate restarts the lockout" invariant. Validates that
the store-based replacement of the let-singleton has the same
observable behavior, plus the new invariant that wasn't possible
before (timer composition under StrictMode double-mount).
Side effect: two non-test source files were converted to `import type`
to keep the test bundle from accidentally pulling in the renderer SDK
transitively:
- src/components/wired-tools/WiredCreatorTools.types.ts
(`import type { AvatarInfoFurni }`)
- src/components/wired-tools/WiredCreatorTools.helpers.ts
(`import type { HotelDateTimeParts, MonitorSnapshot }`)
This is harmless — TypeScript already treated them as type-only —
and improves tree-shaking on build as a side benefit.
Verification
- yarn test -> 2 files, 22 tests passing in ~1.0s.
- yarn eslint on tests/ + the two type-only-import files: 0 errors,
0 warnings.
Migration path
- Next adoption targets: cover useDoorbellState reducer (data hook
split), the new useNitroQuery adapter (timeout/cleanup behavior),
and the smaller pure formatters under src/api/.
- React component tests (via @testing-library/react) deferred until
there's a small mock layer for the renderer SDK. The
@testing-library/* deps are already installed so that PR is
unblocked.
https://claude.ai/code/session_01GrR87LAqnAEyKG2ZbmQt5Q
The single-file WiredCreatorToolsView.tsx was 4493 lines, which is one
of the main reasons the React Compiler reports
"Compilation Skipped: Existing memoization could not be preserved" on
this module. Split is conservative — only the pure leading sections
move out, the component itself is untouched (state, effects, JSX all
stay in place).
New files (sibling to the view):
- WiredCreatorTools.types.ts (~233 lines): every interface and type
alias declared at the top of the original file.
- WiredCreatorTools.constants.ts (~225 lines): TABS, MONITOR_LOG_ORDER,
poll constants, MONITOR_ERROR_INFO, INSPECTION_ELEMENTS,
VARIABLES_ELEMENTS, EDITABLE_*, VARIABLE_DEFINITIONS,
WIRED_FREEZE_EFFECT_IDS, TEAM_COLOR_NAMES, WEEKDAY/MONTH/DIRECTION
names. The createVariableDefinition factory is kept as a local helper
in this file (only used to build VARIABLE_DEFINITIONS).
- WiredCreatorTools.helpers.ts (~147 lines): createEmptyMonitorSnapshot,
getHotelTimeFormatter (with its module-private cache map),
getHotelDateTimeParts, formatMonitorLatestOccurrence,
formatMonitorHistoryOccurrence, formatVariableTimestamp,
formatMonitorSource, normalizeMonitorReason. All pure (or
cache-stable), no closure on component state.
WiredCreatorToolsView.tsx changes:
- 4493 -> 3901 lines (-592, ~13% reduction).
- The four inspection-icon asset imports (furni/global/user/context)
move to the constants file alongside the only consumers
(INSPECTION_ELEMENTS / VARIABLES_ELEMENTS).
- AvatarInfoFurni was only referenced by the extracted
InspectionFurniSelection interface and is removed from the main
file's api import.
- New import block at the top pulls back the symbols actually used by
the component body.
Verification:
- yarn eslint on the three new files: 0 errors / 0 warnings.
- yarn eslint on WiredCreatorToolsView.tsx: 26 errors before split,
26 errors after split (identical pre-existing set; nothing new
introduced).
- yarn tsc --noEmit on the four files: clean (only the project-wide
pre-existing TS2307 about @nitrots/nitro-renderer not being
installed locally remains, same as before).
This unblocks future per-tab splits (Monitor / Inspection / Variables
JSX panels are still inline in the view and represent the next ~1600
lines that could move out, but require introducing a shared state
context first since the current setState chain is intertwined).
https://claude.ai/code/session_01GrR87LAqnAEyKG2ZbmQt5Q
Run eslint --fix across src/ to clear ~1900 mechanical lint errors
surfaced by the @typescript-eslint v8 + react-hooks v7 + react-compiler
upgrade in the React 19 modernization PR.
Issues fixed automatically:
- brace-style (Allman): try/catch one-liners reformatted to multi-line
- indent: tab-vs-space and depth corrections
- semi: missing trailing semicolons
- no-trailing-spaces
No semantic changes. Remaining 701 errors are real-code issues
(set-state-in-effect, rules-of-hooks, no-unsafe-* type checks) that
need manual per-file review.
https://claude.ai/code/session_01GrR87LAqnAEyKG2ZbmQt5Q
- add the new :wired inspection/monitor panel with furni, user and global tabs
- add live variables, previews, inline editing and keep-selected behavior
- add global room diagnostics placeholders, monitor artwork and server/client timezone display
- add editor support for wf_xtra_text_output_furni_name and related UI texts/assets