@designfever/web-review-kit 0.7.3 → 0.8.1
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.
- package/README.md +8 -4
- package/dist/{chunk-RPVLRULC.js → chunk-4ZP7B7R6.js} +2345 -1786
- package/dist/chunk-4ZP7B7R6.js.map +1 -0
- package/dist/index.cjs +2348 -1793
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -4
- package/dist/index.d.ts +11 -4
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/dist/react-shell.cjs +14936 -11239
- package/dist/react-shell.cjs.map +1 -1
- package/dist/react-shell.d.cts +6 -4
- package/dist/react-shell.d.ts +6 -4
- package/dist/react-shell.js +11615 -8399
- package/dist/react-shell.js.map +1 -1
- package/dist/{types-DT9Z66mV.d.cts → types-BM8E7BFV.d.cts} +63 -3
- package/dist/{types-DT9Z66mV.d.ts → types-BM8E7BFV.d.ts} +63 -3
- package/dist/vite.cjs +344 -48
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.d.cts +2 -0
- package/dist/vite.d.ts +2 -0
- package/dist/vite.js +345 -49
- package/dist/vite.js.map +1 -1
- package/docs/README.md +20 -13
- package/docs/adapters.md +27 -4
- package/docs/adaptor.sample.ts +53 -3
- package/docs/architecture.md +117 -3
- package/docs/figma-overlay.md +51 -0
- package/docs/grid-overlay.md +5 -0
- package/docs/installation.md +46 -8
- package/docs/release-notes-0.8.0.md +175 -0
- package/docs/release-notes-0.8.1.md +23 -0
- package/docs/testing.md +68 -0
- package/package.json +14 -5
- package/dist/chunk-RPVLRULC.js.map +0 -1
- package/docs/code-review-0.6.0.md +0 -232
- package/docs/figma-image-mvp-0.7.0.md +0 -330
package/docs/adaptor.sample.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
REVIEW_WORKFLOW_STATUS_OPTIONS,
|
|
3
|
+
type ReviewAttachment,
|
|
4
|
+
type ReviewAttachmentUploadInput,
|
|
3
5
|
type ReviewItem,
|
|
4
6
|
type ReviewItemQuery,
|
|
5
7
|
type ReviewItemStatus,
|
|
@@ -17,17 +19,21 @@ type RemoteReviewAdapterOptions = {
|
|
|
17
19
|
source?: ReviewSource;
|
|
18
20
|
token?: string;
|
|
19
21
|
fields?: ReviewShellAdapter['fields'];
|
|
22
|
+
attachmentUploadPath?: string;
|
|
20
23
|
assigneeTitle?: string;
|
|
21
24
|
assigneeOptions?: ReviewShellAssigneeOption[];
|
|
22
25
|
};
|
|
23
26
|
|
|
24
27
|
type RemoteReviewItemResponse = ReviewItem | { item: ReviewItem };
|
|
28
|
+
type RemoteReviewAttachmentResponse =
|
|
29
|
+
| ReviewAttachment
|
|
30
|
+
| { attachment: ReviewAttachment };
|
|
25
31
|
|
|
26
32
|
/*
|
|
27
33
|
* WebReviewKitAdapter is the core storage contract.
|
|
28
34
|
*
|
|
29
35
|
* ReviewItem is the full QA payload. Persist it as structured JSON so marker,
|
|
30
|
-
* anchor, selection, viewport, scroll, status, and external
|
|
36
|
+
* anchor, selection, viewport, scroll, status, and external link fields survive.
|
|
31
37
|
*
|
|
32
38
|
* ReviewItemQuery is used by the shell for current-page lists and sitemap counts.
|
|
33
39
|
* A remote backend should support at least projectId, routeKey, status, source,
|
|
@@ -101,12 +107,14 @@ export function createRemoteReviewAdapter(
|
|
|
101
107
|
*
|
|
102
108
|
* label becomes the URL source, for example /review?source=remote.
|
|
103
109
|
* create controls whether the shell can write to this adapter.
|
|
104
|
-
* canWrite can be true or limited to ['dom', '
|
|
110
|
+
* canWrite can be true or limited to ['dom', 'area'].
|
|
105
111
|
* update enables title/comment edits in the QA panel.
|
|
106
112
|
* fields enables optional UI fields such as title. Omit title to keep comment-only UI.
|
|
107
113
|
* updateStatus drives the status buttons in the QA panel.
|
|
108
114
|
* assigneeOptions + updateAssignee drive the assignee select next to status.
|
|
109
115
|
* assigneeTitle customizes the empty option/field label. Defaults to "Assignee".
|
|
116
|
+
* uploadAttachment lets paste/capture flows upload File/Blob data before the
|
|
117
|
+
* returned metadata is stored on ReviewItem.attachments.
|
|
110
118
|
* remove enables delete actions for this source.
|
|
111
119
|
*/
|
|
112
120
|
export function createRemoteReviewShellAdapter(
|
|
@@ -129,10 +137,44 @@ export function createRemoteReviewShellAdapter(
|
|
|
129
137
|
assigneeOptions: options.assigneeOptions ?? [],
|
|
130
138
|
updateAssignee: ({ id, assigneeId, assigneeName }) =>
|
|
131
139
|
adapter.update(id, { assigneeId, assigneeName }),
|
|
140
|
+
uploadAttachment: options.attachmentUploadPath
|
|
141
|
+
? (input) => uploadReviewAttachment(input, options)
|
|
142
|
+
: undefined,
|
|
132
143
|
remove: (id) => adapter.remove(id),
|
|
133
144
|
};
|
|
134
145
|
}
|
|
135
146
|
|
|
147
|
+
async function uploadReviewAttachment(
|
|
148
|
+
input: ReviewAttachmentUploadInput,
|
|
149
|
+
options: RemoteReviewAdapterOptions
|
|
150
|
+
) {
|
|
151
|
+
if (!options.attachmentUploadPath) {
|
|
152
|
+
throw new Error('remote review attachment upload path is not configured');
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const name =
|
|
156
|
+
input.name || (input.file instanceof File ? input.file.name : 'attachment');
|
|
157
|
+
const mime = input.mime || input.file.type;
|
|
158
|
+
const form = new FormData();
|
|
159
|
+
form.set('file', input.file, name);
|
|
160
|
+
form.set('name', name);
|
|
161
|
+
if (mime) form.set('mime', mime);
|
|
162
|
+
if (input.kind) form.set('kind', input.kind);
|
|
163
|
+
if (input.item) form.set('item_id', input.item.id);
|
|
164
|
+
if (input.metadata) form.set('metadata', JSON.stringify(input.metadata));
|
|
165
|
+
|
|
166
|
+
return readReviewAttachment(
|
|
167
|
+
await requestJson<RemoteReviewAttachmentResponse>(
|
|
168
|
+
options.attachmentUploadPath,
|
|
169
|
+
options,
|
|
170
|
+
{
|
|
171
|
+
method: 'POST',
|
|
172
|
+
body: form,
|
|
173
|
+
}
|
|
174
|
+
)
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
|
|
136
178
|
function appendParam(
|
|
137
179
|
params: URLSearchParams,
|
|
138
180
|
key: string,
|
|
@@ -160,7 +202,11 @@ async function requestJson<T>(
|
|
|
160
202
|
const headers = new Headers(init.headers);
|
|
161
203
|
|
|
162
204
|
headers.set('Accept', 'application/json');
|
|
163
|
-
if (
|
|
205
|
+
if (
|
|
206
|
+
init.body &&
|
|
207
|
+
!(init.body instanceof FormData) &&
|
|
208
|
+
!headers.has('Content-Type')
|
|
209
|
+
) {
|
|
164
210
|
headers.set('Content-Type', 'application/json');
|
|
165
211
|
}
|
|
166
212
|
if (options.token) {
|
|
@@ -185,6 +231,10 @@ function readReviewItem(response: RemoteReviewItemResponse) {
|
|
|
185
231
|
return 'item' in response ? response.item : response;
|
|
186
232
|
}
|
|
187
233
|
|
|
234
|
+
function readReviewAttachment(response: RemoteReviewAttachmentResponse) {
|
|
235
|
+
return 'attachment' in response ? response.attachment : response;
|
|
236
|
+
}
|
|
237
|
+
|
|
188
238
|
function ensureTrailingSlash(value: string) {
|
|
189
239
|
return value.endsWith('/') ? value : `${value}/`;
|
|
190
240
|
}
|
package/docs/architecture.md
CHANGED
|
@@ -17,7 +17,7 @@ React shell
|
|
|
17
17
|
|
|
18
18
|
Core runtime
|
|
19
19
|
-> mounts a shadow DOM overlay
|
|
20
|
-
-> handles
|
|
20
|
+
-> handles area/DOM selection
|
|
21
21
|
-> creates markers and highlights over the target viewport
|
|
22
22
|
-> persists ReviewItem records through the configured adapter
|
|
23
23
|
```
|
|
@@ -33,14 +33,14 @@ createWebReviewKit({
|
|
|
33
33
|
});
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
`ui.panel: false` means the React shell owns the side panel and toolbar. Core still owns target overlays such as
|
|
36
|
+
`ui.panel: false` means the React shell owns the side panel and toolbar. Core still owns target overlays such as area selection boxes, DOM hover outlines, saved item markers, and highlights.
|
|
37
37
|
|
|
38
38
|
When the React shell provides a composer host, core docks DOM/area draft composer UI into the QA panel instead of rendering it as a floating target overlay. Core still owns draft creation, anchor capture, geometry, and adapter submission; React shell only provides the stable panel host.
|
|
39
39
|
|
|
40
40
|
## Core Modules
|
|
41
41
|
|
|
42
42
|
- `web.review.kit.app.ts`: controller lifecycle, state transitions, adapter calls, item creation, restore flow.
|
|
43
|
-
- `web.review.kit.view.ts`:
|
|
43
|
+
- `web.review.kit.view.ts`: thin render orchestrator. Decides which overlay layers to render and docks the draft composer into the shell panel. All DOM building lives in `view/`.
|
|
44
44
|
- `draft.metrics.ts`: pure geometry for draft adjustment (nudge/scale) previews, kept out of the renderer.
|
|
45
45
|
- `dom.anchor.ts`: selector candidate generation, anchor rebinding, text fingerprint matching.
|
|
46
46
|
- `geometry.ts`: target-space and host-space coordinate conversion.
|
|
@@ -50,6 +50,21 @@ When the React shell provides a composer host, core docks DOM/area draft compose
|
|
|
50
50
|
- `scroll.ts`: scroll restore helpers.
|
|
51
51
|
- `location.ts`: public URL and route key helpers.
|
|
52
52
|
|
|
53
|
+
### Core View Modules (`src/core/view/`)
|
|
54
|
+
|
|
55
|
+
The overlay renderer is split by role. Modules never reach into the app directly; they receive `WebReviewKitViewConfig` (options + state getter + actions) or the narrower `DraftLayerContext` defined in `view/types.ts`.
|
|
56
|
+
|
|
57
|
+
- `dom.draft.ts`: DOM draft layer — pin, highlight, composer popover, adjustment (nudge/scale) controls, pin/composer drag.
|
|
58
|
+
- `area.draft.ts`: area draft form, on-page selection overlay, and floating/docked composer popover.
|
|
59
|
+
- `selection.layers.ts`: element-pick hover layer and area drag-select layer.
|
|
60
|
+
- `markers.ts`: stored item marker/highlight layer.
|
|
61
|
+
- `panel.ts`: built-in side panel for standalone core usage (header, toolbar, item list). Disabled under the React shell.
|
|
62
|
+
- `form.widgets.ts`: shared draft form widgets (title input, assignee select, save/cancel actions, drag handle).
|
|
63
|
+
- `draft.capture.ts`: viewport capture button and capture payload builders.
|
|
64
|
+
- `composer.position.ts`: composer sizing/clamping and drag wiring (pure placement math).
|
|
65
|
+
- `draft.text.ts`: metric/adjustment display formatting and the saved-comment adjustment suffix.
|
|
66
|
+
- `icons.ts`: stateless SVG icon and spinner builders.
|
|
67
|
+
|
|
53
68
|
## Coordinate Spaces
|
|
54
69
|
|
|
55
70
|
Core uses two coordinate spaces:
|
|
@@ -103,6 +118,105 @@ The default local adapter is for draft/local review work. Supabase is optional h
|
|
|
103
118
|
|
|
104
119
|
React shell should call the core controller instead of duplicating target overlay logic.
|
|
105
120
|
|
|
121
|
+
### React Shell Runtime Map
|
|
122
|
+
|
|
123
|
+
`review/shell.tsx` is the React shell entrypoint. It creates instance-scoped
|
|
124
|
+
config, refs, and zustand store objects, then delegates runtime wiring and layout
|
|
125
|
+
assembly to smaller modules.
|
|
126
|
+
|
|
127
|
+
```mermaid
|
|
128
|
+
flowchart TD
|
|
129
|
+
Shell["review/shell.tsx"]
|
|
130
|
+
Config["store/shell.config.ts"]
|
|
131
|
+
Store["store/create.review.shell.store.ts"]
|
|
132
|
+
Refs["store/shell.refs.ts"]
|
|
133
|
+
Runtime["hooks/use.review.shell.runtime.ts"]
|
|
134
|
+
Providers["review/shell.providers.tsx"]
|
|
135
|
+
FrameContainer["review/shell.frame.container.tsx"]
|
|
136
|
+
Frame["review/shell.frame.tsx"]
|
|
137
|
+
Containers["feature *.container.tsx"]
|
|
138
|
+
Views["presentational UI components"]
|
|
139
|
+
|
|
140
|
+
Shell --> Config
|
|
141
|
+
Shell --> Store
|
|
142
|
+
Shell --> Refs
|
|
143
|
+
Shell --> Runtime
|
|
144
|
+
Runtime --> Providers
|
|
145
|
+
Providers --> FrameContainer
|
|
146
|
+
FrameContainer --> Frame
|
|
147
|
+
Frame --> Containers
|
|
148
|
+
Containers --> Views
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
The store is created once per mounted `ReviewShell` instance. There is no
|
|
152
|
+
module-level shell store, so a host app using zustand does not share this state.
|
|
153
|
+
|
|
154
|
+
### State Ownership
|
|
155
|
+
|
|
156
|
+
| Layer | Files | Owns |
|
|
157
|
+
|---|---|---|
|
|
158
|
+
| Shell config | `store/shell.config.ts` | Normalized props and mostly static shell options |
|
|
159
|
+
| Shell refs | `store/shell.refs.ts` | iframe, frame scroll, controller, and one-shot pending refs |
|
|
160
|
+
| Zustand store | `store/*.slice.ts` | Target, QA, side panel, and local UI state |
|
|
161
|
+
| Runtime hooks | `hooks/use.review.shell.*`, feature hooks | Effects, adapter refresh, core controller wiring, and action composition |
|
|
162
|
+
| Runtime contexts | `review/shell.providers.tsx`, `*.context.tsx` | Non-store controllers consumed by feature containers |
|
|
163
|
+
| Containers | `*.container.tsx` | Read store/context and bind actions to views |
|
|
164
|
+
| Presentational views | non-container `.tsx` components | Render UI from explicit props |
|
|
165
|
+
|
|
166
|
+
### Container Pattern
|
|
167
|
+
|
|
168
|
+
Feature UI should not receive long prop chains from `ReviewShell`. Containers
|
|
169
|
+
read the closest state source directly, then pass only render-ready props to
|
|
170
|
+
presentational components.
|
|
171
|
+
|
|
172
|
+
```mermaid
|
|
173
|
+
flowchart LR
|
|
174
|
+
Store["zustand store"]
|
|
175
|
+
Config["config/ref contexts"]
|
|
176
|
+
RuntimeContext["runtime contexts"]
|
|
177
|
+
Container["feature container"]
|
|
178
|
+
View["presentational view"]
|
|
179
|
+
|
|
180
|
+
Store --> Container
|
|
181
|
+
Config --> Container
|
|
182
|
+
RuntimeContext --> Container
|
|
183
|
+
Container --> View
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
When adding shell behavior, prefer this flow:
|
|
187
|
+
|
|
188
|
+
1. Put persistent UI state in the matching zustand slice.
|
|
189
|
+
2. Put instance config in `shell.config.ts`.
|
|
190
|
+
3. Put DOM/controller refs in `shell.refs.ts`.
|
|
191
|
+
4. Put side effects and adapter/core orchestration in a focused hook.
|
|
192
|
+
5. Expose cross-feature commands through `ReviewShellActions` only when multiple
|
|
193
|
+
containers need the same command.
|
|
194
|
+
|
|
195
|
+
### Shell Hook Decomposition
|
|
196
|
+
|
|
197
|
+
`hooks/use.review.shell.runtime.ts` is the runtime assembler. It composes smaller
|
|
198
|
+
hooks and returns provider values; it should not become a render component.
|
|
199
|
+
|
|
200
|
+
- `hooks/use.review.shell.state.ts`: bridge from zustand/config/refs into runtime hook inputs.
|
|
201
|
+
- `hooks/use.review.shell.data.ts`: item list, filters, counts, target URL, and derived view data.
|
|
202
|
+
- `hooks/use.review.shell.refresh.ts`: adapter refresh for current route and sitemap counts.
|
|
203
|
+
- `hooks/use.review.shell.effects.ts`: shell-level effects such as pending restore, frame recentering, and Figma pointer lock.
|
|
204
|
+
- `hooks/use.review.shell.runtime.actions.ts`: local command builders for transient UI, mode, panels, and iframe load.
|
|
205
|
+
- `hooks/use.review.shell.actions.value.ts`: final `ReviewShellActions` context value.
|
|
206
|
+
- `hooks/use.review.controller.ts`: core runtime wiring (init/reload/restore/mode).
|
|
207
|
+
- `hooks/use.review.item.actions.ts`: QA item mutations and prompt/link copy actions.
|
|
208
|
+
- `hooks/use.review.side.panel.ts`: side panel selection, availability fallback, and browser-local persistence.
|
|
209
|
+
- `hooks/use.review.target.navigation.ts`: address parsing, page/source switching, selected-item clearing, and shell URL sync.
|
|
210
|
+
- `hooks/use.review.source.inspector.ts`: source inspector state and target-iframe shortcut binding.
|
|
211
|
+
- `hooks/use.review.section.outline.ts`: Source Tree outline extraction, filter/collapse state, refresh scheduling, and entry actions.
|
|
212
|
+
- `hooks/use.review.command.key.ts`: hide-all-overlays-while-command-held tracking across host and iframe.
|
|
213
|
+
|
|
214
|
+
### Comment Policy
|
|
215
|
+
|
|
216
|
+
Prefer comments only at module boundaries or non-obvious runtime contracts. Avoid
|
|
217
|
+
file-wide restatements of import names, prop-by-prop explanations, or comments
|
|
218
|
+
that duplicate what a function name already says.
|
|
219
|
+
|
|
106
220
|
## Figma Overlay Direction
|
|
107
221
|
|
|
108
222
|
Figma overlay work should stay outside core unless it needs target runtime primitives.
|
package/docs/figma-overlay.md
CHANGED
|
@@ -23,6 +23,42 @@ the same-origin image store request as a fallback.
|
|
|
23
23
|
|
|
24
24
|
Treat this as a review/debug convenience. Do not expose `VITE_FIGMA_TOKEN`.
|
|
25
25
|
|
|
26
|
+
### Security note: browser-stored token
|
|
27
|
+
|
|
28
|
+
The Settings token lives in plain `localStorage`. A Figma personal access token
|
|
29
|
+
grants read access to every file the account can see, so any XSS on the host
|
|
30
|
+
origin can read this key and exfiltrate it. Reduce the blast radius:
|
|
31
|
+
|
|
32
|
+
- Prefer the server-side `FIGMA_TOKEN` env path. Only fall back to the Settings
|
|
33
|
+
token when a dev/reviewer genuinely cannot set server env.
|
|
34
|
+
- When you must use the Settings token, use a short-lived or narrowly scoped
|
|
35
|
+
token and clear it from Settings when you are done.
|
|
36
|
+
- Never commit or share the token, and never expose it as `VITE_FIGMA_TOKEN`
|
|
37
|
+
(that ships it to every browser bundle).
|
|
38
|
+
|
|
39
|
+
The token is only sent to the same-origin image store endpoint via the
|
|
40
|
+
`X-Figma-Token` header; it is not sent to `api.figma.com` from the browser.
|
|
41
|
+
|
|
42
|
+
## Dev Server Image Store Hardening
|
|
43
|
+
|
|
44
|
+
The `reviewFigmaImageStore()` Vite plugin runs only under `vite dev` (`apply:
|
|
45
|
+
'serve'`); it is not part of `vite build` output, so production/Vercel deploys
|
|
46
|
+
are unaffected. Because the dev endpoint is unauthenticated, its middleware
|
|
47
|
+
applies minimal request checks:
|
|
48
|
+
|
|
49
|
+
- **Cross-origin block**: browser requests whose `Origin` does not match the
|
|
50
|
+
request `Host` (and is not loopback) are rejected with `403`. Requests without
|
|
51
|
+
an `Origin` header (curl, scripts) and same-origin requests — including LAN IP
|
|
52
|
+
access for mobile testing — are allowed.
|
|
53
|
+
- **JSON content type**: request bodies must be `application/json`. This blocks
|
|
54
|
+
`text/plain` "simple" cross-site POSTs that would otherwise skip a CORS
|
|
55
|
+
preflight. Rejected with `415`.
|
|
56
|
+
- **Body size limit**: JSON bodies are capped (default 25 MB, configurable via
|
|
57
|
+
the `maxRequestBytes` plugin option). Oversized bodies are rejected with `413`.
|
|
58
|
+
|
|
59
|
+
These guards protect the developer's local `FIGMA_TOKEN` and `.df-review`
|
|
60
|
+
working files from CSRF-style requests made by other pages open in the browser.
|
|
61
|
+
|
|
26
62
|
## Availability
|
|
27
63
|
|
|
28
64
|
The shell currently enables the Figma overlay on viewport presets whose `kind` is:
|
|
@@ -46,6 +82,18 @@ Expected behavior:
|
|
|
46
82
|
|
|
47
83
|
The review shell uses those selectors only to detect whether the overlay is active.
|
|
48
84
|
|
|
85
|
+
When the package-managed Figma image store is configured, the shell renders image
|
|
86
|
+
overlays into the iframe instead. Those overlays use:
|
|
87
|
+
|
|
88
|
+
- `#df-review-figma-image-target-root`
|
|
89
|
+
- `.df-review-figma-image-target-overlay`
|
|
90
|
+
|
|
91
|
+
The image overlay hit layer is interactive only when the image can be dragged.
|
|
92
|
+
During element review mode or `Option` source selection, the shell temporarily
|
|
93
|
+
locks both host helper layers and package image overlays with
|
|
94
|
+
`pointer-events: none` so target selection is not blocked. Releasing `Option`
|
|
95
|
+
restores the image overlay hit area.
|
|
96
|
+
|
|
49
97
|
## Troubleshooting
|
|
50
98
|
|
|
51
99
|
If the button does nothing:
|
|
@@ -54,6 +102,9 @@ If the button does nothing:
|
|
|
54
102
|
- Confirm the host helper listens for `KeyF`.
|
|
55
103
|
- Confirm the helper renders `.helper-figma-root` or `.helper-figma-loading-backdrop`.
|
|
56
104
|
- Confirm the current viewport preset is `mobile` or `wide`.
|
|
105
|
+
- If `Option` source selection cannot pick an element under a Figma image
|
|
106
|
+
overlay, confirm the overlay root uses the package selectors above or the host
|
|
107
|
+
helper selectors listed in Host Requirements.
|
|
57
108
|
|
|
58
109
|
If the overlay needs a private shared Figma integration, move that work to a
|
|
59
110
|
backend/admin service and expose only browser-safe state to the host page.
|
package/docs/grid-overlay.md
CHANGED
|
@@ -21,11 +21,16 @@ Expected behavior:
|
|
|
21
21
|
- `.helper.onShow`
|
|
22
22
|
|
|
23
23
|
The review shell uses those signals to keep the toolbar button state in sync.
|
|
24
|
+
It also injects a small stacking-order safeguard so recognized grid/helper
|
|
25
|
+
layers render above host Figma helpers and package-managed Figma image overlays.
|
|
24
26
|
|
|
25
27
|
## Notes
|
|
26
28
|
|
|
27
29
|
- The package does not prescribe the grid design.
|
|
28
30
|
- The grid overlay is not persisted as QA data.
|
|
31
|
+
- Recognized grid roots are `.helper.onShow`, `body.is-help .helper`,
|
|
32
|
+
`#df-review-grid-overlay`, `.df-review-grid-overlay`, and
|
|
33
|
+
`[data-df-review-grid-overlay]`.
|
|
29
34
|
- Use project-specific CSS/helper code in the host page when the grid differs by brand or design system.
|
|
30
35
|
|
|
31
36
|
## Troubleshooting
|
package/docs/installation.md
CHANGED
|
@@ -8,7 +8,7 @@ For the QA adapter and Figma image store split, see [Adapter boundaries](adapter
|
|
|
8
8
|
## Package Install
|
|
9
9
|
|
|
10
10
|
```bash
|
|
11
|
-
pnpm add @designfever/web-review-kit react react-dom
|
|
11
|
+
pnpm add @designfever/web-review-kit react react-dom zustand
|
|
12
12
|
```
|
|
13
13
|
|
|
14
14
|
Supabase is optional. Install it only in host projects that use the Supabase adapter.
|
|
@@ -17,7 +17,7 @@ Supabase is optional. Install it only in host projects that use the Supabase ada
|
|
|
17
17
|
pnpm add @supabase/supabase-js
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
## Environment
|
|
20
|
+
## Environment Reference
|
|
21
21
|
|
|
22
22
|
Copy the repository [.env.sample](../.env.sample) into the host project as `.env.local`.
|
|
23
23
|
|
|
@@ -109,6 +109,29 @@ mountReviewShell({
|
|
|
109
109
|
|
|
110
110
|
If omitted, the default label is `Responsive CSS px adjustments`. This option only changes the label before the generated `x`, `y`, and `scale` values.
|
|
111
111
|
|
|
112
|
+
## Prompt Handoff
|
|
113
|
+
|
|
114
|
+
Use `initialPrompt` for the global review handoff modal, and `qaPrompt` for the custom instruction prepended to every copied QA item prompt.
|
|
115
|
+
|
|
116
|
+
```tsx
|
|
117
|
+
mountReviewShell({
|
|
118
|
+
projectId: REVIEW_PROJECT_ID,
|
|
119
|
+
pages,
|
|
120
|
+
adapters,
|
|
121
|
+
initialPrompt: [
|
|
122
|
+
'You are fixing QA issues in this project.',
|
|
123
|
+
'Read AGENTS.md and the project README before editing.',
|
|
124
|
+
].join('\n'),
|
|
125
|
+
qaPrompt: [
|
|
126
|
+
'Follow this project coding style before touching the selected QA item.',
|
|
127
|
+
'Keep the fix limited to the target route and viewport unless the bug is shared.',
|
|
128
|
+
].join('\n'),
|
|
129
|
+
reviewPathPrefix: REVIEW_PATH_PREFIX,
|
|
130
|
+
});
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
If `qaPrompt` is omitted, copied QA prompts keep the package default header.
|
|
134
|
+
|
|
112
135
|
## Supabase Adapter
|
|
113
136
|
|
|
114
137
|
Host projects that choose Supabase create the client themselves and pass it into the package adapter.
|
|
@@ -236,9 +259,9 @@ export default defineConfig({
|
|
|
236
259
|
});
|
|
237
260
|
```
|
|
238
261
|
|
|
239
|
-
Captured DOM nodes will include `data-wrk-source-file`, `data-wrk-source-line`, and `data-wrk-source-column`.
|
|
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.
|
|
240
263
|
|
|
241
|
-
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. 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.
|
|
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.
|
|
242
265
|
|
|
243
266
|
Source opening reads these optional host env values from `.env.local`:
|
|
244
267
|
|
|
@@ -268,11 +291,11 @@ mountReviewShell({
|
|
|
268
291
|
});
|
|
269
292
|
```
|
|
270
293
|
|
|
271
|
-
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. The `data-font` overlay still belongs to the target project markup and is not required for source opening.
|
|
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.
|
|
272
295
|
|
|
273
296
|
Use this only in dev/review builds. Source paths are written into the browser DOM and can be persisted with QA items.
|
|
274
297
|
|
|
275
|
-
Source Tree filter/options, side panel state,
|
|
298
|
+
Source Tree filter/options, side panel state, QA status filter, and tooltip visibility are browser-local UI preferences. They are stored in localStorage and are not sent through the adapter.
|
|
276
299
|
|
|
277
300
|
In React shell mode, DOM/area draft composers dock into the QA panel when the shell provides a composer host. This keeps mobile Safari keyboard/viewport resize from moving a floating composer layer over the target frame.
|
|
278
301
|
|
|
@@ -287,6 +310,20 @@ The sample explains the main interfaces:
|
|
|
287
310
|
- `WebReviewKitAdapter`: core CRUD contract.
|
|
288
311
|
- `ReviewShellAdapter`: React shell wiring for source labels, write modes, status updates, and delete actions.
|
|
289
312
|
|
|
313
|
+
### External Links
|
|
314
|
+
|
|
315
|
+
`ReviewItem.externalLinks` can carry multiple external issue/sheet links. Each link should include `label` and `url`, with optional `title` and `icon`.
|
|
316
|
+
|
|
317
|
+
If `externalLinks` is omitted, the shell still falls back to `externalIssueUrl` and renders it as a single `Remote` action. Use `externalLinks` when a host needs separate sheet, issue, preview, or admin links for the same QA item.
|
|
318
|
+
|
|
319
|
+
### Attachments and Capture
|
|
320
|
+
|
|
321
|
+
`ReviewItem.attachments` stores uploaded QA attachment metadata. Use `ReviewShellAdapter.uploadAttachment` to upload pasted files or iframe captures before adding the returned `ReviewAttachment` to an item.
|
|
322
|
+
|
|
323
|
+
The upload method receives a browser `File | Blob` plus optional `kind`, `name`, `mime`, `item`, and `metadata`, then returns `url`, `name`, `mime`, `size`, and optional storage metadata. If `uploadAttachment` is omitted and a draft contains attachments, submit fails with adapter feedback instead of silently dropping files.
|
|
324
|
+
|
|
325
|
+
Iframe captures are emitted as WebP when the DOM renderer succeeds and fall back to SVG only when raster capture is unavailable. Capture is based on same-origin iframe DOM access; it works on `localhost` and same-origin review hosts and is not HTTPS-only.
|
|
326
|
+
|
|
290
327
|
Private keys, admin credentials, canonical numbering, and permission checks should stay in your backend, not in browser code.
|
|
291
328
|
|
|
292
329
|
## Environment
|
|
@@ -338,7 +375,7 @@ Open `http://127.0.0.1:5177/review/`.
|
|
|
338
375
|
|
|
339
376
|
Fixture pages:
|
|
340
377
|
|
|
341
|
-
- `/`:
|
|
378
|
+
- `/`: area and DOM marker creation
|
|
342
379
|
- `/components/`: controls and panel spacing
|
|
343
380
|
- `/long-form/`: scroll and anchor restore
|
|
344
381
|
|
|
@@ -348,6 +385,7 @@ Package repo:
|
|
|
348
385
|
|
|
349
386
|
```bash
|
|
350
387
|
pnpm typecheck
|
|
388
|
+
pnpm test
|
|
351
389
|
pnpm build
|
|
352
390
|
pnpm typecheck:dev
|
|
353
391
|
pnpm build:dev
|
|
@@ -363,6 +401,6 @@ pnpm build
|
|
|
363
401
|
Manual smoke:
|
|
364
402
|
|
|
365
403
|
1. Open `/review`.
|
|
366
|
-
2. Create local
|
|
404
|
+
2. Create local DOM marker and area marker.
|
|
367
405
|
3. If Supabase is enabled, submit a local item to remote.
|
|
368
406
|
4. Confirm local draft removal, remote list display, status update, delete, and deep-link restore.
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# 릴리즈 노트: 0.8.0
|
|
2
|
+
|
|
3
|
+
0.7.3 이후 QA 작성, source inspection, iframe capture, dev review fixture를 함께 보강한 minor release.
|
|
4
|
+
|
|
5
|
+
비교 기준: `0.7.3`
|
|
6
|
+
검토 기준: `main` release candidate
|
|
7
|
+
|
|
8
|
+
## 주요 변경
|
|
9
|
+
|
|
10
|
+
- QA item에 여러 외부 링크를 표시할 수 있는 `externalLinks` 필드를 추가했다.
|
|
11
|
+
- QA DOM/area composer에서 paste attachment와 iframe viewport capture를 같은 attachment queue로 다룬다.
|
|
12
|
+
- `ReviewShellAdapter.uploadAttachment`와 `ReviewItem.attachments` contract를 추가했다.
|
|
13
|
+
- point-only Note QA를 제거하고 `ReviewItem.kind`를 `dom | area`로 정리했다.
|
|
14
|
+
- Vitest adapter contract suite를 추가해 local/Supabase adapter의 CRUD, 필터, legacy row 처리를 검증한다.
|
|
15
|
+
- iframe viewport capture는 WebP를 우선 생성하고, raster capture가 실패하면 SVG attachment로 fallback한다.
|
|
16
|
+
- source locator가 TSX/JSX AST를 읽어 `data-wrk-source-component`를 주입한다.
|
|
17
|
+
- Source Tree가 function component의 parent JSX call site를 `used in`으로 표시하고 바로 열 수 있다.
|
|
18
|
+
- Option source inspector의 후보 매칭을 DOM path, component stack, QA target, text, 반복 index 기준으로 개선했다.
|
|
19
|
+
- Source Tree가 component hierarchy를 더 잘 보여주도록 root 수집과 기본 표시 depth를 보정했다.
|
|
20
|
+
- dev review fixture를 page/section/card/component 단위로 나눠 Source Tree와 후보 매칭을 검증하기 쉽게 만들었다.
|
|
21
|
+
- Option source selection 중 Figma image overlay hit layer가 target hit-test를 가로채지 않도록 pointer lock을 분리했다.
|
|
22
|
+
- icon-only control에 hover/focus tooltip을 추가하고 Settings에서 표시 여부를 끌 수 있게 했다.
|
|
23
|
+
- keyboard shortcut matching이 한글 입력 상태의 물리 키를 함께 인식한다.
|
|
24
|
+
- DF logo help modal에 shortcut list를 추가하고 prompt/help modal shell을 공통 component로 정리했다.
|
|
25
|
+
|
|
26
|
+
## 변경
|
|
27
|
+
|
|
28
|
+
### QA External Links
|
|
29
|
+
|
|
30
|
+
`ReviewItem.externalLinks`를 추가해 한 QA item에서 여러 remote issue, sheet, admin URL을 표시할 수 있게 했다.
|
|
31
|
+
|
|
32
|
+
- 각 link는 `label`, `url`, optional `title`, optional `icon`을 가진다.
|
|
33
|
+
- QA card는 `externalLinks`를 우선 렌더링한다.
|
|
34
|
+
- 기존 `externalIssueUrl`만 있는 item은 `Remote` link로 fallback 렌더링한다.
|
|
35
|
+
- remote submit 후 local draft의 외부 링크 필드는 중복되지 않도록 정리한다.
|
|
36
|
+
|
|
37
|
+
### Attachments and Capture
|
|
38
|
+
|
|
39
|
+
QA draft에 attachment queue를 추가했다.
|
|
40
|
+
|
|
41
|
+
- image paste는 draft attachment로 들어가고, 제출 전에 adapter `uploadAttachment`로 업로드된다.
|
|
42
|
+
- DOM/area draft는 attachment만 있어도 제출할 수 있다.
|
|
43
|
+
- `ReviewAttachment`는 `url`, `name`, `mime`, `size`, optional `kind`, `metadata`를 저장한다.
|
|
44
|
+
- `ReviewAttachmentUploadInput`은 browser `File | Blob`과 draft item context를 함께 넘긴다.
|
|
45
|
+
- iframe capture는 현재 viewport, marker, selection을 합성한 attachment를 만든다.
|
|
46
|
+
- capture metadata에는 route, viewport, scroll, marker, selection, timestamp, renderer 정보가 들어간다.
|
|
47
|
+
- capture는 same-origin iframe DOM 접근이 가능한 환경에서 동작한다. HTTPS 전용 기능은 아니다.
|
|
48
|
+
|
|
49
|
+
### Adapter Contract and Note Removal
|
|
50
|
+
|
|
51
|
+
QA item kind를 DOM/area 중심으로 정리했다.
|
|
52
|
+
|
|
53
|
+
- `ReviewItemKind`는 `dom | area`만 허용한다.
|
|
54
|
+
- `ReviewMode`는 `idle | element | area`만 남긴다.
|
|
55
|
+
- point-only Note QA toolbar, shortcut, draft layer, popover style을 제거했다.
|
|
56
|
+
- 기존 DOM QA는 `kind: 'dom'`으로 저장된다.
|
|
57
|
+
- local/Supabase adapter는 legacy `note` row를 QA list에 노출하지 않는다.
|
|
58
|
+
- legacy `capture` row는 local adapter에서 `area`로 정규화한다.
|
|
59
|
+
|
|
60
|
+
Adapter 회귀를 줄이기 위해 Vitest를 추가했다.
|
|
61
|
+
|
|
62
|
+
- `pnpm test`는 `vitest run`을 실행한다.
|
|
63
|
+
- `pnpm test:watch`는 watch 모드로 Vitest를 실행한다.
|
|
64
|
+
- `src/adapters/adapter.contract.test.ts`에서 local adapter와 Supabase adapter mock을 같은 contract로 검증한다.
|
|
65
|
+
- contract는 `create/list/get/update/remove`, route/status filter, attachments, externalLinks, assignee/status 보존, legacy `note` 필터링을 확인한다.
|
|
66
|
+
|
|
67
|
+
### Capture Format
|
|
68
|
+
|
|
69
|
+
capture output은 용량을 줄이기 위해 WebP를 우선 사용한다.
|
|
70
|
+
|
|
71
|
+
- `html2canvas`로 iframe DOM을 rasterize한 뒤 `image/webp`로 인코딩한다.
|
|
72
|
+
- 실패하면 기존 SVG clone을 canvas에 그려 WebP로 다시 시도한다.
|
|
73
|
+
- 두 raster path가 모두 실패할 때만 `image/svg+xml` attachment로 저장한다.
|
|
74
|
+
- WebP metadata에는 `captureRenderer`와 `captureScale`이 기록된다.
|
|
75
|
+
|
|
76
|
+
### Source Locator and Source Tree
|
|
77
|
+
|
|
78
|
+
source opening의 실제 후보 품질을 높였다.
|
|
79
|
+
|
|
80
|
+
- Vite `reviewSourceLocator()`가 TypeScript가 있는 host에서 TSX/JSX를 파싱한다.
|
|
81
|
+
- intrinsic JSX node에 component 이름을 `data-wrk-source-component`로 주입한다.
|
|
82
|
+
- function component render path에는 parent JSX call site를 `data-wrk-source-parent-*` hint로 전달한다.
|
|
83
|
+
- Source Tree는 nested source roots를 flat root로 중복 수집하지 않고 parent/child hierarchy로 보여준다.
|
|
84
|
+
- Source Tree row는 parent usage가 있으면 `used in` meta와 usage source open action을 보여준다.
|
|
85
|
+
- 기본 표시 depth를 늘려 dev fixture처럼 page/section/card로 나뉜 구조가 바로 보인다.
|
|
86
|
+
- `includePlacer: false`일 때 Placer 계열 primitive는 Source Tree와 candidate list에서 숨긴다.
|
|
87
|
+
|
|
88
|
+
### Source Candidate Matching
|
|
89
|
+
|
|
90
|
+
Option source inspector 후보 정렬을 보강했다.
|
|
91
|
+
|
|
92
|
+
- 후보 dedupe 기준을 file-only에서 source identity 기준으로 바꿨다.
|
|
93
|
+
- target element, QA data attribute, component stack, text match, section hint, line/column을 함께 점수화한다.
|
|
94
|
+
- 같은 component가 반복되는 카드/리스트는 `#1/3`, `#2/3`처럼 반복 index를 표시한다.
|
|
95
|
+
- candidate popover에는 `23:9 · component · target · qa · text · #1/3`처럼 선택 이유를 노출한다.
|
|
96
|
+
- file별 후보는 최대 3개, 전체 후보는 최대 8개까지 보여준다.
|
|
97
|
+
|
|
98
|
+
### Figma Overlay Interaction
|
|
99
|
+
|
|
100
|
+
Option source selection과 Figma overlay의 hit-test 충돌을 막았다.
|
|
101
|
+
|
|
102
|
+
- 기존 element review mode의 Figma pointer lock은 유지한다.
|
|
103
|
+
- Option source selection용 pointer lock을 별도 style id로 분리했다.
|
|
104
|
+
- lock 대상에 host helper selector와 package Figma image overlay selector를 함께 포함했다.
|
|
105
|
+
- Option 키를 누른 동안 overlay image가 source target hit-test를 가로채지 않고, 키를 떼면 기존 overlay 조작이 복구된다.
|
|
106
|
+
|
|
107
|
+
### Icon Tooltips
|
|
108
|
+
|
|
109
|
+
아이콘만 있는 주요 control에 커스텀 tooltip을 추가했다.
|
|
110
|
+
|
|
111
|
+
- topbar action, overlay toggle, side rail, QA card action, Source Tree action, Figma image action에 기능명을 표시한다.
|
|
112
|
+
- tooltip은 `hover`와 `focus-visible`에서 표시되어 마우스와 키보드 탐색 모두에서 확인할 수 있다.
|
|
113
|
+
- Settings의 Tooltips 옵션으로 custom tooltip과 해당 control의 native `title` tooltip을 함께 끌 수 있다.
|
|
114
|
+
- tooltip 표시 여부는 `df-review-tooltips-enabled` localStorage key에 browser-local UI preference로 저장된다.
|
|
115
|
+
|
|
116
|
+
### Shortcuts and Help
|
|
117
|
+
|
|
118
|
+
단축키 접근성을 정리했다.
|
|
119
|
+
|
|
120
|
+
- `G/F/R/E/A` shell shortcut은 한글 입력 상태에서도 `ㅎ/ㄹ/ㄱ/ㄷ/ㅁ`로 동작한다.
|
|
121
|
+
- `Shift+Q`와 Figma dev overlay `Shift+F`도 같은 hotkey matcher를 사용한다.
|
|
122
|
+
- side rail 순서를 Figma Images, QA, Component List로 정리하고 `Shift+1/2/3` panel shortcut을 추가했다.
|
|
123
|
+
- DF logo로 여는 help modal에 shortcut list를 추가했다.
|
|
124
|
+
- 기존 설명글은 제거하고 header에 package version만 표시한다.
|
|
125
|
+
- help/prompt modal은 max-height를 제한하고 header 아래 body만 내부 스크롤되게 정리했다.
|
|
126
|
+
- help/prompt 계열 modal은 공통 `ReviewModal` component가 wrapper를 담당하고 contents는 children으로 받는다.
|
|
127
|
+
|
|
128
|
+
### Dev Review Fixture
|
|
129
|
+
|
|
130
|
+
`pnpm dev:review` fixture를 release 검증용으로 더 현실적으로 나눴다.
|
|
131
|
+
|
|
132
|
+
- page routing, nav, home, components, long-form fixture를 분리했다.
|
|
133
|
+
- home fixture는 hero/action list/smoke grid/card 계층을 가진다.
|
|
134
|
+
- components fixture는 controls, metrics panel, state preview grid로 나뉜다.
|
|
135
|
+
- long-form fixture는 scroll, anchor restore, Source Tree depth 확인에 사용한다.
|
|
136
|
+
|
|
137
|
+
## Host 영향
|
|
138
|
+
|
|
139
|
+
- attachment paste/capture를 저장하려면 host `ReviewShellAdapter`에 `uploadAttachment`를 구현해야 한다.
|
|
140
|
+
- `uploadAttachment`가 없는 adapter에서 attachment가 포함된 draft를 제출하면 저장하지 않고 error feedback을 표시한다.
|
|
141
|
+
- `note` kind를 저장하거나 반환하던 host adapter는 `dom` 또는 `area`로 매핑해야 한다.
|
|
142
|
+
- capture는 browser package dependency로 `html2canvas`를 사용한다.
|
|
143
|
+
- source locator component/parent usage hint는 TypeScript가 host dependency로 있을 때만 동작한다. 없으면 기존 file/line/column hint만 사용한다.
|
|
144
|
+
- source hints는 DOM에 source path와 component 이름을 쓰므로 dev/review build에서만 켜야 한다.
|
|
145
|
+
- 기존 `externalIssueUrl`만 쓰는 host는 계속 동작한다. 여러 링크가 필요할 때만 `externalLinks`를 추가하면 된다.
|
|
146
|
+
- Figma image overlay를 쓰는 host는 Option source selection 중 overlay drag가 잠깐 비활성화된다.
|
|
147
|
+
|
|
148
|
+
## 문서
|
|
149
|
+
|
|
150
|
+
- README 최신 release note 링크를 0.8.0으로 갱신했다.
|
|
151
|
+
- docs index에 0.8.0 release note와 0.7.3 patch note를 정리했다.
|
|
152
|
+
- installation guide에 external links, attachment upload, WebP capture contract를 정리했다.
|
|
153
|
+
- adapter boundary 문서에 QA attachment, item kind, contract test, Figma image store 책임 분리를 반영했다.
|
|
154
|
+
- Vitest adapter contract 문서를 추가했다.
|
|
155
|
+
- Figma overlay 문서에 package image overlay selector와 source selection pointer lock behavior를 추가했다.
|
|
156
|
+
|
|
157
|
+
## 검증
|
|
158
|
+
|
|
159
|
+
아래 명령을 확인했다.
|
|
160
|
+
|
|
161
|
+
- `pnpm typecheck`
|
|
162
|
+
- `pnpm test`
|
|
163
|
+
- `pnpm typecheck:dev`
|
|
164
|
+
- `pnpm build`
|
|
165
|
+
- `pnpm build:dev`
|
|
166
|
+
|
|
167
|
+
수동 확인:
|
|
168
|
+
|
|
169
|
+
- iframe fake Figma image overlay에서 Option down/up hit-test가 overlay -> target -> overlay 순서로 바뀌는지 확인했다.
|
|
170
|
+
- source candidate 반복 카드가 `#1/3`, `#2/3`, `#3/3`으로 구분되는지 확인했다.
|
|
171
|
+
- Source Tree가 `/`, `/components/`, `/long-form/` fixture에서 depth 있는 hierarchy와 `used in` parent usage를 보여주는지 확인했다.
|
|
172
|
+
- viewport capture가 WebP attachment와 renderer metadata를 생성하는지 확인했다.
|
|
173
|
+
- icon-only control hover 시 tooltip이 표시되고 Settings에서 끄면 사라지는지 확인했다.
|
|
174
|
+
- 한글 키 synthetic event로 shell shortcut이 처리되는지 확인했다.
|
|
175
|
+
- DF logo help modal에서 shortcut list 13개와 modal layout을 확인했다.
|