@designfever/web-review-kit 0.5.0 → 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/dist/index.cjs CHANGED
@@ -1520,6 +1520,14 @@ function createStyleElement() {
1520
1520
  cursor: default;
1521
1521
  }
1522
1522
 
1523
+ .dfwr-shell.is-docked-composer {
1524
+ position: relative;
1525
+ inset: auto;
1526
+ z-index: auto;
1527
+ padding: 0;
1528
+ pointer-events: auto;
1529
+ }
1530
+
1523
1531
  .dfwr-panel {
1524
1532
  position: fixed;
1525
1533
  right: 16px;
@@ -2020,6 +2028,20 @@ function createStyleElement() {
2020
2028
  border-color: rgba(99, 215, 199, 0.56);
2021
2029
  }
2022
2030
 
2031
+ .dfwr-shell.is-docked-composer .dfwr-note-popover.is-docked-composer,
2032
+ .dfwr-shell.is-docked-composer .dfwr-area-draft.is-docked-composer {
2033
+ position: relative;
2034
+ left: auto;
2035
+ right: auto;
2036
+ top: auto;
2037
+ z-index: auto;
2038
+ max-height: none;
2039
+ }
2040
+
2041
+ .dfwr-shell.is-docked-composer .dfwr-textarea {
2042
+ min-height: 184px;
2043
+ }
2044
+
2023
2045
  .dfwr-note-popover.is-dragging,
2024
2046
  .dfwr-area-draft.is-dragging {
2025
2047
  user-select: none;
@@ -2068,6 +2090,50 @@ function createStyleElement() {
2068
2090
  padding: 0;
2069
2091
  }
2070
2092
 
2093
+ .dfwr-actions.has-leading {
2094
+ align-items: center;
2095
+ justify-content: space-between;
2096
+ gap: 12px;
2097
+ }
2098
+
2099
+ .dfwr-actions-leading,
2100
+ .dfwr-actions-primary {
2101
+ display: flex;
2102
+ align-items: center;
2103
+ gap: 8px;
2104
+ min-width: 0;
2105
+ }
2106
+
2107
+ .dfwr-actions-primary {
2108
+ margin-left: auto;
2109
+ }
2110
+
2111
+ .dfwr-shell.is-docked-composer .dfwr-actions.has-leading {
2112
+ align-items: stretch;
2113
+ }
2114
+
2115
+ .dfwr-shell.is-docked-composer .dfwr-actions.has-leading .dfwr-button,
2116
+ .dfwr-shell.is-docked-composer .dfwr-actions.has-leading .dfwr-adjust-toggle {
2117
+ height: var(--df-review-control-height-md);
2118
+ min-height: var(--df-review-control-height-md);
2119
+ border-radius: var(--df-review-radius-sm);
2120
+ }
2121
+
2122
+ .dfwr-shell.is-docked-composer .dfwr-actions.has-leading .dfwr-button {
2123
+ min-width: 96px;
2124
+ padding: 0 12px;
2125
+ font-size: var(--df-review-font-size-sm);
2126
+ }
2127
+
2128
+ .dfwr-shell.is-docked-composer .dfwr-actions.has-leading .dfwr-adjust-toggle {
2129
+ width: var(--df-review-control-height-md);
2130
+ }
2131
+
2132
+ .dfwr-shell.is-docked-composer .dfwr-actions.has-leading .dfwr-adjust-toggle svg {
2133
+ width: 18px;
2134
+ height: 18px;
2135
+ }
2136
+
2071
2137
  .dfwr-note-actions {
2072
2138
  justify-content: flex-end;
2073
2139
  }
@@ -2392,10 +2458,12 @@ function createStyleElement() {
2392
2458
 
2393
2459
  @media (max-width: 520px) {
2394
2460
  .dfwr-panel {
2461
+ left: 8px;
2395
2462
  right: 8px;
2396
- top: 8px;
2397
- width: calc(100vw - 16px);
2398
- max-height: calc(100vh - 16px);
2463
+ top: auto;
2464
+ bottom: 8px;
2465
+ width: auto;
2466
+ max-height: min(70vh, calc(100vh - 16px));
2399
2467
  }
2400
2468
  }
2401
2469
  `;
@@ -2475,6 +2543,7 @@ var WebReviewKitView = class {
2475
2543
  }
2476
2544
  clearDraftPreview() {
2477
2545
  this.restoreDraftPreview();
2546
+ this.clearShellComposer();
2478
2547
  }
2479
2548
  render(shadow, hiddenItemsStyle) {
2480
2549
  const state = this.state;
@@ -2485,11 +2554,13 @@ var WebReviewKitView = class {
2485
2554
  shadow.append(createStyleElement());
2486
2555
  shadow.append(hiddenItemsStyle);
2487
2556
  const hasDismissableDraft = Boolean(state.noteDraft || state.areaDraft);
2557
+ const shouldDockComposer = this.config.options.ui?.panel === false && hasDismissableDraft && Boolean(this.getShellComposerHost());
2558
+ let dockedComposer;
2488
2559
  const shell = document.createElement("div");
2489
2560
  shell.className = [
2490
2561
  "dfwr-shell",
2491
2562
  state.isOpen ? "is-open" : "",
2492
- hasDismissableDraft ? "has-dismissible-draft" : ""
2563
+ hasDismissableDraft && !shouldDockComposer ? "has-dismissible-draft" : ""
2493
2564
  ].filter(Boolean).join(" ");
2494
2565
  shell.setAttribute("aria-hidden", state.isOpen ? "false" : "true");
2495
2566
  if (this.config.options.ui?.panel !== false) {
@@ -2506,13 +2577,21 @@ var WebReviewKitView = class {
2506
2577
  shell.append(panel);
2507
2578
  }
2508
2579
  shell.append(this.createMarkerLayer());
2509
- if (state.isOpen && hasDismissableDraft) {
2580
+ if (state.isOpen && hasDismissableDraft && !shouldDockComposer) {
2510
2581
  shell.append(this.createDraftCancelLayer());
2511
2582
  }
2512
2583
  if (state.isOpen && (state.mode === "note" || state.mode === "element")) {
2513
- shell.append(
2514
- state.noteDraft ? this.createNotePopover(state.noteDraft) : state.mode === "element" ? this.createElementLayer() : this.createNoteLayer()
2515
- );
2584
+ if (state.noteDraft) {
2585
+ const noteDraft = this.createNotePopover(state.noteDraft, {
2586
+ dockComposer: shouldDockComposer
2587
+ });
2588
+ shell.append(noteDraft.layer);
2589
+ dockedComposer = noteDraft.composer;
2590
+ } else {
2591
+ shell.append(
2592
+ state.mode === "element" ? this.createElementLayer() : this.createNoteLayer()
2593
+ );
2594
+ }
2516
2595
  }
2517
2596
  if (state.isOpen && state.mode === "area" && !state.areaDraft) {
2518
2597
  shell.append(this.createAreaLayer());
@@ -2521,32 +2600,73 @@ var WebReviewKitView = class {
2521
2600
  if (state.areaDraft.selection) {
2522
2601
  shell.append(this.createAreaDraftOverlay(state.areaDraft));
2523
2602
  }
2524
- shell.append(this.createAreaDraftPopover(state.areaDraft));
2603
+ const areaComposer = this.createAreaDraftPopover(state.areaDraft, {
2604
+ dockComposer: shouldDockComposer
2605
+ });
2606
+ if (shouldDockComposer) {
2607
+ dockedComposer = areaComposer;
2608
+ } else {
2609
+ shell.append(areaComposer);
2610
+ }
2525
2611
  }
2526
2612
  shadow.append(shell);
2613
+ this.renderShellComposer(dockedComposer);
2527
2614
  }
2528
2615
  get state() {
2529
2616
  return this.config.getState();
2530
2617
  }
2618
+ getShellComposerHost() {
2619
+ const environment = this.config.getEnvironment();
2620
+ if (this.config.options.ui?.panel !== false) return void 0;
2621
+ return environment?.composerHost ?? void 0;
2622
+ }
2623
+ renderShellComposer(composer) {
2624
+ const host = composer ? this.getShellComposerHost() : void 0;
2625
+ if (!host || !composer) {
2626
+ this.clearShellComposer();
2627
+ return;
2628
+ }
2629
+ if (this.shellComposerHost && this.shellComposerHost !== host) {
2630
+ this.clearShellComposer();
2631
+ }
2632
+ this.shellComposerHost = host;
2633
+ host.dataset.hasDraftComposer = "true";
2634
+ if (host.parentElement) {
2635
+ host.parentElement.dataset.hasDraftComposer = "true";
2636
+ }
2637
+ const shell = document.createElement("div");
2638
+ shell.className = "dfwr-shell is-open is-shell-draft is-docked-composer";
2639
+ shell.append(composer);
2640
+ host.replaceChildren(createStyleElement(), shell);
2641
+ }
2642
+ clearShellComposer() {
2643
+ const host = this.shellComposerHost;
2644
+ host?.replaceChildren();
2645
+ if (host) {
2646
+ delete host.dataset.hasDraftComposer;
2647
+ delete host.parentElement?.dataset.hasDraftComposer;
2648
+ }
2649
+ this.shellComposerHost = void 0;
2650
+ }
2531
2651
  createDraftCancelLayer() {
2532
2652
  const layer = document.createElement("div");
2533
2653
  layer.className = "dfwr-draft-cancel-layer";
2534
2654
  layer.setAttribute("aria-hidden", "true");
2535
- const cancel = (event) => {
2536
- event.preventDefault();
2537
- event.stopPropagation();
2538
- event.stopImmediatePropagation();
2539
- this.config.actions.setModeState("idle");
2540
- this.config.actions.clearDrafts();
2541
- this.config.actions.setSelectingArea(false);
2542
- this.config.actions.render();
2543
- };
2544
2655
  layer.addEventListener("pointerdown", (event) => {
2545
2656
  if (event.button !== 0) return;
2546
- cancel(event);
2657
+ this.cancelDraft(event);
2547
2658
  });
2548
2659
  return layer;
2549
2660
  }
2661
+ cancelDraft(event) {
2662
+ event?.preventDefault();
2663
+ event?.stopPropagation();
2664
+ event?.stopImmediatePropagation();
2665
+ this.config.actions.setModeState("idle");
2666
+ this.config.actions.clearDrafts();
2667
+ this.config.actions.setSelectingArea(false);
2668
+ this.config.actions.render();
2669
+ }
2550
2670
  getDraftAdjustmentMetrics(draft) {
2551
2671
  const adjustment = draft.adjustment;
2552
2672
  const x = adjustment?.x ?? 0;
@@ -2940,11 +3060,11 @@ ${adjustment}` : adjustment;
2940
3060
  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.";
2941
3061
  return empty;
2942
3062
  }
2943
- createNotePopover(draft) {
3063
+ createNotePopover(draft, options = {}) {
2944
3064
  const environment = this.config.getEnvironment();
2945
3065
  const group = document.createElement("div");
2946
3066
  group.className = "dfwr-note-draft";
2947
- if (!environment) return group;
3067
+ if (!environment) return { layer: group, composer: void 0 };
2948
3068
  const isElementDraft = this.state.mode === "element" && Boolean(draft.selection);
2949
3069
  const hostPoint = toHostPoint(
2950
3070
  isElementDraft ? this.getAdjustedDraftPoint(draft.marker.viewport, draft) : draft.marker.viewport,
@@ -2968,8 +3088,14 @@ ${adjustment}` : adjustment;
2968
3088
  pin.style.top = `${hostPoint.y}px`;
2969
3089
  const popover = document.createElement("div");
2970
3090
  const position = getPopoverPosition(hostPoint, environment);
2971
- popover.className = `dfwr-note-popover${isElementDraft ? " is-composer" : ""}`;
2972
- if (isElementDraft) {
3091
+ popover.className = [
3092
+ "dfwr-note-popover",
3093
+ isElementDraft ? "is-composer" : "",
3094
+ options.dockComposer ? "is-docked-composer" : ""
3095
+ ].filter(Boolean).join(" ");
3096
+ if (options.dockComposer) {
3097
+ popover.style.width = "100%";
3098
+ } else if (isElementDraft) {
2973
3099
  const selection = draft.selection ? toHostSelection(
2974
3100
  this.getAdjustedDraftSelection(
2975
3101
  toViewportSelection(draft.selection.viewport),
@@ -3028,18 +3154,27 @@ ${adjustment}` : adjustment;
3028
3154
  pin,
3029
3155
  popover,
3030
3156
  selectionHighlight,
3031
- textarea
3157
+ textarea,
3158
+ dockToggle: options.dockComposer
3032
3159
  }) : void 0;
3033
- const actions = this.createFormActions("Save note", saveDraft);
3160
+ const actions = this.createFormActions("Save note", saveDraft, {
3161
+ leading: adjustmentControls?.actionButton ? [adjustmentControls.actionButton] : void 0
3162
+ });
3034
3163
  form.append(
3035
3164
  ...meta ? [meta] : [],
3036
3165
  ...adjustmentControls ? [adjustmentControls.panel] : [],
3037
3166
  textarea,
3038
3167
  actions
3039
3168
  );
3040
- const dragHandle = isElementDraft ? this.createDraftDragHandle("Move DOM composer") : void 0;
3041
- popover.append(...dragHandle ? [dragHandle] : [], form);
3042
- group.append(pin, popover);
3169
+ const dragHandle = isElementDraft && !options.dockComposer ? this.createDraftDragHandle("Move DOM composer") : void 0;
3170
+ popover.append(
3171
+ ...dragHandle ? [dragHandle] : [],
3172
+ form
3173
+ );
3174
+ group.append(pin);
3175
+ if (!options.dockComposer) {
3176
+ group.append(popover);
3177
+ }
3043
3178
  if (dragHandle) {
3044
3179
  this.attachDraftComposerDrag(popover, dragHandle, (composerPosition) => {
3045
3180
  const noteDraft = this.state.noteDraft ?? draft;
@@ -3052,18 +3187,23 @@ ${adjustment}` : adjustment;
3052
3187
  }
3053
3188
  this.attachDraftPinDrag(
3054
3189
  pin,
3055
- isElementDraft ? void 0 : popover,
3190
+ isElementDraft || options.dockComposer ? void 0 : popover,
3056
3191
  meta,
3057
3192
  textarea
3058
3193
  );
3059
- window.setTimeout(() => {
3060
- if (draft.adjustment?.isActive) {
3061
- adjustmentControls?.focusTarget.focus();
3062
- return;
3063
- }
3064
- textarea.focus();
3065
- }, 0);
3066
- return group;
3194
+ if (!options.dockComposer) {
3195
+ window.setTimeout(() => {
3196
+ if (draft.adjustment?.isActive) {
3197
+ adjustmentControls?.focusTarget.focus();
3198
+ return;
3199
+ }
3200
+ textarea.focus();
3201
+ }, 0);
3202
+ }
3203
+ return {
3204
+ layer: group,
3205
+ composer: options.dockComposer ? popover : void 0
3206
+ };
3067
3207
  }
3068
3208
  createDraftDragHandle(label) {
3069
3209
  const handle = document.createElement("button");
@@ -3155,7 +3295,8 @@ ${adjustment}` : adjustment;
3155
3295
  pin,
3156
3296
  popover,
3157
3297
  selectionHighlight,
3158
- textarea
3298
+ textarea,
3299
+ dockToggle
3159
3300
  }) {
3160
3301
  const panel = document.createElement("div");
3161
3302
  panel.className = "dfwr-adjust-panel is-dom-adjust-panel";
@@ -3231,12 +3372,16 @@ ${adjustment}` : adjustment;
3231
3372
  }
3232
3373
  }));
3233
3374
  });
3234
- header.append(help, adjust);
3375
+ header.append(help);
3376
+ if (!dockToggle) {
3377
+ header.append(adjust);
3378
+ }
3235
3379
  panel.append(header, xyStatus, scaleStatus);
3236
3380
  syncControls(draft);
3237
3381
  return {
3238
3382
  panel,
3239
- focusTarget: adjust
3383
+ focusTarget: adjust,
3384
+ actionButton: dockToggle ? adjust : void 0
3240
3385
  };
3241
3386
  }
3242
3387
  getAdjustmentKeyDelta(event) {
@@ -3362,11 +3507,17 @@ ${adjustment}` : adjustment;
3362
3507
  }
3363
3508
  return layer;
3364
3509
  }
3365
- createAreaDraftPopover(draft) {
3510
+ createAreaDraftPopover(draft, options = {}) {
3366
3511
  const environment = this.config.getEnvironment();
3367
3512
  const popover = document.createElement("div");
3368
- popover.className = "dfwr-area-draft is-composer";
3369
- if (environment && draft.selection) {
3513
+ popover.className = [
3514
+ "dfwr-area-draft",
3515
+ "is-composer",
3516
+ options.dockComposer ? "is-docked-composer" : ""
3517
+ ].filter(Boolean).join(" ");
3518
+ if (options.dockComposer) {
3519
+ popover.style.width = "100%";
3520
+ } else if (environment && draft.selection) {
3370
3521
  const selection = toHostSelection(
3371
3522
  toViewportSelection(draft.selection.viewport),
3372
3523
  environment
@@ -3382,15 +3533,20 @@ ${adjustment}` : adjustment;
3382
3533
  popover.style.width = `${composer.width}px`;
3383
3534
  popover.style.right = "auto";
3384
3535
  }
3385
- const dragHandle = this.createDraftDragHandle("Move area composer");
3386
- popover.append(dragHandle, this.createAreaForm());
3387
- this.attachDraftComposerDrag(popover, dragHandle, (composerPosition) => {
3388
- const areaDraft = this.state.areaDraft ?? draft;
3389
- this.config.actions.setAreaDraft({
3390
- ...areaDraft,
3391
- composerPosition
3536
+ const dragHandle = options.dockComposer ? void 0 : this.createDraftDragHandle("Move area composer");
3537
+ popover.append(
3538
+ ...dragHandle ? [dragHandle] : [],
3539
+ this.createAreaForm()
3540
+ );
3541
+ if (dragHandle) {
3542
+ this.attachDraftComposerDrag(popover, dragHandle, (composerPosition) => {
3543
+ const areaDraft = this.state.areaDraft ?? draft;
3544
+ this.config.actions.setAreaDraft({
3545
+ ...areaDraft,
3546
+ composerPosition
3547
+ });
3392
3548
  });
3393
- });
3549
+ }
3394
3550
  return popover;
3395
3551
  }
3396
3552
  createFormActions(saveLabel, onSave, options) {
@@ -3410,12 +3566,19 @@ ${adjustment}` : adjustment;
3410
3566
  cancel.type = "button";
3411
3567
  cancel.textContent = "Cancel";
3412
3568
  cancel.addEventListener("click", (event) => {
3413
- event.preventDefault();
3414
- event.stopPropagation();
3415
- this.config.actions.setModeState("idle");
3416
- this.config.actions.clearDrafts();
3417
- this.config.actions.render();
3569
+ this.cancelDraft(event);
3418
3570
  });
3571
+ if (options?.leading?.length) {
3572
+ actions.classList.add("has-leading");
3573
+ const leading = document.createElement("div");
3574
+ leading.className = "dfwr-actions-leading";
3575
+ leading.append(...options.leading);
3576
+ const primary = document.createElement("div");
3577
+ primary.className = "dfwr-actions-primary";
3578
+ primary.append(save, cancel);
3579
+ actions.append(leading, primary);
3580
+ return actions;
3581
+ }
3419
3582
  if (options?.beforeSave?.length || options?.className) {
3420
3583
  actions.append(cancel, ...options.beforeSave ?? [], save);
3421
3584
  return actions;
@@ -3844,9 +4007,10 @@ var WebReviewKitApp = class {
3844
4007
  this.toggle();
3845
4008
  };
3846
4009
  this.handleViewportChange = () => {
3847
- if (!this.isOpen || this.renderFrame) return;
4010
+ if (!this.isOpen || this.renderFrame || this.isDraftComposerFocused()) return;
3848
4011
  this.renderFrame = window.requestAnimationFrame(() => {
3849
4012
  this.renderFrame = void 0;
4013
+ if (this.isDraftComposerFocused()) return;
3850
4014
  this.render();
3851
4015
  });
3852
4016
  };
@@ -4023,6 +4187,14 @@ var WebReviewKitApp = class {
4023
4187
  this.render();
4024
4188
  return true;
4025
4189
  }
4190
+ isDraftComposerFocused() {
4191
+ if (!this.noteDraft && !this.areaDraft) return false;
4192
+ const composerHost = this.getEnvironment()?.composerHost;
4193
+ const activeElement = composerHost?.ownerDocument.activeElement;
4194
+ return Boolean(
4195
+ composerHost && activeElement && composerHost.contains(activeElement)
4196
+ );
4197
+ }
4026
4198
  getEnvironment() {
4027
4199
  const target = typeof this.options.target === "function" ? this.options.target() : this.options.target;
4028
4200
  if (!target) {
@@ -4051,6 +4223,7 @@ var WebReviewKitApp = class {
4051
4223
  height: target.window.innerHeight
4052
4224
  };
4053
4225
  const overlayRect = target.getOverlayRect?.() ?? rect;
4226
+ const composerHost = target.getComposerHost?.();
4054
4227
  return {
4055
4228
  window: target.window,
4056
4229
  document: target.document,
@@ -4065,7 +4238,8 @@ var WebReviewKitApp = class {
4065
4238
  top: overlayRect.top,
4066
4239
  width: overlayRect.width,
4067
4240
  height: overlayRect.height
4068
- }
4241
+ },
4242
+ composerHost
4069
4243
  };
4070
4244
  } catch {
4071
4245
  return void 0;