@agent-native/toolkit 0.14.1 → 0.14.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.
@@ -235,7 +235,7 @@ export type CanvasEscapeResult<TObjectId = string> =
235
235
  selectedObjectIds: readonly TObjectId[];
236
236
  };
237
237
 
238
- export interface CanvasResizeInput {
238
+ export interface CanvasResizeInput extends CanvasModifiers {
239
239
  handle: CanvasResizeHandle;
240
240
  delta: CanvasPoint;
241
241
  preserveAspectRatio?: boolean;
@@ -537,8 +537,8 @@ export function constrainCanvasDragDelta(
537
537
  }
538
538
 
539
539
  /**
540
- * Resizes against the opposite edge. Shift preserves aspect ratio on corners;
541
- * midpoint handles stay single-axis so their fixed edge remains predictable.
540
+ * Resizes against the opposite edge, or from the center with Alt. Shift
541
+ * preserves aspect ratio on every handle; derived dimensions are centered.
542
542
  */
543
543
  export function resizeCanvasRect(
544
544
  start: CanvasRect,
@@ -554,37 +554,68 @@ export function resizeCanvasRect(
554
554
  input.handle === "sw" || input.handle === "s" || input.handle === "se";
555
555
  const resizesHorizontally = fromWest || fromEast;
556
556
  const resizesVertically = fromNorth || fromSouth;
557
+ const resizeFromCenter = Boolean(input.altKey);
557
558
  let width =
558
- start.width + (fromWest ? -input.delta.x : fromEast ? input.delta.x : 0);
559
+ start.width +
560
+ (fromWest ? -input.delta.x : fromEast ? input.delta.x : 0) *
561
+ (resizeFromCenter ? 2 : 1);
559
562
  let height =
560
- start.height + (fromNorth ? -input.delta.y : fromSouth ? input.delta.y : 0);
563
+ start.height +
564
+ (fromNorth ? -input.delta.y : fromSouth ? input.delta.y : 0) *
565
+ (resizeFromCenter ? 2 : 1);
561
566
 
562
567
  const minWidth = input.minWidth ?? DEFAULT_CANVAS_MIN_SIZE;
563
568
  const minHeight = input.minHeight ?? DEFAULT_CANVAS_MIN_SIZE;
564
-
565
- if (
566
- input.preserveAspectRatio &&
567
- resizesHorizontally &&
568
- resizesVertically &&
569
- start.width > 0 &&
570
- start.height > 0
571
- ) {
572
- const horizontalScale = width / start.width;
573
- const verticalScale = height / start.height;
574
- const scale =
575
- Math.abs(horizontalScale - 1) >= Math.abs(verticalScale - 1)
576
- ? horizontalScale
577
- : verticalScale;
578
- const minScale = Math.max(minWidth / start.width, minHeight / start.height);
579
- width = start.width * Math.max(minScale, scale);
580
- height = start.height * Math.max(minScale, scale);
569
+ const preserveAspectRatio =
570
+ Boolean(input.preserveAspectRatio) && start.width > 0 && start.height > 0;
571
+ const widthChange = Math.abs(width - start.width);
572
+ const heightChange = Math.abs(height - start.height);
573
+ const derivesHeight =
574
+ preserveAspectRatio && resizesHorizontally && !resizesVertically;
575
+ const derivesWidth =
576
+ preserveAspectRatio && resizesVertically && !resizesHorizontally;
577
+
578
+ if (derivesHeight) {
579
+ height = width / (start.width / start.height);
580
+ } else if (derivesWidth) {
581
+ width = height * (start.width / start.height);
582
+ } else if (preserveAspectRatio && resizesHorizontally && resizesVertically) {
583
+ if (widthChange >= heightChange) {
584
+ height = width / (start.width / start.height);
585
+ } else {
586
+ width = height * (start.width / start.height);
587
+ }
581
588
  }
582
589
 
590
+ const widthBelowMinimum = width < minWidth;
591
+ const heightBelowMinimum = height < minHeight;
583
592
  width = Math.max(minWidth, width);
584
593
  height = Math.max(minHeight, height);
594
+ if (preserveAspectRatio) {
595
+ if (widthBelowMinimum && !heightBelowMinimum) {
596
+ height = Math.max(minHeight, width / (start.width / start.height));
597
+ } else if (heightBelowMinimum && !widthBelowMinimum) {
598
+ width = Math.max(minWidth, height * (start.width / start.height));
599
+ } else if (widthBelowMinimum && heightBelowMinimum) {
600
+ width = Math.max(minWidth, minHeight * (start.width / start.height));
601
+ height = width / (start.width / start.height);
602
+ }
603
+ }
604
+ const centerDerivedHeight = derivesHeight && !resizeFromCenter;
605
+ const centerDerivedWidth = derivesWidth && !resizeFromCenter;
585
606
  return {
586
- x: fromWest ? start.x + start.width - width : start.x,
587
- y: fromNorth ? start.y + start.height - height : start.y,
607
+ x:
608
+ resizeFromCenter || centerDerivedWidth
609
+ ? start.x + (start.width - width) / 2
610
+ : fromWest
611
+ ? start.x + start.width - width
612
+ : start.x,
613
+ y:
614
+ resizeFromCenter || centerDerivedHeight
615
+ ? start.y + (start.height - height) / 2
616
+ : fromNorth
617
+ ? start.y + start.height - height
618
+ : start.y,
588
619
  width,
589
620
  height,
590
621
  };
@@ -827,6 +858,7 @@ export function createCanvasGestureController<TObjectId = string>(
827
858
  rect: core.resize(gestureStart.rect, {
828
859
  handle: gestureStart.handle,
829
860
  delta: convertedDelta,
861
+ altKey: pointer.altKey,
830
862
  preserveAspectRatio: Boolean(pointer.shiftKey),
831
863
  }),
832
864
  };
@@ -0,0 +1,44 @@
1
+ // @vitest-environment happy-dom
2
+
3
+ import { act } from "react";
4
+ import { createRoot, type Root } from "react-dom/client";
5
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
6
+
7
+ import { PresenceBar } from "./PresenceBar.js";
8
+
9
+ describe("PresenceBar", () => {
10
+ let container: HTMLDivElement;
11
+ let root: Root;
12
+
13
+ beforeEach(() => {
14
+ vi.stubGlobal("IS_REACT_ACT_ENVIRONMENT", true);
15
+ container = document.createElement("div");
16
+ document.body.appendChild(container);
17
+ root = createRoot(container);
18
+ });
19
+
20
+ afterEach(() => {
21
+ act(() => root.unmount());
22
+ container.remove();
23
+ vi.restoreAllMocks();
24
+ vi.unstubAllGlobals();
25
+ });
26
+
27
+ it("gives the integrated AI editing label space after the avatar", () => {
28
+ act(() => {
29
+ root.render(
30
+ <PresenceBar
31
+ activeUsers={[]}
32
+ agentPresent
33
+ agentActive
34
+ showAgentEditingDot={false}
35
+ />,
36
+ );
37
+ });
38
+
39
+ const label = Array.from(container.querySelectorAll("span")).find(
40
+ (element) => element.textContent === "AI editing",
41
+ );
42
+ expect(label?.style.padding).toBe("0px 0px 0px 2px");
43
+ });
44
+ });
@@ -247,7 +247,7 @@ function AgentEditingChip({
247
247
  alignItems: "center",
248
248
  gap: showDot ? 4 : 0,
249
249
  height: integrated ? "auto" : 20,
250
- padding: integrated ? 0 : "0 8px",
250
+ padding: integrated ? "0 0 0 2px" : "0 8px",
251
251
  borderRadius: integrated ? 0 : 9999,
252
252
  backgroundColor: integrated ? "transparent" : `${AGENT_COLOR}20`,
253
253
  color: AGENT_COLOR,
@@ -58,9 +58,11 @@ describe("createTiptapComposerExtensions", () => {
58
58
  });
59
59
 
60
60
  it("uses compact GPT-5.6 model and effort names in the collapsed trigger", () => {
61
- expect(compactComposerModelName("gpt-5.6-sol")).toBe("Sol");
62
- expect(compactComposerModelName("gpt-5-6-terra")).toBe("Terra");
63
- expect(compactComposerModelName("openai/gpt-5.6-luna")).toBe("Luna");
61
+ expect(compactComposerModelName("gpt-5.6-sol")).toBe("GPT-5.6 Sol");
62
+ expect(compactComposerModelName("gpt-5-6-terra")).toBe("GPT-5.6 Terra");
63
+ expect(compactComposerModelName("openai/gpt-5.6-luna")).toBe(
64
+ "GPT-5.6 Luna",
65
+ );
64
66
  expect(compactComposerModelName("claude-sonnet-5")).toBe("Sonnet 5");
65
67
  expect(compactComposerModelName("codex-cli")).toBe("Codex");
66
68
  expect(compactComposerReasoningEffortLabel("medium")).toBe("Med");
@@ -934,7 +934,9 @@ export function compactComposerModelName(model: string): string {
934
934
  /^(?:openai\/)?gpt-5[.-]6[.-](sol|terra|luna)$/i,
935
935
  )?.[1];
936
936
  if (gpt56Variant) {
937
- return gpt56Variant[0].toUpperCase() + gpt56Variant.slice(1).toLowerCase();
937
+ const variant =
938
+ gpt56Variant[0].toUpperCase() + gpt56Variant.slice(1).toLowerCase();
939
+ return `GPT-5.6 ${variant}`;
938
940
  }
939
941
  return friendlyModelName(model);
940
942
  }
@@ -147,7 +147,7 @@ export function VoiceButton({ voice, isMac, disabled }: VoiceButtonProps) {
147
147
  ? "Stop recording"
148
148
  : transcribing
149
149
  ? "Transcribing…"
150
- : `Dictate (${isMac ? "⌘⇧M" : "Ctrl+Shift+M"})`;
150
+ : `Dictate (${isMac ? "Cmd Shift M" : "Ctrl Shift M"})`;
151
151
 
152
152
  const onClick = () => {
153
153
  if (recording) stop();