@designfever/web-review-kit 0.4.1 → 0.6.0
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 +20 -4
- package/dist/{chunk-6L2KJ7XL.js → chunk-IN36JHEU.js} +309 -59
- package/dist/chunk-IN36JHEU.js.map +1 -0
- package/dist/index.cjs +306 -58
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/react-shell.cjs +3329 -907
- package/dist/react-shell.cjs.map +1 -1
- package/dist/react-shell.d.cts +19 -1
- package/dist/react-shell.d.ts +19 -1
- package/dist/react-shell.js +2771 -595
- package/dist/react-shell.js.map +1 -1
- package/dist/{types-D_qYtwTs.d.cts → types-DFHHVRBc.d.cts} +2 -0
- package/dist/{types-D_qYtwTs.d.ts → types-DFHHVRBc.d.ts} +2 -0
- package/dist/vite.cjs +50 -0
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.d.cts +17 -1
- package/dist/vite.d.ts +17 -1
- package/dist/vite.js +49 -0
- package/dist/vite.js.map +1 -1
- package/docs/README.md +2 -0
- package/docs/architecture.md +4 -0
- package/docs/installation.md +21 -3
- package/docs/release-notes-0.5.0.md +134 -0
- package/docs/release-notes-0.6.0.md +108 -0
- package/package.json +1 -1
- package/dist/chunk-6L2KJ7XL.js.map +0 -1
package/README.md
CHANGED
|
@@ -26,6 +26,7 @@ This package does not own internal operator tools, private admin keys, or produc
|
|
|
26
26
|
- [Architecture and runtime logic](docs/architecture.md): core runtime, React shell, coordinate, anchor, and extension boundaries.
|
|
27
27
|
- [Figma overlay](docs/figma-overlay.md): how the shell toggles a host Figma overlay.
|
|
28
28
|
- [Grid overlay](docs/grid-overlay.md): how the shell toggles a host grid/helper overlay.
|
|
29
|
+
- [Release notes 0.6.0](docs/release-notes-0.6.0.md): latest shell/source tree changes and validation notes.
|
|
29
30
|
|
|
30
31
|
## Quick Start
|
|
31
32
|
|
|
@@ -92,12 +93,15 @@ Browser env must use a Supabase `anon` key only. Do not put `service_role` or Op
|
|
|
92
93
|
```ts
|
|
93
94
|
import { createWebReviewKit, localAdapter } from '@designfever/web-review-kit';
|
|
94
95
|
import { mountReviewShell } from '@designfever/web-review-kit/react-shell';
|
|
95
|
-
import {
|
|
96
|
+
import {
|
|
97
|
+
reviewDataLocator,
|
|
98
|
+
reviewSourceLocator,
|
|
99
|
+
} from '@designfever/web-review-kit/vite';
|
|
96
100
|
```
|
|
97
101
|
|
|
98
102
|
- `@designfever/web-review-kit`: core API, adapters, shared types.
|
|
99
103
|
- `@designfever/web-review-kit/react-shell`: review shell UI, presence adapters, page glob helper.
|
|
100
|
-
- `@designfever/web-review-kit/vite`: dev-only
|
|
104
|
+
- `@designfever/web-review-kit/vite`: dev-only source/data locators for review hints.
|
|
101
105
|
- `src/*` is not a public import path.
|
|
102
106
|
|
|
103
107
|
## Optional Source Locator
|
|
@@ -106,7 +110,10 @@ For local QA, add the Vite plugin to inject source hints into rendered DOM nodes
|
|
|
106
110
|
|
|
107
111
|
```ts
|
|
108
112
|
import { defineConfig } from 'vite';
|
|
109
|
-
import {
|
|
113
|
+
import {
|
|
114
|
+
reviewDataLocator,
|
|
115
|
+
reviewSourceLocator,
|
|
116
|
+
} from '@designfever/web-review-kit/vite';
|
|
110
117
|
|
|
111
118
|
export default defineConfig({
|
|
112
119
|
plugins: [
|
|
@@ -115,11 +122,16 @@ export default defineConfig({
|
|
|
115
122
|
include: ['src'],
|
|
116
123
|
filePath: 'absolute',
|
|
117
124
|
}),
|
|
125
|
+
reviewDataLocator({
|
|
126
|
+
enabled: true,
|
|
127
|
+
include: ['src/data'],
|
|
128
|
+
filePath: 'absolute',
|
|
129
|
+
}),
|
|
118
130
|
],
|
|
119
131
|
});
|
|
120
132
|
```
|
|
121
133
|
|
|
122
|
-
When source hints are available, hold `Option` over the review target to inspect source candidates from the DOM ancestry. Click the target to pin the candidate list, then choose a file to open. DOM QA cards
|
|
134
|
+
When source hints are available, hold `Option` over the review target to inspect source candidates from the DOM ancestry. Click the target to pin the candidate list, then choose a file to open. The side rail can also open a Source Tree panel with section/source/data links, live box metrics, text/font/media metadata, and class tags. DOM QA cards show a source action when the saved item has source hints. Source Tree filter/options, QA panel mode, and QA status filter are stored in browser localStorage. Keep these plugins disabled for production builds because they write source paths into the DOM.
|
|
123
135
|
|
|
124
136
|
```tsx
|
|
125
137
|
mountReviewShell({
|
|
@@ -129,6 +141,10 @@ mountReviewShell({
|
|
|
129
141
|
sourceRoot: import.meta.env.VITE_REVIEW_SOURCE_ROOT,
|
|
130
142
|
sourceInspector: {
|
|
131
143
|
editor: 'cursor', // 'vscode' | 'cursor' | 'webstorm' | 'custom'
|
|
144
|
+
maxDepth: 9,
|
|
145
|
+
hoverOutline: true,
|
|
146
|
+
includePlacer: false,
|
|
147
|
+
ignore: ['core.section', 'control.render'],
|
|
132
148
|
// urlTemplate: 'my-editor://open?file={encodedPath}&line={line}&column={column}',
|
|
133
149
|
},
|
|
134
150
|
});
|
|
@@ -400,6 +400,20 @@ function getDomAnchorFromPoint(point, configuredAttribute = "data-qa-id", enviro
|
|
|
400
400
|
source: getDomSourceHint(target)
|
|
401
401
|
};
|
|
402
402
|
}
|
|
403
|
+
function getDomAnchorFromElement(target, configuredAttribute = "data-qa-id", environment) {
|
|
404
|
+
if (target.ownerDocument !== environment.document) return void 0;
|
|
405
|
+
const candidates = createAnchorCandidates(target, configuredAttribute);
|
|
406
|
+
const primary = candidates[0];
|
|
407
|
+
if (!primary) return void 0;
|
|
408
|
+
return {
|
|
409
|
+
...primary,
|
|
410
|
+
candidates,
|
|
411
|
+
htmlSnippet: getElementHtmlSnippet(
|
|
412
|
+
getAnchorSourceElement(target, primary, configuredAttribute) ?? target
|
|
413
|
+
),
|
|
414
|
+
source: getDomSourceHint(target)
|
|
415
|
+
};
|
|
416
|
+
}
|
|
403
417
|
function getElementViewportSelection(anchor, environment, preferredSelection) {
|
|
404
418
|
const element = getAnchorElement(anchor, environment, preferredSelection);
|
|
405
419
|
if (!element) return void 0;
|
|
@@ -1252,6 +1266,14 @@ function createStyleElement() {
|
|
|
1252
1266
|
cursor: default;
|
|
1253
1267
|
}
|
|
1254
1268
|
|
|
1269
|
+
.dfwr-shell.is-docked-composer {
|
|
1270
|
+
position: relative;
|
|
1271
|
+
inset: auto;
|
|
1272
|
+
z-index: auto;
|
|
1273
|
+
padding: 0;
|
|
1274
|
+
pointer-events: auto;
|
|
1275
|
+
}
|
|
1276
|
+
|
|
1255
1277
|
.dfwr-panel {
|
|
1256
1278
|
position: fixed;
|
|
1257
1279
|
right: 16px;
|
|
@@ -1752,6 +1774,20 @@ function createStyleElement() {
|
|
|
1752
1774
|
border-color: rgba(99, 215, 199, 0.56);
|
|
1753
1775
|
}
|
|
1754
1776
|
|
|
1777
|
+
.dfwr-shell.is-docked-composer .dfwr-note-popover.is-docked-composer,
|
|
1778
|
+
.dfwr-shell.is-docked-composer .dfwr-area-draft.is-docked-composer {
|
|
1779
|
+
position: relative;
|
|
1780
|
+
left: auto;
|
|
1781
|
+
right: auto;
|
|
1782
|
+
top: auto;
|
|
1783
|
+
z-index: auto;
|
|
1784
|
+
max-height: none;
|
|
1785
|
+
}
|
|
1786
|
+
|
|
1787
|
+
.dfwr-shell.is-docked-composer .dfwr-textarea {
|
|
1788
|
+
min-height: 184px;
|
|
1789
|
+
}
|
|
1790
|
+
|
|
1755
1791
|
.dfwr-note-popover.is-dragging,
|
|
1756
1792
|
.dfwr-area-draft.is-dragging {
|
|
1757
1793
|
user-select: none;
|
|
@@ -1800,6 +1836,50 @@ function createStyleElement() {
|
|
|
1800
1836
|
padding: 0;
|
|
1801
1837
|
}
|
|
1802
1838
|
|
|
1839
|
+
.dfwr-actions.has-leading {
|
|
1840
|
+
align-items: center;
|
|
1841
|
+
justify-content: space-between;
|
|
1842
|
+
gap: 12px;
|
|
1843
|
+
}
|
|
1844
|
+
|
|
1845
|
+
.dfwr-actions-leading,
|
|
1846
|
+
.dfwr-actions-primary {
|
|
1847
|
+
display: flex;
|
|
1848
|
+
align-items: center;
|
|
1849
|
+
gap: 8px;
|
|
1850
|
+
min-width: 0;
|
|
1851
|
+
}
|
|
1852
|
+
|
|
1853
|
+
.dfwr-actions-primary {
|
|
1854
|
+
margin-left: auto;
|
|
1855
|
+
}
|
|
1856
|
+
|
|
1857
|
+
.dfwr-shell.is-docked-composer .dfwr-actions.has-leading {
|
|
1858
|
+
align-items: stretch;
|
|
1859
|
+
}
|
|
1860
|
+
|
|
1861
|
+
.dfwr-shell.is-docked-composer .dfwr-actions.has-leading .dfwr-button,
|
|
1862
|
+
.dfwr-shell.is-docked-composer .dfwr-actions.has-leading .dfwr-adjust-toggle {
|
|
1863
|
+
height: var(--df-review-control-height-md);
|
|
1864
|
+
min-height: var(--df-review-control-height-md);
|
|
1865
|
+
border-radius: var(--df-review-radius-sm);
|
|
1866
|
+
}
|
|
1867
|
+
|
|
1868
|
+
.dfwr-shell.is-docked-composer .dfwr-actions.has-leading .dfwr-button {
|
|
1869
|
+
min-width: 96px;
|
|
1870
|
+
padding: 0 12px;
|
|
1871
|
+
font-size: var(--df-review-font-size-sm);
|
|
1872
|
+
}
|
|
1873
|
+
|
|
1874
|
+
.dfwr-shell.is-docked-composer .dfwr-actions.has-leading .dfwr-adjust-toggle {
|
|
1875
|
+
width: var(--df-review-control-height-md);
|
|
1876
|
+
}
|
|
1877
|
+
|
|
1878
|
+
.dfwr-shell.is-docked-composer .dfwr-actions.has-leading .dfwr-adjust-toggle svg {
|
|
1879
|
+
width: 18px;
|
|
1880
|
+
height: 18px;
|
|
1881
|
+
}
|
|
1882
|
+
|
|
1803
1883
|
.dfwr-note-actions {
|
|
1804
1884
|
justify-content: flex-end;
|
|
1805
1885
|
}
|
|
@@ -1836,6 +1916,12 @@ function createStyleElement() {
|
|
|
1836
1916
|
outline-offset: 1px;
|
|
1837
1917
|
}
|
|
1838
1918
|
|
|
1919
|
+
@media (hover: none) and (pointer: coarse) {
|
|
1920
|
+
.dfwr-textarea {
|
|
1921
|
+
font-size: 16px;
|
|
1922
|
+
}
|
|
1923
|
+
}
|
|
1924
|
+
|
|
1839
1925
|
.dfwr-adjust-panel {
|
|
1840
1926
|
display: grid;
|
|
1841
1927
|
gap: 4px;
|
|
@@ -2118,10 +2204,12 @@ function createStyleElement() {
|
|
|
2118
2204
|
|
|
2119
2205
|
@media (max-width: 520px) {
|
|
2120
2206
|
.dfwr-panel {
|
|
2207
|
+
left: 8px;
|
|
2121
2208
|
right: 8px;
|
|
2122
|
-
top:
|
|
2123
|
-
|
|
2124
|
-
|
|
2209
|
+
top: auto;
|
|
2210
|
+
bottom: 8px;
|
|
2211
|
+
width: auto;
|
|
2212
|
+
max-height: min(70vh, calc(100vh - 16px));
|
|
2125
2213
|
}
|
|
2126
2214
|
}
|
|
2127
2215
|
`;
|
|
@@ -2201,6 +2289,7 @@ var WebReviewKitView = class {
|
|
|
2201
2289
|
}
|
|
2202
2290
|
clearDraftPreview() {
|
|
2203
2291
|
this.restoreDraftPreview();
|
|
2292
|
+
this.clearShellComposer();
|
|
2204
2293
|
}
|
|
2205
2294
|
render(shadow, hiddenItemsStyle) {
|
|
2206
2295
|
const state = this.state;
|
|
@@ -2211,11 +2300,13 @@ var WebReviewKitView = class {
|
|
|
2211
2300
|
shadow.append(createStyleElement());
|
|
2212
2301
|
shadow.append(hiddenItemsStyle);
|
|
2213
2302
|
const hasDismissableDraft = Boolean(state.noteDraft || state.areaDraft);
|
|
2303
|
+
const shouldDockComposer = this.config.options.ui?.panel === false && hasDismissableDraft && Boolean(this.getShellComposerHost());
|
|
2304
|
+
let dockedComposer;
|
|
2214
2305
|
const shell = document.createElement("div");
|
|
2215
2306
|
shell.className = [
|
|
2216
2307
|
"dfwr-shell",
|
|
2217
2308
|
state.isOpen ? "is-open" : "",
|
|
2218
|
-
hasDismissableDraft ? "has-dismissible-draft" : ""
|
|
2309
|
+
hasDismissableDraft && !shouldDockComposer ? "has-dismissible-draft" : ""
|
|
2219
2310
|
].filter(Boolean).join(" ");
|
|
2220
2311
|
shell.setAttribute("aria-hidden", state.isOpen ? "false" : "true");
|
|
2221
2312
|
if (this.config.options.ui?.panel !== false) {
|
|
@@ -2232,13 +2323,21 @@ var WebReviewKitView = class {
|
|
|
2232
2323
|
shell.append(panel);
|
|
2233
2324
|
}
|
|
2234
2325
|
shell.append(this.createMarkerLayer());
|
|
2235
|
-
if (state.isOpen && hasDismissableDraft) {
|
|
2326
|
+
if (state.isOpen && hasDismissableDraft && !shouldDockComposer) {
|
|
2236
2327
|
shell.append(this.createDraftCancelLayer());
|
|
2237
2328
|
}
|
|
2238
2329
|
if (state.isOpen && (state.mode === "note" || state.mode === "element")) {
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2330
|
+
if (state.noteDraft) {
|
|
2331
|
+
const noteDraft = this.createNotePopover(state.noteDraft, {
|
|
2332
|
+
dockComposer: shouldDockComposer
|
|
2333
|
+
});
|
|
2334
|
+
shell.append(noteDraft.layer);
|
|
2335
|
+
dockedComposer = noteDraft.composer;
|
|
2336
|
+
} else {
|
|
2337
|
+
shell.append(
|
|
2338
|
+
state.mode === "element" ? this.createElementLayer() : this.createNoteLayer()
|
|
2339
|
+
);
|
|
2340
|
+
}
|
|
2242
2341
|
}
|
|
2243
2342
|
if (state.isOpen && state.mode === "area" && !state.areaDraft) {
|
|
2244
2343
|
shell.append(this.createAreaLayer());
|
|
@@ -2247,32 +2346,73 @@ var WebReviewKitView = class {
|
|
|
2247
2346
|
if (state.areaDraft.selection) {
|
|
2248
2347
|
shell.append(this.createAreaDraftOverlay(state.areaDraft));
|
|
2249
2348
|
}
|
|
2250
|
-
|
|
2349
|
+
const areaComposer = this.createAreaDraftPopover(state.areaDraft, {
|
|
2350
|
+
dockComposer: shouldDockComposer
|
|
2351
|
+
});
|
|
2352
|
+
if (shouldDockComposer) {
|
|
2353
|
+
dockedComposer = areaComposer;
|
|
2354
|
+
} else {
|
|
2355
|
+
shell.append(areaComposer);
|
|
2356
|
+
}
|
|
2251
2357
|
}
|
|
2252
2358
|
shadow.append(shell);
|
|
2359
|
+
this.renderShellComposer(dockedComposer);
|
|
2253
2360
|
}
|
|
2254
2361
|
get state() {
|
|
2255
2362
|
return this.config.getState();
|
|
2256
2363
|
}
|
|
2364
|
+
getShellComposerHost() {
|
|
2365
|
+
const environment = this.config.getEnvironment();
|
|
2366
|
+
if (this.config.options.ui?.panel !== false) return void 0;
|
|
2367
|
+
return environment?.composerHost ?? void 0;
|
|
2368
|
+
}
|
|
2369
|
+
renderShellComposer(composer) {
|
|
2370
|
+
const host = composer ? this.getShellComposerHost() : void 0;
|
|
2371
|
+
if (!host || !composer) {
|
|
2372
|
+
this.clearShellComposer();
|
|
2373
|
+
return;
|
|
2374
|
+
}
|
|
2375
|
+
if (this.shellComposerHost && this.shellComposerHost !== host) {
|
|
2376
|
+
this.clearShellComposer();
|
|
2377
|
+
}
|
|
2378
|
+
this.shellComposerHost = host;
|
|
2379
|
+
host.dataset.hasDraftComposer = "true";
|
|
2380
|
+
if (host.parentElement) {
|
|
2381
|
+
host.parentElement.dataset.hasDraftComposer = "true";
|
|
2382
|
+
}
|
|
2383
|
+
const shell = document.createElement("div");
|
|
2384
|
+
shell.className = "dfwr-shell is-open is-shell-draft is-docked-composer";
|
|
2385
|
+
shell.append(composer);
|
|
2386
|
+
host.replaceChildren(createStyleElement(), shell);
|
|
2387
|
+
}
|
|
2388
|
+
clearShellComposer() {
|
|
2389
|
+
const host = this.shellComposerHost;
|
|
2390
|
+
host?.replaceChildren();
|
|
2391
|
+
if (host) {
|
|
2392
|
+
delete host.dataset.hasDraftComposer;
|
|
2393
|
+
delete host.parentElement?.dataset.hasDraftComposer;
|
|
2394
|
+
}
|
|
2395
|
+
this.shellComposerHost = void 0;
|
|
2396
|
+
}
|
|
2257
2397
|
createDraftCancelLayer() {
|
|
2258
2398
|
const layer = document.createElement("div");
|
|
2259
2399
|
layer.className = "dfwr-draft-cancel-layer";
|
|
2260
2400
|
layer.setAttribute("aria-hidden", "true");
|
|
2261
|
-
const cancel = (event) => {
|
|
2262
|
-
event.preventDefault();
|
|
2263
|
-
event.stopPropagation();
|
|
2264
|
-
event.stopImmediatePropagation();
|
|
2265
|
-
this.config.actions.setModeState("idle");
|
|
2266
|
-
this.config.actions.clearDrafts();
|
|
2267
|
-
this.config.actions.setSelectingArea(false);
|
|
2268
|
-
this.config.actions.render();
|
|
2269
|
-
};
|
|
2270
2401
|
layer.addEventListener("pointerdown", (event) => {
|
|
2271
2402
|
if (event.button !== 0) return;
|
|
2272
|
-
|
|
2403
|
+
this.cancelDraft(event);
|
|
2273
2404
|
});
|
|
2274
2405
|
return layer;
|
|
2275
2406
|
}
|
|
2407
|
+
cancelDraft(event) {
|
|
2408
|
+
event?.preventDefault();
|
|
2409
|
+
event?.stopPropagation();
|
|
2410
|
+
event?.stopImmediatePropagation();
|
|
2411
|
+
this.config.actions.setModeState("idle");
|
|
2412
|
+
this.config.actions.clearDrafts();
|
|
2413
|
+
this.config.actions.setSelectingArea(false);
|
|
2414
|
+
this.config.actions.render();
|
|
2415
|
+
}
|
|
2276
2416
|
getDraftAdjustmentMetrics(draft) {
|
|
2277
2417
|
const adjustment = draft.adjustment;
|
|
2278
2418
|
const x = adjustment?.x ?? 0;
|
|
@@ -2666,11 +2806,11 @@ ${adjustment}` : adjustment;
|
|
|
2666
2806
|
empty.textContent = this.state.noteDraft ? "Write the note in the page box." : this.state.mode === "element" ? "Click an element to add QA." : "Click on the page to place a note.";
|
|
2667
2807
|
return empty;
|
|
2668
2808
|
}
|
|
2669
|
-
createNotePopover(draft) {
|
|
2809
|
+
createNotePopover(draft, options = {}) {
|
|
2670
2810
|
const environment = this.config.getEnvironment();
|
|
2671
2811
|
const group = document.createElement("div");
|
|
2672
2812
|
group.className = "dfwr-note-draft";
|
|
2673
|
-
if (!environment) return group;
|
|
2813
|
+
if (!environment) return { layer: group, composer: void 0 };
|
|
2674
2814
|
const isElementDraft = this.state.mode === "element" && Boolean(draft.selection);
|
|
2675
2815
|
const hostPoint = toHostPoint(
|
|
2676
2816
|
isElementDraft ? this.getAdjustedDraftPoint(draft.marker.viewport, draft) : draft.marker.viewport,
|
|
@@ -2694,8 +2834,14 @@ ${adjustment}` : adjustment;
|
|
|
2694
2834
|
pin.style.top = `${hostPoint.y}px`;
|
|
2695
2835
|
const popover = document.createElement("div");
|
|
2696
2836
|
const position = getPopoverPosition(hostPoint, environment);
|
|
2697
|
-
popover.className =
|
|
2698
|
-
|
|
2837
|
+
popover.className = [
|
|
2838
|
+
"dfwr-note-popover",
|
|
2839
|
+
isElementDraft ? "is-composer" : "",
|
|
2840
|
+
options.dockComposer ? "is-docked-composer" : ""
|
|
2841
|
+
].filter(Boolean).join(" ");
|
|
2842
|
+
if (options.dockComposer) {
|
|
2843
|
+
popover.style.width = "100%";
|
|
2844
|
+
} else if (isElementDraft) {
|
|
2699
2845
|
const selection = draft.selection ? toHostSelection(
|
|
2700
2846
|
this.getAdjustedDraftSelection(
|
|
2701
2847
|
toViewportSelection(draft.selection.viewport),
|
|
@@ -2754,18 +2900,27 @@ ${adjustment}` : adjustment;
|
|
|
2754
2900
|
pin,
|
|
2755
2901
|
popover,
|
|
2756
2902
|
selectionHighlight,
|
|
2757
|
-
textarea
|
|
2903
|
+
textarea,
|
|
2904
|
+
dockToggle: options.dockComposer
|
|
2758
2905
|
}) : void 0;
|
|
2759
|
-
const actions = this.createFormActions("Save note", saveDraft
|
|
2906
|
+
const actions = this.createFormActions("Save note", saveDraft, {
|
|
2907
|
+
leading: adjustmentControls?.actionButton ? [adjustmentControls.actionButton] : void 0
|
|
2908
|
+
});
|
|
2760
2909
|
form.append(
|
|
2761
2910
|
...meta ? [meta] : [],
|
|
2762
2911
|
...adjustmentControls ? [adjustmentControls.panel] : [],
|
|
2763
2912
|
textarea,
|
|
2764
2913
|
actions
|
|
2765
2914
|
);
|
|
2766
|
-
const dragHandle = isElementDraft ? this.createDraftDragHandle("Move DOM composer") : void 0;
|
|
2767
|
-
popover.append(
|
|
2768
|
-
|
|
2915
|
+
const dragHandle = isElementDraft && !options.dockComposer ? this.createDraftDragHandle("Move DOM composer") : void 0;
|
|
2916
|
+
popover.append(
|
|
2917
|
+
...dragHandle ? [dragHandle] : [],
|
|
2918
|
+
form
|
|
2919
|
+
);
|
|
2920
|
+
group.append(pin);
|
|
2921
|
+
if (!options.dockComposer) {
|
|
2922
|
+
group.append(popover);
|
|
2923
|
+
}
|
|
2769
2924
|
if (dragHandle) {
|
|
2770
2925
|
this.attachDraftComposerDrag(popover, dragHandle, (composerPosition) => {
|
|
2771
2926
|
const noteDraft = this.state.noteDraft ?? draft;
|
|
@@ -2778,18 +2933,23 @@ ${adjustment}` : adjustment;
|
|
|
2778
2933
|
}
|
|
2779
2934
|
this.attachDraftPinDrag(
|
|
2780
2935
|
pin,
|
|
2781
|
-
isElementDraft ? void 0 : popover,
|
|
2936
|
+
isElementDraft || options.dockComposer ? void 0 : popover,
|
|
2782
2937
|
meta,
|
|
2783
2938
|
textarea
|
|
2784
2939
|
);
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2940
|
+
if (!options.dockComposer) {
|
|
2941
|
+
window.setTimeout(() => {
|
|
2942
|
+
if (draft.adjustment?.isActive) {
|
|
2943
|
+
adjustmentControls?.focusTarget.focus();
|
|
2944
|
+
return;
|
|
2945
|
+
}
|
|
2946
|
+
textarea.focus();
|
|
2947
|
+
}, 0);
|
|
2948
|
+
}
|
|
2949
|
+
return {
|
|
2950
|
+
layer: group,
|
|
2951
|
+
composer: options.dockComposer ? popover : void 0
|
|
2952
|
+
};
|
|
2793
2953
|
}
|
|
2794
2954
|
createDraftDragHandle(label) {
|
|
2795
2955
|
const handle = document.createElement("button");
|
|
@@ -2881,7 +3041,8 @@ ${adjustment}` : adjustment;
|
|
|
2881
3041
|
pin,
|
|
2882
3042
|
popover,
|
|
2883
3043
|
selectionHighlight,
|
|
2884
|
-
textarea
|
|
3044
|
+
textarea,
|
|
3045
|
+
dockToggle
|
|
2885
3046
|
}) {
|
|
2886
3047
|
const panel = document.createElement("div");
|
|
2887
3048
|
panel.className = "dfwr-adjust-panel is-dom-adjust-panel";
|
|
@@ -2957,12 +3118,16 @@ ${adjustment}` : adjustment;
|
|
|
2957
3118
|
}
|
|
2958
3119
|
}));
|
|
2959
3120
|
});
|
|
2960
|
-
header.append(help
|
|
3121
|
+
header.append(help);
|
|
3122
|
+
if (!dockToggle) {
|
|
3123
|
+
header.append(adjust);
|
|
3124
|
+
}
|
|
2961
3125
|
panel.append(header, xyStatus, scaleStatus);
|
|
2962
3126
|
syncControls(draft);
|
|
2963
3127
|
return {
|
|
2964
3128
|
panel,
|
|
2965
|
-
focusTarget: adjust
|
|
3129
|
+
focusTarget: adjust,
|
|
3130
|
+
actionButton: dockToggle ? adjust : void 0
|
|
2966
3131
|
};
|
|
2967
3132
|
}
|
|
2968
3133
|
getAdjustmentKeyDelta(event) {
|
|
@@ -3088,11 +3253,17 @@ ${adjustment}` : adjustment;
|
|
|
3088
3253
|
}
|
|
3089
3254
|
return layer;
|
|
3090
3255
|
}
|
|
3091
|
-
createAreaDraftPopover(draft) {
|
|
3256
|
+
createAreaDraftPopover(draft, options = {}) {
|
|
3092
3257
|
const environment = this.config.getEnvironment();
|
|
3093
3258
|
const popover = document.createElement("div");
|
|
3094
|
-
popover.className =
|
|
3095
|
-
|
|
3259
|
+
popover.className = [
|
|
3260
|
+
"dfwr-area-draft",
|
|
3261
|
+
"is-composer",
|
|
3262
|
+
options.dockComposer ? "is-docked-composer" : ""
|
|
3263
|
+
].filter(Boolean).join(" ");
|
|
3264
|
+
if (options.dockComposer) {
|
|
3265
|
+
popover.style.width = "100%";
|
|
3266
|
+
} else if (environment && draft.selection) {
|
|
3096
3267
|
const selection = toHostSelection(
|
|
3097
3268
|
toViewportSelection(draft.selection.viewport),
|
|
3098
3269
|
environment
|
|
@@ -3108,15 +3279,20 @@ ${adjustment}` : adjustment;
|
|
|
3108
3279
|
popover.style.width = `${composer.width}px`;
|
|
3109
3280
|
popover.style.right = "auto";
|
|
3110
3281
|
}
|
|
3111
|
-
const dragHandle = this.createDraftDragHandle("Move area composer");
|
|
3112
|
-
popover.append(
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3282
|
+
const dragHandle = options.dockComposer ? void 0 : this.createDraftDragHandle("Move area composer");
|
|
3283
|
+
popover.append(
|
|
3284
|
+
...dragHandle ? [dragHandle] : [],
|
|
3285
|
+
this.createAreaForm()
|
|
3286
|
+
);
|
|
3287
|
+
if (dragHandle) {
|
|
3288
|
+
this.attachDraftComposerDrag(popover, dragHandle, (composerPosition) => {
|
|
3289
|
+
const areaDraft = this.state.areaDraft ?? draft;
|
|
3290
|
+
this.config.actions.setAreaDraft({
|
|
3291
|
+
...areaDraft,
|
|
3292
|
+
composerPosition
|
|
3293
|
+
});
|
|
3118
3294
|
});
|
|
3119
|
-
}
|
|
3295
|
+
}
|
|
3120
3296
|
return popover;
|
|
3121
3297
|
}
|
|
3122
3298
|
createFormActions(saveLabel, onSave, options) {
|
|
@@ -3136,12 +3312,19 @@ ${adjustment}` : adjustment;
|
|
|
3136
3312
|
cancel.type = "button";
|
|
3137
3313
|
cancel.textContent = "Cancel";
|
|
3138
3314
|
cancel.addEventListener("click", (event) => {
|
|
3139
|
-
|
|
3140
|
-
event.stopPropagation();
|
|
3141
|
-
this.config.actions.setModeState("idle");
|
|
3142
|
-
this.config.actions.clearDrafts();
|
|
3143
|
-
this.config.actions.render();
|
|
3315
|
+
this.cancelDraft(event);
|
|
3144
3316
|
});
|
|
3317
|
+
if (options?.leading?.length) {
|
|
3318
|
+
actions.classList.add("has-leading");
|
|
3319
|
+
const leading = document.createElement("div");
|
|
3320
|
+
leading.className = "dfwr-actions-leading";
|
|
3321
|
+
leading.append(...options.leading);
|
|
3322
|
+
const primary = document.createElement("div");
|
|
3323
|
+
primary.className = "dfwr-actions-primary";
|
|
3324
|
+
primary.append(save, cancel);
|
|
3325
|
+
actions.append(leading, primary);
|
|
3326
|
+
return actions;
|
|
3327
|
+
}
|
|
3145
3328
|
if (options?.beforeSave?.length || options?.className) {
|
|
3146
3329
|
actions.append(cancel, ...options.beforeSave ?? [], save);
|
|
3147
3330
|
return actions;
|
|
@@ -3542,6 +3725,7 @@ function createWebReviewKit(options) {
|
|
|
3542
3725
|
close: () => app.close(),
|
|
3543
3726
|
toggle: () => app.toggle(),
|
|
3544
3727
|
setMode: (mode) => app.setMode(mode),
|
|
3728
|
+
startElementReview: (element, comment) => app.startElementReview(element, comment),
|
|
3545
3729
|
getMode: () => app.getMode(),
|
|
3546
3730
|
highlightItem: (itemId) => app.highlightItem(itemId),
|
|
3547
3731
|
setHiddenItemIds: (itemIds) => app.setHiddenItemIds(itemIds),
|
|
@@ -3569,9 +3753,10 @@ var WebReviewKitApp = class {
|
|
|
3569
3753
|
this.toggle();
|
|
3570
3754
|
};
|
|
3571
3755
|
this.handleViewportChange = () => {
|
|
3572
|
-
if (!this.isOpen || this.renderFrame) return;
|
|
3756
|
+
if (!this.isOpen || this.renderFrame || this.isDraftComposerFocused()) return;
|
|
3573
3757
|
this.renderFrame = window.requestAnimationFrame(() => {
|
|
3574
3758
|
this.renderFrame = void 0;
|
|
3759
|
+
if (this.isDraftComposerFocused()) return;
|
|
3575
3760
|
this.render();
|
|
3576
3761
|
});
|
|
3577
3762
|
};
|
|
@@ -3672,6 +3857,16 @@ var WebReviewKitApp = class {
|
|
|
3672
3857
|
this.areaDraft = void 0;
|
|
3673
3858
|
this.render();
|
|
3674
3859
|
}
|
|
3860
|
+
async startElementReview(element, comment) {
|
|
3861
|
+
if (!this.isOpen) {
|
|
3862
|
+
this.isOpen = true;
|
|
3863
|
+
}
|
|
3864
|
+
this.setModeState("element");
|
|
3865
|
+
this.noteDraft = void 0;
|
|
3866
|
+
this.areaDraft = void 0;
|
|
3867
|
+
this.isSelectingArea = false;
|
|
3868
|
+
await this.bindElementDraftToElement(element, comment);
|
|
3869
|
+
}
|
|
3675
3870
|
getMode() {
|
|
3676
3871
|
return this.mode;
|
|
3677
3872
|
}
|
|
@@ -3738,6 +3933,14 @@ var WebReviewKitApp = class {
|
|
|
3738
3933
|
this.render();
|
|
3739
3934
|
return true;
|
|
3740
3935
|
}
|
|
3936
|
+
isDraftComposerFocused() {
|
|
3937
|
+
if (!this.noteDraft && !this.areaDraft) return false;
|
|
3938
|
+
const composerHost = this.getEnvironment()?.composerHost;
|
|
3939
|
+
const activeElement = composerHost?.ownerDocument.activeElement;
|
|
3940
|
+
return Boolean(
|
|
3941
|
+
composerHost && activeElement && composerHost.contains(activeElement)
|
|
3942
|
+
);
|
|
3943
|
+
}
|
|
3741
3944
|
getEnvironment() {
|
|
3742
3945
|
const target = typeof this.options.target === "function" ? this.options.target() : this.options.target;
|
|
3743
3946
|
if (!target) {
|
|
@@ -3766,6 +3969,7 @@ var WebReviewKitApp = class {
|
|
|
3766
3969
|
height: target.window.innerHeight
|
|
3767
3970
|
};
|
|
3768
3971
|
const overlayRect = target.getOverlayRect?.() ?? rect;
|
|
3972
|
+
const composerHost = target.getComposerHost?.();
|
|
3769
3973
|
return {
|
|
3770
3974
|
window: target.window,
|
|
3771
3975
|
document: target.document,
|
|
@@ -3780,7 +3984,8 @@ var WebReviewKitApp = class {
|
|
|
3780
3984
|
top: overlayRect.top,
|
|
3781
3985
|
width: overlayRect.width,
|
|
3782
3986
|
height: overlayRect.height
|
|
3783
|
-
}
|
|
3987
|
+
},
|
|
3988
|
+
composerHost
|
|
3784
3989
|
};
|
|
3785
3990
|
} catch {
|
|
3786
3991
|
return void 0;
|
|
@@ -3880,6 +4085,47 @@ var WebReviewKitApp = class {
|
|
|
3880
4085
|
this.noteDraft = draft;
|
|
3881
4086
|
this.render();
|
|
3882
4087
|
}
|
|
4088
|
+
async bindElementDraftToElement(element, comment) {
|
|
4089
|
+
const environment = this.getEnvironment();
|
|
4090
|
+
if (!environment || element.ownerDocument !== environment.document) return;
|
|
4091
|
+
const viewport = getViewportSize(environment);
|
|
4092
|
+
const draft = await this.withOverlayHidden(() => {
|
|
4093
|
+
const rect = element.getBoundingClientRect();
|
|
4094
|
+
if (rect.width <= 0 || rect.height <= 0) return void 0;
|
|
4095
|
+
const selection = {
|
|
4096
|
+
left: rect.left,
|
|
4097
|
+
top: rect.top,
|
|
4098
|
+
width: rect.width,
|
|
4099
|
+
height: rect.height
|
|
4100
|
+
};
|
|
4101
|
+
const anchor = getDomAnchorFromElement(
|
|
4102
|
+
element,
|
|
4103
|
+
this.options.anchors?.attribute,
|
|
4104
|
+
environment
|
|
4105
|
+
);
|
|
4106
|
+
const markerPoint = { x: selection.left, y: selection.top };
|
|
4107
|
+
const marker = {
|
|
4108
|
+
viewport: roundPoint(markerPoint),
|
|
4109
|
+
relative: anchor ? getRelativePoint(markerPoint, anchor, environment) : void 0
|
|
4110
|
+
};
|
|
4111
|
+
const reviewSelection = {
|
|
4112
|
+
viewport: toPublicSelection(selection),
|
|
4113
|
+
relative: anchor ? getRelativeSelection(selection, anchor, environment) : void 0
|
|
4114
|
+
};
|
|
4115
|
+
const previewElement = "style" in element ? element : void 0;
|
|
4116
|
+
return {
|
|
4117
|
+
viewport,
|
|
4118
|
+
anchor,
|
|
4119
|
+
marker,
|
|
4120
|
+
selection: reviewSelection,
|
|
4121
|
+
comment,
|
|
4122
|
+
previewElement
|
|
4123
|
+
};
|
|
4124
|
+
});
|
|
4125
|
+
if (!draft) return;
|
|
4126
|
+
this.noteDraft = draft;
|
|
4127
|
+
this.render();
|
|
4128
|
+
}
|
|
3883
4129
|
async createAreaDraft(selection) {
|
|
3884
4130
|
const environment = this.getEnvironment();
|
|
3885
4131
|
if (!environment) return;
|
|
@@ -3984,6 +4230,8 @@ function createNoopController() {
|
|
|
3984
4230
|
},
|
|
3985
4231
|
setMode() {
|
|
3986
4232
|
},
|
|
4233
|
+
async startElementReview() {
|
|
4234
|
+
},
|
|
3987
4235
|
getMode() {
|
|
3988
4236
|
return "idle";
|
|
3989
4237
|
},
|
|
@@ -4006,12 +4254,14 @@ export {
|
|
|
4006
4254
|
REVIEW_WORKFLOW_STATUS_OPTIONS,
|
|
4007
4255
|
normalizeReviewItemStatus,
|
|
4008
4256
|
localAdapter,
|
|
4257
|
+
clamp,
|
|
4009
4258
|
DEFAULT_REVIEW_VIEWPORTS,
|
|
4010
4259
|
findReviewViewportPreset,
|
|
4011
4260
|
getReviewViewportScope,
|
|
4012
4261
|
getReviewItemScope,
|
|
4013
4262
|
getReviewItemScopeLabel,
|
|
4014
4263
|
getNumberedReviewItems,
|
|
4264
|
+
runWithAutoScrollBehavior,
|
|
4015
4265
|
createWebReviewKit
|
|
4016
4266
|
};
|
|
4017
|
-
//# sourceMappingURL=chunk-
|
|
4267
|
+
//# sourceMappingURL=chunk-IN36JHEU.js.map
|