@canva/design 2.6.1 → 2.7.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/index.d.ts CHANGED
@@ -2,12 +2,131 @@
2
2
  * Adds an audio track to the user's design.
3
3
  * @public
4
4
  * @param audioTrack - The audio track to add to the user's design.
5
+ *
6
+ * @example Add audio track to design
7
+ * ```typescript
8
+ * import { addAudioTrack } from "@canva/design";
9
+ * import type { AudioTrack } from "@canva/design";
10
+ * import type { AudioRef } from "@canva/asset";
11
+ *
12
+ * const exampleAudioRef = "YOUR_AUDIO_REF" as AudioRef;
13
+ *
14
+ * const audioTrack: AudioTrack = {
15
+ * ref: exampleAudioRef
16
+ * };
17
+ *
18
+ * await addAudioTrack(audioTrack);
19
+ * ```
5
20
  */
6
21
  export declare const addAudioTrack: (audioTrack: AudioTrack) => Promise<void>;
7
22
 
8
23
  /**
9
24
  * @public
10
25
  * Add element to responsive documents, which slot things into a text stream
26
+ *
27
+ * @example Insert an image at cursor position
28
+ * ```typescript
29
+ * import { addElementAtCursor } from "@canva/design";
30
+ * import type { ImageElement } from "@canva/design";
31
+ * import type { ImageRef } from "@canva/asset";
32
+ *
33
+ * const exampleImageRef = "YOUR_IMAGE_REF" as ImageRef;
34
+ *
35
+ * const imageElement: ImageElement = {
36
+ * type: 'image',
37
+ * ref: exampleImageRef,
38
+ * altText: { text: 'Product image', decorative: false }
39
+ * };
40
+ *
41
+ * await addElementAtCursor(imageElement);
42
+ * ```
43
+ *
44
+ * @example Insert a video at cursor position
45
+ * ```typescript
46
+ * import { addElementAtCursor } from "@canva/design";
47
+ * import type { VideoElement } from "@canva/design";
48
+ * import type { VideoRef } from "@canva/asset";
49
+ *
50
+ * const exampleVideoRef = "YOUR_VIDEO_REF" as VideoRef;
51
+ *
52
+ * const videoElement: VideoElement = {
53
+ * type: 'video',
54
+ * ref: exampleVideoRef,
55
+ * altText: { text: 'Product demo', decorative: false }
56
+ * };
57
+ *
58
+ * await addElementAtCursor(videoElement);
59
+ * ```
60
+ *
61
+ * @example Insert embedded content at cursor position
62
+ * ```typescript
63
+ * import { addElementAtCursor } from "@canva/design";
64
+ * import type { EmbedElement } from "@canva/design";
65
+ *
66
+ * const embedElement: EmbedElement = {
67
+ * type: 'embed',
68
+ * url: 'https://www.youtube.com/watch?v=...'
69
+ * };
70
+ *
71
+ * await addElementAtCursor(embedElement);
72
+ * ```
73
+ *
74
+ * @example Insert text at cursor position
75
+ * ```typescript
76
+ * import { addElementAtCursor } from "@canva/design";
77
+ * import type { TextElement } from "@canva/design";
78
+ *
79
+ * const textElement: TextElement = {
80
+ * type: 'text',
81
+ * children: ['Hello World'],
82
+ * fontSize: 24,
83
+ * color: '#000000'
84
+ * };
85
+ *
86
+ * await addElementAtCursor(textElement);
87
+ * ```
88
+ *
89
+ * @example Insert formatted text at cursor position
90
+ * ```typescript
91
+ * import { addElementAtCursor, createRichtextRange } from "@canva/design";
92
+ * import type { RichtextElement } from "@canva/design";
93
+ *
94
+ * const range = createRichtextRange();
95
+ * range.appendText('Rich Text Content', { color: '#000000' });
96
+ *
97
+ * const richtextElement: RichtextElement = {
98
+ * type: 'richtext',
99
+ * range
100
+ * };
101
+ *
102
+ * await addElementAtCursor(richtextElement);
103
+ * ```
104
+ *
105
+ * @example Insert a table at cursor position
106
+ * ```typescript
107
+ * import { addElementAtCursor } from "@canva/design";
108
+ * import type { TableElement } from "@canva/design";
109
+ *
110
+ * const tableElement: TableElement = {
111
+ * type: 'table',
112
+ * rows: [
113
+ * {
114
+ * cells: [
115
+ * { type: 'string', value: 'Header 1' },
116
+ * { type: 'string', value: 'Header 2' }
117
+ * ]
118
+ * },
119
+ * {
120
+ * cells: [
121
+ * { type: 'string', value: 'Data 1' },
122
+ * { type: 'string', value: 'Data 2' }
123
+ * ]
124
+ * }
125
+ * ]
126
+ * };
127
+ *
128
+ * await addElementAtCursor(tableElement);
129
+ * ```
11
130
  */
12
131
  export declare const addElementAtCursor: (
13
132
  element: ElementAtCursor,
@@ -16,6 +135,84 @@ export declare const addElementAtCursor: (
16
135
  /**
17
136
  * @public
18
137
  * Add element to fixed designs, which use a coordinate-based positioning system.
138
+ *
139
+ * @example Insert an image at specific coordinates
140
+ * ```typescript
141
+ * import { addElementAtPoint } from "@canva/design";
142
+ * import type { ImageElementAtPoint } from "@canva/design";
143
+ * import type { ImageRef } from "@canva/asset";
144
+ *
145
+ * const exampleImageRef = "YOUR_IMAGE_REF" as ImageRef;
146
+ *
147
+ * const imageElement: ImageElementAtPoint = {
148
+ * type: 'image',
149
+ * ref: exampleImageRef,
150
+ * altText: { text: 'Product image', decorative: false },
151
+ * top: 100,
152
+ * left: 100,
153
+ * width: 300,
154
+ * height: 200
155
+ * };
156
+ *
157
+ * await addElementAtPoint(imageElement);
158
+ * ```
159
+ *
160
+ * @example Insert a video at specific coordinates
161
+ * ```typescript
162
+ * import { addElementAtPoint } from "@canva/design";
163
+ * import type { VideoElementAtPoint } from "@canva/design";
164
+ * import type { VideoRef } from "@canva/asset";
165
+ *
166
+ * const exampleVideoRef = "YOUR_VIDEO_REF" as VideoRef;
167
+ *
168
+ * const videoElement: VideoElementAtPoint = {
169
+ * type: 'video',
170
+ * ref: exampleVideoRef,
171
+ * altText: { text: 'Product demo', decorative: false },
172
+ * top: 100,
173
+ * left: 100,
174
+ * width: 400,
175
+ * height: 300
176
+ * };
177
+ *
178
+ * await addElementAtPoint(videoElement);
179
+ * ```
180
+ *
181
+ * @example Insert embedded content at specific coordinates
182
+ * ```typescript
183
+ * import { addElementAtPoint } from "@canva/design";
184
+ * import type { EmbedElementAtPoint } from "@canva/design";
185
+ *
186
+ * const embedElement: EmbedElementAtPoint = {
187
+ * type: 'embed',
188
+ * url: 'https://www.youtube.com/watch?v=...',
189
+ * top: 100,
190
+ * left: 100,
191
+ * width: 560,
192
+ * height: 315
193
+ * };
194
+ *
195
+ * await addElementAtPoint(embedElement);
196
+ * ```
197
+ *
198
+ * @example Insert text at specific coordinates
199
+ * ```typescript
200
+ * import { addElementAtPoint } from "@canva/design";
201
+ * import type { TextElementAtPoint } from "@canva/design";
202
+ *
203
+ * const textElement: TextElementAtPoint = {
204
+ * type: 'text',
205
+ * children: ['Hello World'],
206
+ * top: 100,
207
+ * left: 100,
208
+ * width: 200,
209
+ * fontSize: 24,
210
+ * color: '#000000',
211
+ * textAlign: 'justify'
212
+ * };
213
+ *
214
+ * await addElementAtPoint(textElement);
215
+ * ```
19
216
  */
20
217
  export declare const addElementAtPoint: (
21
218
  element: DesignElement | ElementAtPoint,
@@ -26,6 +223,22 @@ export declare const addElementAtPoint: (
26
223
  * @public
27
224
  * Adds a native element to the user's design.
28
225
  * @param element - The element to add to the user's design.
226
+ *
227
+ * @example Basic usage
228
+ * ```typescript
229
+ * import { addNativeElement } from "@canva/design";
230
+ * import type { NativeElementWithBox } from "@canva/design";
231
+ *
232
+ * const element: NativeElementWithBox = {
233
+ * type: 'text',
234
+ * children: ['Legacy element'],
235
+ * top: 100,
236
+ * left: 100,
237
+ * width: 200
238
+ * };
239
+ *
240
+ * await addNativeElement(element);
241
+ * ```
29
242
  */
30
243
  export declare const addNativeElement: (
31
244
  element: NativeElement | NativeElementWithBox,
@@ -35,6 +248,94 @@ export declare const addNativeElement: (
35
248
  * @public
36
249
  * Adds a new page immediately after the currently selected page.
37
250
  * @param opts - Configuration for the new page to be added.
251
+ *
252
+ * @example Create empty page
253
+ * ```typescript
254
+ * import { addPage } from "@canva/design";
255
+ *
256
+ * await addPage();
257
+ * ```
258
+ *
259
+ * @example Create page with title
260
+ * ```typescript
261
+ * import { addPage } from "@canva/design";
262
+ *
263
+ * await addPage({
264
+ * title: 'My New Page'
265
+ * });
266
+ * ```
267
+ *
268
+ * @example Create page with background color
269
+ * ```typescript
270
+ * import { addPage } from "@canva/design";
271
+ * import type { PageBackgroundFill } from "@canva/design";
272
+ *
273
+ * const background: PageBackgroundFill = {
274
+ * color: '#F5F5F5',
275
+ * };
276
+ *
277
+ * await addPage({ background });
278
+ * ```
279
+ *
280
+ * @example Create page with background image
281
+ * ```typescript
282
+ * import { addPage } from "@canva/design";
283
+ * import type { PageBackgroundFill } from "@canva/design";
284
+ * import type { ImageRef } from "@canva/asset";
285
+ *
286
+ * const exampleImageRef = "YOUR_IMAGE_REF" as ImageRef;
287
+ *
288
+ * const background: PageBackgroundFill = {
289
+ * asset: {
290
+ * type: 'image',
291
+ * ref: exampleImageRef,
292
+ * altText: { text: 'Background image', decorative: true }
293
+ * },
294
+ * };
295
+ *
296
+ * await addPage({ background });
297
+ * ```
298
+ *
299
+ * @example Create page with multiple elements
300
+ * ```typescript
301
+ * import { addPage } from "@canva/design";
302
+ * import type { TextElementAtPoint, ImageElementAtPoint } from "@canva/design";
303
+ * import type { ImageRef } from "@canva/asset";
304
+ *
305
+ * const exampleImageRef = "YOUR_IMAGE_REF" as ImageRef;
306
+ *
307
+ * await addPage({
308
+ * elements: [
309
+ * {
310
+ * type: 'text',
311
+ * children: ['Page Title'],
312
+ * top: 50,
313
+ * left: 100,
314
+ * width: 400,
315
+ * fontSize: 32,
316
+ * textAlign: 'center'
317
+ * } as TextElementAtPoint,
318
+ * {
319
+ * type: 'text',
320
+ * children: ['Subtitle text'],
321
+ * top: 100,
322
+ * left: 100,
323
+ * width: 400,
324
+ * fontSize: 18,
325
+ * textAlign: 'center'
326
+ * } as TextElementAtPoint,
327
+ * {
328
+ * type: 'image',
329
+ * ref: exampleImageRef,
330
+ * altText: { text: 'Featured image', decorative: false },
331
+ * top: 150,
332
+ * left: 200,
333
+ * width: 200,
334
+ * height: 200
335
+ * } as ImageElementAtPoint,
336
+ * ]
337
+ * });
338
+ * ```
38
339
  */
39
340
  export declare const addPage: (opts?: {
40
341
  /** Elements to be added to the page */
@@ -75,6 +376,67 @@ export declare type AltText = {
75
376
  * - the user selects an existing app element
76
377
  *
77
378
  * @param appElement - Information about the app element that was changed.
379
+ *
380
+ * @example Handle element selection
381
+ * ```typescript
382
+ * import { initAppElement } from "@canva/design";
383
+ *
384
+ * const appElement = initAppElement<{ content: string }>({
385
+ * render: (data) => {
386
+ * // Render based on data
387
+ * return [{
388
+ * type: 'text',
389
+ * children: [data.content || 'Default text'],
390
+ * top: 0,
391
+ * left: 0,
392
+ * width: 200
393
+ * }];
394
+ * }
395
+ * });
396
+ *
397
+ * appElement.registerOnElementChange((element) => {
398
+ * if (element) {
399
+ * // Element selected or created, do something with the `element.data`
400
+ * } else {
401
+ * // No element selected
402
+ * }
403
+ * });
404
+ * ```
405
+ *
406
+ * @example Update element data when selected
407
+ * ```typescript
408
+ * import { initAppElement } from "@canva/design";
409
+ *
410
+ * const appElement = initAppElement<{
411
+ * content: string;
412
+ * lastSelected: number;
413
+ * lastUpdated: number;
414
+ * metadata: { lastEdited: number; editCount: number };
415
+ * }>({
416
+ * render: (data) => {
417
+ * // Render based on data
418
+ * return [{
419
+ * type: 'text',
420
+ * children: [data.content || 'Default text'],
421
+ * top: 0,
422
+ * left: 0,
423
+ * width: 200
424
+ * }];
425
+ * }
426
+ * });
427
+ *
428
+ * appElement.registerOnElementChange(async (element) => {
429
+ * if (element) {
430
+ * // Use the update method to modify the element's data
431
+ * await element.update({
432
+ * data: {
433
+ * ...element.data,
434
+ * lastSelected: Date.now()
435
+ * }
436
+ * });
437
+ * }
438
+ * });
439
+ * ```
78
440
  */
79
441
  export declare type AppElementChangeHandler<A extends AppElementData> = (
80
442
  appElement:
@@ -89,6 +451,55 @@ export declare type AppElementChangeHandler<A extends AppElementData> = (
89
451
  version: number;
90
452
  /**
91
453
  * Function to update the app element data.
454
+ *
455
+ * @param opts - The data and placement to update the app element with.
456
+ *
457
+ * @example Update element data only
458
+ * ```typescript
459
+ * if (element) {
460
+ * await element.update({
461
+ * data: {
462
+ * ...element.data,
463
+ * content: 'Updated content',
464
+ * lastUpdated: Date.now()
465
+ * }
466
+ * });
467
+ * }
468
+ * ```
469
+ *
470
+ * @example Update data and placement
471
+ * ```typescript
472
+ * if (element) {
473
+ * await element.update({
474
+ * data: {
475
+ * ...element.data,
476
+ * content: 'Positioned element'
477
+ * },
478
+ * placement: {
479
+ * top: 200,
480
+ * left: 200,
481
+ * width: 300,
482
+ * height: 100
483
+ * }
484
+ * });
485
+ * }
486
+ * ```
487
+ *
488
+ * @example Add metadata to element
489
+ * ```typescript
490
+ * if (element) {
491
+ * await element.update({
492
+ * data: {
493
+ * ...element.data,
494
+ * metadata: {
495
+ * ...(element.data.metadata || {}),
496
+ * lastEdited: Date.now(),
497
+ * editCount: (element.data.metadata?.editCount || 0) + 1,
498
+ * },
499
+ * },
500
+ * });
501
+ * }
502
+ * ```
92
503
  */
93
504
  update: (opts: AppElementOptions<A>) => Promise<void>;
94
505
  }
@@ -106,11 +517,135 @@ export declare interface AppElementClient<A extends AppElementData> {
106
517
  * Otherwise, the provided data is used to create a new app element.
107
518
  * @param appElementData - The data to attach to the app element. Existing data will be overwritten.
108
519
  * @param placement - The position, dimensions, and rotation of the app element.
520
+ *
521
+ * @example Create or update an element (deprecated)
522
+ * ```typescript
523
+ * import { initAppElement } from "@canva/design";
524
+ *
525
+ * // Initialize the app element client
526
+ * const appElement = initAppElement<{ content: string; timestamp: number }>({
527
+ * render: (data) => {
528
+ * return [{
529
+ * type: 'text',
530
+ * children: [data.content || 'Default text'],
531
+ * top: 100,
532
+ * left: 100,
533
+ * width: 200
534
+ * }];
535
+ * }
536
+ * });
537
+ *
538
+ * // Create a new element or update selected element
539
+ * await appElement.addOrUpdateElement({
540
+ * content: 'Hello from the app',
541
+ * timestamp: Date.now()
542
+ * });
543
+ * ```
544
+ *
545
+ * @example Update with specific placement (deprecated)
546
+ * ```typescript
547
+ * import { initAppElement } from "@canva/design";
548
+ *
549
+ * const appElement = initAppElement<{ content: string }>({
550
+ * render: (data) => {
551
+ * return [{
552
+ * type: 'text',
553
+ * children: [data.content || 'Default text'],
554
+ * top: 0,
555
+ * left: 0,
556
+ * width: 200
557
+ * }];
558
+ * }
559
+ * });
560
+ *
561
+ * // Create or update with specific placement
562
+ * await appElement.addOrUpdateElement(
563
+ * {
564
+ * content: 'Positioned content'
565
+ * },
566
+ * {
567
+ * top: 200,
568
+ * left: 200,
569
+ * width: 300,
570
+ * height: 100
571
+ * }
572
+ * );
573
+ * ```
109
574
  */
110
575
  addOrUpdateElement(appElementData: A, placement?: Placement): Promise<void>;
111
576
  /**
112
577
  * Adds a new app element to the design.
113
578
  * @param opts - The data and placement of the app element.
579
+ *
580
+ * @example Add new element with data
581
+ * ```typescript
582
+ * import { initAppElement } from "@canva/design";
583
+ *
584
+ * const appElement = initAppElement<{ content: string; id: string }>({
585
+ * render: (data) => {
586
+ * return [{
587
+ * type: 'text',
588
+ * children: [data.content || 'Default text'],
589
+ * top: 0,
590
+ * left: 0,
591
+ * width: 200
592
+ * }];
593
+ * }
594
+ * });
595
+ *
596
+ * // Add a new element
597
+ * await appElement.addElement({
598
+ * data: {
599
+ * content: 'New element content',
600
+ * id: 'element-' + Date.now()
601
+ * }
602
+ * });
603
+ * ```
604
+ *
605
+ * @example Add element with specific placement
606
+ * ```typescript
607
+ * import { initAppElement } from "@canva/design";
608
+ *
609
+ * const appElement = initAppElement<{
610
+ * title: string;
611
+ * description: string;
612
+ * createdAt: number;
613
+ * }>({
614
+ * render: (data) => {
615
+ * return [{
616
+ * type: 'text',
617
+ * children: [data.title || 'Default title'],
618
+ * top: 0,
619
+ * left: 0,
620
+ * width: 300,
621
+ * fontWeight: 'bold',
622
+ * fontSize: 24
623
+ * }, {
624
+ * type: 'text',
625
+ * children: [data.description || 'Default description'],
626
+ * top: 50,
627
+ * left: 0,
628
+ * width: 300
629
+ * }];
630
+ * }
631
+ * });
632
+ *
633
+ * // Add element with specific placement
634
+ * await appElement.addElement({
635
+ * data: {
636
+ * title: 'Element Title',
637
+ * description: 'This is a description of the element',
638
+ * createdAt: Date.now()
639
+ * },
640
+ * placement: {
641
+ * top: 100,
642
+ * left: 100,
643
+ * width: 400,
644
+ * height: 150,
645
+ * rotation: 0
646
+ * }
647
+ * });
648
+ * ```
114
649
  */
115
650
  addElement(opts: AppElementOptions<A>): Promise<void>;
116
651
  /**
@@ -121,6 +656,89 @@ export declare interface AppElementClient<A extends AppElementData> {
121
656
  * - the user selects an existing app element
122
657
  *
123
658
  * @param handler - The callback to run when the app element changes.
659
+ *
660
+ * @example Handle element selection and update
661
+ * ```typescript
662
+ * import { initAppElement } from "@canva/design";
663
+ *
664
+ * const appElement = initAppElement<{ content: string }>({
665
+ * render: (data) => {
666
+ * return [{
667
+ * type: 'text',
668
+ * children: [data.content || 'Default text'],
669
+ * top: 0,
670
+ * left: 0,
671
+ * width: 200
672
+ * }];
673
+ * }
674
+ * });
675
+ *
676
+ * // Register a handler for element changes
677
+ * appElement.registerOnElementChange((element) => {
678
+ * if (element) {
679
+ * // Element is created or selected
680
+ * // Optionally update the element
681
+ * // element.update({
682
+ * // data: { ...element.data, lastSelected: Date.now() }
683
+ * // });
684
+ * } else {
685
+ * // No element is selected
686
+ * }
687
+ * });
688
+ * ```
689
+ *
690
+ * @example Update element when selected
691
+ * ```typescript
692
+ * import { initAppElement } from "@canva/design";
693
+ *
694
+ * const appElement = initAppElement<{
695
+ * content: string;
696
+ * metadata: { created: number; lastSelected: number };
697
+ * }>({
698
+ * render: (data) => {
699
+ * // Render based on data
700
+ * return [{
701
+ * type: 'text',
702
+ * children: [data.content || ''],
703
+ * top: 0,
704
+ * left: 0,
705
+ * width: 200
706
+ * }];
707
+ * }
708
+ * });
709
+ *
710
+ * // Update element when selected
711
+ * appElement.registerOnElementChange(async (element) => {
712
+ * if (element) {
713
+ * // Check if this is a newly created or a selected element
714
+ * const isNewElement = !element.data.metadata?.created;
715
+ *
716
+ * if (isNewElement) {
717
+ * // Update a new element with initial metadata
718
+ * await element.update({
719
+ * data: {
720
+ * ...element.data,
721
+ * metadata: {
722
+ * created: Date.now(),
723
+ * lastSelected: Date.now()
724
+ * }
725
+ * }
726
+ * });
727
+ * } else {
728
+ * // Update existing element's last selected time
729
+ * await element.update({
730
+ * data: {
731
+ * ...element.data,
732
+ * metadata: {
733
+ * ...element.data.metadata,
734
+ * lastSelected: Date.now()
735
+ * }
736
+ * }
737
+ * });
738
+ * }
739
+ * }
740
+ * });
741
+ * ```
124
742
  */
125
743
  registerOnElementChange(handler: AppElementChangeHandler<A>): void;
126
744
  }
@@ -344,6 +962,55 @@ export declare interface ContentDraft<T> {
344
962
  * - Any changes the app has made to to the content will be reflected in the user's design.
345
963
  * - Any changes the user has made to the content since the snapshot was created may be overwritten.
346
964
  * - Only properties that are different from the original state will be written to the design.
965
+ *
966
+ * @example Save changes to selected text
967
+ * ```typescript
968
+ * import { selection } from "@canva/design";
969
+ *
970
+ * selection.registerOnChange({
971
+ * scope: 'plaintext',
972
+ * onChange: async (event) => {
973
+ * if (event.count > 0) {
974
+ * const draft = await event.read();
975
+ *
976
+ * // Make changes to the content
977
+ * for (const content of draft.contents) {
978
+ * content.text = content.text.toUpperCase();
979
+ * }
980
+ *
981
+ * // Save the changes to the design
982
+ * await draft.save();
983
+ * }
984
+ * }
985
+ * });
986
+ * ```
987
+ *
988
+ * @example Modify then save rich text content
989
+ * ```typescript
990
+ * import { selection } from "@canva/design";
991
+ *
992
+ * selection.registerOnChange({
993
+ * scope: 'richtext',
994
+ * onChange: async (event) => {
995
+ * if (event.count > 0) {
996
+ * const draft = await event.read();
997
+ * const range = draft.contents[0];
998
+ *
999
+ * // Get the plain text
1000
+ * const text = range.readPlaintext();
1001
+ *
1002
+ * // Apply formatting to the entire text
1003
+ * range.formatText(
1004
+ * { index: 0, length: text.length },
1005
+ * { fontWeight: 'bold', color: '#0066CC' }
1006
+ * );
1007
+ *
1008
+ * // Save the formatted text back to the design
1009
+ * await draft.save();
1010
+ * }
1011
+ * }
1012
+ * });
1013
+ * ```
347
1014
  */
348
1015
  save(): Promise<void>;
349
1016
  }
@@ -380,6 +1047,76 @@ export declare type Coordinates = {
380
1047
  /**
381
1048
  * @public
382
1049
  * Creates a new RichtextRange object, which contains methods to manipulate text.
1050
+ *
1051
+ * @example Create formatted text range
1052
+ * ```typescript
1053
+ * import { createRichtextRange } from "@canva/design";
1054
+ * import type { InlineFormatting } from "@canva/design";
1055
+ *
1056
+ * const range = createRichtextRange();
1057
+ *
1058
+ * range.appendText('Hello World', {
1059
+ * color: '#000000',
1060
+ * fontWeight: 'bold'
1061
+ * } as InlineFormatting);
1062
+ * ```
1063
+ *
1064
+ * @example Format paragraph styles
1065
+ * ```typescript
1066
+ * import { createRichtextRange } from "@canva/design";
1067
+ * import type { RichtextFormatting } from "@canva/design";
1068
+ *
1069
+ * const range = createRichtextRange();
1070
+ *
1071
+ * const bounds = range.appendText('Centered Title\n');
1072
+ * range.formatParagraph(bounds.bounds, {
1073
+ * fontSize: 32,
1074
+ * textAlign: 'center'
1075
+ * } as RichtextFormatting);
1076
+ * ```
1077
+ *
1078
+ * @example Create bulleted list
1079
+ * ```typescript
1080
+ * import { createRichtextRange } from "@canva/design";
1081
+ *
1082
+ * const range = createRichtextRange();
1083
+ *
1084
+ * const item = range.appendText('List item\n');
1085
+ * range.formatParagraph(item.bounds, {
1086
+ * fontSize: 16,
1087
+ * listLevel: 1,
1088
+ * listMarker: 'disc'
1089
+ * });
1090
+ * ```
1091
+ *
1092
+ * @example Extract text content
1093
+ * ```typescript
1094
+ * import { createRichtextRange } from "@canva/design";
1095
+ *
1096
+ * const range = createRichtextRange();
1097
+ * range.appendText('Sample text');
1098
+ *
1099
+ * // Get plain text content
1100
+ * const text = range.readPlaintext();
1101
+ *
1102
+ * // Get formatted regions
1103
+ * const regions = range.readTextRegions();
1104
+ * ```
1105
+ *
1106
+ * @example Replace text with formatting
1107
+ * ```typescript
1108
+ * import { createRichtextRange } from "@canva/design";
1109
+ *
1110
+ * const range = createRichtextRange();
1111
+ * range.appendText('Original text');
1112
+ *
1113
+ * // Replace text while adding formatting
1114
+ * range.replaceText(
1115
+ * { index: 0, length: range.readPlaintext().length },
1116
+ * 'Modified',
1117
+ * { color: '#0066CC', decoration: 'underline' }
1118
+ * );
1119
+ * ```
383
1120
  */
384
1121
  export declare const createRichtextRange: () => RichtextRange;
385
1122
 
@@ -1911,6 +2648,40 @@ export declare type DesignElement =
1911
2648
  | RichtextElement
1912
2649
  | TableElement;
1913
2650
 
2651
+ /**
2652
+ * @public
2653
+ * Information about the design.
2654
+ */
2655
+ export declare type DesignMetadata = {
2656
+ /**
2657
+ * The title of the user's design.
2658
+ * @remarks
2659
+ * This is optional and will be `undefined` if the user hasn't set a title.
2660
+ */
2661
+ title?: string;
2662
+ /**
2663
+ * The default dimensions that a new page will have when it is added to a design.
2664
+ * It is possible for a user to resize a page without resizing the entire design, e.g. by clicking
2665
+ * "Expand to Whiteboard". However, there will always be a single set of default dimensions for a
2666
+ * design that is applied whenever a new page is created.
2667
+ * @remarks
2668
+ * This is optional and will be `undefined` if the design is unbounded (e.g. Whiteboard or Doc).
2669
+ */
2670
+ defaultPageDimensions?: PageDimensions;
2671
+ /**
2672
+ * The information associated with each page of the design.
2673
+ * @remarks
2674
+ * The order of pages is not guaranteed.
2675
+ */
2676
+ pageMetadata: Iterable<PageMetadata>;
2677
+ /**
2678
+ * The duration of the whole design in seconds.
2679
+ * @remarks
2680
+ * This is the precise value, which differs from what is displayed in the UI as duration in Canva UI is formatted differently.
2681
+ */
2682
+ durationInSeconds: number;
2683
+ };
2684
+
1914
2685
  /**
1915
2686
  * @public
1916
2687
  * A callback for reading and updating part of a design.
@@ -1934,6 +2705,80 @@ export declare type DesignOverlay = {
1934
2705
  /**
1935
2706
  * Registers a callback that runs when the `canOpen` state of an overlay target changes.
1936
2707
  * @param opts - Options for configuring the callback.
2708
+ *
2709
+ * @example Register overlay handler
2710
+ * ```typescript
2711
+ * import { overlay } from "@canva/design";
2712
+ *
2713
+ * overlay.registerOnCanOpen({
2714
+ * target: 'image_selection',
2715
+ * onCanOpen: async (event) => {
2716
+ * if (event.canOpen) {
2717
+ * // Can open overlay for selected image
2718
+ * }
2719
+ * }
2720
+ * });
2721
+ * ```
2722
+ *
2723
+ * @example Open image editing overlay
2724
+ * ```typescript
2725
+ * import { overlay } from "@canva/design";
2726
+ *
2727
+ * overlay.registerOnCanOpen({
2728
+ * target: 'image_selection',
2729
+ * onCanOpen: async (event) => {
2730
+ * if (event.canOpen) {
2731
+ * const processId = await event.open({
2732
+ * launchParameters: {
2733
+ * mode: 'edit'
2734
+ * }
2735
+ * });
2736
+ * // Overlay process started, with `processId`
2737
+ * }
2738
+ * }
2739
+ * });
2740
+ * ```
2741
+ *
2742
+ * @example Open overlay with filters
2743
+ * ```typescript
2744
+ * import { overlay } from "@canva/design";
2745
+ *
2746
+ * overlay.registerOnCanOpen({
2747
+ * target: 'image_selection',
2748
+ * onCanOpen: async (event) => {
2749
+ * if (event.canOpen) {
2750
+ * await event.open({
2751
+ * launchParameters: {
2752
+ * mode: 'edit',
2753
+ * filters: ['brightness', 'contrast', 'saturation']
2754
+ * }
2755
+ * });
2756
+ * }
2757
+ * }
2758
+ * });
2759
+ * ```
2760
+ *
2761
+ * @example Handle overlay unavailability
2762
+ * ```typescript
2763
+ * import { overlay } from "@canva/design";
2764
+ *
2765
+ * overlay.registerOnCanOpen({
2766
+ * target: 'image_selection',
2767
+ * onCanOpen: async (event) => {
2768
+ * if (!event.canOpen) {
2769
+ * // Cannot open overlay, handle specific reasons
2770
+ * switch (event.reason) {
2771
+ * case 'no_selection':
2772
+ * // No image is selected
2773
+ * break;
2774
+ * case 'invalid_selection':
2775
+ * // Selected content cannot be edited
2776
+ * break;
2777
+ * }
2778
+ * }
2779
+ * }
2780
+ * });
2781
+ * ```
1937
2782
  */
1938
2783
  registerOnCanOpen<Target extends OverlayTarget>(opts: {
1939
2784
  /**
@@ -1964,6 +2809,67 @@ export declare type DesignSelection = {
1964
2809
  *
1965
2810
  * @remarks
1966
2811
  * This callback fires immediately if content is already selected when the callback is registered.
2812
+ *
2813
+ * @example Handling plaintext selection
2814
+ * ```typescript
2815
+ * import { selection } from "@canva/design";
2816
+ *
2817
+ * selection.registerOnChange({
2818
+ * scope: 'plaintext',
2819
+ * onChange: async (event) => {
2820
+ * if (event.count > 0) {
2821
+ * const draft = await event.read();
2822
+ * // Do something with the selected text, e.g. `draft.contents[0].text`
2823
+ * }
2824
+ * }
2825
+ * });
2826
+ * ```
2827
+ *
2828
+ * @example Handling image selection
2829
+ * ```typescript
2830
+ * import { selection } from "@canva/design";
2831
+ *
2832
+ * selection.registerOnChange({
2833
+ * scope: 'image',
2834
+ * onChange: async (event) => {
2835
+ * if (event.count > 0) {
2836
+ * const draft = await event.read();
2837
+ * // Do something with the selected image ref, e.g. `draft.contents[0].ref`
2838
+ * }
2839
+ * }
2840
+ * });
2841
+ * ```
2842
+ *
2843
+ * @example Handling video selection
2844
+ * ```typescript
2845
+ * import { selection } from "@canva/design";
2846
+ *
2847
+ * selection.registerOnChange({
2848
+ * scope: 'video',
2849
+ * onChange: async (event) => {
2850
+ * if (event.count > 0) {
2851
+ * const draft = await event.read();
2852
+ * // Do something with the selected video ref, e.g. `draft.contents[0].ref`
2853
+ * }
2854
+ * }
2855
+ * });
2856
+ * ```
2857
+ *
2858
+ * @example Handling richtext selection
2859
+ * ```typescript
2860
+ * import { selection } from "@canva/design";
2861
+ *
2862
+ * selection.registerOnChange({
2863
+ * scope: 'richtext',
2864
+ * onChange: async (event) => {
2865
+ * if (event.count > 0) {
2866
+ * const draft = await event.read();
2867
+ * const range = draft.contents[0];
2868
+ * // Do something with the selected richtext, e.g. `range.readPlaintext()`
2869
+ * }
2870
+ * }
2871
+ * });
2872
+ * ```
1967
2873
  */
1968
2874
  registerOnChange<Scope extends SelectionScope>(opts: {
1969
2875
  /**
@@ -2017,6 +2923,18 @@ export declare type DragStartEvent<E extends Element> = Pick<
2017
2923
  * Reads and edits content of the specified type from the user's design.
2018
2924
  * @param options - Options for configuring how a design is read.
2019
2925
  * @param callback - A callback for operating on the read content.
2926
+ *
2927
+ * @example Read richtext content
2928
+ * ```typescript
2929
+ * import { editContent } from "@canva/design";
2930
+ *
2931
+ * await editContent(
2932
+ * { contentType: 'richtext', target: 'current_page' },
2933
+ * async (session) => {
2934
+ * // Do something with the richtext content, e.g. `session.contents`
2935
+ * }
2936
+ * );
2937
+ * ```
2020
2938
  */
2021
2939
  export declare const editContent: (
2022
2940
  options: EditContentOptions,
@@ -2300,6 +3218,18 @@ export declare type FontWeight =
2300
3218
  * Allows to get the context of currently selected page.
2301
3219
  * @public
2302
3220
  * @returns Page context of currently selected page
3221
+ *
3222
+ * @example Get current page information
3223
+ * ```typescript
3224
+ * import { getCurrentPageContext } from "@canva/design";
3225
+ *
3226
+ * const pageContext = await getCurrentPageContext();
3227
+ * if (pageContext.dimensions) {
3228
+ * // Do something with the page dimensions, e.g. `pageContext.dimensions.width` and `pageContext.dimensions.height`
3229
+ * } else {
3230
+ * // This page type does not have fixed dimensions, e.g. Whiteboard or Doc
3231
+ * }
3232
+ * ```
2303
3233
  */
2304
3234
  export declare const getCurrentPageContext: () => Promise<PageContext>;
2305
3235
 
@@ -2311,14 +3241,92 @@ export declare const getCurrentPageContext: () => Promise<PageContext>;
2311
3241
  * design that is applied whenever a new page is created.
2312
3242
  *
2313
3243
  * Returns `undefined` if the design is unbounded (e.g. Whiteboard or Doc).
3244
+ *
3245
+ * @example Get default page dimensions
3246
+ * ```typescript
3247
+ * import { getDefaultPageDimensions } from "@canva/design";
3248
+ *
3249
+ * const dimensions = await getDefaultPageDimensions();
3250
+ *
3251
+ * if (dimensions) {
3252
+ * // Do something with the dimensions, e.g. `dimensions.width` and `dimensions.height`
3253
+ * } else {
3254
+ * // This design type does not have fixed dimensions, e.g. Whiteboard or Doc
3255
+ * }
3256
+ * ```
3257
+ *
3258
+ * @example Center element using page dimensions
3259
+ * ```typescript
3260
+ * import { getDefaultPageDimensions, addElementAtPoint } from "@canva/design";
3261
+ * import type { ImageElementAtPoint } from "@canva/design";
3262
+ *
3263
+ * const dimensions = await getDefaultPageDimensions();
3264
+ *
3265
+ * if (dimensions) {
3266
+ * const elementWidth = 300;
3267
+ * const elementHeight = 200;
3268
+ *
3269
+ * const element: ImageElementAtPoint = {
3270
+ * type: 'image',
3271
+ * dataUrl: 'data:image/png;base64,...',
3272
+ * altText: { text: 'Centered image', decorative: false },
3273
+ * top: (dimensions.height - elementHeight) / 2,
3274
+ * left: (dimensions.width - elementWidth) / 2,
3275
+ * width: elementWidth,
3276
+ * height: elementHeight
3277
+ * };
3278
+ *
3279
+ * await addElementAtPoint(element);
3280
+ * }
3281
+ * ```
2314
3282
  */
2315
3283
  export declare const getDefaultPageDimensions: () => Promise<
2316
3284
  Dimensions | undefined
2317
3285
  >;
2318
3286
 
3287
+ /**
3288
+ * @public
3289
+ * Retrieves information about the design.
3290
+ *
3291
+ * @example Get design metadata
3292
+ * ```typescript
3293
+ * import { getDesignMetadata } from "@canva/design";
3294
+ *
3295
+ * const metadata = await getDesignMetadata();
3296
+ *
3297
+ * const { title, defaultPageDimensions, pageMetadata, durationInSeconds } = metadata;
3298
+ * ```
3299
+ */
3300
+ export declare const getDesignMetadata: () => Promise<DesignMetadata>;
3301
+
2319
3302
  /**
2320
3303
  * @public
2321
3304
  * Retrieves a signed JWT that contains the Design ID, App ID and User ID.
3305
+ *
3306
+ * @example Get design token
3307
+ * ```typescript
3308
+ * import { getDesignToken } from "@canva/design";
3309
+ *
3310
+ * const { token } = await getDesignToken();
3311
+ * ```
3312
+ *
3313
+ * @example Verify token with backend service
3314
+ * ```typescript
3315
+ * import { getDesignToken } from "@canva/design";
3316
+ *
3317
+ * const { token } = await getDesignToken();
3318
+ *
3319
+ * const verifyResponse = await fetch('https://your-backend.com/verify', {
3320
+ * method: 'POST',
3321
+ * headers: {
3322
+ * 'Content-Type': 'application/json'
3323
+ * },
3324
+ * body: JSON.stringify({ token })
3325
+ * });
3326
+ *
3327
+ * const json = await verifyResponse.json();
3328
+ * const { designId, appId, userId } = json;
3329
+ * ```
2322
3330
  */
2323
3331
  export declare const getDesignToken: () => Promise<DesignToken>;
2324
3332
 
@@ -2472,6 +3480,40 @@ export declare type ImageRef = string & {
2472
3480
  /**
2473
3481
  * @public
2474
3482
  * @param appElementConfig - Configuration for an AppElementClient
3483
+ *
3484
+ * @example Initialize app element client
3485
+ * ```typescript
3486
+ * import { initAppElement } from "@canva/design";
3487
+ *
3488
+ * const appElement = initAppElement<{ content: string }>({
3489
+ * render: (data) => {
3490
+ * return [{
3491
+ * type: 'text',
3492
+ * children: [data.content],
3493
+ * top: 100,
3494
+ * left: 100,
3495
+ * width: 200
3496
+ * }];
3497
+ * }
3498
+ * });
3499
+ * ```
3500
+ *
3501
+ * @example Initialize V2 app element client
3502
+ * ```typescript
3503
+ * import { initAppElement } from "@canva/design";
3504
+ *
3505
+ * const appElement = initAppElement<{ content: string }>({
3506
+ * render: (data) => {
3507
+ * return [{
3508
+ * type: 'text',
3509
+ * children: [data.content],
3510
+ * top: 100,
3511
+ * left: 100,
3512
+ * width: 200
3513
+ * }];
3514
+ * }
3515
+ * });
3516
+ * ```
2475
3517
  */
2476
3518
  export declare const initAppElement: <A extends AppElementData>(
2477
3519
  appElementConfig: AppElementClientConfiguration<A>,
@@ -2762,6 +3804,20 @@ export declare type PageDimensions = {
2762
3804
  height: number;
2763
3805
  };
2764
3806
 
3807
+ /**
3808
+ * @public
3809
+ * Information about a page.
3810
+ */
3811
+ export declare type PageMetadata = {
3812
+ /**
3813
+ * The dimensions of the page, in pixels.
3814
+ *
3815
+ * @remarks
3816
+ * This may be `undefined` because some types of pages don't have dimensions, such as whiteboards.
3817
+ */
3818
+ dimensions?: PageDimensions;
3819
+ };
3820
+
2765
3821
  /**
2766
3822
  * @public
2767
3823
  * The outline of a path.
@@ -2859,10 +3915,121 @@ export declare interface RichtextContentRange extends RichtextRange {
2859
3915
 
2860
3916
  /**
2861
3917
  * @public
2862
- * Session for reading and updating richtext content in a user's design.
3918
+ * A callback for reading and updating the requested design content.
3919
+ * @param session - The result of reading the content in the design.
3920
+ *
3921
+ * @example Read and update richtext content
3922
+ * ```typescript
3923
+ * import { editContent } from "@canva/design";
3924
+ *
3925
+ * await editContent(
3926
+ * { contentType: 'richtext', target: 'current_page' },
3927
+ * async (session) => {
3928
+ * // Read the content
3929
+ * const contents = session.contents;
3930
+ *
3931
+ * if (contents.length > 0) {
3932
+ * const range = contents[0];
3933
+ *
3934
+ * // Modify the content (e.g., adding text)
3935
+ * range.appendText("\nAppended text from app");
3936
+ *
3937
+ * // Sync changes back to the design
3938
+ * await session.sync();
3939
+ * }
3940
+ * }
3941
+ * );
3942
+ * ```
3943
+ *
3944
+ * @example Format all richtext content in the design
3945
+ * ```typescript
3946
+ * import { editContent } from "@canva/design";
3947
+ *
3948
+ * await editContent(
3949
+ * { contentType: 'richtext', target: 'current_page' },
3950
+ * async (session) => {
3951
+ * // Process each richtext range in the content
3952
+ * for (const range of session.contents) {
3953
+ * // Skip if the content has been deleted
3954
+ * if (range.deleted) continue;
3955
+ *
3956
+ * // Get the text content
3957
+ * const text = range.readPlaintext();
3958
+ * if (text.length === 0) continue;
3959
+ *
3960
+ * // Apply consistent formatting
3961
+ * range.formatParagraph(
3962
+ * { index: 0, length: text.length },
3963
+ * {
3964
+ * fontRef: 'YOUR_FONT_REF',
3965
+ * fontSize: 16,
3966
+ * textAlign: 'start'
3967
+ * }
3968
+ * );
3969
+ * }
3970
+ *
3971
+ * // Sync all changes back to the design
3972
+ * await session.sync();
3973
+ * }
3974
+ * );
3975
+ * ```
3976
+ *
3977
+ * @example Modify content without saving changes
3978
+ * ```typescript
3979
+ * import { editContent } from "@canva/design";
3980
+ *
3981
+ * await editContent(
3982
+ * { contentType: 'richtext', target: 'current_page' },
3983
+ * async (session) => {
3984
+ * // Read and analyze the content without making changes
3985
+ * for (const range of session.contents) {
3986
+ * const text = range.readPlaintext();
3987
+ * // Do something with the content preview, e.g. `text.substring(0, 50)`
3988
+ *
3989
+ * // No call to session.sync() means no changes are saved
3990
+ * }
3991
+ *
3992
+ * // Since we're not calling sync(), no changes will be made to the design
3993
+ * }
3994
+ * );
3995
+ * ```
2863
3996
  */
2864
3997
  export declare interface RichtextContentSession {
3998
+ /**
3999
+ * Richtext content in the design.
4000
+ */
2865
4001
  readonly contents: readonly RichtextContentRange[];
4002
+ /**
4003
+ * Saves any changes made during the session while keeping the transaction open.
4004
+ *
4005
+ * @remarks
4006
+ * - Any changes in the session are only reflected in the design after this method is called.
4007
+ * - Once this method is called, further changes in the session can still be made.
4008
+ *
4009
+ * @example Sync changes after modifying content
4010
+ * ```typescript
4011
+ * import { editContent } from "@canva/design";
4012
+ *
4013
+ * await editContent(
4014
+ * { contentType: 'richtext', target: 'current_page' },
4015
+ * async (session) => {
4016
+ * if (session.contents.length > 0) {
4017
+ * const range = session.contents[0];
4018
+ *
4019
+ * // Make modifications to the content
4020
+ * range.appendText(" - Modified by app");
4021
+ *
4022
+ * try {
4023
+ * // Save changes back to the design
4024
+ * await session.sync();
4025
+ * } catch (error) {
4026
+ * console.error('Failed to sync changes:', error);
4027
+ * }
4028
+ * }
4029
+ * }
4030
+ * );
4031
+ * ```
4032
+ */
2866
4033
  sync(): Promise<void>;
2867
4034
  }
2868
4035
 
@@ -2956,6 +4123,42 @@ export declare type RichtextRange = {
2956
4123
  * - The `\n` character indicates the end of a paragraph.
2957
4124
  * - All paragraphs that overlap the provided bounds will be formatted in their entirety.
2958
4125
  *
4126
+ * @example Format paragraph as a heading
4127
+ * ```typescript
4128
+ * import { createRichtextRange } from "@canva/design";
4129
+ *
4130
+ * const range = createRichtextRange();
4131
+ *
4132
+ * range.appendText("Heading Text\nRegular paragraph text.");
4133
+ *
4134
+ * // Format just the first paragraph as a heading
4135
+ * range.formatParagraph(
4136
+ * { index: 0, length: 12 }, // Only need to include part of the paragraph
4137
+ * {
4138
+ * fontSize: 24,
4139
+ * fontWeight: 'bold',
4140
+ * textAlign: 'center'
4141
+ * }
4142
+ * );
4143
+ * ```
4144
+ *
4145
+ * @example Create a bulleted list
4146
+ * ```typescript
4147
+ * import { createRichtextRange } from "@canva/design";
4148
+ *
4149
+ * const range = createRichtextRange();
4150
+ * const text = "Item 1\nItem 2\nItem 3";
4151
+ * range.appendText(text);
4152
+ *
4153
+ * // Format all paragraphs as a bulleted list
4154
+ * range.formatParagraph(
4155
+ * { index: 0, length: text.length },
4156
+ * {
4157
+ * listLevel: 1,
4158
+ * listMarker: 'disc'
4159
+ * }
4160
+ * );
4161
+ * ```
2959
4162
  */
2960
4163
  formatParagraph(bounds: Bounds, formatting: RichtextFormatting): void;
2961
4164
  /**
@@ -2963,13 +4166,79 @@ export declare type RichtextRange = {
2963
4166
  *
2964
4167
  * @param bounds - The segment of the range on which to apply the formatting.
2965
4168
  * @param formatting - The formatting to apply to the text.
4169
+ *
4170
+ * @example Format specific words in a paragraph
4171
+ * ```typescript
4172
+ * import { createRichtextRange } from "@canva/design";
4173
+ *
4174
+ * const range = createRichtextRange();
4175
+ * range.appendText("This text contains important information.");
4176
+ *
4177
+ * // Format just the word "important"
4178
+ * range.formatText(
4179
+ * { index: 16, length: 9 },
4180
+ * {
4181
+ * fontWeight: 'bold',
4182
+ * color: '#FF0000'
4183
+ * }
4184
+ * );
4185
+ * ```
4186
+ *
4187
+ * @example Add a link to text
4188
+ * ```typescript
4189
+ * import { createRichtextRange } from "@canva/design";
4190
+ *
4191
+ * const range = createRichtextRange();
4192
+ * range.appendText("Visit our website for more information.");
4193
+ *
4194
+ * // Add a link to "our website"
4195
+ * range.formatText(
4196
+ * { index: 6, length: 11 },
4197
+ * {
4198
+ * link: "https://www.example.com",
4199
+ * decoration: 'underline',
4200
+ * color: '#0066CC'
4201
+ * }
4202
+ * );
4203
+ * ```
2966
4204
  */
2967
4205
  formatText(bounds: Bounds, formatting: InlineFormatting): void;
2968
4206
  /**
2969
4207
  * Appends the specified characters to the end of the range.
2970
4208
  *
2971
4209
  * @param characters - The characters to append to the richtext range.
2972
- * @param fo -
4210
+ * @param formatting - Optional formatting to apply to the appended text.
4211
+ *
4212
+ * @example Append plain text
4213
+ * ```typescript
4214
+ * import { createRichtextRange } from "@canva/design";
4215
+ *
4216
+ * const range = createRichtextRange();
4217
+ * range.appendText("First paragraph. ");
4218
+ *
4219
+ * // Append more text to the existing content
4220
+ * const result = range.appendText("This is additional text.");
4221
+ *
4222
+ * // The bounds of the newly added text are returned
4223
+ * // Do something with the bounds - result.bounds, e.g. { index: 17, length: 24 }
4224
+ * ```
4225
+ *
4226
+ * @example Append formatted text
4227
+ * ```typescript
4228
+ * import { createRichtextRange } from "@canva/design";
4229
+ *
4230
+ * const range = createRichtextRange();
4231
+ * range.appendText("Normal text followed by ");
4232
+ *
4233
+ * // Append formatted text
4234
+ * range.appendText("bold red text", {
4235
+ * fontWeight: 'bold',
4236
+ * color: '#FF0000'
4237
+ * });
4238
+ *
4239
+ * // Append a new paragraph
4240
+ * range.appendText("\nThis is a new paragraph.");
4241
+ * ```
2973
4242
  */
2974
4243
  appendText(
2975
4244
  characters: string,
@@ -2983,6 +4252,42 @@ export declare type RichtextRange = {
2983
4252
  * @param bounds - The segment of the range to replace.
2984
4253
  * @param characters - The replacement characters.
2985
4254
  * @param formatting - The formatting to apply to the replaced text.
4255
+ *
4256
+ * @example Replace text while maintaining some formatting
4257
+ * ```typescript
4258
+ * import { createRichtextRange } from "@canva/design";
4259
+ *
4260
+ * const range = createRichtextRange();
4261
+ * range.appendText("This text needs correction.");
4262
+ *
4263
+ * // Replace "needs correction" with "is correct"
4264
+ * const result = range.replaceText(
4265
+ * { index: 10, length: 16 },
4266
+ * "is correct"
4267
+ * );
4268
+ *
4269
+ * // The bounds of the replaced text are returned
4270
+ * // Do something with the bounds - result.bounds, e.g. { index: 10, length: 10 }
4271
+ * ```
4272
+ *
4273
+ * @example Replace text with formatted text
4274
+ * ```typescript
4275
+ * import { createRichtextRange } from "@canva/design";
4276
+ *
4277
+ * const range = createRichtextRange();
4278
+ * range.appendText("Regular text that needs emphasis.");
4279
+ *
4280
+ * // Replace "needs emphasis" with formatted text
4281
+ * range.replaceText(
4282
+ * { index: 17, length: 15 },
4283
+ * "is important",
4284
+ * {
4285
+ * fontWeight: 'bold',
4286
+ * fontStyle: 'italic',
4287
+ * color: '#0066CC'
4288
+ * }
4289
+ * );
4290
+ * ```
2986
4291
  */
2987
4292
  replaceText(
2988
4293
  bounds: Bounds,
@@ -2996,11 +4301,87 @@ export declare type RichtextRange = {
2996
4301
  };
2997
4302
  /**
2998
4303
  * Returns the current state of the richtext as plaintext.
4304
+ *
4305
+ * @example Extract plain text content
4306
+ * ```typescript
4307
+ * import { createRichtextRange } from "@canva/design";
4308
+ *
4309
+ * const range = createRichtextRange();
4310
+ * range.appendText("First paragraph.\n", { fontWeight: 'bold' });
4311
+ * range.appendText("Second paragraph with formatting.", { color: '#FF0000' });
4312
+ *
4313
+ * // Get plain text content without formatting
4314
+ * const plainText = range.readPlaintext();
4315
+ * // Do something with the plain text - plainText, e.g. "First paragraph.\nSecond paragraph with formatting."
4316
+ * ```
4317
+ *
4318
+ * @example Search within text content
4319
+ * ```typescript
4320
+ * import { createRichtextRange } from "@canva/design";
4321
+ *
4322
+ * const range = createRichtextRange();
4323
+ * range.appendText("This text contains a searchable term.");
4324
+ *
4325
+ * // Search for a specific word
4326
+ * const plainText = range.readPlaintext();
4327
+ * const searchTerm = "searchable";
4328
+ * const index = plainText.indexOf(searchTerm);
4329
+ *
4330
+ * if (index !== -1) {
4331
+ * // Format the found term
4332
+ * range.formatText(
4333
+ * { index, length: searchTerm.length },
4334
+ * { fontWeight: 'bold', decoration: 'underline' }
4335
+ * );
4336
+ * }
4337
+ * ```
2999
4338
  */
3000
4339
  readPlaintext(): string;
3001
4340
  /**
3002
4341
  * Returns the current state of the richtext as one or more text regions.
3003
4342
  * Each region is an object that contains the text content and its formatting.
4343
+ *
4344
+ * @example Get text with formatting information
4345
+ * ```typescript
4346
+ * import { createRichtextRange } from "@canva/design";
4347
+ *
4348
+ * const range = createRichtextRange();
4349
+ * range.appendText("Normal text ", {});
4350
+ * range.appendText("bold text", { fontWeight: 'bold' });
4351
+ * range.appendText(" and ", {});
4352
+ * range.appendText("red text", { color: '#FF0000' });
4353
+ *
4354
+ * // Get formatted regions
4355
+ * const regions = range.readTextRegions();
4356
+ * // Do something with the regions, e.g.
4357
+ * // [
4358
+ * // { text: "Normal text ", formatting: {} },
4359
+ * // { text: "bold text", formatting: { fontWeight: 'bold' } },
4360
+ * // { text: " and ", formatting: {} },
4361
+ * // { text: "red text", formatting: { color: '#FF0000' } }
4362
+ * // ]
4363
+ * ```
4364
+ *
4365
+ * @example Analyze formatting variations
4366
+ * ```typescript
4367
+ * import { createRichtextRange } from "@canva/design";
4368
+ *
4369
+ * const range = createRichtextRange();
4370
+ * range.appendText("Mixed ", {});
4371
+ * range.appendText("formatted ", { fontWeight: 'bold' });
4372
+ * range.appendText("text", { color: '#0066CC' });
4373
+ *
4374
+ * // Analyze formatting variations
4375
+ * const regions = range.readTextRegions();
4376
+ * const formattingTypes = regions.map(region => {
4377
+ * const formatting = region.formatting || {};
4378
+ * return {
4379
+ * text: region.text,
4380
+ * hasWeight: !!formatting.fontWeight,
4381
+ * hasColor: !!formatting.color
4382
+ * };
4383
+ * });
4384
+ * ```
3004
4385
  */
3005
4386
  readTextRegions(): TextRegion[];
3006
4387
  };
@@ -3030,17 +4411,68 @@ export declare interface SelectionEvent<Scope extends SelectionScope> {
3030
4411
  * Any changes made to `contents` are not immediately persisted or reflected in the user's design.
3031
4412
  * To persist the changes, call the `save` method that's available via the draft.
3032
4413
  *
3033
- * @example Replacing text
4414
+ * @example Read and modify plaintext selection
4415
+ * ```typescript
4416
+ * import { selection } from "@canva/design";
4417
+ *
4418
+ * selection.registerOnChange({
4419
+ * scope: 'plaintext',
4420
+ * onChange: async (event) => {
4421
+ * if (event.count > 0) {
4422
+ * // Read the content
4423
+ * const draft = await event.read();
4424
+ *
4425
+ * // Handle selected text `draft.contents[0].text`
4426
+ *
4427
+ * // Modify the text if needed
4428
+ * // draft.contents[0].text = 'Modified text';
4429
+ * // await draft.save();
4430
+ * }
4431
+ * }
4432
+ * });
3034
4433
  * ```
3035
- * const draft = await selectionEvent.read();
3036
4434
  *
3037
- * for(const content of draft.contents) {
3038
- * // This change won't immediately appear in the user's design
3039
- * content.text = "This is the new text";
3040
- * }
4435
+ * @example Read and analyze image selection
4436
+ * ```typescript
4437
+ * import { selection } from "@canva/design";
3041
4438
  *
3042
- * // The changes will now appear in the user's design
3043
- * await draft.save();
4439
+ * selection.registerOnChange({
4440
+ * scope: 'image',
4441
+ * onChange: async (event) => {
4442
+ * // Check if any images are selected
4443
+ * if (event.count === 0) {
4444
+ * // Handle no images selected case
4445
+ * return;
4446
+ * }
4447
+ *
4448
+ * // Read the content
4449
+ * const draft = await event.read();
4450
+ *
4451
+ * // Get information about selected images
4452
+ * const imageRefs = draft.contents.map(content => content.ref);
4453
+ *
4454
+ * // The ref can be used with other API methods
4455
+ * }
4456
+ * });
4457
+ * ```
4458
+ *
4459
+ * @example Process multiple selected items
4460
+ * ```typescript
4461
+ * import { selection } from "@canva/design";
4462
+ *
4463
+ * selection.registerOnChange({
4464
+ * scope: 'richtext',
4465
+ * onChange: async (event) => {
4466
+ * if (event.count > 0) {
4467
+ * const draft = await event.read();
4468
+ *
4469
+ * // Process each selected range
4470
+ * draft.contents.forEach((range) => {
4471
+ * // Do something with the range content and formatted regions, with `range.readPlaintext()` and `range.readTextRegions()`
4472
+ * });
4473
+ * }
4474
+ * }
4475
+ * });
3044
4476
  * ```
3045
4477
  */
3046
4478
  read(): Promise<ContentDraft<SelectionValue<Scope>>>;
@@ -3123,6 +4555,56 @@ export declare type SelectionValue<Scope extends SelectionScope> = {
3123
4555
  * @public
3124
4556
  * Updates the background of the user's current page. The background can be a solid color,
3125
4557
  * an image or a video.
4558
+ *
4559
+ * @example Set background color
4560
+ * ```typescript
4561
+ * import { setCurrentPageBackground } from "@canva/design";
4562
+ * import type { PageBackgroundFill } from "@canva/design";
4563
+ *
4564
+ * const background: PageBackgroundFill = {
4565
+ * color: '#F5F5F5',
4566
+ * };
4567
+ *
4568
+ * await setCurrentPageBackground(background);
4569
+ * ```
4570
+ *
4571
+ * @example Set background image
4572
+ * ```typescript
4573
+ * import { setCurrentPageBackground } from "@canva/design";
4574
+ * import type { PageBackgroundFill } from "@canva/design";
4575
+ * import type { ImageRef } from "@canva/asset";
4576
+ *
4577
+ * const exampleImageRef = "YOUR_IMAGE_REF" as ImageRef;
4578
+ *
4579
+ * const background: PageBackgroundFill = {
4580
+ * asset: {
4581
+ * type: 'image',
4582
+ * ref: exampleImageRef,
4583
+ * altText: { text: 'Background image', decorative: true }
4584
+ * },
4585
+ * };
4586
+ *
4587
+ * await setCurrentPageBackground(background);
4588
+ * ```
4589
+ *
4590
+ * @example Set background video
4591
+ * ```typescript
4592
+ * import { setCurrentPageBackground } from "@canva/design";
4593
+ * import type { PageBackgroundFill } from "@canva/design";
4594
+ * import type { VideoRef } from "@canva/asset";
4595
+ *
4596
+ * const exampleVideoRef = "YOUR_VIDEO_REF" as VideoRef;
4597
+ *
4598
+ * const background: PageBackgroundFill = {
4599
+ * asset: {
4600
+ * type: 'video',
4601
+ * ref: exampleVideoRef,
4602
+ * altText: { text: 'Background video', decorative: true }
4603
+ * },
4604
+ * };
4605
+ *
4606
+ * await setCurrentPageBackground(background);
4607
+ * ```
3126
4608
  */
3127
4609
  export declare const setCurrentPageBackground: (
3128
4610
  opts: PageBackgroundFill,