@designfever/web-review-kit 0.8.1 → 0.8.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -211,29 +211,55 @@ hooks and returns provider values; it should not become a render component.
211
211
  - `hooks/use.review.section.outline.ts`: Source Tree outline extraction, filter/collapse state, refresh scheduling, and entry actions.
212
212
  - `hooks/use.review.command.key.ts`: hide-all-overlays-while-command-held tracking across host and iframe.
213
213
 
214
+ ### Sitemap Feature Boundary
215
+
216
+ Sitemap state and row derivation are intentionally separate:
217
+
218
+ - `sitemap/modal.tsx`: owns search, sort, status filters, and collapsed-folder UI state.
219
+ - `sitemap/tree.ts`: converts the page list into visible tree or flat result rows.
220
+ - `sitemap/count.ts`: owns the QA count shape, viewport column keys, and count aggregation.
221
+ - `sitemap/row.tsx`: renders the shared page, folder, and All QA row content.
222
+
223
+ The modal mounts on first open and is hidden instead of unmounted on close. This
224
+ preserves search, sort, collapsed folders, active status filters, and scroll
225
+ position while the review shell remains mounted.
226
+
227
+ Page rows show only that page's direct QA count. Folder rows aggregate their
228
+ descendant pages. Enabled status filters use OR with each other and AND with the
229
+ search query; while status filtering is active, only matching pages are shown
230
+ as flat full paths so a parent folder aggregate cannot look like a match.
231
+
214
232
  ### Comment Policy
215
233
 
216
234
  Prefer comments only at module boundaries or non-obvious runtime contracts. Avoid
217
235
  file-wide restatements of import names, prop-by-prop explanations, or comments
218
236
  that duplicate what a function name already says.
219
237
 
220
- ## Figma Overlay Direction
238
+ ## Figma Image Feature Boundary
221
239
 
222
240
  Figma overlay work should stay outside core unless it needs target runtime primitives.
223
241
 
224
- Preferred direction:
242
+ Current ownership:
225
243
 
226
244
  ```txt
227
245
  src/react-shell/figma/
228
- controls.tsx
229
- sync.ts
230
- overlay.state.ts
246
+ image.controller.ts # image store list and mutations
247
+ image.overlay.controller.ts # React effects and overlay commands
248
+ image.overlay.state.ts # route-keyed localStorage and migration
249
+ images.panel*.tsx # shell panel UI
250
+
251
+ src/react-shell/target/
252
+ figma.image.overlay.ts # iframe DOM rendering and drag behavior
231
253
 
232
254
  src/figma/
233
- matching.ts
234
- types.ts
255
+ image.types.ts # public image/store contracts
235
256
  ```
236
257
 
258
+ `image.overlay.controller.ts` re-exports the overlay types used by existing
259
+ shell modules, but persistence and normalization live in
260
+ `image.overlay.state.ts`. Keep storage migrations and default-value cleanup out
261
+ of the React controller.
262
+
237
263
  Shared coordinate math can reuse `core/geometry.ts` or move to a future shared module if both core and Figma need it heavily.
238
264
 
239
265
  Avoid turning `core` into a feature bucket. Core should stay focused on target review runtime behavior.
@@ -88,6 +88,30 @@ overlays into the iframe instead. Those overlays use:
88
88
  - `#df-review-figma-image-target-root`
89
89
  - `.df-review-figma-image-target-overlay`
90
90
 
91
+ ## Image Overlay State
92
+
93
+ Package-managed image overlay controls are stored separately for each project,
94
+ page, viewport, and optional slot. The localStorage key starts with:
95
+
96
+ ```txt
97
+ df-review-figma-image-overlay-state:
98
+ ```
99
+
100
+ Each target stores the selected image, per-image visibility, opacity, lock,
101
+ normal/invert mode, vertical offset, and the images that were visible before a
102
+ hide-all action. Default state removes the storage entry instead of leaving an
103
+ empty route key behind. Storage events keep another tab on the same origin in
104
+ sync.
105
+
106
+ `src/react-shell/figma/image.overlay.state.ts` owns the storage shape,
107
+ normalization, and the legacy flat-state migration. The React effects and user
108
+ commands stay in `image.overlay.controller.ts`; iframe DOM creation and drag
109
+ behavior stay in `src/react-shell/target/figma.image.overlay.ts`.
110
+
111
+ When the store refreshes its image list, removed image IDs are pruned. If the
112
+ effective state did not change, the controller preserves the existing state
113
+ identity so it does not rewrite the same localStorage value.
114
+
91
115
  The image overlay hit layer is interactive only when the image can be dragged.
92
116
  During element review mode or `Option` source selection, the shell temporarily
93
117
  locks both host helper layers and package image overlays with
@@ -246,12 +246,10 @@ import {
246
246
  export default defineConfig({
247
247
  plugins: [
248
248
  reviewSourceLocator({
249
- enabled: true,
250
249
  include: ['src'],
251
250
  filePath: 'absolute',
252
251
  }),
253
252
  reviewDataLocator({
254
- enabled: true,
255
253
  include: ['src/data'],
256
254
  filePath: 'absolute',
257
255
  }),
@@ -259,9 +257,9 @@ export default defineConfig({
259
257
  });
260
258
  ```
261
259
 
262
- Captured DOM nodes will include `data-wrk-source-file`, `data-wrk-source-line`, and `data-wrk-source-column`. When TypeScript is available in the host toolchain, the source locator parses TSX/JSX and also adds `data-wrk-source-component` to intrinsic JSX nodes. For function component render paths, it records the parent JSX call site as `data-wrk-source-parent-*` hints so Source Tree can open the file that used the component. Data locator injects `__wrkDataFile` and `__wrkDataLine` props into page data section objects so the shell can expose matching `data-wrk-data-*` hints when host components forward those props to section wrappers.
260
+ The locator plugins run automatically on the Vite dev server and stay disabled in production builds. Source Tree and the `Option` shortcut stay available without `sourceRoot` or an `enabled` option; `sourceRoot` is only needed to open relative source paths. Captured DOM nodes will include `data-wrk-source-file`, `data-wrk-source-line`, and `data-wrk-source-column`. When TypeScript is available in the host toolchain, the source locator parses TSX/JSX and also adds `data-wrk-source-component` to intrinsic JSX nodes. For function component render paths, it records the parent JSX call site as `data-wrk-source-parent-*` hints so Source Tree can open the file that used the component. Data locator injects `__wrkDataFile` and `__wrkDataLine` props into page data section objects so the shell can expose matching `data-wrk-data-*` hints when host components forward those props to section wrappers.
263
261
 
264
- In the review shell, hold `Option` over the target iframe to show source candidates from the DOM ancestry. Click the target to pin the candidate list, then choose which file to open. The side rail Source Tree panel lists section/source/data candidates and can scroll to a section or open its source/data file. When parent usage hints exist, each row shows `used in` with the parent component and call-site file/position, plus an action to open that usage source. It can also show live box metrics, text/font metadata, media URLs, and class tags for each node. If the file path is absolute, it opens directly. If the plugin stores relative paths, pass `sourceRoot` when mounting the shell.
262
+ In the review shell, hold `Option` over the target iframe to show its source outline, then click the target to open the closest component in Source Tree. The side rail Source Tree panel lists section/source/data candidates and can scroll to a section or open its source/data file. When parent usage hints exist, each row shows `used in` with the parent component and call-site file/position, plus an action to open that usage source. It can also show live box metrics, text/font metadata, media URLs, and class tags for each node. If the file path is absolute, it opens directly. If the plugin stores relative paths, pass `sourceRoot` when mounting the shell.
265
263
 
266
264
  Source opening reads these optional host env values from `.env.local`:
267
265
 
@@ -291,7 +289,7 @@ mountReviewShell({
291
289
  });
292
290
  ```
293
291
 
294
- Set `sourceInspector.enabled` to `false` when source code opening should be unavailable. Use `sourceInspector.ignore` to hide infrastructure files from source candidates and the Source Tree. Use `sourceInspector.maxDepth` to cap Source Tree traversal depth. Set `sourceInspector.hoverOutline` to `false` to disable iframe target outlines while hovering Source Tree items. Set `sourceInspector.includePlacer` to `true` when primitive Placer nodes should appear in Source Tree or source candidate lists. The `data-font` overlay still belongs to the target project markup and is not required for source opening.
292
+ Use `sourceInspector.ignore` to hide infrastructure files from source matching and the Source Tree. Use `sourceInspector.maxDepth` to cap Source Tree traversal depth. Set `sourceInspector.hoverOutline` to `false` to disable iframe target outlines while hovering Source Tree items. Set `sourceInspector.includePlacer` to `true` when primitive Placer nodes should appear in Source Tree or Option source matching. The `data-font` overlay still belongs to the target project markup and is not required for source opening.
295
293
 
296
294
  Use this only in dev/review builds. Source paths are written into the browser DOM and can be persisted with QA items.
297
295
 
@@ -0,0 +1,50 @@
1
+ # 릴리즈 노트: 0.8.2
2
+
3
+ ## Source Tree / 소스 추적
4
+
5
+ - Source Tree와 Option 소스 선택을 dev 서버에서 자동 활성화하고 production build에서는 비활성화한다.
6
+ - `VITE_REVIEW_SOURCE_HINT`와 legacy `enabled` 조건 없이 dev source/data locator가 동작한다.
7
+ - Option으로 선택한 DOM을 Component List에 동기화하고 source, data, parent usage metadata를 표시한다.
8
+ - Component List의 전체 item 영역을 선택 영역으로 사용하고 불필요한 컴포넌트명 복사 버튼을 제거했다.
9
+
10
+ ## DOM 선택과 이동
11
+
12
+ - Component 선택, DOM QA 선택, DOM 이동을 독립된 상태로 분리했다.
13
+ - QA 선택은 파란색, DOM 선택과 이동은 연두색으로 구분했다.
14
+ - Component List의 DOM 이동을 canvas snapshot layer 방식으로 변경했다.
15
+ - 같은 페이지에서 여러 DOM 이동을 유지하고 원본 DOM은 투명 처리한다.
16
+ - canvas의 clear 버튼이나 Component List의 Clear 동작으로 이동을 초기화할 수 있다.
17
+ - 바깥 영역을 클릭하면 이동 선택을 종료하고 좌표는 고정 폭 `x : y` 형식으로 표시한다.
18
+ - Source Tree DOM 이동에서 scale 조작을 제거했다.
19
+
20
+ ## 선택과 포커스
21
+
22
+ - 같은 Component 또는 QA item을 다시 클릭하면 선택을 해제한다.
23
+ - iframe을 포함한 중앙 공란을 클릭하면 현재 Component 또는 QA 선택을 해제한다.
24
+ - Component List focus는 연두색, QA List focus는 파란색으로 통일했다.
25
+ - Escape를 누르면 DOM outline, Component List focus, QA 선택과 QA card focus를 함께 해제한다.
26
+ - Component List panel이 target outline보다 위에 표시되도록 layer 순서를 조정했다.
27
+
28
+ ## SPA iframe 이동
29
+
30
+ - iframe의 `history.pushState()`와 `history.replaceState()`를 감지한다.
31
+ - SPA 이동은 iframe을 재로드하지 않고 shell target과 QA route만 동기화한다.
32
+ - host router가 처리한 링크는 가로채지 않고, 일반 링크와 back/hash 이동은 hard navigation으로 처리한다.
33
+ - SPA fixture와 navigation 회귀 테스트를 추가했다.
34
+
35
+ ## Figma Images
36
+
37
+ - Figma API 요청, 이미지 다운로드, 이미지 처리 timeout을 단계별로 분리했다.
38
+ - timeout 발생 시 `AbortController`로 진행 중인 요청을 중단한다.
39
+ - 이미지 decode를 한 번만 수행하고 WebP 변환 실패 시 원본 이미지로 fallback한다.
40
+ - host에서 client render `timeoutMs`를 설정할 수 있다.
41
+ - Figma image layer card의 edit/delete icon tooltip을 제거해 panel 내부 가로 스크롤을 막았다.
42
+
43
+ ## Verification
44
+
45
+ - `pnpm typecheck`
46
+ - `pnpm typecheck:dev`
47
+ - `pnpm test`
48
+ - `pnpm lint:dead-code`
49
+ - `pnpm build`
50
+ - Lexus review shell에서 SPA 이동과 QA 등록/삭제를 확인했다.
@@ -0,0 +1,48 @@
1
+ # 릴리즈 노트: 0.8.3
2
+
3
+ 전체 코드 리뷰에서 나온 버그 수정과 중복 코드 정리를 담은 patch release. 동작 오류 4건을 고치고, sitemap 사용성을 개선하고, 큰 feature 파일을 역할별로 분리하고 문서를 현행화했다.
4
+
5
+ 비교 기준: `0.8.2`
6
+
7
+ ## 버그 수정
8
+
9
+ - Source Tree panel이 열린 상태에서 DOM/Area draft를 시작하면 docked composer가 panel 뒤에 가려져 사용할 수 없던 문제를 수정했다. composer가 있을 때 draft host를 panel보다 위로 올린다.
10
+ - `<select>`에 포커스가 있을 때 shell 단축키(`e`, `a`, `r`, `g`, `f`)가 동작하던 문제를 수정했다. select에서 글자 입력은 option 이동이므로 다른 입력 요소와 동일하게 단축키를 차단한다.
11
+ - Figma image overlay 상태 동기화의 no-change guard가 항상 새 객체 비교로 실패해, 이미지 목록이 갱신될 때마다 동일한 상태를 localStorage에 다시 쓰던 문제를 수정했다.
12
+ - shell이 `history.replaceState()`로 URL을 갱신할 때 `#hash`가 유실되던 문제를 수정했다.
13
+
14
+ ## 개선
15
+
16
+ - Sitemap modal을 닫아도 unmount 하지 않고 숨겨서, 다시 열면 검색어·정렬·폴더 접힘·목록 스크롤이 마지막 상태 그대로 복원된다. 첫 오픈 전에는 기존처럼 mount 하지 않는다.
17
+ - Sitemap header의 요약 카운트(`N todo · N review · N hold`)를 클릭하면 해당 status QA가 있는 페이지만 필터링한다. 켜진 status끼리는 OR, 검색어와는 AND로 동작하고, 활성 필터는 색상과 밑줄로 표시한다. 필터 중에는 tree 대신 매칭 페이지를 전체 경로의 평평한 목록으로 보여준다.
18
+
19
+ ## 내부 정리
20
+
21
+ - `isEditableEventTarget` 4벌 복사본을 `core/hotkey.ts` 하나로 통합했다. 복사본 간 드리프트(SELECT 누락)가 위 단축키 버그의 원인이었다.
22
+ - `captureDomDraft`/`captureAreaDraft`의 동일한 capture 로직을 draft 접근자를 받는 함수 하나로 합쳤다.
23
+ - shell settings의 localStorage 접근을 `readStorage`/`writeStorage` 헬퍼로 통일해 SSR guard와 try/catch 반복을 제거했다.
24
+ - unknown error 메시지 추출을 `core/error.ts`의 `getErrorMessage`로 공유한다.
25
+ - Figma image overlay controller의 selected image setter 6개를 공통 updater로 축소했다.
26
+ - Figma image overlay의 저장 상태 로직과 sitemap의 QA 집계·row UI를 각각 분리해 controller와 modal의 역할을 줄였다.
27
+ - 상태 identity, storage migration, sitemap 집계, row 이벤트 전파처럼 이름만으로 의도가 드러나지 않는 runtime contract에 주석을 추가했다.
28
+ - 기존 `image.overlay.controller.ts`와 `sitemap/tree.ts` import 경로는 re-export로 유지해 공개 API와 내부 소비 코드의 호환성을 보존했다.
29
+ - 동일한 구현이 중복된 source candidate key builder와 도달 불가능한 supabase `externalIssueUrl` fallback을 제거했다.
30
+ - git에 추적되던 `dist` 빌드 산출물을 제거하고 `.gitignore`에 추가했다. 배포 패키지에는 영향이 없다.
31
+
32
+ ## 문서
33
+
34
+ - Architecture 문서에 sitemap의 modal/tree/count/row 책임과 direct page count·folder aggregate 규칙을 추가했다.
35
+ - Figma overlay 문서에 route·viewport별 localStorage 상태, legacy migration, storage event 동기화, 불필요한 재저장 방지 구조를 추가했다.
36
+ - Testing 문서에 새 hotkey, URL hash, Figma overlay storage, sitemap filter/state 회귀 테스트와 전체 release 검증 명령을 반영했다.
37
+ - root README와 docs index가 0.8.3 릴리즈 노트 및 현재 architecture/Figma 문서를 가리키도록 갱신했다.
38
+
39
+ ## 검증
40
+
41
+ - `pnpm typecheck`
42
+ - `pnpm typecheck:dev`
43
+ - `pnpm test`
44
+ - `pnpm lint:dead-code`
45
+ - `pnpm build`
46
+ - `pnpm build:dev`
47
+ - `npm pack --dry-run --json`
48
+ - dev review shell 브라우저 테스트: Source Tree 위 draft composer 표시, select 단축키 차단, URL hash 유지, sitemap status 필터와 검색 조합, 닫기/재오픈 상태 복원, Figma image panel 렌더링을 확인했다. Vite error overlay와 console error는 없었다.
package/docs/testing.md CHANGED
@@ -14,9 +14,11 @@ Use the full package check before release or when touching public types:
14
14
  ```bash
15
15
  pnpm typecheck
16
16
  pnpm test
17
+ pnpm lint:dead-code
17
18
  pnpm build
18
19
  pnpm typecheck:dev
19
20
  pnpm build:dev
21
+ npm pack --dry-run --json
20
22
  ```
21
23
 
22
24
  ## Current Coverage
@@ -33,15 +35,19 @@ pnpm build:dev
33
35
 
34
36
  The Supabase coverage uses an in-memory PostgREST/RPC mock. It does not contact a real Supabase project.
35
37
 
36
- ### Pure function unit suites
38
+ ### Regression and unit suites
37
39
 
38
- Colocated `*.test.ts` files cover the core pure-function modules that refactors depend on:
40
+ Colocated `*.test.ts` and `*.test.tsx` files cover the runtime contracts that
41
+ refactors depend on:
39
42
 
40
43
  - `src/core/geometry.test.ts`: coordinate conversion (host/target spaces), clamping, selection shapes, popover placement.
41
- - `src/core/hotkey.test.ts`: hotkey matching with modifiers, Korean IME key aliases, physical key-code fallback.
44
+ - `src/core/hotkey.test.ts`: hotkey matching with modifiers, Korean IME key aliases, physical key-code fallback, and editable-target blocking including `<select>`.
42
45
  - `src/core/location.test.ts`: page URL building and review-internal query param stripping.
43
46
  - `src/core/review/scope.test.ts`: viewport preset matching, scope inference, and item numbering/draft labels.
44
- - `src/route.test.ts`: route path normalization (`index.html`, query/hash) and item route keys.
47
+ - `src/react-shell/route.test.ts`: shell URL updates preserve the current hash while changing target or selected QA item.
48
+ - `src/react-shell/figma/image.overlay.controller.test.tsx`: unchanged image-list refreshes do not rewrite overlay state in localStorage.
49
+ - `src/react-shell/sitemap/tree.test.ts`: status filters use OR with each other, AND with search, and return flat full-path page rows.
50
+ - `src/react-shell/sitemap/modal.test.tsx`: closing and reopening the sitemap preserves search and status-filter state.
45
51
  - `src/figma/parse.test.ts`: Figma URL/node-ref parsing, including non-figma host rejection.
46
52
  - `src/vite/figma-asset.test.ts`: asset storage key validation, including path traversal rejection, and mime/format helpers.
47
53
  - `src/vite/figma-image-store.server.test.ts`: dev middleware request guards — cross-origin (CSRF) rejection, JSON content-type enforcement, body size limit.
@@ -59,6 +65,8 @@ Add or extend Vitest coverage when changing:
59
65
  - Supabase row mapping, RPC payloads, or review URL generation
60
66
  - attachment upload contracts
61
67
  - status, assignee, or external link fields
68
+ - route-keyed Figma image overlay storage or migration behavior
69
+ - sitemap count aggregation, filtering, sorting, or close/reopen state
62
70
  - coordinate/scope/route/parsing helpers listed above (extend the colocated suite)
63
71
 
64
72
  ## Known Behavior Notes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@designfever/web-review-kit",
3
- "version": "0.8.1",
3
+ "version": "0.8.3",
4
4
  "type": "module",
5
5
  "description": "Designfever web page review overlay toolkit.",
6
6
  "license": "Apache-2.0",