@orangecatai/adgen-canvas 0.0.39 → 0.1.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.
Files changed (95) hide show
  1. package/dist/dev/chunk-2K6ZAAHB.js +1535 -0
  2. package/dist/dev/chunk-2K6ZAAHB.js.map +7 -0
  3. package/dist/dev/{chunk-E7VZGEUJ.js → chunk-2Q5Z4UTF.js} +2 -2
  4. package/dist/dev/{chunk-E7VZGEUJ.js.map → chunk-2Q5Z4UTF.js.map} +1 -1
  5. package/dist/dev/{chunk-LIELFD5T.js → chunk-3WIRZ6S7.js} +6 -1
  6. package/dist/dev/chunk-3WIRZ6S7.js.map +7 -0
  7. package/dist/dev/{chunk-5XP2WJAQ.js → chunk-7XZBXIDZ.js} +1300 -1252
  8. package/dist/dev/chunk-7XZBXIDZ.js.map +7 -0
  9. package/dist/dev/chunk-AKA4GZ3R.js +62 -0
  10. package/dist/dev/chunk-AKA4GZ3R.js.map +7 -0
  11. package/dist/dev/chunk-LWUV2KR2.js +27 -0
  12. package/dist/dev/chunk-LWUV2KR2.js.map +7 -0
  13. package/dist/dev/chunk-T57LHRZV.js +2167 -0
  14. package/dist/dev/chunk-T57LHRZV.js.map +7 -0
  15. package/dist/dev/components/auto-resize/nativeResizeAgent-5XWJJ74W.js +1074 -0
  16. package/dist/dev/components/auto-resize/nativeResizeAgent-5XWJJ74W.js.map +7 -0
  17. package/dist/dev/data/{image-PUPXCX7M.js → image-MTDE3WXB.js} +4 -3
  18. package/dist/dev/index.css +618 -27
  19. package/dist/dev/index.css.map +3 -3
  20. package/dist/dev/index.js +6769 -8217
  21. package/dist/dev/index.js.map +4 -4
  22. package/dist/dev/locales/{en-VCZQBJ2N.js → en-3S2H3QGO.js} +2 -2
  23. package/dist/dev/model-capabilities.js +47 -0
  24. package/dist/dev/model-capabilities.js.map +7 -0
  25. package/dist/dev/subset-shared.chunk.js +1 -1
  26. package/dist/dev/subset-worker.chunk.js +1 -1
  27. package/dist/prod/chunk-6YYSQB5E.js +1 -0
  28. package/dist/prod/{chunk-CLQPYXMS.js → chunk-PIM2DC2L.js} +3 -3
  29. package/dist/prod/chunk-POCDVKZK.js +142 -0
  30. package/dist/prod/chunk-PWBUVPCU.js +1 -0
  31. package/dist/prod/{chunk-WBFDC4WN.js → chunk-R4DNAEVN.js} +1 -1
  32. package/dist/prod/chunk-U2I2OXQ7.js +4 -0
  33. package/dist/prod/chunk-UR7GPHHO.js +1 -0
  34. package/dist/prod/components/auto-resize/nativeResizeAgent-45UNA3LO.js +5 -0
  35. package/dist/prod/data/image-U4RMOYQQ.js +1 -0
  36. package/dist/prod/index.css +1 -1
  37. package/dist/prod/index.js +67 -298
  38. package/dist/prod/locales/{en-ZZURI326.js → en-Z3CKUL4S.js} +1 -1
  39. package/dist/prod/model-capabilities.js +1 -0
  40. package/dist/prod/subset-shared.chunk.js +1 -1
  41. package/dist/prod/subset-worker.chunk.js +1 -1
  42. package/dist/types/common/src/utils.d.ts +4 -1
  43. package/dist/types/element/src/index.d.ts +3 -0
  44. package/dist/types/element/src/newElement.d.ts +2 -1
  45. package/dist/types/element/src/textHtml.d.ts +14 -0
  46. package/dist/types/element/src/textLayout.d.ts +97 -0
  47. package/dist/types/element/src/textStyleRanges.d.ts +62 -0
  48. package/dist/types/element/src/textWrapping.d.ts +27 -0
  49. package/dist/types/element/src/types.d.ts +35 -0
  50. package/dist/types/excalidraw/actions/actionFrame.d.ts +1 -0
  51. package/dist/types/excalidraw/actions/actionLinearEditor.d.ts +1 -0
  52. package/dist/types/excalidraw/actions/actionProperties.d.ts +50 -0
  53. package/dist/types/excalidraw/actions/index.d.ts +1 -1
  54. package/dist/types/excalidraw/actions/types.d.ts +1 -1
  55. package/dist/types/excalidraw/components/AIChatPanel.d.ts +18 -2
  56. package/dist/types/excalidraw/components/App.d.ts +6 -0
  57. package/dist/types/excalidraw/components/FontSizeInput.d.ts +19 -0
  58. package/dist/types/excalidraw/components/ImageGeneratorPanel.d.ts +946 -45
  59. package/dist/types/excalidraw/components/VideoGeneratorPanel.d.ts +67 -53
  60. package/dist/types/excalidraw/components/ai-chat/ActivityTimeline.d.ts +18 -0
  61. package/dist/types/excalidraw/components/ai-chat/activitySteps.d.ts +106 -0
  62. package/dist/types/excalidraw/components/ai-chat/agentLoop.d.ts +66 -3
  63. package/dist/types/excalidraw/components/ai-chat/canvasTools.d.ts +23 -8
  64. package/dist/types/excalidraw/components/ai-chat/htmlToExcalidraw.d.ts +3 -0
  65. package/dist/types/excalidraw/components/ai-chat/openRouterStream.d.ts +13 -0
  66. package/dist/types/excalidraw/components/auto-resize/ResizeActivityCard.d.ts +7 -0
  67. package/dist/types/excalidraw/components/auto-resize/autoResizeEngine.d.ts +5 -2
  68. package/dist/types/excalidraw/components/auto-resize/autoResizeStore.d.ts +23 -0
  69. package/dist/types/excalidraw/components/auto-resize/imageBounds.d.ts +11 -0
  70. package/dist/types/excalidraw/components/auto-resize/nativeResizeAgent.d.ts +5 -0
  71. package/dist/types/excalidraw/components/auto-resize/resizeFitting.d.ts +7 -0
  72. package/dist/types/excalidraw/components/auto-resize/resizeLayout.d.ts +33 -0
  73. package/dist/types/excalidraw/components/icons.d.ts +6 -0
  74. package/dist/types/excalidraw/components/template-builder/TemplateBuilderTray.d.ts +1 -0
  75. package/dist/types/excalidraw/index.d.ts +9 -0
  76. package/dist/types/excalidraw/modelCapabilities/index.d.ts +17 -0
  77. package/dist/types/excalidraw/modelCapabilities/registry.image.d.ts +2 -0
  78. package/dist/types/excalidraw/modelCapabilities/registry.video.d.ts +2 -0
  79. package/dist/types/excalidraw/modelCapabilities/shared.d.ts +24 -0
  80. package/dist/types/excalidraw/modelCapabilities/types.d.ts +276 -0
  81. package/dist/types/excalidraw/modelCapabilities/validate.d.ts +48 -0
  82. package/dist/types/excalidraw/types.d.ts +4 -4
  83. package/dist/types/excalidraw/utils/imageApi.d.ts +3 -0
  84. package/dist/types/excalidraw/utils/referenceBudget.d.ts +12 -23
  85. package/dist/types/excalidraw/utils/videoApi.d.ts +21 -1
  86. package/dist/types/excalidraw/wysiwyg/richTextEditable.d.ts +36 -0
  87. package/dist/types/excalidraw/wysiwyg/textSelectionStyles.d.ts +32 -0
  88. package/dist/types/excalidraw/wysiwyg/textWysiwyg.d.ts +6 -2
  89. package/package.json +10 -4
  90. package/dist/dev/chunk-5XP2WJAQ.js.map +0 -7
  91. package/dist/dev/chunk-LIELFD5T.js.map +0 -7
  92. package/dist/prod/chunk-T3ZLBHX4.js +0 -4
  93. package/dist/prod/data/image-AG3CTRSJ.js +0 -1
  94. /package/dist/dev/data/{image-PUPXCX7M.js.map → image-MTDE3WXB.js.map} +0 -0
  95. /package/dist/dev/locales/{en-VCZQBJ2N.js.map → en-3S2H3QGO.js.map} +0 -0
@@ -1 +1 @@
1
- import{A,B,C,D,E,F,G,H,I,J,K,L,M,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z}from"../chunk-CLQPYXMS.js";import"../chunk-SRAX5OIU.js";export{f as alerts,e as buttons,l as canvasError,G as chat,s as clearCanvasDialog,C as colorPicker,A as colors,K as commandPalette,v as confirmDialog,M as default,i as element,b as elementLink,x as encrypted,p as errorDialog,m as errorSplash,g as errors,q as exportDialog,I as fontList,j as headings,r as helpDialog,k as hints,w as imageExportDialog,L as keys,a as labels,c as library,E as mermaid,D as overwriteConfirm,t as publishDialog,u as publishSuccessDialog,H as quickSearch,o as roomDialog,d as search,n as shareDialog,y as stats,z as toast,h as toolBar,F as ttd,J as userList,B as welcomeScreen};
1
+ import{A,B,C,D,E,F,G,H,I,J,K,L,M,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z}from"../chunk-PIM2DC2L.js";import"../chunk-SRAX5OIU.js";export{f as alerts,e as buttons,l as canvasError,G as chat,s as clearCanvasDialog,C as colorPicker,A as colors,K as commandPalette,v as confirmDialog,M as default,i as element,b as elementLink,x as encrypted,p as errorDialog,m as errorSplash,g as errors,q as exportDialog,I as fontList,j as headings,r as helpDialog,k as hints,w as imageExportDialog,L as keys,a as labels,c as library,E as mermaid,D as overwriteConfirm,t as publishDialog,u as publishSuccessDialog,H as quickSearch,o as roomDialog,d as search,n as shareDialog,y as stats,z as toast,h as toolBar,F as ttd,J as userList,B as welcomeScreen};
@@ -0,0 +1 @@
1
+ import{a,b,c as i,d as j,e as k,f as l,g as m,h as n,i as o,j as p,k as q,l as r,m as s}from"./chunk-UR7GPHHO.js";import{a as c,b as d,c as e,d as f,e as g,f as h}from"./chunk-6YYSQB5E.js";import"./chunk-R4DNAEVN.js";import"./chunk-SRAX5OIU.js";export{h as ADAPTIVE_ASPECT_RATIO,q as ALL_MODEL_CAPABILITIES,i as AUTO_DURATION,f as HOST_ASSET_BYTE_RESERVATION,a as IMAGE_MODEL_CAPABILITIES,d as MAX_REFERENCE_IMAGES,c as MAX_USER_REFERENCE_IMAGES,e as REFERENCE_WIRE_BUDGET_BYTES,g as RESOLUTION_RANK,b as VIDEO_MODEL_CAPABILITIES,o as allowedResolutionsFor,l as effectiveUserReferenceLimit,r as getCapabilities,k as groupImages,n as maxResolutionFor,j as normalizeInputs,s as registeredModelIds,m as requiredDurationFor,p as validateInputs};
@@ -1 +1 @@
1
- import{a,b,c,d}from"./chunk-Z5NKEFVG.js";import"./chunk-WBFDC4WN.js";import"./chunk-SRAX5OIU.js";export{a as Commands,b as subsetToBase64,c as subsetToBinary,d as toBase64};
1
+ import{a,b,c,d}from"./chunk-Z5NKEFVG.js";import"./chunk-R4DNAEVN.js";import"./chunk-SRAX5OIU.js";export{a as Commands,b as subsetToBase64,c as subsetToBinary,d as toBase64};
@@ -1 +1 @@
1
- import{a as r,c as t}from"./chunk-Z5NKEFVG.js";import"./chunk-WBFDC4WN.js";import"./chunk-SRAX5OIU.js";var s=import.meta.url?new URL(import.meta.url):void 0;typeof window>"u"&&typeof self<"u"&&(self.onmessage=async e=>{switch(e.data.command){case r.Subset:let a=await t(e.data.arrayBuffer,e.data.codePoints);self.postMessage(a,{transfer:[a]});break}});export{s as WorkerUrl};
1
+ import{a as r,c as t}from"./chunk-Z5NKEFVG.js";import"./chunk-R4DNAEVN.js";import"./chunk-SRAX5OIU.js";var s=import.meta.url?new URL(import.meta.url):void 0;typeof window>"u"&&typeof self<"u"&&(self.onmessage=async e=>{switch(e.data.command){case r.Subset:let a=await t(e.data.arrayBuffer,e.data.codePoints);self.postMessage(a,{transfer:[a]});break}});export{s as WorkerUrl};
@@ -14,9 +14,12 @@ export declare const getFontFamilyString: ({ fontFamily, }: {
14
14
  fontFamily: FontFamilyValues;
15
15
  }) => string;
16
16
  /** returns fontSize+fontFamily string for assignment to DOM elements */
17
- export declare const getFontString: ({ fontSize, fontFamily, }: {
17
+ export declare const getFontString: ({ fontSize, fontFamily, bold, italic, }: {
18
18
  fontSize: number;
19
19
  fontFamily: FontFamilyValues;
20
+ /** per-run overrides (rich text); omitted for uniformly styled text */
21
+ bold?: boolean;
22
+ italic?: boolean;
20
23
  }) => FontString;
21
24
  /** executes callback in the frame that's after the current one */
22
25
  export declare const nextAnimationFrame: (cb: () => any) => Promise<void>;
@@ -50,6 +50,9 @@ export * from "./store";
50
50
  export * from "./textElement";
51
51
  export * from "./textMeasurements";
52
52
  export * from "./textWrapping";
53
+ export * from "./textStyleRanges";
54
+ export * from "./textLayout";
55
+ export * from "./textHtml";
53
56
  export * from "./transform";
54
57
  export * from "./transformHandles";
55
58
  export * from "./typeChecks";
@@ -1,5 +1,5 @@
1
1
  import type { MarkOptional } from "@orangecatai/common/utility-types";
2
- import type { ExcalidrawImageElement, ExcalidrawVideoElement, ExcalidrawTextElement, ExcalidrawLinearElement, ExcalidrawGenericElement, NonDeleted, TextAlign, VerticalAlign, Arrowhead, ExcalidrawFreeDrawElement, FontFamilyValues, ExcalidrawTextContainer, ExcalidrawFrameElement, ExcalidrawEmbeddableElement, ExcalidrawMagicFrameElement, ExcalidrawIframeElement, ElementsMap, ExcalidrawArrowElement, ExcalidrawElbowArrowElement, ExcalidrawLineElement } from "./types";
2
+ import type { ExcalidrawImageElement, ExcalidrawVideoElement, ExcalidrawTextElement, ExcalidrawLinearElement, ExcalidrawGenericElement, NonDeleted, TextAlign, VerticalAlign, Arrowhead, ExcalidrawFreeDrawElement, FontFamilyValues, ExcalidrawTextContainer, ExcalidrawFrameElement, ExcalidrawEmbeddableElement, ExcalidrawMagicFrameElement, ExcalidrawIframeElement, ElementsMap, ExcalidrawArrowElement, ExcalidrawElbowArrowElement, ExcalidrawLineElement, TextStyleRange } from "./types";
3
3
  export type ElementConstructorOpts = MarkOptional<Omit<ExcalidrawGenericElement, "id" | "type" | "isDeleted" | "updated">, "width" | "height" | "angle" | "groupIds" | "frameId" | "index" | "boundElements" | "seed" | "version" | "versionNonce" | "link" | "strokeStyle" | "fillStyle" | "strokeColor" | "backgroundColor" | "roughness" | "strokeWidth" | "roundness" | "locked" | "opacity" | "customData">;
4
4
  export declare const newElement: (opts: {
5
5
  type: ExcalidrawGenericElement["type"];
@@ -26,6 +26,7 @@ export declare const newTextElement: (opts: {
26
26
  containerId?: ExcalidrawTextContainer["id"] | null;
27
27
  lineHeight?: ExcalidrawTextElement["lineHeight"];
28
28
  autoResize?: ExcalidrawTextElement["autoResize"];
29
+ styleRanges?: readonly TextStyleRange[];
29
30
  } & ElementConstructorOpts) => NonDeleted<ExcalidrawTextElement>;
30
31
  export declare const refreshTextDimensions: (textElement: ExcalidrawTextElement, container: ExcalidrawTextContainer | null, elementsMap: ElementsMap, text?: string) => {
31
32
  x: number;
@@ -0,0 +1,14 @@
1
+ import type { FontFamilyValues, TextStyleRange } from "./types";
2
+ /**
3
+ * Parses an inline HTML fragment into text + style ranges. Unknown markup is
4
+ * flattened to its text content rather than dropped.
5
+ */
6
+ export declare const parseHtmlToStyledText: (html: string) => {
7
+ text: string;
8
+ styleRanges: TextStyleRange[] | undefined;
9
+ };
10
+ /**
11
+ * Serializes styled text back to inline HTML (`<span style=...>` per run, with
12
+ * newlines as `<br>`), so a round-trip through HTML preserves formatting.
13
+ */
14
+ export declare const styledTextToHtml: (text: string, styleRanges: readonly TextStyleRange[] | undefined, getFontFamilyName?: (fontFamily: FontFamilyValues) => string) => string;
@@ -0,0 +1,97 @@
1
+ import { type ResolvedTextRunStyle } from "./textStyleRanges";
2
+ import type { ExcalidrawTextElement, FontString, TextStyleRange } from "./types";
3
+ import type { LineSlice, TextSliceMeasurer } from "./textWrapping";
4
+ /**
5
+ * Turns a text element into positioned, styled text.
6
+ *
7
+ * This is the single source of truth for text layout — measurement, the canvas
8
+ * renderer, the SVG exporter and the WYSIWYG editor all read from it, so they
9
+ * can't drift apart. For uniformly styled text (no `styleRanges`) it produces
10
+ * exactly the same numbers as the pre-rich-text code did.
11
+ */
12
+ /** the subset of a text element layout depends on */
13
+ export type TextLayoutSource = Pick<ExcalidrawTextElement, "fontSize" | "fontFamily" | "strokeColor" | "lineHeight" | "text" | "originalText" | "styleRanges">;
14
+ export type TextLayoutSegment = {
15
+ text: string;
16
+ /** offsets into the *source* text the layout was computed from */
17
+ start: number;
18
+ end: number;
19
+ style: ResolvedTextRunStyle;
20
+ fontString: FontString;
21
+ /** x offset from the start of the line, before horizontal alignment */
22
+ x: number;
23
+ width: number;
24
+ };
25
+ export type TextLayoutLine = {
26
+ text: string;
27
+ start: number;
28
+ end: number;
29
+ segments: TextLayoutSegment[];
30
+ width: number;
31
+ /** line box height — `max(run fontSize) * lineHeight` */
32
+ height: number;
33
+ /** y offset of the line box top */
34
+ y: number;
35
+ /** alphabetic baseline offset from the line box top */
36
+ baseline: number;
37
+ };
38
+ export type TextLayout = {
39
+ lines: TextLayoutLine[];
40
+ width: number;
41
+ height: number;
42
+ };
43
+ export declare const getFontStringForStyle: (style: {
44
+ fontSize: number;
45
+ fontFamily: ExcalidrawTextElement["fontFamily"];
46
+ bold?: boolean;
47
+ italic?: boolean;
48
+ }) => FontString;
49
+ /**
50
+ * A measurer that measures each style run with its own font, summing the
51
+ * pieces. With no style ranges it collapses to a single `getLineWidth` call,
52
+ * i.e. to the exact pre-rich-text behaviour.
53
+ */
54
+ export declare const createElementMeasurer: (text: string, element: TextLayoutSource, ranges: readonly TextStyleRange[] | undefined) => TextSliceMeasurer;
55
+ /**
56
+ * Wraps an element's `originalText` to `maxWidth`, returning both the wrapped
57
+ * string (what gets stored as `element.text`) and the source slices it came
58
+ * from.
59
+ */
60
+ export declare const wrapTextForElement: (element: TextLayoutSource, maxWidth: number) => {
61
+ text: string;
62
+ slices: LineSlice[];
63
+ };
64
+ /**
65
+ * Recovers, for an already-wrapped `element.text`, which slice of
66
+ * `originalText` each line came from.
67
+ *
68
+ * Wrapping only ever drops trailing whitespace and inserts line breaks, so
69
+ * every wrapped line is a contiguous slice of the source. Returns `null` if the
70
+ * two have drifted apart (e.g. `text` was set independently), in which case
71
+ * callers fall back to treating `text` as the source.
72
+ */
73
+ export declare const mapWrappedTextToSource: (originalText: string, text: string) => LineSlice[] | null;
74
+ /**
75
+ * Lays out an element's (already wrapped) text.
76
+ */
77
+ export declare const layoutTextElement: (element: TextLayoutSource) => TextLayout;
78
+ /**
79
+ * Measures an element's text, run-aware. Equivalent to `measureText` for
80
+ * uniformly styled text.
81
+ */
82
+ export declare const measureTextElement: (element: TextLayoutSource) => {
83
+ width: number;
84
+ height: number;
85
+ };
86
+ /**
87
+ * Style-aware `measureText`. Uniformly styled text takes the original,
88
+ * cheaper path so its measurements are unchanged.
89
+ */
90
+ export declare const measureElementText: (element: TextLayoutSource, text?: string, originalText?: string) => {
91
+ width: number;
92
+ height: number;
93
+ };
94
+ /**
95
+ * Style-aware `wrapText`, wrapping `source` (an element's unwrapped text).
96
+ */
97
+ export declare const wrapElementText: (element: TextLayoutSource, source: string, maxWidth: number) => string;
@@ -0,0 +1,62 @@
1
+ import type { ExcalidrawTextElement, FontFamilyValues, TextRunStyle, TextStyleRange } from "./types";
2
+ declare const STYLE_KEYS: readonly ["fontFamily", "fontSize", "color", "bold", "italic", "underline", "strikethrough", "highlight"];
3
+ export type TextRunStyleKey = typeof STYLE_KEYS[number];
4
+ /**
5
+ * Strips fields that carry no information (unset, or `false` for booleans
6
+ * whose base value is always `false`), so that equal styles compare equal and
7
+ * merging works. Returns `undefined` when nothing is left.
8
+ */
9
+ export declare const sanitizeStyle: (style: TextRunStyle | undefined | null) => TextRunStyle | undefined;
10
+ export declare const isSameStyle: (a: TextRunStyle | undefined, b: TextRunStyle | undefined) => boolean;
11
+ export declare const normalizeStyleRanges: (ranges: readonly TextStyleRange[] | undefined | null, textLength: number) => TextStyleRange[] | undefined;
12
+ /**
13
+ * Applies a style patch to `[start, end)`, merging into whatever is already
14
+ * there. A patch field explicitly set to `undefined` *removes* that override.
15
+ */
16
+ export declare const applyStyleToRange: (ranges: readonly TextStyleRange[] | undefined, start: number, end: number, patch: TextRunStyle, textLength: number) => TextStyleRange[] | undefined;
17
+ export declare const getStyleAtOffset: (ranges: readonly TextStyleRange[] | undefined, offset: number) => TextRunStyle;
18
+ /**
19
+ * The style shared by every character in `[start, end)`. Fields that differ
20
+ * across the range are reported in `mixed` instead (the properties panel uses
21
+ * this to show a "mixed" state).
22
+ */
23
+ export declare const getCommonStyleInRange: (ranges: readonly TextStyleRange[] | undefined, start: number, end: number) => {
24
+ style: TextRunStyle;
25
+ mixed: TextRunStyleKey[];
26
+ };
27
+ export type TextRun = {
28
+ text: string;
29
+ start: number;
30
+ end: number;
31
+ style: TextRunStyle;
32
+ };
33
+ /**
34
+ * Splits `text` into consecutive runs covering the whole string, including
35
+ * unstyled gaps (which get an empty style object).
36
+ */
37
+ export declare const splitTextIntoRuns: (text: string, ranges: readonly TextStyleRange[] | undefined) => TextRun[];
38
+ /**
39
+ * Remaps ranges across a text splice (`deleteCount` chars removed at `index`,
40
+ * `insertLength` chars inserted there).
41
+ *
42
+ * Offsets at or after the splice point move, which means text typed at the end
43
+ * of a styled range extends it, while text typed at its start does not — the
44
+ * same behaviour as the browser's own inline editing.
45
+ */
46
+ export declare const spliceStyleRanges: (ranges: readonly TextStyleRange[] | undefined, index: number, deleteCount: number, insertLength: number, nextTextLength: number) => TextStyleRange[] | undefined;
47
+ /** Derives the splice from old/new text (common prefix + suffix diff). */
48
+ export declare const remapStyleRangesForTextChange: (ranges: readonly TextStyleRange[] | undefined, oldText: string, newText: string) => TextStyleRange[] | undefined;
49
+ export type ResolvedTextRunStyle = {
50
+ fontFamily: FontFamilyValues;
51
+ fontSize: number;
52
+ color: string;
53
+ bold: boolean;
54
+ italic: boolean;
55
+ underline: boolean;
56
+ strikethrough: boolean;
57
+ highlight?: string;
58
+ };
59
+ /** Overlays a run style onto the element-level base style. */
60
+ export declare const resolveRunStyle: (element: Pick<ExcalidrawTextElement, "fontFamily" | "fontSize" | "strokeColor">, style: TextRunStyle | undefined) => ResolvedTextRunStyle;
61
+ export declare const hasStyleRanges: (element: Pick<ExcalidrawTextElement, "styleRanges">) => boolean;
62
+ export {};
@@ -7,7 +7,34 @@ export declare const containsCJK: (text: string) => boolean;
7
7
  * Breaks the line into the tokens based on the found line break opporutnities.
8
8
  */
9
9
  export declare const parseTokens: (line: string) => string[];
10
+ /**
11
+ * A half-open `[start, end)` slice of the source text making up one laid-out
12
+ * line. Every wrapped line is a *contiguous* slice of the source (wrapping only
13
+ * ever drops trailing whitespace), which is what lets style ranges — indexed
14
+ * against the source text — survive wrapping.
15
+ */
16
+ export type LineSlice = {
17
+ start: number;
18
+ end: number;
19
+ };
20
+ /**
21
+ * Measures slices of the source text. Implementations decide how the text is
22
+ * styled; for uniformly styled text this is a single `getLineWidth` call, for
23
+ * rich text the slice is measured run by run (see `textLayout.ts`).
24
+ */
25
+ export type TextSliceMeasurer = {
26
+ /** width of `text.slice(start, end)` */
27
+ measureSlice: (start: number, end: number) => number;
28
+ /** width of the single character at `offset` (cached) */
29
+ measureChar: (offset: number, char: string) => number;
30
+ };
31
+ export declare const createUniformMeasurer: (text: string, font: FontString) => TextSliceMeasurer;
10
32
  /**
11
33
  * Wraps the original text into the lines based on the given width.
12
34
  */
13
35
  export declare const wrapText: (text: string, font: FontString, maxWidth: number) => string;
36
+ /**
37
+ * Offset-preserving core of the wrapping algorithm: returns the laid-out lines
38
+ * as slices of `text` instead of as strings.
39
+ */
40
+ export declare const wrapTextIntoSlices: (text: string, measurer: TextSliceMeasurer, maxWidth: number) => LineSlice[];
@@ -182,6 +182,35 @@ export type NonDeleted<TElement extends ExcalidrawElement> = TElement & {
182
182
  isDeleted: boolean;
183
183
  };
184
184
  export type NonDeletedExcalidrawElement = NonDeleted<ExcalidrawElement>;
185
+ /**
186
+ * Per-range ("run") text style overrides. Every field is optional — an unset
187
+ * field falls back to the element-level property (`fontSize`, `fontFamily`,
188
+ * `strokeColor`), which remains the base style of the element.
189
+ */
190
+ export type TextRunStyle = {
191
+ fontFamily?: FontFamilyValues;
192
+ fontSize?: number;
193
+ /** falls back to the element's `strokeColor` */
194
+ color?: string;
195
+ bold?: boolean;
196
+ italic?: boolean;
197
+ underline?: boolean;
198
+ strikethrough?: boolean;
199
+ /** background painted behind the run */
200
+ highlight?: string;
201
+ };
202
+ /**
203
+ * A styled slice of a text element. Offsets are half-open `[start, end)`
204
+ * indices into the element's `originalText`.
205
+ *
206
+ * Ranges are kept normalized: sorted, non-overlapping, clamped to the text
207
+ * length, with adjacent equal-styled ranges merged. See `textStyleRanges.ts`.
208
+ */
209
+ export type TextStyleRange = {
210
+ start: number;
211
+ end: number;
212
+ style: TextRunStyle;
213
+ };
185
214
  export type ExcalidrawTextElement = _ExcalidrawElementBase & Readonly<{
186
215
  type: "text";
187
216
  fontSize: number;
@@ -205,6 +234,12 @@ export type ExcalidrawTextElement = _ExcalidrawElementBase & Readonly<{
205
234
  lineHeight: number & {
206
235
  _brand: "unitlessLineHeight";
207
236
  };
237
+ /**
238
+ * Per-range style overrides, indexed against `originalText`.
239
+ * `undefined` (the default) means uniformly styled text, in which case
240
+ * every code path behaves exactly as it did before rich text existed.
241
+ */
242
+ styleRanges?: readonly TextStyleRange[];
208
243
  }>;
209
244
  export type ExcalidrawBindableElement = ExcalidrawRectangleElement | ExcalidrawDiamondElement | ExcalidrawEllipseElement | ExcalidrawTextElement | ExcalidrawImageElement | ExcalidrawIframeElement | ExcalidrawEmbeddableElement | ExcalidrawFrameElement | ExcalidrawMagicFrameElement;
210
245
  export type ExcalidrawTextContainer = ExcalidrawRectangleElement | ExcalidrawDiamondElement | ExcalidrawEllipseElement | ExcalidrawArrowElement;
@@ -1325,6 +1325,7 @@ export declare const actionWrapSelectionInFrame: {
1325
1325
  lineHeight: number & {
1326
1326
  _brand: "unitlessLineHeight";
1327
1327
  };
1328
+ styleRanges?: readonly import("@orangecatai/element/types").TextStyleRange[];
1328
1329
  }> & {
1329
1330
  index: import("@orangecatai/element/types").FractionalIndex;
1330
1331
  }) | (Readonly<{
@@ -655,6 +655,7 @@ export declare const actionTogglePolygon: {
655
655
  lineHeight: number & {
656
656
  _brand: "unitlessLineHeight";
657
657
  };
658
+ styleRanges?: readonly import("@orangecatai/element/types").TextStyleRange[];
658
659
  }> & {
659
660
  index: import("@orangecatai/element/types").FractionalIndex;
660
661
  }) | (Readonly<{
@@ -24,6 +24,47 @@ export declare const actionChangeStrokeStyle: import("./types").Action<import("@
24
24
  export declare const actionChangeOpacity: import("./types").Action<number> & {
25
25
  keyTest?: ((event: React.KeyboardEvent | KeyboardEvent, appState: AppState, elements: readonly ExcalidrawElement[], app: AppClassProperties) => boolean) | undefined;
26
26
  };
27
+ /**
28
+ * Per-run text styles that have no element-level equivalent (bold, italic,
29
+ * underline, strikethrough).
30
+ *
31
+ * With text being edited and part of it highlighted, the toggle applies to
32
+ * that range only; otherwise it applies to the whole of each selected text
33
+ * element (as a range spanning all of it).
34
+ */
35
+ declare const TEXT_STYLE_TOGGLES: readonly [{
36
+ readonly key: "bold";
37
+ readonly labelKey: "labels.bold";
38
+ readonly icon: import("react/jsx-runtime").JSX.Element;
39
+ readonly testId: "bold";
40
+ }, {
41
+ readonly key: "italic";
42
+ readonly labelKey: "labels.italic";
43
+ readonly icon: import("react/jsx-runtime").JSX.Element;
44
+ readonly testId: "italic";
45
+ }, {
46
+ readonly key: "underline";
47
+ readonly labelKey: "labels.underline";
48
+ readonly icon: import("react/jsx-runtime").JSX.Element;
49
+ readonly testId: "underline";
50
+ }, {
51
+ readonly key: "strikethrough";
52
+ readonly labelKey: "labels.strikethrough";
53
+ readonly icon: import("react/jsx-runtime").JSX.Element;
54
+ readonly testId: "strikethrough";
55
+ }, {
56
+ readonly key: "highlight";
57
+ readonly labelKey: "labels.textHighlight";
58
+ readonly icon: import("react/jsx-runtime").JSX.Element;
59
+ readonly testId: "highlight";
60
+ }];
61
+ type TextStyleToggleKey = typeof TEXT_STYLE_TOGGLES[number]["key"];
62
+ export declare const actionChangeTextStyle: import("./types").Action<{
63
+ key: TextStyleToggleKey;
64
+ value: boolean;
65
+ }> & {
66
+ keyTest?: ((event: React.KeyboardEvent | KeyboardEvent, appState: AppState, elements: readonly ExcalidrawElement[], app: AppClassProperties) => boolean) | undefined;
67
+ };
27
68
  export declare const actionChangeFontSize: import("./types").Action<number> & {
28
69
  keyTest?: ((event: React.KeyboardEvent | KeyboardEvent, appState: AppState, elements: readonly ExcalidrawElement[], app: AppClassProperties) => boolean) | undefined;
29
70
  };
@@ -33,6 +74,10 @@ export declare const actionDecreaseFontSize: {
33
74
  icon: import("react/jsx-runtime").JSX.Element;
34
75
  trackEvent: false;
35
76
  perform: (elements: readonly import("@orangecatai/element/types").OrderedExcalidrawElement[], appState: Readonly<AppState>, value: unknown, app: AppClassProperties) => {
77
+ appState: AppState;
78
+ captureUpdate: "IMMEDIATELY";
79
+ elements?: undefined;
80
+ } | {
36
81
  elements: ExcalidrawElement[];
37
82
  appState: {
38
83
  currentItemFontSize: number;
@@ -205,6 +250,10 @@ export declare const actionIncreaseFontSize: {
205
250
  icon: import("react/jsx-runtime").JSX.Element;
206
251
  trackEvent: false;
207
252
  perform: (elements: readonly import("@orangecatai/element/types").OrderedExcalidrawElement[], appState: Readonly<AppState>, value: unknown, app: AppClassProperties) => {
253
+ appState: AppState;
254
+ captureUpdate: "IMMEDIATELY";
255
+ elements?: undefined;
256
+ } | {
208
257
  elements: ExcalidrawElement[];
209
258
  appState: {
210
259
  currentItemFontSize: number;
@@ -404,3 +453,4 @@ export declare const actionChangeArrowProperties: {
404
453
  export declare const actionChangeArrowType: import("./types").Action<"round" | "sharp" | "elbow"> & {
405
454
  keyTest?: ((event: React.KeyboardEvent | KeyboardEvent, appState: AppState, elements: readonly ExcalidrawElement[], app: AppClassProperties) => boolean) | undefined;
406
455
  };
456
+ export {};
@@ -2,7 +2,7 @@ export { actionDeleteSelected } from "./actionDeleteSelected";
2
2
  export { actionBringForward, actionBringToFront, actionSendBackward, actionSendToBack, } from "./actionZindex";
3
3
  export { actionSelectAll } from "./actionSelectAll";
4
4
  export { actionDuplicateSelection } from "./actionDuplicateSelection";
5
- export { actionChangeStrokeColor, actionChangeBackgroundColor, actionChangeStrokeWidth, actionChangeFillStyle, actionChangeSloppiness, actionChangeOpacity, actionChangeFontSize, actionChangeFontFamily, actionChangeTextAlign, actionChangeVerticalAlign, actionChangeArrowProperties, } from "./actionProperties";
5
+ export { actionChangeStrokeColor, actionChangeBackgroundColor, actionChangeStrokeWidth, actionChangeFillStyle, actionChangeSloppiness, actionChangeOpacity, actionChangeFontSize, actionChangeTextStyle, actionChangeFontFamily, actionChangeTextAlign, actionChangeVerticalAlign, actionChangeArrowProperties, } from "./actionProperties";
6
6
  export { actionChangeViewBackgroundColor, actionClearCanvas, actionZoomIn, actionZoomOut, actionResetZoom, actionScrollBackToContent, actionZoomToFit, actionToggleTheme, } from "./actionCanvas";
7
7
  export { actionSetEmbeddableAsActiveTool } from "./actionEmbeddable";
8
8
  export { actionFinalize } from "./actionFinalize";
@@ -14,7 +14,7 @@ export type ActionResult = {
14
14
  type ActionFn<TData = any> = (elements: readonly OrderedExcalidrawElement[], appState: Readonly<AppState>, formData: TData | undefined, app: AppClassProperties) => ActionResult | Promise<ActionResult>;
15
15
  export type UpdaterFn = (res: ActionResult) => void;
16
16
  export type ActionFilterFn = (action: Action) => void;
17
- export type ActionName = "copy" | "cut" | "paste" | "copyAsPng" | "copyAsSvg" | "copyText" | "sendBackward" | "bringForward" | "sendToBack" | "bringToFront" | "copyStyles" | "selectAll" | "pasteStyles" | "gridMode" | "zenMode" | "objectsSnapMode" | "stats" | "changeStrokeColor" | "changeBackgroundColor" | "changeFillStyle" | "changeStrokeWidth" | "changeStrokeShape" | "changeSloppiness" | "changeStrokeStyle" | "changeArrowhead" | "changeArrowType" | "changeArrowProperties" | "changeOpacity" | "changeFontSize" | "undo" | "redo" | "finalize" | "changeProjectName" | "changeExportBackground" | "changeExportEmbedScene" | "changeExportScale" | "saveToActiveFile" | "saveFileToDisk" | "loadScene" | "duplicateSelection" | "deleteSelectedElements" | "changeViewBackgroundColor" | "clearCanvas" | "zoomIn" | "zoomOut" | "resetZoom" | "scrollBackToContent" | "zoomToFit" | "zoomToFitSelection" | "zoomToFitSelectionInViewport" | "changeFontFamily" | "changeTextAlign" | "changeVerticalAlign" | "toggleFullScreen" | "toggleShortcuts" | "group" | "ungroup" | "goToCollaborator" | "addToLibrary" | "changeRoundness" | "alignTop" | "alignBottom" | "alignLeft" | "alignRight" | "alignVerticallyCentered" | "alignHorizontallyCentered" | "distributeHorizontally" | "distributeVertically" | "flipHorizontal" | "flipVertical" | "viewMode" | "exportWithDarkMode" | "toggleTheme" | "increaseFontSize" | "decreaseFontSize" | "unbindText" | "hyperlink" | "bindText" | "unlockAllElements" | "toggleElementLock" | "toggleLinearEditor" | "toggleEraserTool" | "toggleHandTool" | "selectAllElementsInFrame" | "removeAllElementsFromFrame" | "updateFrameRendering" | "setFrameAsActiveTool" | "setEmbeddableAsActiveTool" | "openImageGenerator" | "openVideoGenerator" | "createContainerFromText" | "wrapTextInContainer" | "commandPalette" | "autoResize" | "elementStats" | "searchMenu" | "copyElementLink" | "linkToElement" | "cropEditor" | "wrapSelectionInFrame" | "cycleThroughFrameChildren" | "toggleLassoTool" | "toggleShapeSwitch" | "togglePolygon";
17
+ export type ActionName = "copy" | "cut" | "paste" | "copyAsPng" | "copyAsSvg" | "copyText" | "sendBackward" | "bringForward" | "sendToBack" | "bringToFront" | "copyStyles" | "selectAll" | "pasteStyles" | "gridMode" | "zenMode" | "objectsSnapMode" | "stats" | "changeStrokeColor" | "changeBackgroundColor" | "changeFillStyle" | "changeStrokeWidth" | "changeStrokeShape" | "changeSloppiness" | "changeStrokeStyle" | "changeArrowhead" | "changeArrowType" | "changeArrowProperties" | "changeOpacity" | "changeFontSize" | "changeTextStyle" | "undo" | "redo" | "finalize" | "changeProjectName" | "changeExportBackground" | "changeExportEmbedScene" | "changeExportScale" | "saveToActiveFile" | "saveFileToDisk" | "loadScene" | "duplicateSelection" | "deleteSelectedElements" | "changeViewBackgroundColor" | "clearCanvas" | "zoomIn" | "zoomOut" | "resetZoom" | "scrollBackToContent" | "zoomToFit" | "zoomToFitSelection" | "zoomToFitSelectionInViewport" | "changeFontFamily" | "changeTextAlign" | "changeVerticalAlign" | "toggleFullScreen" | "toggleShortcuts" | "group" | "ungroup" | "goToCollaborator" | "addToLibrary" | "changeRoundness" | "alignTop" | "alignBottom" | "alignLeft" | "alignRight" | "alignVerticallyCentered" | "alignHorizontallyCentered" | "distributeHorizontally" | "distributeVertically" | "flipHorizontal" | "flipVertical" | "viewMode" | "exportWithDarkMode" | "toggleTheme" | "increaseFontSize" | "decreaseFontSize" | "unbindText" | "hyperlink" | "bindText" | "unlockAllElements" | "toggleElementLock" | "toggleLinearEditor" | "toggleEraserTool" | "toggleHandTool" | "selectAllElementsInFrame" | "removeAllElementsFromFrame" | "updateFrameRendering" | "setFrameAsActiveTool" | "setEmbeddableAsActiveTool" | "openImageGenerator" | "openVideoGenerator" | "createContainerFromText" | "wrapTextInContainer" | "commandPalette" | "autoResize" | "elementStats" | "searchMenu" | "copyElementLink" | "linkToElement" | "cropEditor" | "wrapSelectionInFrame" | "cycleThroughFrameChildren" | "toggleLassoTool" | "toggleShapeSwitch" | "togglePolygon";
18
18
  export type PanelComponentProps = {
19
19
  elements: readonly ExcalidrawElement[];
20
20
  appState: AppState;
@@ -1,5 +1,6 @@
1
1
  import React from "react";
2
2
  import { type ToolAction, type FrameGenerationMeta } from "./ai-chat/agentLoop";
3
+ import { type ActivityStep } from "./ai-chat/activitySteps";
3
4
  import "./AIChatPanel.scss";
4
5
  import type { ReviewerFeedback } from "./ai-chat/reviewerAgent";
5
6
  import type { ExcalidrawImperativeAPI } from "../types";
@@ -9,6 +10,13 @@ export type ChatMessage = {
9
10
  content: string;
10
11
  timestamp: Date;
11
12
  toolActions?: ToolAction[];
13
+ /**
14
+ * What the agent actually did on this turn — thinking, tool calls, reviewer
15
+ * rounds — in order. Rendered inline as a timeline and persisted by the host,
16
+ * so the work stays visible after a reload. Absent on messages saved before
17
+ * activity steps existed; those fall back to `toolActions`.
18
+ */
19
+ steps?: ActivityStep[];
12
20
  attachments?: Array<{
13
21
  name: string;
14
22
  type: "image" | "text" | "pdf" | "docx";
@@ -131,8 +139,8 @@ export type AIChatPanelProps = {
131
139
  transcribeUrl?: string;
132
140
  /**
133
141
  * OpenRouter model ID used by the agent's generate_image tool.
134
- * @default "openai/gpt-image-2"
135
- * @example "google/gemini-3.1-flash-image-preview"
142
+ * @default "openai/gpt-image-2.5-flare"
143
+ * @example "google/gemini-3.1-flash-lite-image"
136
144
  */
137
145
  agentImageModel?: string;
138
146
  /**
@@ -211,5 +219,13 @@ export type AIChatPanelProps = {
211
219
  * @default 2
212
220
  */
213
221
  maxReviewRounds?: number;
222
+ /**
223
+ * Ask the model for reasoning tokens and stream them into the activity
224
+ * timeline's "Thinking" block. Leave unset to send no `reasoning` field at
225
+ * all — the timeline then narrates the agent's own steps instead, which
226
+ * costs nothing extra and is also what happens for models that return no
227
+ * reasoning.
228
+ */
229
+ reasoningEffort?: "low" | "medium" | "high";
214
230
  };
215
231
  export declare const AIChatPanel: React.ForwardRefExoticComponent<AIChatPanelProps & React.RefAttributes<AIChatPanelRef>>;
@@ -367,6 +367,12 @@ declare class App extends React.Component<AppProps, AppState> {
367
367
  fitToContent?: boolean;
368
368
  }) => void;
369
369
  private addElementsFromMixedContentPaste;
370
+ /**
371
+ * Text is painted with `strokeColor`, but the default stroke color is
372
+ * `transparent` (shapes are fill-only by default here) — which would make
373
+ * every new text element invisible. Text falls back to black.
374
+ */
375
+ private getCurrentItemTextColor;
370
376
  private addTextFromPaste;
371
377
  setAppState: React.Component<any, AppState>["setState"];
372
378
  removePointer: (event: React.PointerEvent<HTMLElement> | PointerEvent) => void;
@@ -0,0 +1,19 @@
1
+ import "./FontSizeInput.scss";
2
+ export declare const MIN_FONT_SIZE = 1;
3
+ export declare const MAX_FONT_SIZE = 9999;
4
+ export interface FontSizeInputProps {
5
+ /** current font size, or `null` when the selection has mixed sizes */
6
+ value: number | null;
7
+ onChange: (value: number) => void;
8
+ /** size to step from when the current value is mixed */
9
+ fallbackValue?: number;
10
+ }
11
+ /**
12
+ * Numeric font size control (type a size, or step it with the +/- buttons and
13
+ * the arrow keys), replacing the S/M/L/XL presets.
14
+ *
15
+ * Typing doesn't commit on every keystroke — otherwise typing "120" would
16
+ * resize the text to 1, then 12, then 120, each an undo step. The value is
17
+ * committed on Enter and on blur; Escape reverts.
18
+ */
19
+ export declare const FontSizeInput: ({ value, onChange, fallbackValue, }: FontSizeInputProps) => import("react/jsx-runtime").JSX.Element;