@canva/design 2.6.2-beta.1 → 2.7.1-beta.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/beta.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
  }
@@ -385,6 +1052,76 @@ export declare type Coordinates = {
385
1052
  /**
386
1053
  * @public
387
1054
  * Creates a new RichtextRange object, which contains methods to manipulate text.
1055
+ *
1056
+ * @example Create formatted text range
1057
+ * ```typescript
1058
+ * import { createRichtextRange } from "@canva/design";
1059
+ * import type { InlineFormatting } from "@canva/design";
1060
+ *
1061
+ * const range = createRichtextRange();
1062
+ *
1063
+ * range.appendText('Hello World', {
1064
+ * color: '#000000',
1065
+ * fontWeight: 'bold'
1066
+ * } as InlineFormatting);
1067
+ * ```
1068
+ *
1069
+ * @example Format paragraph styles
1070
+ * ```typescript
1071
+ * import { createRichtextRange } from "@canva/design";
1072
+ * import type { RichtextFormatting } from "@canva/design";
1073
+ *
1074
+ * const range = createRichtextRange();
1075
+ *
1076
+ * const bounds = range.appendText('Centered Title\n');
1077
+ * range.formatParagraph(bounds.bounds, {
1078
+ * fontSize: 32,
1079
+ * textAlign: 'center'
1080
+ * } as RichtextFormatting);
1081
+ * ```
1082
+ *
1083
+ * @example Create bulleted list
1084
+ * ```typescript
1085
+ * import { createRichtextRange } from "@canva/design";
1086
+ *
1087
+ * const range = createRichtextRange();
1088
+ *
1089
+ * const item = range.appendText('List item\n');
1090
+ * range.formatParagraph(item.bounds, {
1091
+ * fontSize: 16,
1092
+ * listLevel: 1,
1093
+ * listMarker: 'disc'
1094
+ * });
1095
+ * ```
1096
+ *
1097
+ * @example Extract text content
1098
+ * ```typescript
1099
+ * import { createRichtextRange } from "@canva/design";
1100
+ *
1101
+ * const range = createRichtextRange();
1102
+ * range.appendText('Sample text');
1103
+ *
1104
+ * // Get plain text content
1105
+ * const text = range.readPlaintext();
1106
+ *
1107
+ * // Get formatted regions
1108
+ * const regions = range.readTextRegions();
1109
+ * ```
1110
+ *
1111
+ * @example Replace text with formatting
1112
+ * ```typescript
1113
+ * import { createRichtextRange } from "@canva/design";
1114
+ *
1115
+ * const range = createRichtextRange();
1116
+ * range.appendText('Original text');
1117
+ *
1118
+ * // Replace text while adding formatting
1119
+ * range.replaceText(
1120
+ * { index: 0, length: range.readPlaintext().length },
1121
+ * 'Modified',
1122
+ * { color: '#0066CC', decoration: 'underline' }
1123
+ * );
1124
+ * ```
388
1125
  */
389
1126
  export declare const createRichtextRange: () => RichtextRange;
390
1127
 
@@ -1917,7 +2654,7 @@ export declare type DesignElement =
1917
2654
  | TableElement;
1918
2655
 
1919
2656
  /**
1920
- * @beta
2657
+ * @public
1921
2658
  * Information about the design.
1922
2659
  */
1923
2660
  export declare type DesignMetadata = {
@@ -1941,7 +2678,7 @@ export declare type DesignMetadata = {
1941
2678
  * @remarks
1942
2679
  * The order of pages is not guaranteed.
1943
2680
  */
1944
- pageMetadata: Iterable<PageContext>;
2681
+ pageMetadata: Iterable<PageMetadata>;
1945
2682
  /**
1946
2683
  * The duration of the whole design in seconds.
1947
2684
  * @remarks
@@ -1973,6 +2710,80 @@ export declare type DesignOverlay = {
1973
2710
  /**
1974
2711
  * Registers a callback that runs when the `canOpen` state of an overlay target changes.
1975
2712
  * @param opts - Options for configuring the callback.
2713
+ *
2714
+ * @example Register overlay handler
2715
+ * ```typescript
2716
+ * import { overlay } from "@canva/design";
2717
+ *
2718
+ * overlay.registerOnCanOpen({
2719
+ * target: 'image_selection',
2720
+ * onCanOpen: async (event) => {
2721
+ * if (event.canOpen) {
2722
+ * // Can open overlay for selected image
2723
+ * }
2724
+ * }
2725
+ * });
2726
+ * ```
2727
+ *
2728
+ * @example Open image editing overlay
2729
+ * ```typescript
2730
+ * import { overlay } from "@canva/design";
2731
+ *
2732
+ * overlay.registerOnCanOpen({
2733
+ * target: 'image_selection',
2734
+ * onCanOpen: async (event) => {
2735
+ * if (event.canOpen) {
2736
+ * const processId = await event.open({
2737
+ * launchParameters: {
2738
+ * mode: 'edit'
2739
+ * }
2740
+ * });
2741
+ * // Overlay process started, with `processId`
2742
+ * }
2743
+ * }
2744
+ * });
2745
+ * ```
2746
+ *
2747
+ * @example Open overlay with filters
2748
+ * ```typescript
2749
+ * import { overlay } from "@canva/design";
2750
+ *
2751
+ * overlay.registerOnCanOpen({
2752
+ * target: 'image_selection',
2753
+ * onCanOpen: async (event) => {
2754
+ * if (event.canOpen) {
2755
+ * await event.open({
2756
+ * launchParameters: {
2757
+ * mode: 'edit',
2758
+ * filters: ['brightness', 'contrast', 'saturation']
2759
+ * }
2760
+ * });
2761
+ * }
2762
+ * }
2763
+ * });
2764
+ * ```
2765
+ *
2766
+ * @example Handle overlay unavailability
2767
+ * ```typescript
2768
+ * import { overlay } from "@canva/design";
2769
+ *
2770
+ * overlay.registerOnCanOpen({
2771
+ * target: 'image_selection',
2772
+ * onCanOpen: async (event) => {
2773
+ * if (!event.canOpen) {
2774
+ * // Cannot open overlay, handle specific reasons
2775
+ * switch (event.reason) {
2776
+ * case 'no_selection':
2777
+ * // No image is selected
2778
+ * break;
2779
+ * case 'invalid_selection':
2780
+ * // Selected content cannot be edited
2781
+ * break;
2782
+ * }
2783
+ * }
2784
+ * }
2785
+ * });
2786
+ * ```
1976
2787
  */
1977
2788
  registerOnCanOpen<Target extends OverlayTarget>(opts: {
1978
2789
  /**
@@ -2003,6 +2814,67 @@ export declare type DesignSelection = {
2003
2814
  *
2004
2815
  * @remarks
2005
2816
  * This callback fires immediately if content is already selected when the callback is registered.
2817
+ *
2818
+ * @example Handling plaintext selection
2819
+ * ```typescript
2820
+ * import { selection } from "@canva/design";
2821
+ *
2822
+ * selection.registerOnChange({
2823
+ * scope: 'plaintext',
2824
+ * onChange: async (event) => {
2825
+ * if (event.count > 0) {
2826
+ * const draft = await event.read();
2827
+ * // Do something with the selected text, e.g. `draft.contents[0].text`
2828
+ * }
2829
+ * }
2830
+ * });
2831
+ * ```
2832
+ *
2833
+ * @example Handling image selection
2834
+ * ```typescript
2835
+ * import { selection } from "@canva/design";
2836
+ *
2837
+ * selection.registerOnChange({
2838
+ * scope: 'image',
2839
+ * onChange: async (event) => {
2840
+ * if (event.count > 0) {
2841
+ * const draft = await event.read();
2842
+ * // Do something with the selected image ref, e.g. `draft.contents[0].ref`
2843
+ * }
2844
+ * }
2845
+ * });
2846
+ * ```
2847
+ *
2848
+ * @example Handling video selection
2849
+ * ```typescript
2850
+ * import { selection } from "@canva/design";
2851
+ *
2852
+ * selection.registerOnChange({
2853
+ * scope: 'video',
2854
+ * onChange: async (event) => {
2855
+ * if (event.count > 0) {
2856
+ * const draft = await event.read();
2857
+ * // Do something with the selected video ref, e.g. `draft.contents[0].ref`
2858
+ * }
2859
+ * }
2860
+ * });
2861
+ * ```
2862
+ *
2863
+ * @example Handling richtext selection
2864
+ * ```typescript
2865
+ * import { selection } from "@canva/design";
2866
+ *
2867
+ * selection.registerOnChange({
2868
+ * scope: 'richtext',
2869
+ * onChange: async (event) => {
2870
+ * if (event.count > 0) {
2871
+ * const draft = await event.read();
2872
+ * const range = draft.contents[0];
2873
+ * // Do something with the selected richtext, e.g. `range.readPlaintext()`
2874
+ * }
2875
+ * }
2876
+ * });
2877
+ * ```
2006
2878
  */
2007
2879
  registerOnChange<Scope extends SelectionScope>(opts: {
2008
2880
  /**
@@ -2082,7 +2954,7 @@ export declare function editContent(
2082
2954
  /**
2083
2955
  * @beta
2084
2956
  * A callback for reading and updating the requested design content.
2085
- * @param session - The result of reading the content in the design.
2957
+ * @param session - Session for reading and updating content in the design.
2086
2958
  */
2087
2959
  export declare type EditContentCallback = (
2088
2960
  session: RichtextContentSession | FillContentSession,
@@ -2356,12 +3228,38 @@ export declare type Fill = {
2356
3228
  export declare type FillContent =
2357
3229
  | {
2358
3230
  type: "image";
3231
+ /**
3232
+ * A unique identifier that points to an image asset in Canva's backend.
3233
+ */
2359
3234
  ref: ImageRef;
3235
+ /**
3236
+ * A description of the image content.
3237
+ *
3238
+ * @remarks
3239
+ * Use `undefined` for content with no description.
3240
+ */
3241
+ altText?: AltText;
3242
+ /**
3243
+ * Indicates whether the object containing this fill has been deleted.
3244
+ */
2360
3245
  deleted: boolean;
2361
3246
  }
2362
3247
  | {
2363
3248
  type: "video";
3249
+ /**
3250
+ * A unique identifier that points to an video asset in Canva's backend.
3251
+ */
2364
3252
  ref: VideoRef;
3253
+ /**
3254
+ * A description of the video content.
3255
+ *
3256
+ * @remarks
3257
+ * Use `undefined` for content with no description.
3258
+ */
3259
+ altText?: AltText;
3260
+ /**
3261
+ * Indicates whether the object containing this fill has been deleted.
3262
+ */
2365
3263
  deleted: boolean;
2366
3264
  };
2367
3265
 
@@ -2370,7 +3268,17 @@ export declare type FillContent =
2370
3268
  * Session for reading and updating fill content in a user's design.
2371
3269
  */
2372
3270
  export declare interface FillContentSession {
3271
+ /**
3272
+ * Fill content in the design.
3273
+ */
2373
3274
  readonly contents: readonly FillContent[];
3275
+ /**
3276
+ * Saves any changes made during the session while keeping the transaction open.
3277
+ *
3278
+ * @remarks
3279
+ * - Any changes in the session are only reflected in the design after this method is called.
3280
+ * - Once this method is called, further changes in the session can still be made.
3281
+ */
2374
3282
  sync(): Promise<void>;
2375
3283
  }
2376
3284
 
@@ -2401,6 +3309,18 @@ export declare type FontWeight =
2401
3309
  * Allows to get the context of currently selected page.
2402
3310
  * @public
2403
3311
  * @returns Page context of currently selected page
3312
+ *
3313
+ * @example Get current page information
3314
+ * ```typescript
3315
+ * import { getCurrentPageContext } from "@canva/design";
3316
+ *
3317
+ * const pageContext = await getCurrentPageContext();
3318
+ * if (pageContext.dimensions) {
3319
+ * // Do something with the page dimensions, e.g. `pageContext.dimensions.width` and `pageContext.dimensions.height`
3320
+ * } else {
3321
+ * // This page type does not have fixed dimensions, e.g. Whiteboard or Doc
3322
+ * }
3323
+ * ```
2404
3324
  */
2405
3325
  export declare const getCurrentPageContext: () => Promise<PageContext>;
2406
3326
 
@@ -2412,20 +3332,92 @@ export declare const getCurrentPageContext: () => Promise<PageContext>;
2412
3332
  * design that is applied whenever a new page is created.
2413
3333
  *
2414
3334
  * Returns `undefined` if the design is unbounded (e.g. Whiteboard or Doc).
3335
+ *
3336
+ * @example Get default page dimensions
3337
+ * ```typescript
3338
+ * import { getDefaultPageDimensions } from "@canva/design";
3339
+ *
3340
+ * const dimensions = await getDefaultPageDimensions();
3341
+ *
3342
+ * if (dimensions) {
3343
+ * // Do something with the dimensions, e.g. `dimensions.width` and `dimensions.height`
3344
+ * } else {
3345
+ * // This design type does not have fixed dimensions, e.g. Whiteboard or Doc
3346
+ * }
3347
+ * ```
3348
+ *
3349
+ * @example Center element using page dimensions
3350
+ * ```typescript
3351
+ * import { getDefaultPageDimensions, addElementAtPoint } from "@canva/design";
3352
+ * import type { ImageElementAtPoint } from "@canva/design";
3353
+ *
3354
+ * const dimensions = await getDefaultPageDimensions();
3355
+ *
3356
+ * if (dimensions) {
3357
+ * const elementWidth = 300;
3358
+ * const elementHeight = 200;
3359
+ *
3360
+ * const element: ImageElementAtPoint = {
3361
+ * type: 'image',
3362
+ * dataUrl: 'data:image/png;base64,...',
3363
+ * altText: { text: 'Centered image', decorative: false },
3364
+ * top: (dimensions.height - elementHeight) / 2,
3365
+ * left: (dimensions.width - elementWidth) / 2,
3366
+ * width: elementWidth,
3367
+ * height: elementHeight
3368
+ * };
3369
+ *
3370
+ * await addElementAtPoint(element);
3371
+ * }
3372
+ * ```
2415
3373
  */
2416
3374
  export declare const getDefaultPageDimensions: () => Promise<
2417
3375
  Dimensions | undefined
2418
3376
  >;
2419
3377
 
2420
3378
  /**
2421
- * @beta
3379
+ * @public
2422
3380
  * Retrieves information about the design.
3381
+ *
3382
+ * @example Get design metadata
3383
+ * ```typescript
3384
+ * import { getDesignMetadata } from "@canva/design";
3385
+ *
3386
+ * const metadata = await getDesignMetadata();
3387
+ *
3388
+ * const { title, defaultPageDimensions, pageMetadata, durationInSeconds } = metadata;
3389
+ * ```
2423
3390
  */
2424
3391
  export declare const getDesignMetadata: () => Promise<DesignMetadata>;
2425
3392
 
2426
3393
  /**
2427
3394
  * @public
2428
3395
  * Retrieves a signed JWT that contains the Design ID, App ID and User ID.
3396
+ *
3397
+ * @example Get design token
3398
+ * ```typescript
3399
+ * import { getDesignToken } from "@canva/design";
3400
+ *
3401
+ * const { token } = await getDesignToken();
3402
+ * ```
3403
+ *
3404
+ * @example Verify token with backend service
3405
+ * ```typescript
3406
+ * import { getDesignToken } from "@canva/design";
3407
+ *
3408
+ * const { token } = await getDesignToken();
3409
+ *
3410
+ * const verifyResponse = await fetch('https://your-backend.com/verify', {
3411
+ * method: 'POST',
3412
+ * headers: {
3413
+ * 'Content-Type': 'application/json'
3414
+ * },
3415
+ * body: JSON.stringify({ token })
3416
+ * });
3417
+ *
3418
+ * const json = await verifyResponse.json();
3419
+ * const { designId, appId, userId } = json;
3420
+ * ```
2429
3421
  */
2430
3422
  export declare const getDesignToken: () => Promise<DesignToken>;
2431
3423
 
@@ -2579,6 +3571,40 @@ export declare type ImageRef = string & {
2579
3571
  /**
2580
3572
  * @public
2581
3573
  * @param appElementConfig - Configuration for an AppElementClient
3574
+ *
3575
+ * @example Initialize app element client
3576
+ * ```typescript
3577
+ * import { initAppElement } from "@canva/design";
3578
+ *
3579
+ * const appElement = initAppElement<{ content: string }>({
3580
+ * render: (data) => {
3581
+ * return [{
3582
+ * type: 'text',
3583
+ * children: [data.content],
3584
+ * top: 100,
3585
+ * left: 100,
3586
+ * width: 200
3587
+ * }];
3588
+ * }
3589
+ * });
3590
+ * ```
3591
+ *
3592
+ * @example Initialize V2 app element client
3593
+ * ```typescript
3594
+ * import { initAppElement } from "@canva/design";
3595
+ *
3596
+ * const appElement = initAppElement<{ content: string }>({
3597
+ * render: (data) => {
3598
+ * return [{
3599
+ * type: 'text',
3600
+ * children: [data.content],
3601
+ * top: 100,
3602
+ * left: 100,
3603
+ * width: 200
3604
+ * }];
3605
+ * }
3606
+ * });
3607
+ * ```
2582
3608
  */
2583
3609
  export declare const initAppElement: <A extends AppElementData>(
2584
3610
  appElementConfig: AppElementClientConfiguration<A>,
@@ -2869,6 +3895,20 @@ export declare type PageDimensions = {
2869
3895
  height: number;
2870
3896
  };
2871
3897
 
3898
+ /**
3899
+ * @public
3900
+ * Information about a page.
3901
+ */
3902
+ export declare type PageMetadata = {
3903
+ /**
3904
+ * The dimensions of the page, in pixels.
3905
+ *
3906
+ * @remarks
3907
+ * This may be `undefined` because some types of pages don't have dimensions, such as whiteboards.
3908
+ */
3909
+ dimensions?: PageDimensions;
3910
+ };
3911
+
2872
3912
  /**
2873
3913
  * @public
2874
3914
  * The outline of a path.
@@ -2966,10 +4006,121 @@ export declare interface RichtextContentRange extends RichtextRange {
2966
4006
 
2967
4007
  /**
2968
4008
  * @public
2969
- * Session for reading and updating richtext content in a user's design.
4009
+ * A callback for reading and updating the requested design content.
4010
+ * @param session - The result of reading the content in the design.
4011
+ *
4012
+ * @example Read and update richtext content
4013
+ * ```typescript
4014
+ * import { editContent } from "@canva/design";
4015
+ *
4016
+ * await editContent(
4017
+ * { contentType: 'richtext', target: 'current_page' },
4018
+ * async (session) => {
4019
+ * // Read the content
4020
+ * const contents = session.contents;
4021
+ *
4022
+ * if (contents.length > 0) {
4023
+ * const range = contents[0];
4024
+ *
4025
+ * // Modify the content (e.g., adding text)
4026
+ * range.appendText("\nAppended text from app");
4027
+ *
4028
+ * // Sync changes back to the design
4029
+ * await session.sync();
4030
+ * }
4031
+ * }
4032
+ * );
4033
+ * ```
4034
+ *
4035
+ * @example Format all richtext content in the design
4036
+ * ```typescript
4037
+ * import { editContent } from "@canva/design";
4038
+ *
4039
+ * await editContent(
4040
+ * { contentType: 'richtext', target: 'current_page' },
4041
+ * async (session) => {
4042
+ * // Process each richtext range in the content
4043
+ * for (const range of session.contents) {
4044
+ * // Skip if the content has been deleted
4045
+ * if (range.deleted) continue;
4046
+ *
4047
+ * // Get the text content
4048
+ * const text = range.readPlaintext();
4049
+ * if (text.length === 0) continue;
4050
+ *
4051
+ * // Apply consistent formatting
4052
+ * range.formatParagraph(
4053
+ * { index: 0, length: text.length },
4054
+ * {
4055
+ * fontRef: 'YOUR_FONT_REF',
4056
+ * fontSize: 16,
4057
+ * textAlign: 'start'
4058
+ * }
4059
+ * );
4060
+ * }
4061
+ *
4062
+ * // Sync all changes back to the design
4063
+ * await session.sync();
4064
+ * }
4065
+ * );
4066
+ * ```
4067
+ *
4068
+ * @example Modify content without saving changes
4069
+ * ```typescript
4070
+ * import { editContent } from "@canva/design";
4071
+ *
4072
+ * await editContent(
4073
+ * { contentType: 'richtext', target: 'current_page' },
4074
+ * async (session) => {
4075
+ * // Read and analyze the content without making changes
4076
+ * for (const range of session.contents) {
4077
+ * const text = range.readPlaintext();
4078
+ * // Do something with the content preview, e.g. `text.substring(0, 50)`
4079
+ *
4080
+ * // No call to session.sync() means no changes are saved
4081
+ * }
4082
+ *
4083
+ * // Since we're not calling sync(), no changes will be made to the design
4084
+ * }
4085
+ * );
4086
+ * ```
2970
4087
  */
2971
4088
  export declare interface RichtextContentSession {
4089
+ /**
4090
+ * Richtext content in the design.
4091
+ */
2972
4092
  readonly contents: readonly RichtextContentRange[];
4093
+ /**
4094
+ * Saves any changes made during the session while keeping the transaction open.
4095
+ *
4096
+ * @remarks
4097
+ * - Any changes in the session are only reflected in the design after this method is called.
4098
+ * - Once this method is called, further changes in the session can still be made.
4099
+ *
4100
+ * @example Sync changes after modifying content
4101
+ * ```typescript
4102
+ * import { editContent } from "@canva/design";
4103
+ *
4104
+ * await editContent(
4105
+ * { contentType: 'richtext', target: 'current_page' },
4106
+ * async (session) => {
4107
+ * if (session.contents.length > 0) {
4108
+ * const range = session.contents[0];
4109
+ *
4110
+ * // Make modifications to the content
4111
+ * range.appendText(" - Modified by app");
4112
+ *
4113
+ * try {
4114
+ * // Save changes back to the design
4115
+ * await session.sync();
4116
+ * } catch (error) {
4117
+ * console.error('Failed to sync changes:', error);
4118
+ * }
4119
+ * }
4120
+ * }
4121
+ * );
4122
+ * ```
4123
+ */
2973
4124
  sync(): Promise<void>;
2974
4125
  }
2975
4126
 
@@ -3063,6 +4214,42 @@ export declare type RichtextRange = {
3063
4214
  * - The `\n` character indicates the end of a paragraph.
3064
4215
  * - All paragraphs that overlap the provided bounds will be formatted in their entirety.
3065
4216
  *
4217
+ * @example Format paragraph as a heading
4218
+ * ```typescript
4219
+ * import { createRichtextRange } from "@canva/design";
4220
+ *
4221
+ * const range = createRichtextRange();
4222
+ *
4223
+ * range.appendText("Heading Text\nRegular paragraph text.");
4224
+ *
4225
+ * // Format just the first paragraph as a heading
4226
+ * range.formatParagraph(
4227
+ * { index: 0, length: 12 }, // Only need to include part of the paragraph
4228
+ * {
4229
+ * fontSize: 24,
4230
+ * fontWeight: 'bold',
4231
+ * textAlign: 'center'
4232
+ * }
4233
+ * );
4234
+ * ```
4235
+ *
4236
+ * @example Create a bulleted list
4237
+ * ```typescript
4238
+ * import { createRichtextRange } from "@canva/design";
4239
+ *
4240
+ * const range = createRichtextRange();
4241
+ * const text = "Item 1\nItem 2\nItem 3";
4242
+ * range.appendText(text);
4243
+ *
4244
+ * // Format all paragraphs as a bulleted list
4245
+ * range.formatParagraph(
4246
+ * { index: 0, length: text.length },
4247
+ * {
4248
+ * listLevel: 1,
4249
+ * listMarker: 'disc'
4250
+ * }
4251
+ * );
4252
+ * ```
3066
4253
  */
3067
4254
  formatParagraph(bounds: Bounds, formatting: RichtextFormatting): void;
3068
4255
  /**
@@ -3070,13 +4257,79 @@ export declare type RichtextRange = {
3070
4257
  *
3071
4258
  * @param bounds - The segment of the range on which to apply the formatting.
3072
4259
  * @param formatting - The formatting to apply to the text.
4260
+ *
4261
+ * @example Format specific words in a paragraph
4262
+ * ```typescript
4263
+ * import { createRichtextRange } from "@canva/design";
4264
+ *
4265
+ * const range = createRichtextRange();
4266
+ * range.appendText("This text contains important information.");
4267
+ *
4268
+ * // Format just the word "important"
4269
+ * range.formatText(
4270
+ * { index: 16, length: 9 },
4271
+ * {
4272
+ * fontWeight: 'bold',
4273
+ * color: '#FF0000'
4274
+ * }
4275
+ * );
4276
+ * ```
4277
+ *
4278
+ * @example Add a link to text
4279
+ * ```typescript
4280
+ * import { createRichtextRange } from "@canva/design";
4281
+ *
4282
+ * const range = createRichtextRange();
4283
+ * range.appendText("Visit our website for more information.");
4284
+ *
4285
+ * // Add a link to "our website"
4286
+ * range.formatText(
4287
+ * { index: 6, length: 11 },
4288
+ * {
4289
+ * link: "https://www.example.com",
4290
+ * decoration: 'underline',
4291
+ * color: '#0066CC'
4292
+ * }
4293
+ * );
4294
+ * ```
3073
4295
  */
3074
4296
  formatText(bounds: Bounds, formatting: InlineFormatting): void;
3075
4297
  /**
3076
4298
  * Appends the specified characters to the end of the range.
3077
4299
  *
3078
4300
  * @param characters - The characters to append to the richtext range.
3079
- * @param fo -
4301
+ * @param formatting - Optional formatting to apply to the appended text.
4302
+ *
4303
+ * @example Append plain text
4304
+ * ```typescript
4305
+ * import { createRichtextRange } from "@canva/design";
4306
+ *
4307
+ * const range = createRichtextRange();
4308
+ * range.appendText("First paragraph. ");
4309
+ *
4310
+ * // Append more text to the existing content
4311
+ * const result = range.appendText("This is additional text.");
4312
+ *
4313
+ * // The bounds of the newly added text are returned
4314
+ * // Do something with the bounds - result.bounds, e.g. { index: 17, length: 24 }
4315
+ * ```
4316
+ *
4317
+ * @example Append formatted text
4318
+ * ```typescript
4319
+ * import { createRichtextRange } from "@canva/design";
4320
+ *
4321
+ * const range = createRichtextRange();
4322
+ * range.appendText("Normal text followed by ");
4323
+ *
4324
+ * // Append formatted text
4325
+ * range.appendText("bold red text", {
4326
+ * fontWeight: 'bold',
4327
+ * color: '#FF0000'
4328
+ * });
4329
+ *
4330
+ * // Append a new paragraph
4331
+ * range.appendText("\nThis is a new paragraph.");
4332
+ * ```
3080
4333
  */
3081
4334
  appendText(
3082
4335
  characters: string,
@@ -3090,6 +4343,42 @@ export declare type RichtextRange = {
3090
4343
  * @param bounds - The segment of the range to replace.
3091
4344
  * @param characters - The replacement characters.
3092
4345
  * @param formatting - The formatting to apply to the replaced text.
4346
+ *
4347
+ * @example Replace text while maintaining some formatting
4348
+ * ```typescript
4349
+ * import { createRichtextRange } from "@canva/design";
4350
+ *
4351
+ * const range = createRichtextRange();
4352
+ * range.appendText("This text needs correction.");
4353
+ *
4354
+ * // Replace "needs correction" with "is correct"
4355
+ * const result = range.replaceText(
4356
+ * { index: 10, length: 16 },
4357
+ * "is correct"
4358
+ * );
4359
+ *
4360
+ * // The bounds of the replaced text are returned
4361
+ * // Do something with the bounds - result.bounds, e.g. { index: 10, length: 10 }
4362
+ * ```
4363
+ *
4364
+ * @example Replace text with formatted text
4365
+ * ```typescript
4366
+ * import { createRichtextRange } from "@canva/design";
4367
+ *
4368
+ * const range = createRichtextRange();
4369
+ * range.appendText("Regular text that needs emphasis.");
4370
+ *
4371
+ * // Replace "needs emphasis" with formatted text
4372
+ * range.replaceText(
4373
+ * { index: 17, length: 15 },
4374
+ * "is important",
4375
+ * {
4376
+ * fontWeight: 'bold',
4377
+ * fontStyle: 'italic',
4378
+ * color: '#0066CC'
4379
+ * }
4380
+ * );
4381
+ * ```
3093
4382
  */
3094
4383
  replaceText(
3095
4384
  bounds: Bounds,
@@ -3103,11 +4392,87 @@ export declare type RichtextRange = {
3103
4392
  };
3104
4393
  /**
3105
4394
  * Returns the current state of the richtext as plaintext.
4395
+ *
4396
+ * @example Extract plain text content
4397
+ * ```typescript
4398
+ * import { createRichtextRange } from "@canva/design";
4399
+ *
4400
+ * const range = createRichtextRange();
4401
+ * range.appendText("First paragraph.\n", { fontWeight: 'bold' });
4402
+ * range.appendText("Second paragraph with formatting.", { color: '#FF0000' });
4403
+ *
4404
+ * // Get plain text content without formatting
4405
+ * const plainText = range.readPlaintext();
4406
+ * // Do something with the plain text - plainText, e.g. "First paragraph.\nSecond paragraph with formatting."
4407
+ * ```
4408
+ *
4409
+ * @example Search within text content
4410
+ * ```typescript
4411
+ * import { createRichtextRange } from "@canva/design";
4412
+ *
4413
+ * const range = createRichtextRange();
4414
+ * range.appendText("This text contains a searchable term.");
4415
+ *
4416
+ * // Search for a specific word
4417
+ * const plainText = range.readPlaintext();
4418
+ * const searchTerm = "searchable";
4419
+ * const index = plainText.indexOf(searchTerm);
4420
+ *
4421
+ * if (index !== -1) {
4422
+ * // Format the found term
4423
+ * range.formatText(
4424
+ * { index, length: searchTerm.length },
4425
+ * { fontWeight: 'bold', decoration: 'underline' }
4426
+ * );
4427
+ * }
4428
+ * ```
3106
4429
  */
3107
4430
  readPlaintext(): string;
3108
4431
  /**
3109
4432
  * Returns the current state of the richtext as one or more text regions.
3110
4433
  * Each region is an object that contains the text content and its formatting.
4434
+ *
4435
+ * @example Get text with formatting information
4436
+ * ```typescript
4437
+ * import { createRichtextRange } from "@canva/design";
4438
+ *
4439
+ * const range = createRichtextRange();
4440
+ * range.appendText("Normal text ", {});
4441
+ * range.appendText("bold text", { fontWeight: 'bold' });
4442
+ * range.appendText(" and ", {});
4443
+ * range.appendText("red text", { color: '#FF0000' });
4444
+ *
4445
+ * // Get formatted regions
4446
+ * const regions = range.readTextRegions();
4447
+ * // Do something with the regions, e.g.
4448
+ * // [
4449
+ * // { text: "Normal text ", formatting: {} },
4450
+ * // { text: "bold text", formatting: { fontWeight: 'bold' } },
4451
+ * // { text: " and ", formatting: {} },
4452
+ * // { text: "red text", formatting: { color: '#FF0000' } }
4453
+ * // ]
4454
+ * ```
4455
+ *
4456
+ * @example Analyze formatting variations
4457
+ * ```typescript
4458
+ * import { createRichtextRange } from "@canva/design";
4459
+ *
4460
+ * const range = createRichtextRange();
4461
+ * range.appendText("Mixed ", {});
4462
+ * range.appendText("formatted ", { fontWeight: 'bold' });
4463
+ * range.appendText("text", { color: '#0066CC' });
4464
+ *
4465
+ * // Analyze formatting variations
4466
+ * const regions = range.readTextRegions();
4467
+ * const formattingTypes = regions.map(region => {
4468
+ * const formatting = region.formatting || {};
4469
+ * return {
4470
+ * text: region.text,
4471
+ * hasWeight: !!formatting.fontWeight,
4472
+ * hasColor: !!formatting.color
4473
+ * };
4474
+ * });
4475
+ * ```
3111
4476
  */
3112
4477
  readTextRegions(): TextRegion[];
3113
4478
  };
@@ -3137,17 +4502,68 @@ export declare interface SelectionEvent<Scope extends SelectionScope> {
3137
4502
  * Any changes made to `contents` are not immediately persisted or reflected in the user's design.
3138
4503
  * To persist the changes, call the `save` method that's available via the draft.
3139
4504
  *
3140
- * @example Replacing text
4505
+ * @example Read and modify plaintext selection
4506
+ * ```typescript
4507
+ * import { selection } from "@canva/design";
4508
+ *
4509
+ * selection.registerOnChange({
4510
+ * scope: 'plaintext',
4511
+ * onChange: async (event) => {
4512
+ * if (event.count > 0) {
4513
+ * // Read the content
4514
+ * const draft = await event.read();
4515
+ *
4516
+ * // Handle selected text `draft.contents[0].text`
4517
+ *
4518
+ * // Modify the text if needed
4519
+ * // draft.contents[0].text = 'Modified text';
4520
+ * // await draft.save();
4521
+ * }
4522
+ * }
4523
+ * });
3141
4524
  * ```
3142
- * const draft = await selectionEvent.read();
3143
4525
  *
3144
- * for(const content of draft.contents) {
3145
- * // This change won't immediately appear in the user's design
3146
- * content.text = "This is the new text";
3147
- * }
4526
+ * @example Read and analyze image selection
4527
+ * ```typescript
4528
+ * import { selection } from "@canva/design";
3148
4529
  *
3149
- * // The changes will now appear in the user's design
3150
- * await draft.save();
4530
+ * selection.registerOnChange({
4531
+ * scope: 'image',
4532
+ * onChange: async (event) => {
4533
+ * // Check if any images are selected
4534
+ * if (event.count === 0) {
4535
+ * // Handle no images selected case
4536
+ * return;
4537
+ * }
4538
+ *
4539
+ * // Read the content
4540
+ * const draft = await event.read();
4541
+ *
4542
+ * // Get information about selected images
4543
+ * const imageRefs = draft.contents.map(content => content.ref);
4544
+ *
4545
+ * // The ref can be used with other API methods
4546
+ * }
4547
+ * });
4548
+ * ```
4549
+ *
4550
+ * @example Process multiple selected items
4551
+ * ```typescript
4552
+ * import { selection } from "@canva/design";
4553
+ *
4554
+ * selection.registerOnChange({
4555
+ * scope: 'richtext',
4556
+ * onChange: async (event) => {
4557
+ * if (event.count > 0) {
4558
+ * const draft = await event.read();
4559
+ *
4560
+ * // Process each selected range
4561
+ * draft.contents.forEach((range) => {
4562
+ * // Do something with the range content and formatted regions, with `range.readPlaintext()` and `range.readTextRegions()`
4563
+ * });
4564
+ * }
4565
+ * }
4566
+ * });
3151
4567
  * ```
3152
4568
  */
3153
4569
  read(): Promise<ContentDraft<SelectionValue<Scope>>>;
@@ -3230,6 +4646,56 @@ export declare type SelectionValue<Scope extends SelectionScope> = {
3230
4646
  * @public
3231
4647
  * Updates the background of the user's current page. The background can be a solid color,
3232
4648
  * an image or a video.
4649
+ *
4650
+ * @example Set background color
4651
+ * ```typescript
4652
+ * import { setCurrentPageBackground } from "@canva/design";
4653
+ * import type { PageBackgroundFill } from "@canva/design";
4654
+ *
4655
+ * const background: PageBackgroundFill = {
4656
+ * color: '#F5F5F5',
4657
+ * };
4658
+ *
4659
+ * await setCurrentPageBackground(background);
4660
+ * ```
4661
+ *
4662
+ * @example Set background image
4663
+ * ```typescript
4664
+ * import { setCurrentPageBackground } from "@canva/design";
4665
+ * import type { PageBackgroundFill } from "@canva/design";
4666
+ * import type { ImageRef } from "@canva/asset";
4667
+ *
4668
+ * const exampleImageRef = "YOUR_IMAGE_REF" as ImageRef;
4669
+ *
4670
+ * const background: PageBackgroundFill = {
4671
+ * asset: {
4672
+ * type: 'image',
4673
+ * ref: exampleImageRef,
4674
+ * altText: { text: 'Background image', decorative: true }
4675
+ * },
4676
+ * };
4677
+ *
4678
+ * await setCurrentPageBackground(background);
4679
+ * ```
4680
+ *
4681
+ * @example Set background video
4682
+ * ```typescript
4683
+ * import { setCurrentPageBackground } from "@canva/design";
4684
+ * import type { PageBackgroundFill } from "@canva/design";
4685
+ * import type { VideoRef } from "@canva/asset";
4686
+ *
4687
+ * const exampleVideoRef = "YOUR_VIDEO_REF" as VideoRef;
4688
+ *
4689
+ * const background: PageBackgroundFill = {
4690
+ * asset: {
4691
+ * type: 'video',
4692
+ * ref: exampleVideoRef,
4693
+ * altText: { text: 'Background video', decorative: true }
4694
+ * },
4695
+ * };
4696
+ *
4697
+ * await setCurrentPageBackground(background);
4698
+ * ```
3233
4699
  */
3234
4700
  export declare const setCurrentPageBackground: (
3235
4701
  opts: PageBackgroundFill,