@myoc/excalidraw 0.19.534 → 0.19.536

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/CHANGELOG.md CHANGED
@@ -5959,3 +5959,110 @@ First release of `@excalidraw/excalidraw`## Excalidraw Library
5959
5959
 
5960
5960
  ---
5961
5961
 
5962
+ ## Excalidraw Library
5963
+
5964
+ **_This section lists the updates made to the excalidraw library and will not affect the integration._**
5965
+
5966
+ ### Features
5967
+
5968
+ - Add ability to turn off compression for files that are smaller than a given size
5969
+
5970
+ - Add lock tool to the dropdown and also add the status of the extra tools to be the same icon as the selected tool
5971
+
5972
+ - Add view mode button
5973
+
5974
+ - Add multiple image copy paste or drag and drop
5975
+
5976
+ - Multiple image additions from clipboard
5977
+
5978
+ - Add arrange elements action
5979
+
5980
+ - Add top picks to appProps for both stoke color and background color
5981
+
5982
+ ### Fixes
5983
+
5984
+ - Issues
5985
+
5986
+ - Make mobile mode more myoc looking
5987
+
5988
+ - Add normalise functionality
5989
+
5990
+ - Update with excalidraw
5991
+
5992
+ - Fix imports
5993
+
5994
+ - Fix mutateGroup to use scene.mutateGroup
5995
+
5996
+ - Imports
5997
+
5998
+ - Ensure that fileId is different for compressed vs uncompressed file
5999
+
6000
+ - Remove not working prop for dontResizeLimitMBs
6001
+
6002
+ - Add smartview for mobile
6003
+
6004
+ - Hide the alignment buttons if there is only one group selected (they do nothing if only one group is selected)
6005
+
6006
+ - Use css vars already provided instead of hard coding directly from oc-gray
6007
+
6008
+ - Remove unused variables
6009
+
6010
+ - Pass the new top pick color props properly
6011
+
6012
+ - Incorrect import for color (was moved to common)
6013
+
6014
+ ---
6015
+
6016
+ ## Excalidraw Library
6017
+
6018
+ **_This section lists the updates made to the excalidraw library and will not affect the integration._**
6019
+
6020
+ ### Features
6021
+
6022
+ - Add ability to turn off compression for files that are smaller than a given size
6023
+
6024
+ - Add lock tool to the dropdown and also add the status of the extra tools to be the same icon as the selected tool
6025
+
6026
+ - Add view mode button
6027
+
6028
+ - Add multiple image copy paste or drag and drop
6029
+
6030
+ - Multiple image additions from clipboard
6031
+
6032
+ - Add arrange elements action
6033
+
6034
+ - Add top picks to appProps for both stoke color and background color
6035
+
6036
+ ### Fixes
6037
+
6038
+ - Issues
6039
+
6040
+ - Make mobile mode more myoc looking
6041
+
6042
+ - Add normalise functionality
6043
+
6044
+ - Update with excalidraw
6045
+
6046
+ - Fix imports
6047
+
6048
+ - Fix mutateGroup to use scene.mutateGroup
6049
+
6050
+ - Imports
6051
+
6052
+ - Ensure that fileId is different for compressed vs uncompressed file
6053
+
6054
+ - Remove not working prop for dontResizeLimitMBs
6055
+
6056
+ - Add smartview for mobile
6057
+
6058
+ - Hide the alignment buttons if there is only one group selected (they do nothing if only one group is selected)
6059
+
6060
+ - Use css vars already provided instead of hard coding directly from oc-gray
6061
+
6062
+ - Remove unused variables
6063
+
6064
+ - Pass the new top pick color props properly
6065
+
6066
+ - Incorrect import for color (was moved to common)
6067
+
6068
+ ---
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  define_import_meta_env_default
3
- } from "./chunk-LXITAORX.js";
3
+ } from "./chunk-GMDJS52C.js";
4
4
  import {
5
5
  __publicField
6
6
  } from "./chunk-XDFCUUT6.js";
@@ -5428,7 +5428,7 @@ var parseFileContents = async (blob) => {
5428
5428
  let contents;
5429
5429
  if (blob.type === MIME_TYPES6.png) {
5430
5430
  try {
5431
- return await (await import("./data/image-42C5IMES.js")).decodePngMetadata(blob);
5431
+ return await (await import("./data/image-ADOTOLKB.js")).decodePngMetadata(blob);
5432
5432
  } catch (error) {
5433
5433
  if (error.message === "INVALID") {
5434
5434
  throw new ImageSceneDataError(
@@ -5866,4 +5866,4 @@ export {
5866
5866
  createFile,
5867
5867
  normalizeFile
5868
5868
  };
5869
- //# sourceMappingURL=chunk-LMB2JFA3.js.map
5869
+ //# sourceMappingURL=chunk-E5FRZJMM.js.map
@@ -1,7 +1,7 @@
1
1
  // <define:import.meta.env>
2
- var define_import_meta_env_default = { MODE: "development", VITE_APP_BACKEND_V2_GET_URL: "https://json-dev.excalidraw.com/api/v2/", VITE_APP_BACKEND_V2_POST_URL: "https://json-dev.excalidraw.com/api/v2/post/", VITE_APP_LIBRARY_URL: "https://libraries.excalidraw.com", VITE_APP_LIBRARY_BACKEND: "https://us-central1-excalidraw-room-persistence.cloudfunctions.net/libraries", VITE_APP_WS_SERVER_URL: "http://localhost:3002", VITE_APP_PLUS_LP: "https://plus.excalidraw.com", VITE_APP_PLUS_APP: "http://localhost:3000", VITE_APP_AI_BACKEND: "http://localhost:3016", VITE_APP_FIREBASE_CONFIG: '{"apiKey":"AIzaSyCMkxA60XIW8KbqMYL7edC4qT5l4qHX2h8","authDomain":"excalidraw-oss-dev.firebaseapp.com","projectId":"excalidraw-oss-dev","storageBucket":"excalidraw-oss-dev.appspot.com","messagingSenderId":"664559512677","appId":"1:664559512677:web:a385181f2928d328a7aa8c"}', VITE_APP_DEV_DISABLE_LIVE_RELOAD: "", VITE_APP_ENABLE_TRACKING: "true", FAST_REFRESH: "false", VITE_APP_PORT: "3001", VITE_APP_DEBUG_ENABLE_TEXT_CONTAINER_BOUNDING_BOX: "", VITE_APP_COLLAPSE_OVERLAY: "true", VITE_APP_ENABLE_ESLINT: "true", VITE_APP_ENABLE_PWA: "false", VITE_APP_PLUS_EXPORT_PUBLIC_KEY: "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm2g5T+Rub6Kbf1Mf57t0\n7r2zeHuVg4dla3r5ryXMswtzz6x767octl6oLThn33mQsPSy3GKglFZoCTXJR4ij\nba8SxB04sL/N8eRrKja7TFWjCVtRwTTfyy771NYYNFVJclkxHyE5qw4m27crHF1y\nUNWEjuqNMi/lwAErS9fFa2oJlWyT8U7zzv/5kQREkxZI6y9v0AF3qcbsy2731FnD\ns9ChJvOUW9toIab2gsIdrKW8ZNpu084ZFVKb6LNjvIXI1Se4oMTHeszXzNptzlot\nkdxxjOoaQMAyfljFSot1F1FlU6MQlag7UnFGvFjRHN1JI5q4K+n3a67DX+TMyRqS\nHQIDAQAB", VITE_APP_DISABLE_PREVENT_UNLOAD: "", PKG_NAME: "@myoc/excalidraw", PKG_VERSION: "0.19.533", DEV: true };
2
+ var define_import_meta_env_default = { MODE: "development", VITE_APP_BACKEND_V2_GET_URL: "https://json-dev.excalidraw.com/api/v2/", VITE_APP_BACKEND_V2_POST_URL: "https://json-dev.excalidraw.com/api/v2/post/", VITE_APP_LIBRARY_URL: "https://libraries.excalidraw.com", VITE_APP_LIBRARY_BACKEND: "https://us-central1-excalidraw-room-persistence.cloudfunctions.net/libraries", VITE_APP_WS_SERVER_URL: "http://localhost:3002", VITE_APP_PLUS_LP: "https://plus.excalidraw.com", VITE_APP_PLUS_APP: "http://localhost:3000", VITE_APP_AI_BACKEND: "http://localhost:3016", VITE_APP_FIREBASE_CONFIG: '{"apiKey":"AIzaSyCMkxA60XIW8KbqMYL7edC4qT5l4qHX2h8","authDomain":"excalidraw-oss-dev.firebaseapp.com","projectId":"excalidraw-oss-dev","storageBucket":"excalidraw-oss-dev.appspot.com","messagingSenderId":"664559512677","appId":"1:664559512677:web:a385181f2928d328a7aa8c"}', VITE_APP_DEV_DISABLE_LIVE_RELOAD: "", VITE_APP_ENABLE_TRACKING: "true", FAST_REFRESH: "false", VITE_APP_PORT: "3001", VITE_APP_DEBUG_ENABLE_TEXT_CONTAINER_BOUNDING_BOX: "", VITE_APP_COLLAPSE_OVERLAY: "true", VITE_APP_ENABLE_ESLINT: "true", VITE_APP_ENABLE_PWA: "false", VITE_APP_PLUS_EXPORT_PUBLIC_KEY: "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm2g5T+Rub6Kbf1Mf57t0\n7r2zeHuVg4dla3r5ryXMswtzz6x767octl6oLThn33mQsPSy3GKglFZoCTXJR4ij\nba8SxB04sL/N8eRrKja7TFWjCVtRwTTfyy771NYYNFVJclkxHyE5qw4m27crHF1y\nUNWEjuqNMi/lwAErS9fFa2oJlWyT8U7zzv/5kQREkxZI6y9v0AF3qcbsy2731FnD\ns9ChJvOUW9toIab2gsIdrKW8ZNpu084ZFVKb6LNjvIXI1Se4oMTHeszXzNptzlot\nkdxxjOoaQMAyfljFSot1F1FlU6MQlag7UnFGvFjRHN1JI5q4K+n3a67DX+TMyRqS\nHQIDAQAB", VITE_APP_DISABLE_PREVENT_UNLOAD: "", PKG_NAME: "@myoc/excalidraw", PKG_VERSION: "0.19.535", DEV: true };
3
3
 
4
4
  export {
5
5
  define_import_meta_env_default
6
6
  };
7
- //# sourceMappingURL=chunk-LXITAORX.js.map
7
+ //# sourceMappingURL=chunk-GMDJS52C.js.map
@@ -2,12 +2,12 @@ import {
2
2
  decodePngMetadata,
3
3
  encodePngMetadata,
4
4
  getTEXtChunk
5
- } from "../chunk-LMB2JFA3.js";
6
- import "../chunk-LXITAORX.js";
5
+ } from "../chunk-E5FRZJMM.js";
6
+ import "../chunk-GMDJS52C.js";
7
7
  import "../chunk-XDFCUUT6.js";
8
8
  export {
9
9
  decodePngMetadata,
10
10
  encodePngMetadata,
11
11
  getTEXtChunk
12
12
  };
13
- //# sourceMappingURL=image-42C5IMES.js.map
13
+ //# sourceMappingURL=image-ADOTOLKB.js.map
package/dist/dev/index.js CHANGED
@@ -63,10 +63,10 @@ import {
63
63
  serializeAsJSON,
64
64
  strokeRectWithRotation_simple,
65
65
  zoomToFitBounds
66
- } from "./chunk-LMB2JFA3.js";
66
+ } from "./chunk-E5FRZJMM.js";
67
67
  import {
68
68
  define_import_meta_env_default
69
- } from "./chunk-LXITAORX.js";
69
+ } from "./chunk-GMDJS52C.js";
70
70
  import {
71
71
  en_default
72
72
  } from "./chunk-SKCAT7JG.js";
@@ -9377,6 +9377,31 @@ import clsx18 from "clsx";
9377
9377
  import { useEffect as useEffect18, useState as useState11 } from "react";
9378
9378
  import { KEYS as KEYS13, capitalizeString as capitalizeString2 } from "@excalidraw/common";
9379
9379
 
9380
+ // keyboardShortcuts.ts
9381
+ var matchesKeyboardShortcut = (event, shortcut) => {
9382
+ if (!shortcut.key && !shortcut.code) {
9383
+ return false;
9384
+ }
9385
+ const keyMatches = shortcut.key ? shortcut.key.length === 1 ? event.key.toLocaleLowerCase() === shortcut.key.toLocaleLowerCase() : event.key === shortcut.key : true;
9386
+ const codeMatches = shortcut.code ? event.code === shortcut.code : true;
9387
+ const ctrlOrCmd = shortcut.ctrlOrCmd === true;
9388
+ return keyMatches && codeMatches && (ctrlOrCmd ? event.ctrlKey || event.metaKey : event.ctrlKey === !!shortcut.ctrl) && (ctrlOrCmd ? true : event.metaKey === !!shortcut.meta) && event.altKey === !!shortcut.alt && event.shiftKey === !!shortcut.shift;
9389
+ };
9390
+ var matchesKeyboardShortcuts = (event, shortcuts) => shortcuts.some((shortcut) => matchesKeyboardShortcut(event, shortcut));
9391
+ var formatKeyboardShortcut = (shortcut) => {
9392
+ const modifiers = [
9393
+ shortcut.ctrlOrCmd && "CtrlOrCmd",
9394
+ shortcut.ctrl && "Ctrl",
9395
+ shortcut.meta && "Meta",
9396
+ shortcut.alt && "Alt",
9397
+ shortcut.shift && "Shift"
9398
+ ].filter(Boolean);
9399
+ const key = shortcut.key ?? shortcut.code ?? "";
9400
+ return getShortcutKey(
9401
+ [...modifiers, key.length === 1 ? key.toLocaleUpperCase() : key].join("+")
9402
+ );
9403
+ };
9404
+
9380
9405
  // components/ToolPopover.tsx
9381
9406
  import { useEffect as useEffect17, useState as useState10 } from "react";
9382
9407
  import clsx17 from "clsx";
@@ -9575,6 +9600,26 @@ var findShapeByKey = (key, app, shiftKey = false) => {
9575
9600
  }
9576
9601
  return null;
9577
9602
  };
9603
+ var findShapeByKeyboardEvent = (event, app) => {
9604
+ for (const type of Object.keys(TOOLS)) {
9605
+ const override = app.props.keyboardShortcuts?.[`tool:${type}`];
9606
+ if (override !== void 0) {
9607
+ if (matchesKeyboardShortcuts(event, override)) {
9608
+ return type === "selection" ? app.state.preferredSelectionTool.type : type;
9609
+ }
9610
+ continue;
9611
+ }
9612
+ }
9613
+ if (event.ctrlKey || event.metaKey || event.altKey) {
9614
+ return null;
9615
+ }
9616
+ const defaultShape = findShapeByKey(event.key, app, event.shiftKey);
9617
+ if (!defaultShape) {
9618
+ return null;
9619
+ }
9620
+ const defaultCommand = (defaultShape === "selection" || defaultShape === "lasso") && TOOLS.selection.letterKey === event.key.toLocaleLowerCase() ? "tool:selection" : `tool:${defaultShape}`;
9621
+ return app.props.keyboardShortcuts?.[defaultCommand] === void 0 ? defaultShape : null;
9622
+ };
9578
9623
  var isToolButtonDisabled = (app, type) => app.props.activeTool != null && app.props.activeTool.type !== type;
9579
9624
  var createToolButton = (type, behavior) => {
9580
9625
  const config = TOOLS[type];
@@ -9586,7 +9631,8 @@ var createToolButton = (type, behavior) => {
9586
9631
  hideShortcut
9587
9632
  }) => {
9588
9633
  const label = capitalizeString2(t(`toolBar.${type}`));
9589
- const shortcut = hideShortcut ? null : getToolShortcut(shortcutType);
9634
+ const shortcutOverride = app.props.keyboardShortcuts?.[`tool:${shortcutType}`];
9635
+ const shortcut = hideShortcut ? null : shortcutOverride !== void 0 ? shortcutOverride[0] ? formatKeyboardShortcut(shortcutOverride[0]) : null : getToolShortcut(shortcutType);
9590
9636
  return /* @__PURE__ */ jsx38(
9591
9637
  IconButton,
9592
9638
  {
@@ -9596,7 +9642,7 @@ var createToolButton = (type, behavior) => {
9596
9642
  checked: activeTool.type === type,
9597
9643
  disabled: isToolButtonDisabled(app, type),
9598
9644
  title: shortcut ? `${label} \u2014 ${shortcut}` : label,
9599
- keyBindingLabel: hideKeyBinding || hideShortcut ? void 0 : getToolKeyBindingLabel(shortcutType),
9645
+ keyBindingLabel: hideKeyBinding || hideShortcut ? void 0 : shortcutOverride !== void 0 ? shortcut?.length === 1 ? shortcut : void 0 : getToolKeyBindingLabel(shortcutType),
9600
9646
  "aria-label": label,
9601
9647
  "aria-keyshortcuts": shortcut ?? void 0,
9602
9648
  "data-testid": `toolbar-${type}`,
@@ -10000,6 +10046,7 @@ var actionFinalize = register({
10000
10046
  };
10001
10047
  },
10002
10048
  keyTest: (event, appState) => event.key === KEYS14.ESCAPE && appState.selectedLinearElement?.isEditing || (event.key === KEYS14.ESCAPE || event.key === KEYS14.ENTER) && appState.multiElement !== null,
10049
+ keyCondition: (_event, appState) => !!appState.selectedLinearElement?.isEditing || appState.multiElement !== null,
10003
10050
  PanelComponent: ({ appState, updateData, data }) => /* @__PURE__ */ jsx39(
10004
10051
  IconButton,
10005
10052
  {
@@ -10125,7 +10172,8 @@ var actionDeselect = register({
10125
10172
  return false;
10126
10173
  }
10127
10174
  return !appState.newElement && appState.multiElement === null && !appState.selectedLinearElement?.isEditing && (appState.activeEmbeddable !== null || appState.activeTool.type !== app.state.preferredSelectionTool.type || !!appState.editingGroupId || !!appState.selectedLinearElement || isSomeElementSelected2(app.scene.getNonDeletedElements(), appState));
10128
- }
10175
+ },
10176
+ keyCondition: (event, appState, _, app) => !isWritableElement2(event.target) && !appState.newElement && appState.multiElement === null && !appState.selectedLinearElement?.isEditing && (appState.activeEmbeddable !== null || appState.activeTool.type !== app.state.preferredSelectionTool.type || !!appState.editingGroupId || !!appState.selectedLinearElement || isSomeElementSelected2(app.scene.getNonDeletedElements(), appState))
10129
10177
  });
10130
10178
 
10131
10179
  // actions/actionExport.tsx
@@ -10968,7 +11016,7 @@ var exportCanvas = async (type, elements, appState, files, {
10968
11016
  let blob = canvasToBlob(tempCanvas);
10969
11017
  if (appState.exportEmbedScene) {
10970
11018
  blob = blob.then(
10971
- (blob2) => import("./data/image-42C5IMES.js").then(
11019
+ (blob2) => import("./data/image-ADOTOLKB.js").then(
10972
11020
  ({ encodePngMetadata: encodePngMetadata2 }) => encodePngMetadata2({
10973
11021
  blob: blob2,
10974
11022
  metadata: serializeAsJSON(elements, appState, files, "local")
@@ -13928,7 +13976,11 @@ var actionToggleElementLock = register({
13928
13976
  selectedElementIds: appState.selectedElementIds,
13929
13977
  includeBoundTextElement: false
13930
13978
  }).length > 0;
13931
- }
13979
+ },
13980
+ keyCondition: (_event, appState, _elements, app) => app.scene.getSelectedElements({
13981
+ selectedElementIds: appState.selectedElementIds,
13982
+ includeBoundTextElement: false
13983
+ }).length > 0
13932
13984
  });
13933
13985
  var actionUnlockAllElements = register({
13934
13986
  name: "unlockAllElements",
@@ -16993,14 +17045,25 @@ var ActionManager = class {
16993
17045
  return false;
16994
17046
  }
16995
17047
  const canvasActions = this.app.props.UIOptions.canvasActions;
16996
- const data = Object.values(this.actions).sort((a, b) => (b.keyPriority || 0) - (a.keyPriority || 0)).filter(
16997
- (action2) => (action2.name in canvasActions ? canvasActions[action2.name] : true) && action2.keyTest && action2.keyTest(
16998
- event,
16999
- this.getAppState(),
17000
- this.getElementsIncludingDeleted(),
17001
- this.app
17002
- )
17003
- );
17048
+ const data = Object.values(this.actions).sort((a, b) => (b.keyPriority || 0) - (a.keyPriority || 0)).filter((action2) => {
17049
+ const override = this.app.props.keyboardShortcuts?.[action2.name];
17050
+ return (action2.name in canvasActions ? canvasActions[action2.name] : true) && (action2.keyTest || override !== void 0) && (() => {
17051
+ if (override !== void 0) {
17052
+ return matchesKeyboardShortcuts(event, override) && (!action2.keyCondition || action2.keyCondition(
17053
+ event,
17054
+ this.getAppState(),
17055
+ this.getElementsIncludingDeleted(),
17056
+ this.app
17057
+ ));
17058
+ }
17059
+ return action2.keyTest(
17060
+ event,
17061
+ this.getAppState(),
17062
+ this.getElementsIncludingDeleted(),
17063
+ this.app
17064
+ );
17065
+ })();
17066
+ });
17004
17067
  if (data.length !== 1) {
17005
17068
  if (data.length > 1) {
17006
17069
  console.warn("Canceling as multiple actions match this shortcut", data);
@@ -24580,7 +24643,7 @@ var AppGifPlayback = class {
24580
24643
  }
24581
24644
  }
24582
24645
  if (didAdvanceFrame) {
24583
- this.app.scene.triggerUpdate();
24646
+ this.app.imagePlaceholderUpdateEmitter.trigger();
24584
24647
  }
24585
24648
  if (shouldContinue) {
24586
24649
  this.playbackRaf = requestAnimationFrame(this.tick);
@@ -37965,6 +38028,10 @@ var App = class _App extends React41.Component {
37965
38028
  }
37966
38029
  ));
37967
38030
  // Input handling
38031
+ __publicField(this, "matchesShortcut", (command, event, defaultMatch) => {
38032
+ const override = this.props.keyboardShortcuts?.[command];
38033
+ return override === void 0 ? defaultMatch : matchesKeyboardShortcuts(event, override);
38034
+ });
37968
38035
  __publicField(this, "onKeyDown", withBatchedUpdates(
37969
38036
  (event) => {
37970
38037
  if (!this.isInteractionEnabled()) {
@@ -38044,12 +38111,20 @@ var App = class _App extends React41.Component {
38044
38111
  ) {
38045
38112
  return;
38046
38113
  }
38047
- if (event.key === KEYS52.QUESTION_MARK) {
38114
+ if (this.matchesShortcut(
38115
+ "helpDialog",
38116
+ event,
38117
+ event.key === KEYS52.QUESTION_MARK
38118
+ )) {
38048
38119
  this.setState({
38049
38120
  openDialog: { name: "help" }
38050
38121
  });
38051
38122
  return;
38052
- } else if (event.key.toLowerCase() === KEYS52.E && event.shiftKey && event[KEYS52.CTRL_OR_CMD]) {
38123
+ } else if (this.matchesShortcut(
38124
+ "imageExport",
38125
+ event,
38126
+ event.key.toLowerCase() === KEYS52.E && event.shiftKey && event[KEYS52.CTRL_OR_CMD]
38127
+ )) {
38053
38128
  event.preventDefault();
38054
38129
  this.setState({ openDialog: { name: "imageExport" } });
38055
38130
  return;
@@ -38080,8 +38155,8 @@ var App = class _App extends React41.Component {
38080
38155
  this.setActiveTool({ type: "selection" });
38081
38156
  return;
38082
38157
  }
38083
- if (!shouldPreventToolSwitching && !event.ctrlKey && !event.altKey && !event.metaKey && !this.state.newElement && !this.state.selectionElement && !this.state.selectedElementsAreBeingDragged) {
38084
- const shape = findShapeByKey(event.key, this, event.shiftKey);
38158
+ if (!shouldPreventToolSwitching && !this.state.newElement && !this.state.selectionElement && !this.state.selectedElementsAreBeingDragged) {
38159
+ const shape = findShapeByKeyboardEvent(event, this);
38085
38160
  if (this.state.viewModeEnabled && !oneOf(shape, ["laser", "hand"])) {
38086
38161
  return;
38087
38162
  }
@@ -38114,7 +38189,7 @@ var App = class _App extends React41.Component {
38114
38189
  }
38115
38190
  event.stopPropagation();
38116
38191
  return;
38117
- } else if (event.key === KEYS52.Q) {
38192
+ } else if (this.matchesShortcut("toolLock", event, event.key === KEYS52.Q)) {
38118
38193
  this.toggleLock("keyboard");
38119
38194
  event.stopPropagation();
38120
38195
  return;
@@ -38231,21 +38306,37 @@ var App = class _App extends React41.Component {
38231
38306
  this.cursor.set("zoom-in");
38232
38307
  event.preventDefault();
38233
38308
  }
38234
- if ((event.key === KEYS52.G || event.key === KEYS52.S) && !event.altKey && !event[KEYS52.CTRL_OR_CMD]) {
38309
+ if (this.matchesShortcut(
38310
+ "elementBackground",
38311
+ event,
38312
+ (event.key === KEYS52.G || event.key === KEYS52.S) && !event.altKey && !event[KEYS52.CTRL_OR_CMD]
38313
+ ) || this.matchesShortcut(
38314
+ "elementStroke",
38315
+ event,
38316
+ (event.key === KEYS52.G || event.key === KEYS52.S) && !event.altKey && !event[KEYS52.CTRL_OR_CMD]
38317
+ )) {
38235
38318
  const selectedElements = this.scene.getSelectedElements(this.state);
38236
38319
  if (this.state.activeTool.type === "selection" && !selectedElements.length) {
38237
38320
  return;
38238
38321
  }
38239
- if (event.key === KEYS52.G && (hasBackground(this.state.activeTool.type) || selectedElements.some((element) => hasBackground(element.type)))) {
38322
+ if (this.matchesShortcut(
38323
+ "elementBackground",
38324
+ event,
38325
+ event.key === KEYS52.G
38326
+ ) && (hasBackground(this.state.activeTool.type) || selectedElements.some((element) => hasBackground(element.type)))) {
38240
38327
  this.setState({ openPopup: "elementBackground" });
38241
38328
  event.stopPropagation();
38242
38329
  }
38243
- if (event.key === KEYS52.S) {
38330
+ if (this.matchesShortcut("elementStroke", event, event.key === KEYS52.S)) {
38244
38331
  this.setState({ openPopup: "elementStroke" });
38245
38332
  event.stopPropagation();
38246
38333
  }
38247
38334
  }
38248
- if (!event[KEYS52.CTRL_OR_CMD] && event.shiftKey && event.key.toLowerCase() === KEYS52.F) {
38335
+ if (this.matchesShortcut(
38336
+ "fontFamily",
38337
+ event,
38338
+ !event[KEYS52.CTRL_OR_CMD] && event.shiftKey && event.key.toLowerCase() === KEYS52.F
38339
+ )) {
38249
38340
  const selectedElements = this.scene.getSelectedElements(this.state);
38250
38341
  if (this.state.activeTool.type === "selection" && !selectedElements.length) {
38251
38342
  return;
@@ -38264,9 +38355,19 @@ var App = class _App extends React41.Component {
38264
38355
  const isPlainStrokeEyeDropper = lowerCased === KEYS52.I && !event.shiftKey && !event[KEYS52.CTRL_OR_CMD];
38265
38356
  const isPickingStroke = lowerCased === KEYS52.S && event.shiftKey && !event[KEYS52.CTRL_OR_CMD] || isPlainStrokeEyeDropper;
38266
38357
  const isPickingBackground = lowerCased === KEYS52.I && event.shiftKey && !event[KEYS52.CTRL_OR_CMD];
38267
- if (isPickingStroke || isPickingBackground) {
38358
+ const shouldPickStroke = this.matchesShortcut(
38359
+ "strokeEyeDropper",
38360
+ event,
38361
+ isPickingStroke
38362
+ );
38363
+ const shouldPickBackground = this.matchesShortcut(
38364
+ "backgroundEyeDropper",
38365
+ event,
38366
+ isPickingBackground
38367
+ );
38368
+ if (shouldPickStroke || shouldPickBackground) {
38268
38369
  this.openEyeDropper({
38269
- type: isPickingStroke ? "stroke" : "background",
38370
+ type: shouldPickStroke ? "stroke" : "background",
38270
38371
  swapPreviewOnAlt: !isPlainStrokeEyeDropper
38271
38372
  });
38272
38373
  }
@@ -46552,7 +46653,8 @@ var ExcalidrawBase = (props) => {
46552
46653
  viewportStatusFrame,
46553
46654
  currentUserControls,
46554
46655
  imageOptions,
46555
- showDropEventDebugAlert
46656
+ showDropEventDebugAlert,
46657
+ keyboardShortcuts
46556
46658
  } = props;
46557
46659
  const canvasActions = props.UIOptions?.canvasActions;
46558
46660
  const UIOptions = {
@@ -46668,6 +46770,7 @@ var ExcalidrawBase = (props) => {
46668
46770
  currentUserControls,
46669
46771
  imageOptions: normalizedImageOptions,
46670
46772
  showDropEventDebugAlert,
46773
+ keyboardShortcuts,
46671
46774
  children
46672
46775
  }
46673
46776
  ) }) });