@excalidraw/element 0.18.0-063e025 → 0.18.0-1118751
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dev/index.js +13047 -9808
- package/dist/dev/index.js.map +4 -4
- package/dist/prod/index.js +19 -19
- package/dist/types/common/src/colors.d.ts +22 -0
- package/dist/types/common/src/constants.d.ts +54 -0
- package/dist/types/common/src/keys.d.ts +4 -0
- package/dist/types/common/src/points.d.ts +1 -1
- package/dist/types/common/src/random.d.ts +7 -0
- package/dist/types/common/src/utils.d.ts +1 -1
- package/dist/types/element/src/Scene.d.ts +1 -1
- package/dist/types/element/src/arrowEndpointText.d.ts +49 -0
- package/dist/types/element/src/arrows/focus.d.ts +5 -2
- package/dist/types/element/src/binding.d.ts +15 -8
- package/dist/types/element/src/bucketFill.d.ts +110 -0
- package/dist/types/element/src/collision.d.ts +8 -5
- package/dist/types/element/src/comparisons.d.ts +7 -5
- package/dist/types/element/src/convertToShape.d.ts +23 -0
- package/dist/types/element/src/delta.d.ts +23 -1
- package/dist/types/element/src/dragElements.d.ts +27 -0
- package/dist/types/element/src/duplicate.d.ts +60 -0
- package/dist/types/element/src/flowchart.d.ts +10 -6
- package/dist/types/element/src/frame.d.ts +2 -2
- package/dist/types/element/src/groups.d.ts +1 -1
- package/dist/types/element/src/index.d.ts +4 -0
- package/dist/types/element/src/linearElementEditor.d.ts +17 -0
- package/dist/types/element/src/mutateElement.d.ts +1 -1
- package/dist/types/element/src/newElement.d.ts +37 -2
- package/dist/types/element/src/renderElement.d.ts +21 -4
- package/dist/types/element/src/selection.d.ts +1 -1
- package/dist/types/element/src/shape.d.ts +27 -1
- package/dist/types/element/src/sizeHelpers.d.ts +6 -0
- package/dist/types/element/src/sortElements.d.ts +10 -0
- package/dist/types/element/src/stickyNote.d.ts +183 -0
- package/dist/types/element/src/textElement.d.ts +7 -3
- package/dist/types/element/src/transform.d.ts +25 -6
- package/dist/types/element/src/typeChecks.d.ts +3 -2
- package/dist/types/element/src/types.d.ts +35 -6
- package/dist/types/element/src/utils.d.ts +15 -4
- package/dist/types/element/src/zindex.d.ts +1 -1
- package/dist/types/excalidraw/actions/actionAddToLibrary.d.ts +48 -9
- package/dist/types/excalidraw/actions/actionAlign.d.ts +6 -6
- package/dist/types/excalidraw/actions/actionBoundText.d.ts +32 -6
- package/dist/types/excalidraw/actions/actionCanvas.d.ts +173 -576
- package/dist/types/excalidraw/actions/actionClipboard.d.ts +32 -6
- package/dist/types/excalidraw/actions/actionCropEditor.d.ts +16 -3
- package/dist/types/excalidraw/actions/actionDeleteSelected.d.ts +50 -10
- package/dist/types/excalidraw/actions/actionDeselect.d.ts +13 -3
- package/dist/types/excalidraw/actions/actionDistribute.d.ts +2 -2
- package/dist/types/excalidraw/actions/actionElementLink.d.ts +16 -3
- package/dist/types/excalidraw/actions/actionElementLock.d.ts +32 -6
- package/dist/types/excalidraw/actions/actionExport.d.ts +34 -8
- package/dist/types/excalidraw/actions/actionFinalize.d.ts +1 -0
- package/dist/types/excalidraw/actions/actionFrame.d.ts +99 -185
- package/dist/types/excalidraw/actions/actionGroup.d.ts +33 -7
- package/dist/types/excalidraw/actions/actionLinearEditor.d.ts +68 -4
- package/dist/types/excalidraw/actions/actionLink.d.ts +16 -3
- package/dist/types/excalidraw/actions/actionMenu.d.ts +16 -3
- package/dist/types/excalidraw/actions/actionProperties.d.ts +45 -12
- package/dist/types/excalidraw/actions/actionSelectAll.d.ts +16 -3
- package/dist/types/excalidraw/actions/actionStyles.d.ts +17 -4
- package/dist/types/excalidraw/actions/actionTextAutoResize.d.ts +1 -1
- package/dist/types/excalidraw/actions/actionToggleArrowBinding.d.ts +16 -3
- package/dist/types/excalidraw/actions/actionToggleGridMode.d.ts +16 -3
- package/dist/types/excalidraw/actions/actionToggleMidpointSnapping.d.ts +16 -3
- package/dist/types/excalidraw/actions/actionToggleObjectsSnapMode.d.ts +16 -3
- package/dist/types/excalidraw/actions/actionToggleSearchMenu.d.ts +16 -3
- package/dist/types/excalidraw/actions/actionToggleStats.d.ts +16 -3
- package/dist/types/excalidraw/actions/actionToggleViewMode.d.ts +17 -4
- package/dist/types/excalidraw/actions/actionToggleZenMode.d.ts +16 -3
- package/dist/types/excalidraw/actions/colorTargets.d.ts +39 -0
- package/dist/types/excalidraw/actions/index.d.ts +1 -2
- package/dist/types/excalidraw/actions/manager.d.ts +1 -0
- package/dist/types/excalidraw/actions/shortcuts.d.ts +1 -1
- package/dist/types/excalidraw/actions/types.d.ts +5 -1
- package/dist/types/excalidraw/appState.d.ts +26 -5
- package/dist/types/excalidraw/components/Actions.d.ts +16 -10
- package/dist/types/excalidraw/components/App.arrowText.d.ts +104 -0
- package/dist/types/excalidraw/components/App.bucketFill.d.ts +48 -0
- package/dist/types/excalidraw/components/App.cursor.d.ts +38 -0
- package/dist/types/excalidraw/components/App.d.ts +468 -99
- package/dist/types/excalidraw/components/App.drawshape.d.ts +55 -0
- package/dist/types/excalidraw/components/App.duplicate.d.ts +51 -0
- package/dist/types/excalidraw/components/App.flowchart.d.ts +21 -0
- package/dist/types/excalidraw/components/App.pan.d.ts +54 -0
- package/dist/types/excalidraw/components/App.toolDrag.d.ts +63 -0
- package/dist/types/excalidraw/components/App.viewport.d.ts +73 -0
- package/dist/types/excalidraw/components/App.wheel.d.ts +26 -0
- package/dist/types/excalidraw/components/ColorPicker/ColorPicker.d.ts +8 -2
- package/dist/types/excalidraw/components/ColorPicker/CustomColorList.d.ts +3 -1
- package/dist/types/excalidraw/components/ColorPicker/Picker.d.ts +5 -1
- package/dist/types/excalidraw/components/ColorPicker/PickerColorList.d.ts +9 -2
- package/dist/types/excalidraw/components/ColorPicker/ShadeList.d.ts +4 -2
- package/dist/types/excalidraw/components/ColorPicker/TopPicks.d.ts +8 -1
- package/dist/types/excalidraw/components/ColorPicker/colorTopPicksDnD.d.ts +11 -0
- package/dist/types/excalidraw/components/ColorPicker/keyboardNavHandlers.d.ts +2 -1
- package/dist/types/excalidraw/components/FontPicker/FontPicker.d.ts +4 -1
- package/dist/types/excalidraw/components/FontPicker/FontPickerList.d.ts +6 -1
- package/dist/types/excalidraw/components/FontPicker/fontTopPicksDnD.d.ts +12 -0
- package/dist/types/excalidraw/components/IconButton.d.ts +48 -0
- package/dist/types/excalidraw/components/LaserPointerButton.d.ts +2 -4
- package/dist/types/excalidraw/components/LayerUI.d.ts +5 -2
- package/dist/types/excalidraw/components/LockButton.d.ts +3 -4
- package/dist/types/excalidraw/components/MagicButton.d.ts +0 -2
- package/dist/types/excalidraw/components/MobileMenu.d.ts +4 -4
- package/dist/types/excalidraw/components/MobileToolbar.d.ts +9 -0
- package/dist/types/excalidraw/components/PenModeButton.d.ts +2 -5
- package/dist/types/excalidraw/components/Popover.d.ts +1 -3
- package/dist/types/excalidraw/components/{ButtonIcon.d.ts → RadioButton.d.ts} +2 -5
- package/dist/types/excalidraw/components/ToolPopover.d.ts +3 -6
- package/dist/types/excalidraw/components/Toolbar.d.ts +11 -0
- package/dist/types/excalidraw/components/Tools.d.ts +151 -0
- package/dist/types/excalidraw/components/TopPicksDnD/TopPicksContextMenu.d.ts +14 -0
- package/dist/types/excalidraw/components/TopPicksDnD/TopPicksTip.d.ts +11 -0
- package/dist/types/excalidraw/components/TopPicksDnD/topPicksDnD.d.ts +58 -0
- package/dist/types/excalidraw/components/UserList.d.ts +3 -2
- package/dist/types/excalidraw/components/ViewportStatusFrame/ViewportStatusFrame.d.ts +11 -0
- package/dist/types/excalidraw/components/canvases/InteractiveCanvas.d.ts +2 -0
- package/dist/types/excalidraw/components/canvases/NewElementCanvas.d.ts +2 -0
- package/dist/types/excalidraw/components/footer/Footer.d.ts +3 -1
- package/dist/types/excalidraw/components/icons.d.ts +5 -1
- package/dist/types/excalidraw/components/main-menu/DefaultItems.d.ts +2 -1
- package/dist/types/excalidraw/components/positionElementBesideCursor.d.ts +26 -0
- package/dist/types/excalidraw/components/shapeActionPredicates.d.ts +39 -0
- package/dist/types/excalidraw/data/blob.d.ts +36 -10
- package/dist/types/excalidraw/data/json.d.ts +18 -5
- package/dist/types/excalidraw/drawShapeTrail.d.ts +16 -0
- package/dist/types/excalidraw/fonts/Fonts.d.ts +3 -2
- package/dist/types/excalidraw/hooks/useTextEditorFocus.d.ts +5 -5
- package/dist/types/excalidraw/lasso/utils.d.ts +2 -0
- package/dist/types/excalidraw/renderOverrides.d.ts +9 -0
- package/dist/types/excalidraw/renderer/helpers.d.ts +25 -0
- package/dist/types/excalidraw/renderer/interactiveScene.d.ts +1 -1
- package/dist/types/excalidraw/scene/Renderer.d.ts +64 -2
- package/dist/types/excalidraw/scene/index.d.ts +1 -1
- package/dist/types/excalidraw/scene/types.d.ts +6 -1
- package/dist/types/excalidraw/types.d.ts +341 -21
- package/dist/types/excalidraw/viewport.d.ts +31 -66
- package/dist/types/laser-pointer/src/state.d.ts +1 -0
- package/dist/types/math/src/curve.d.ts +19 -12
- package/dist/types/math/src/index.d.ts +1 -0
- package/dist/types/math/src/pca.d.ts +79 -0
- package/dist/types/math/src/polygon.d.ts +25 -1
- package/dist/types/math/src/segment.d.ts +6 -0
- package/dist/types/utils/src/export.d.ts +1 -0
- package/dist/types/utils/src/shape.d.ts +2 -2
- package/package.json +4 -4
- package/dist/types/excalidraw/actions/actionEmbeddable.d.ts +0 -173
- package/dist/types/excalidraw/components/FollowMode/FollowMode.d.ts +0 -10
- package/dist/types/excalidraw/components/HandButton.d.ts +0 -10
- package/dist/types/excalidraw/components/MobileToolBar.d.ts +0 -10
- package/dist/types/excalidraw/components/ToolButton.d.ts +0 -49
- package/dist/types/excalidraw/components/shapes.d.ts +0 -270
- package/dist/types/excalidraw/cursor.d.ts +0 -5
- package/dist/types/excalidraw/scene/zoom.d.ts +0 -12
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { IMAGE_MIME_TYPES, UserIdleState, throttleRAF, MIME_TYPES, EditorInterface, StrokeWidthKey } from "@excalidraw/common";
|
|
2
2
|
import type { LinearElementEditor } from "@excalidraw/element";
|
|
3
3
|
import type { MaybeTransformHandleType } from "@excalidraw/element";
|
|
4
|
-
import type { PointerType, ExcalidrawLinearElement, NonDeletedExcalidrawElement, NonDeleted, TextAlign, ExcalidrawElement, GroupId, ExcalidrawBindableElement, Arrowhead, FontFamilyValues, FileId, Theme, StrokeRoundness, ExcalidrawEmbeddableElement, ExcalidrawMagicFrameElement, ExcalidrawFrameLikeElement, ExcalidrawElementType, ExcalidrawIframeLikeElement, OrderedExcalidrawElement, ExcalidrawNonSelectionElement, BindMode, ExcalidrawTextElement, StrokeVariability } from "@excalidraw/element/types";
|
|
4
|
+
import type { PointerType, ExcalidrawLinearElement, NonDeletedExcalidrawElement, NonDeleted, TextAlign, ExcalidrawElement, GroupId, ExcalidrawBindableElement, ExcalidrawArrowElement, Arrowhead, FontFamilyValues, FileId, Theme, StrokeRoundness, ExcalidrawEmbeddableElement, ExcalidrawMagicFrameElement, ExcalidrawFrameLikeElement, ExcalidrawElementType, ExcalidrawIframeLikeElement, OrderedExcalidrawElement, ExcalidrawNonSelectionElement, BindMode, ExcalidrawTextElement, StrokeVariability } from "@excalidraw/element/types";
|
|
5
5
|
import type { Merge, MaybePromise, ValueOf, MakeBrand } from "@excalidraw/common/utility-types";
|
|
6
|
-
import type { CaptureUpdateActionType, DurableIncrement, EphemeralIncrement } from "@excalidraw/element";
|
|
6
|
+
import type { CaptureUpdateActionType, DurableIncrement, EphemeralIncrement, OnDuplicateData } from "@excalidraw/element";
|
|
7
7
|
import type { GlobalPoint } from "@excalidraw/math";
|
|
8
8
|
import type { Action } from "./actions/types";
|
|
9
9
|
import type { Spreadsheet } from "./charts";
|
|
@@ -85,7 +85,7 @@ export type BinaryFileData = {
|
|
|
85
85
|
};
|
|
86
86
|
export type BinaryFileMetadata = Omit<BinaryFileData, "dataURL">;
|
|
87
87
|
export type BinaryFiles = Record<ExcalidrawElement["id"], BinaryFileData>;
|
|
88
|
-
export type ToolType = "selection" | "lasso" | "rectangle" | "diamond" | "ellipse" | "arrow" | "line" | "freedraw" | "text" | "image" | "eraser" | "hand" | "frame" | "magicframe" | "embeddable" | "laser";
|
|
88
|
+
export type ToolType = "selection" | "lasso" | "rectangle" | "diamond" | "ellipse" | "arrow" | "line" | "freedraw" | "text" | "image" | "eraser" | "hand" | "frame" | "magicframe" | "stickynote" | "embeddable" | "laser" | "autoshape" | "bucketfill";
|
|
89
89
|
export type ElementOrToolType = ExcalidrawElementType | ToolType | "custom";
|
|
90
90
|
export type ActiveTool = {
|
|
91
91
|
type: ToolType;
|
|
@@ -139,7 +139,9 @@ export type InteractiveCanvasAppState = Readonly<_CommonCanvasAppState & {
|
|
|
139
139
|
newElement: AppState["newElement"];
|
|
140
140
|
isBindingEnabled: AppState["isBindingEnabled"];
|
|
141
141
|
isMidpointSnappingEnabled: AppState["isMidpointSnappingEnabled"];
|
|
142
|
+
gridModeEnabled: AppState["gridModeEnabled"];
|
|
142
143
|
suggestedBinding: AppState["suggestedBinding"];
|
|
144
|
+
hoveredArrowTextAnchor: AppState["hoveredArrowTextAnchor"];
|
|
143
145
|
isRotating: AppState["isRotating"];
|
|
144
146
|
elementsToHighlight: AppState["elementsToHighlight"];
|
|
145
147
|
collaborators: AppState["collaborators"];
|
|
@@ -174,6 +176,11 @@ export type ObservedElementsAppState = {
|
|
|
174
176
|
activeLockedId: AppState["activeLockedId"];
|
|
175
177
|
};
|
|
176
178
|
export type BoxSelectionMode = "contain" | "overlap";
|
|
179
|
+
/**
|
|
180
|
+
* The pointing device the wheel mappings are tuned for. `auto` is reserved
|
|
181
|
+
* for detecting it from the wheel events; see `resolveInputDevice`.
|
|
182
|
+
*/
|
|
183
|
+
export type InputDevice = "auto" | "mouse" | "trackpad";
|
|
177
184
|
/**
|
|
178
185
|
* A box, in scene coordinates, that pan & zoom are constrained to.
|
|
179
186
|
*
|
|
@@ -253,6 +260,14 @@ export interface AppState {
|
|
|
253
260
|
bindingPreference: "enabled" | "disabled";
|
|
254
261
|
/** user preference whether arrow snap to midpoints while binding */
|
|
255
262
|
isMidpointSnappingEnabled: boolean;
|
|
263
|
+
/**
|
|
264
|
+
* user preference for what the wheel does: with a `trackpad` a plain wheel
|
|
265
|
+
* pans; with a `mouse` a plain wheel zooms. Ctrl/cmd+wheel (how a pinch is
|
|
266
|
+
* delivered) zooms with either device. Shift+wheel pans horizontally;
|
|
267
|
+
* ctrl/cmd+shift+wheel pans vertically. `auto` resolves to `trackpad` until
|
|
268
|
+
* device detection exists — see `resolveInputDevice`
|
|
269
|
+
*/
|
|
270
|
+
inputDevice: InputDevice;
|
|
256
271
|
/**
|
|
257
272
|
* The bindable element the UI highlights for the user when an arrow is
|
|
258
273
|
* dragged or otherwise its endpoint being close to said element.
|
|
@@ -261,6 +276,15 @@ export interface AppState {
|
|
|
261
276
|
element: NonDeleted<ExcalidrawBindableElement>;
|
|
262
277
|
midPoint?: GlobalPoint;
|
|
263
278
|
} | null;
|
|
279
|
+
/**
|
|
280
|
+
* Where on a hovered arrow the text tool would attach text if clicked —
|
|
281
|
+
* a free endpoint (binds the arrow to a new text element positioned against
|
|
282
|
+
* that endpoint) or the arrow's midpoint (adds a label bound to the arrow).
|
|
283
|
+
*/
|
|
284
|
+
hoveredArrowTextAnchor: {
|
|
285
|
+
elementId: ExcalidrawArrowElement["id"];
|
|
286
|
+
anchor: "start" | "end" | "label";
|
|
287
|
+
} | null;
|
|
264
288
|
frameToHighlight: NonDeleted<ExcalidrawFrameLikeElement> | null;
|
|
265
289
|
frameRendering: {
|
|
266
290
|
enabled: boolean;
|
|
@@ -268,7 +292,10 @@ export interface AppState {
|
|
|
268
292
|
outline: boolean;
|
|
269
293
|
clip: boolean;
|
|
270
294
|
};
|
|
271
|
-
|
|
295
|
+
/**
|
|
296
|
+
* frame-like element whose name is currently being edited
|
|
297
|
+
*/
|
|
298
|
+
editingFrame: ExcalidrawFrameLikeElement["id"] | null;
|
|
272
299
|
elementsToHighlight: readonly NonDeletedExcalidrawElement[] | null;
|
|
273
300
|
/**
|
|
274
301
|
* set when a new text is created or when an existing text is being edited
|
|
@@ -294,6 +321,8 @@ export interface AppState {
|
|
|
294
321
|
exportWithDarkMode: boolean;
|
|
295
322
|
exportScale: number;
|
|
296
323
|
currentItemStrokeColor: string;
|
|
324
|
+
currentItemStickynoteStrokeColor: string;
|
|
325
|
+
currentItemStickynoteBackgroundColor: string;
|
|
297
326
|
currentItemBackgroundColor: string;
|
|
298
327
|
currentItemFillStyle: ExcalidrawElement["fillStyle"];
|
|
299
328
|
currentItemStrokeWidthKey: StrokeWidthKey;
|
|
@@ -400,10 +429,6 @@ export interface AppState {
|
|
|
400
429
|
y: number;
|
|
401
430
|
} | null;
|
|
402
431
|
objectsSnapModeEnabled: boolean;
|
|
403
|
-
/** the user's socket id & username who is being followed on the canvas */
|
|
404
|
-
userToFollow: UserToFollow | null;
|
|
405
|
-
/** the socket ids of the users following the current user */
|
|
406
|
-
followedBy: Set<SocketId>;
|
|
407
432
|
/** image cropping */
|
|
408
433
|
isCropping: boolean;
|
|
409
434
|
croppingElementId: ExcalidrawElement["id"] | null;
|
|
@@ -418,6 +443,23 @@ export interface AppState {
|
|
|
418
443
|
[groupId: string]: true;
|
|
419
444
|
};
|
|
420
445
|
bindMode: BindMode;
|
|
446
|
+
/** user-customized color-picker top picks (pinned via drag & drop from the
|
|
447
|
+
* color picker popup). `null` means no customization (defaults, or
|
|
448
|
+
* host-supplied `topPicks`, are used). Kept per picker. */
|
|
449
|
+
colorTopPicks: {
|
|
450
|
+
elementStroke: readonly string[] | null;
|
|
451
|
+
elementBackground: readonly string[] | null;
|
|
452
|
+
/** the bucket-fill tool keeps a list separate from `elementBackground`
|
|
453
|
+
* even though both drive `currentItemBackgroundColor` (its defaults and
|
|
454
|
+
* use case differ — no transparent) */
|
|
455
|
+
bucketFill: readonly string[] | null;
|
|
456
|
+
/** sticky notes are their own color domain (own defaults, own picks) */
|
|
457
|
+
stickyNoteStroke: readonly string[] | null;
|
|
458
|
+
stickyNoteBackground: readonly string[] | null;
|
|
459
|
+
};
|
|
460
|
+
/** user-customized font-picker top picks (pinned via drag & drop from the
|
|
461
|
+
* font picker popup). `null` means no customization (defaults are used) */
|
|
462
|
+
fontTopPicks: readonly FontFamilyValues[] | null;
|
|
421
463
|
}
|
|
422
464
|
export type SearchMatch = {
|
|
423
465
|
id: string;
|
|
@@ -430,7 +472,7 @@ export type SearchMatch = {
|
|
|
430
472
|
showOnCanvas: boolean;
|
|
431
473
|
}[];
|
|
432
474
|
};
|
|
433
|
-
export type UIAppState = Omit<AppState, "cursorButton" | "scrollX" | "scrollY" | "zoom" | "shouldCacheIgnoreZoom" | "snapLines" | "originSnapOffset" | "suggestedBinding" | "frameToHighlight" | "elementsToHighlight">;
|
|
475
|
+
export type UIAppState = Omit<AppState, "cursorButton" | "scrollX" | "scrollY" | "zoom" | "shouldCacheIgnoreZoom" | "snapLines" | "originSnapOffset" | "suggestedBinding" | "hoveredArrowTextAnchor" | "frameToHighlight" | "elementsToHighlight">;
|
|
434
476
|
export type NormalizedZoomValue = number & {
|
|
435
477
|
_brand: "normalizedZoom";
|
|
436
478
|
};
|
|
@@ -481,13 +523,160 @@ export type OnUserFollowedPayload = {
|
|
|
481
523
|
userToFollow: UserToFollow;
|
|
482
524
|
action: "FOLLOW" | "UNFOLLOW";
|
|
483
525
|
};
|
|
526
|
+
export type ViewportStatusFrame = {
|
|
527
|
+
/** the badge (bottom-center pill) */
|
|
528
|
+
label?: {
|
|
529
|
+
label: React.ReactNode;
|
|
530
|
+
icon?: React.ReactNode;
|
|
531
|
+
/** badge background; defaults to var(--color-primary-hover) */
|
|
532
|
+
background?: string;
|
|
533
|
+
/** badge text color; defaults to var(--color-primary-light) */
|
|
534
|
+
color?: string;
|
|
535
|
+
/** makes the badge label interactive */
|
|
536
|
+
onClick?: () => void;
|
|
537
|
+
/** renders a close button when set */
|
|
538
|
+
onClose?: () => void;
|
|
539
|
+
};
|
|
540
|
+
/** viewport-edge border: CSS color, or `false` for none */
|
|
541
|
+
border: false | string;
|
|
542
|
+
};
|
|
484
543
|
export type OnExportProgress = {
|
|
485
544
|
type: "progress";
|
|
486
545
|
message?: React.ReactNode;
|
|
487
546
|
/** 0-1 range */
|
|
488
547
|
progress?: number;
|
|
489
548
|
};
|
|
549
|
+
export type InteractionConfig = {
|
|
550
|
+
/**
|
|
551
|
+
* Interactions that stay enabled while the editor is otherwise
|
|
552
|
+
* non-interactive. Opt-in: anything omitted or `false` is disabled.
|
|
553
|
+
*/
|
|
554
|
+
enabled?: {
|
|
555
|
+
/**
|
|
556
|
+
* Element links render their link icon and stay clickable — clicking
|
|
557
|
+
* anywhere on a linked element opens the link, same as in view mode.
|
|
558
|
+
* When disabled, link icons are not rendered at all.
|
|
559
|
+
*
|
|
560
|
+
* @default false
|
|
561
|
+
*/
|
|
562
|
+
links?: boolean;
|
|
563
|
+
/**
|
|
564
|
+
* Embeddable & iframe elements stay interactive — hovering & clicking
|
|
565
|
+
* activates them so their content can be used, same as in view mode.
|
|
566
|
+
*
|
|
567
|
+
* @default false
|
|
568
|
+
*/
|
|
569
|
+
embeds?: boolean;
|
|
570
|
+
/**
|
|
571
|
+
* Umbrella for all interactive content on canvas — shorthand for
|
|
572
|
+
* enabling `links` & `embeds` (and future interactive content kinds)
|
|
573
|
+
* together. Additive: `interactiveContent: true` enables them
|
|
574
|
+
* regardless of their individual values.
|
|
575
|
+
*
|
|
576
|
+
* @default false
|
|
577
|
+
*/
|
|
578
|
+
interactiveContent?: boolean;
|
|
579
|
+
/**
|
|
580
|
+
* Canvas navigation — panning (pointer drag, wheel, PageUp/PageDown)
|
|
581
|
+
* and zooming (ctrl/cmd + wheel, pinch, and the canvas zoom &
|
|
582
|
+
* zoom-to-fit shortcuts: ctrl/cmd +/-/0, shift+1/2/3), same as in view
|
|
583
|
+
* mode. Respects `appState.scrollConstraints` if set, so it composes
|
|
584
|
+
* with viewport locking. The rest of the keyboard stays disabled. Note
|
|
585
|
+
* the editor consumes wheel & touch input again when enabled, so the
|
|
586
|
+
* page no longer scrolls over the editor.
|
|
587
|
+
*
|
|
588
|
+
* @default false
|
|
589
|
+
*/
|
|
590
|
+
navigation?: boolean;
|
|
591
|
+
/**
|
|
592
|
+
* Whether the browser's own zoom remains available over the editor —
|
|
593
|
+
* ctrl/cmd + wheel, pinch, and (while the editor has focus)
|
|
594
|
+
* ctrl/cmd +/-/0 shortcuts. Prevented by default, mirroring the
|
|
595
|
+
* interactive editor. Regular page scrolling stays available either way.
|
|
596
|
+
* With `navigation` enabled, the zoom input (wheel, pinch, keyboard
|
|
597
|
+
* shortcuts) zooms the canvas instead either way, making this moot.
|
|
598
|
+
*
|
|
599
|
+
* @default false
|
|
600
|
+
*/
|
|
601
|
+
browserZoom?: boolean;
|
|
602
|
+
/**
|
|
603
|
+
* Tools that stay user-driven while the editor is otherwise
|
|
604
|
+
* non-interactive: pointer input keeps driving the listed tool when it's
|
|
605
|
+
* the active tool. Does not enable user-driven tool *switching* — the
|
|
606
|
+
* keyboard stays disabled and tool selection remains host-driven
|
|
607
|
+
* (`ExcalidrawAPI.setActiveTool`).
|
|
608
|
+
*
|
|
609
|
+
* Composes with `navigation`: the enabled tool wins the primary-pointer
|
|
610
|
+
* drag, while wheel input (and wheel-button drag) still pans/zooms.
|
|
611
|
+
*/
|
|
612
|
+
tools?: {
|
|
613
|
+
/**
|
|
614
|
+
* The laser pointer stays usable — pointer strokes draw laser trails
|
|
615
|
+
* and pointer positions keep broadcasting via `onPointerUpdate`, so
|
|
616
|
+
* e.g. collaborators see a presenter's laser & cursor.
|
|
617
|
+
*
|
|
618
|
+
* @default false
|
|
619
|
+
*/
|
|
620
|
+
laser?: boolean;
|
|
621
|
+
/**
|
|
622
|
+
* Custom tools (`activeTool.type === "custom"`) stay usable — the
|
|
623
|
+
* editor keeps dispatching `onPointerDown` / `onPointerUp` for them.
|
|
624
|
+
* Tool behavior is host-implemented; activate custom tools with
|
|
625
|
+
* `locked: true` or they revert to the selection tool (and go inert)
|
|
626
|
+
* after the first pointer interaction.
|
|
627
|
+
*
|
|
628
|
+
* @default false
|
|
629
|
+
*/
|
|
630
|
+
custom?: boolean;
|
|
631
|
+
};
|
|
632
|
+
};
|
|
633
|
+
};
|
|
634
|
+
export type UIConfig = {
|
|
635
|
+
/**
|
|
636
|
+
* Default UI controls that stay enabled while the rest of Excalidraw's
|
|
637
|
+
* default UI is hidden. Opt-in: anything omitted or `false` is disabled.
|
|
638
|
+
*/
|
|
639
|
+
enabled: {
|
|
640
|
+
/**
|
|
641
|
+
* The zoom-out, reset-zoom, and zoom-in controls.
|
|
642
|
+
*
|
|
643
|
+
* @default false
|
|
644
|
+
*/
|
|
645
|
+
zoom?: boolean;
|
|
646
|
+
/**
|
|
647
|
+
* The button shown when the viewport is scrolled away from all content.
|
|
648
|
+
*
|
|
649
|
+
* @default false
|
|
650
|
+
*/
|
|
651
|
+
scrollBackToContent?: boolean;
|
|
652
|
+
};
|
|
653
|
+
};
|
|
654
|
+
/** Supported visual changes. Geometry, content, bindings and styles are not overridable. */
|
|
655
|
+
export type ElementRenderOverride = Readonly<{
|
|
656
|
+
/** Absolute render opacity (0–100, clamped). Omitted: use element.opacity. */
|
|
657
|
+
opacity?: number;
|
|
658
|
+
/** Translation in scene units. Bound labels inherit their container's offset and ignore this field. */
|
|
659
|
+
offset?: Readonly<{
|
|
660
|
+
x: number;
|
|
661
|
+
y: number;
|
|
662
|
+
}>;
|
|
663
|
+
}>;
|
|
664
|
+
/** see {@link ExcalidrawImperativeAPI.setElementRenderOverrides} for details */
|
|
665
|
+
export type ElementRenderOverrides = ReadonlyMap<ExcalidrawElement["id"], ElementRenderOverride>;
|
|
666
|
+
/** The translation part of a snapshot: only the entries that carry an offset. */
|
|
667
|
+
export type ElementRenderOffsets = ReadonlyMap<ExcalidrawElement["id"], NonNullable<ElementRenderOverride["offset"]>>;
|
|
490
668
|
export interface ExcalidrawProps {
|
|
669
|
+
className?: string;
|
|
670
|
+
/**
|
|
671
|
+
* Document that owns Excalidraw's mounted DOM.
|
|
672
|
+
*
|
|
673
|
+
* Set only when it differs from the global `document`, such as when code
|
|
674
|
+
* executing in a parent window mounts Excalidraw into an iframe document.
|
|
675
|
+
* The value must remain stable for the editor's lifetime.
|
|
676
|
+
*
|
|
677
|
+
* @default document
|
|
678
|
+
*/
|
|
679
|
+
ownerDocument?: Document;
|
|
491
680
|
onChange?: (elements: readonly OrderedExcalidrawElement[], appState: AppState, files: BinaryFiles) => void;
|
|
492
681
|
onThemeChange?: (theme: Theme | "system") => void;
|
|
493
682
|
/**
|
|
@@ -533,15 +722,95 @@ export interface ExcalidrawProps {
|
|
|
533
722
|
*
|
|
534
723
|
* Returned elements will be used in place of the next elements
|
|
535
724
|
* (you should return all elements, including deleted, and not mutate
|
|
536
|
-
* the element if changes are made)
|
|
725
|
+
* the element if changes are made).
|
|
726
|
+
*
|
|
727
|
+
* The duplicates are the elements in `nextElements` which are not in
|
|
728
|
+
* `prevElements` (see also `data.duplicateElements`). When pasting or
|
|
729
|
+
* inserting onto a frame, their `frameId` is already set. To change a
|
|
730
|
+
* duplicate, return a new object with the same `id`. It is shallow-merged
|
|
731
|
+
* into the duplicate (omitted properties are kept), and your changes are
|
|
732
|
+
* part of the duplication itself (same undo entry, same durable increment).
|
|
733
|
+
*
|
|
734
|
+
* To prevent an element from being duplicated, omit its duplicate from the
|
|
735
|
+
* returned array. References to it from the remaining duplicates are
|
|
736
|
+
* cleared, and a bound text isn't duplicated without its container. To
|
|
737
|
+
* prevent the duplication as a whole, return `false`. If no duplicate
|
|
738
|
+
* remains, the duplication is cancelled and the returned elements are
|
|
739
|
+
* ignored (alt-drag then moves the original elements instead).
|
|
537
740
|
*/
|
|
538
741
|
onDuplicate?: (nextElements: readonly ExcalidrawElement[],
|
|
539
742
|
/** excludes the duplicated elements */
|
|
540
|
-
prevElements: readonly ExcalidrawElement[]
|
|
743
|
+
prevElements: readonly ExcalidrawElement[],
|
|
744
|
+
/** lookups covering just the elements taking part in the duplication */
|
|
745
|
+
data: OnDuplicateData) => ExcalidrawElement[] | void | false;
|
|
541
746
|
renderTopLeftUI?: (isMobile: boolean, appState: UIAppState) => JSX.Element | null;
|
|
542
747
|
renderTopRightUI?: (isMobile: boolean, appState: UIAppState) => JSX.Element | null;
|
|
543
748
|
langCode?: Language["code"];
|
|
544
749
|
viewModeEnabled?: boolean;
|
|
750
|
+
/**
|
|
751
|
+
* Whether the editor accepts user input (pointer, keyboard, wheel, touch,
|
|
752
|
+
* clipboard, drag&drop). When `false`, the scene still renders and reacts
|
|
753
|
+
* to programmatic updates (imperative API), but the user cannot affect it
|
|
754
|
+
* in any way. Implies view mode.
|
|
755
|
+
*
|
|
756
|
+
* Pass a config object to keep specific interactions enabled while the
|
|
757
|
+
* editor is otherwise non-interactive (see `InteractionConfig`):
|
|
758
|
+
*
|
|
759
|
+
* ```tsx
|
|
760
|
+
* <Excalidraw interaction={{ enabled: { links: true } }} />
|
|
761
|
+
* ```
|
|
762
|
+
*
|
|
763
|
+
* @default true
|
|
764
|
+
*/
|
|
765
|
+
interaction?: boolean | InteractionConfig;
|
|
766
|
+
/**
|
|
767
|
+
* Whether Excalidraw's default UI is rendered — toolbar, default menus,
|
|
768
|
+
* footer controls, sidebars, and canvas popups. Host UI passed through
|
|
769
|
+
* children (including exported components such as `MainMenu` and `Footer`)
|
|
770
|
+
* or render props continues to render, together with any supporting dialogs
|
|
771
|
+
* it opens.
|
|
772
|
+
*
|
|
773
|
+
* Canvas content (elements, text editing surface, frame names, embeds) still
|
|
774
|
+
* renders, and the editor remains interactive unless `interaction` is set to
|
|
775
|
+
* `false`.
|
|
776
|
+
*
|
|
777
|
+
* Pass a config object to keep specific default controls rendered while the
|
|
778
|
+
* rest of the default UI is hidden (see `UIConfig`):
|
|
779
|
+
*
|
|
780
|
+
* ```tsx
|
|
781
|
+
* <Excalidraw ui={{ enabled: { zoom: true } }} />
|
|
782
|
+
* ```
|
|
783
|
+
*
|
|
784
|
+
* NOTE: this is WIP and what default UI is/is not rendered when ui=false
|
|
785
|
+
* may yet change.
|
|
786
|
+
*
|
|
787
|
+
* @default true
|
|
788
|
+
*/
|
|
789
|
+
ui?: boolean | UIConfig;
|
|
790
|
+
/**
|
|
791
|
+
* Forces the active editor tool (controlled). While set, user- and
|
|
792
|
+
* API-driven tool switching is ignored — `setActiveTool` refuses with a
|
|
793
|
+
* console warning, non-forced toolbar buttons render disabled — and the
|
|
794
|
+
* editor snaps back if internal flows reset the tool. The forced tool
|
|
795
|
+
* behaves as if locked (see the tool lock / padlock): it doesn't revert to
|
|
796
|
+
* the selection tool after use, and elements drawn with it aren't
|
|
797
|
+
* auto-selected — without mutating `appState.activeTool.locked`, so the
|
|
798
|
+
* user's persisted padlock preference stays untouched. Unset to return
|
|
799
|
+
* tool control to the editor (the current tool stays active).
|
|
800
|
+
*
|
|
801
|
+
* The forced tool must be activatable to take effect: not disabled via
|
|
802
|
+
* `UIOptions.tools`, and — while the editor is non-interactive — allowed
|
|
803
|
+
* via `interaction.enabled.tools`. Otherwise the editor stays on (or, when
|
|
804
|
+
* non-interactive, resets to) the `selection` tool, and the forced tool is
|
|
805
|
+
* applied once it becomes activatable. `image` cannot be forced (its
|
|
806
|
+
* activation opens the file picker).
|
|
807
|
+
*/
|
|
808
|
+
activeTool?: {
|
|
809
|
+
type: Exclude<ToolType, "image">;
|
|
810
|
+
} | {
|
|
811
|
+
type: "custom";
|
|
812
|
+
customType: string;
|
|
813
|
+
};
|
|
545
814
|
zenModeEnabled?: boolean;
|
|
546
815
|
gridModeEnabled?: boolean;
|
|
547
816
|
objectsSnapModeEnabled?: boolean;
|
|
@@ -573,6 +842,21 @@ export interface ExcalidrawProps {
|
|
|
573
842
|
aiEnabled?: boolean;
|
|
574
843
|
showDeprecatedFonts?: boolean;
|
|
575
844
|
renderScrollbars?: boolean;
|
|
845
|
+
viewportStatusFrame?: ViewportStatusFrame | null;
|
|
846
|
+
/**
|
|
847
|
+
* Rendered inside the UserList "who's here" dropdown (desktop) and inline
|
|
848
|
+
* in the mobile menu's collaborators section, below a divider. Accepts a
|
|
849
|
+
* render function — called with `isMobile` so hosts can render different
|
|
850
|
+
* UI for each surface — in addition to a plain node.
|
|
851
|
+
*/
|
|
852
|
+
currentUserControls?: React.ReactNode | ((isMobile: boolean) => React.ReactNode);
|
|
853
|
+
/**
|
|
854
|
+
* The user being followed on the canvas, if any. Controlled by the host —
|
|
855
|
+
* the editor never sets it; it emits follow/unfollow intents via
|
|
856
|
+
* `onUserFollow` (prop or imperative API) and renders the followed
|
|
857
|
+
* user's avatar highlight from this value.
|
|
858
|
+
*/
|
|
859
|
+
userToFollow?: UserToFollow | null;
|
|
576
860
|
/**
|
|
577
861
|
* Called before exporting to a file.
|
|
578
862
|
*
|
|
@@ -598,7 +882,8 @@ export interface ExcalidrawProps {
|
|
|
598
882
|
}) => MaybePromise<void> | AsyncGenerator<OnExportProgress, void>;
|
|
599
883
|
}
|
|
600
884
|
export type SceneData = {
|
|
601
|
-
|
|
885
|
+
/** Expects normalized elements; restore imported data before updating the scene. */
|
|
886
|
+
elements?: readonly ExcalidrawElement[] | null;
|
|
602
887
|
appState?: ImportedDataState["appState"];
|
|
603
888
|
collaborators?: Map<SocketId, Collaborator>;
|
|
604
889
|
captureUpdate?: CaptureUpdateActionType;
|
|
@@ -658,6 +943,8 @@ export type AppProps = Merge<ExcalidrawProps, {
|
|
|
658
943
|
export type AppClassProperties = {
|
|
659
944
|
props: AppProps;
|
|
660
945
|
state: AppState;
|
|
946
|
+
readonly ownerDocument: Document;
|
|
947
|
+
readonly ownerWindow: Window & typeof globalThis;
|
|
661
948
|
api: App["api"];
|
|
662
949
|
sessionExportThemeOverride: App["sessionExportThemeOverride"];
|
|
663
950
|
interactiveCanvas: HTMLCanvasElement | null;
|
|
@@ -678,8 +965,7 @@ export type AppClassProperties = {
|
|
|
678
965
|
id: App["id"];
|
|
679
966
|
onInsertElements: App["onInsertElements"];
|
|
680
967
|
onExportImage: App["onExportImage"];
|
|
681
|
-
|
|
682
|
-
setViewport: App["setViewport"];
|
|
968
|
+
viewport: App["viewport"];
|
|
683
969
|
addFiles: App["addFiles"];
|
|
684
970
|
addElementsFromPasteOrLibrary: App["addElementsFromPasteOrLibrary"];
|
|
685
971
|
togglePenMode: App["togglePenMode"];
|
|
@@ -690,11 +976,18 @@ export type AppClassProperties = {
|
|
|
690
976
|
onMagicframeToolSelect: App["onMagicframeToolSelect"];
|
|
691
977
|
getName: App["getName"];
|
|
692
978
|
dismissLinearEditor: App["dismissLinearEditor"];
|
|
693
|
-
|
|
979
|
+
flowchart: App["flowchart"];
|
|
980
|
+
drawShape: App["drawShape"];
|
|
981
|
+
arrowText: App["arrowText"];
|
|
982
|
+
cursor: App["cursor"];
|
|
983
|
+
bucketFill: App["bucketFill"];
|
|
984
|
+
duplicate: App["duplicate"];
|
|
985
|
+
toolDrag: App["toolDrag"];
|
|
986
|
+
activeResizeHandle: App["activeResizeHandle"];
|
|
987
|
+
isToolLocked: App["isToolLocked"];
|
|
694
988
|
getEffectiveGridSize: App["getEffectiveGridSize"];
|
|
695
989
|
setPlugins: App["setPlugins"];
|
|
696
990
|
plugins: App["plugins"];
|
|
697
|
-
getViewportOffsets: App["getViewportOffsets"];
|
|
698
991
|
visibleElements: App["visibleElements"];
|
|
699
992
|
excalidrawContainerValue: App["excalidrawContainerValue"];
|
|
700
993
|
onPointerUpEmitter: App["onPointerUpEmitter"];
|
|
@@ -703,8 +996,13 @@ export type AppClassProperties = {
|
|
|
703
996
|
onEvent: App["onEvent"];
|
|
704
997
|
onStateChange: App["onStateChange"];
|
|
705
998
|
lastPointerMoveCoords: App["lastPointerMoveCoords"];
|
|
999
|
+
lastPointerMoveEvent: App["lastPointerMoveEvent"];
|
|
706
1000
|
bindModeHandler: App["bindModeHandler"];
|
|
1001
|
+
emitUserFollowIntent: App["emitUserFollowIntent"];
|
|
1002
|
+
requestUnfollow: App["requestUnfollow"];
|
|
707
1003
|
setAppState: App["setAppState"];
|
|
1004
|
+
isInteractionEnabled: App["isInteractionEnabled"];
|
|
1005
|
+
isNavigationEnabled: App["isNavigationEnabled"];
|
|
708
1006
|
};
|
|
709
1007
|
export type PointerDownState = Readonly<{
|
|
710
1008
|
origin: Readonly<{
|
|
@@ -740,6 +1038,7 @@ export type PointerDownState = Readonly<{
|
|
|
740
1038
|
wasAddedToSelection: boolean;
|
|
741
1039
|
hasBeenDuplicated: boolean;
|
|
742
1040
|
hasHitCommonBoundingBoxOfSelectedElements: boolean;
|
|
1041
|
+
arrowLabel: boolean;
|
|
743
1042
|
};
|
|
744
1043
|
withCmdOrCtrl: boolean;
|
|
745
1044
|
drag: {
|
|
@@ -791,16 +1090,32 @@ export interface ExcalidrawImperativeAPI {
|
|
|
791
1090
|
getAppState: () => InstanceType<typeof App>["state"];
|
|
792
1091
|
getFiles: () => InstanceType<typeof App>["files"];
|
|
793
1092
|
getName: InstanceType<typeof App>["getName"];
|
|
794
|
-
setViewport: InstanceType<typeof App>["setViewport"];
|
|
795
|
-
getViewportOffsets: InstanceType<typeof App>["
|
|
1093
|
+
setViewport: InstanceType<typeof App>["viewport"]["setViewport"];
|
|
1094
|
+
getViewportOffsets: InstanceType<typeof App>["viewport"]["getOffsets"];
|
|
1095
|
+
/**
|
|
1096
|
+
* Atomically replaces all transient visual overrides. Values are copied;
|
|
1097
|
+
* omitted IDs/fields use document values, except for inherited label offsets.
|
|
1098
|
+
* null clears the snapshot.
|
|
1099
|
+
* Repaints without document changes, history entries or onChange events;
|
|
1100
|
+
* an equivalent snapshot may still repaint (clearing an already clear
|
|
1101
|
+
* snapshot does not), so submit only when something changed.
|
|
1102
|
+
* Finite opacity is clamped to 0–100; non-finite values reject the snapshot.
|
|
1103
|
+
* Unknown/deleted IDs are ignored when rendering. Reset/unmount clears it.
|
|
1104
|
+
* Bound labels inherit their container's offset; offsets targeting them are
|
|
1105
|
+
* ignored. Label opacity remains independent. Target frame children explicitly.
|
|
1106
|
+
* Frame opacity still multiplies child opacity. Decorations follow their owner.
|
|
1107
|
+
* Exports and interactive geometry (hit tests, selection, editing) use document
|
|
1108
|
+
* values, including while authoring an animation preview in edit mode.
|
|
1109
|
+
*/
|
|
1110
|
+
setElementRenderOverrides: InstanceType<typeof App>["setElementRenderOverrides"];
|
|
796
1111
|
registerAction: (action: Action) => void;
|
|
797
1112
|
refresh: InstanceType<typeof App>["refresh"];
|
|
798
1113
|
setToast: InstanceType<typeof App>["setToast"];
|
|
799
1114
|
addFiles: (data: BinaryFileData[]) => void;
|
|
800
1115
|
id: string;
|
|
801
1116
|
setActiveTool: InstanceType<typeof App>["setActiveTool"];
|
|
802
|
-
setCursor: InstanceType<typeof App>["
|
|
803
|
-
resetCursor: InstanceType<typeof App>["
|
|
1117
|
+
setCursor: InstanceType<typeof App>["cursor"]["set"];
|
|
1118
|
+
resetCursor: InstanceType<typeof App>["cursor"]["reset"];
|
|
804
1119
|
toggleSidebar: InstanceType<typeof App>["toggleSidebar"];
|
|
805
1120
|
getEditorInterface: () => EditorInterface;
|
|
806
1121
|
/**
|
|
@@ -823,7 +1138,6 @@ export type FrameNameBounds = {
|
|
|
823
1138
|
y: number;
|
|
824
1139
|
width: number;
|
|
825
1140
|
height: number;
|
|
826
|
-
angle: number;
|
|
827
1141
|
};
|
|
828
1142
|
export type FrameNameBoundsCache = {
|
|
829
1143
|
get: (frameElement: ExcalidrawFrameLikeElement | ExcalidrawMagicFrameElement) => FrameNameBounds | null;
|
|
@@ -848,6 +1162,12 @@ export type NullableGridSize = (AppState["gridSize"] & MakeBrand<"NullableGridSi
|
|
|
848
1162
|
export type GenerateDiagramToCode = (props: {
|
|
849
1163
|
frame: NonDeleted<ExcalidrawMagicFrameElement>;
|
|
850
1164
|
children: readonly NonDeletedExcalidrawElement[];
|
|
1165
|
+
/**
|
|
1166
|
+
* Optional streaming hook. Call with the accumulated response text as it
|
|
1167
|
+
* streams in so the editor can progressively render the partial HTML
|
|
1168
|
+
* inside the generated frame.
|
|
1169
|
+
*/
|
|
1170
|
+
onPartial?: (html: string) => void;
|
|
851
1171
|
}) => MaybePromise<{
|
|
852
1172
|
html: string;
|
|
853
1173
|
}>;
|