kritzel-stencil 0.4.23 → 0.4.25
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/cjs/index.cjs.js +3 -46
- package/dist/cjs/kritzel-active-users_47.cjs.entry.js +93 -138
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/stencil.cjs.js +1 -1
- package/dist/collection/classes/core/core.class.js +4 -0
- package/dist/collection/classes/providers/sync/hocuspocus-sync-provider.class.js +1 -19
- package/dist/collection/classes/providers/sync/websocket-sync-provider.class.js +2 -27
- package/dist/collection/classes/structures/app-state-map.structure.js +1 -4
- package/dist/collection/classes/structures/object-map.structure.js +64 -61
- package/dist/collection/components/core/kritzel-editor/kritzel-editor.js +20 -32
- package/dist/collection/components/core/kritzel-engine/kritzel-engine.js +21 -73
- package/dist/collection/constants/version.js +1 -1
- package/dist/components/index.js +4 -47
- package/dist/components/kritzel-editor.js +20 -18
- package/dist/components/kritzel-engine.js +1 -1
- package/dist/components/kritzel-settings.js +1 -1
- package/dist/components/{p-Cb-xlpsJ.js → p-0fhjWRmT.js} +1 -1
- package/dist/components/{p-EijwLEZx.js → p-gJcH-huF.js} +75 -123
- package/dist/esm/index.js +3 -46
- package/dist/esm/kritzel-active-users_47.entry.js +93 -138
- package/dist/esm/loader.js +1 -1
- package/dist/esm/stencil.js +1 -1
- package/dist/stencil/index.esm.js +3 -46
- package/dist/stencil/{p-9e38407e.entry.js → p-dc5783ee.entry.js} +93 -138
- package/dist/stencil/stencil.esm.js +1 -1
- package/dist/types/classes/providers/sync/hocuspocus-sync-provider.class.d.ts +1 -5
- package/dist/types/classes/providers/sync/websocket-sync-provider.class.d.ts +1 -6
- package/dist/types/classes/structures/object-map.structure.d.ts +16 -26
- package/dist/types/components/core/kritzel-editor/kritzel-editor.d.ts +3 -4
- package/dist/types/components/core/kritzel-engine/kritzel-engine.d.ts +3 -12
- package/dist/types/components.d.ts +7 -12
- package/dist/types/constants/version.d.ts +1 -1
- package/dist/types/interfaces/sync-provider.interface.d.ts +5 -11
- package/package.json +1 -1
package/dist/cjs/index.cjs.js
CHANGED
|
@@ -570,13 +570,10 @@ class WebSocketSyncProvider {
|
|
|
570
570
|
provider;
|
|
571
571
|
isConnected = false;
|
|
572
572
|
_quiet = false;
|
|
573
|
-
_isSynced = false;
|
|
574
|
-
_syncedResolvers = [];
|
|
575
573
|
get awareness() {
|
|
576
574
|
return this.provider.awareness;
|
|
577
575
|
}
|
|
578
|
-
|
|
579
|
-
get updateOrigin() {
|
|
576
|
+
get rawProvider() {
|
|
580
577
|
return this.provider;
|
|
581
578
|
}
|
|
582
579
|
constructor(docName, doc, options) {
|
|
@@ -625,29 +622,11 @@ class WebSocketSyncProvider {
|
|
|
625
622
|
}
|
|
626
623
|
});
|
|
627
624
|
this.provider.on('sync', (synced) => {
|
|
628
|
-
if (!
|
|
629
|
-
return;
|
|
630
|
-
}
|
|
631
|
-
this._isSynced = true;
|
|
632
|
-
this.releaseSyncedWaiters();
|
|
633
|
-
if (!this._quiet) {
|
|
625
|
+
if (synced && !this._quiet) {
|
|
634
626
|
console.info('WebSocket synced');
|
|
635
627
|
}
|
|
636
628
|
});
|
|
637
629
|
}
|
|
638
|
-
releaseSyncedWaiters() {
|
|
639
|
-
const resolvers = this._syncedResolvers;
|
|
640
|
-
this._syncedResolvers = [];
|
|
641
|
-
resolvers.forEach(resolve => resolve());
|
|
642
|
-
}
|
|
643
|
-
async whenSynced() {
|
|
644
|
-
if (this._isSynced || this.provider.synced) {
|
|
645
|
-
return;
|
|
646
|
-
}
|
|
647
|
-
return new Promise(resolve => {
|
|
648
|
-
this._syncedResolvers.push(resolve);
|
|
649
|
-
});
|
|
650
|
-
}
|
|
651
630
|
async connect() {
|
|
652
631
|
if (this.isConnected) {
|
|
653
632
|
return;
|
|
@@ -679,8 +658,6 @@ class WebSocketSyncProvider {
|
|
|
679
658
|
this.provider.disconnect();
|
|
680
659
|
}
|
|
681
660
|
this.isConnected = false;
|
|
682
|
-
this._isSynced = false;
|
|
683
|
-
this.releaseSyncedWaiters();
|
|
684
661
|
}
|
|
685
662
|
async reconnect() {
|
|
686
663
|
this.disconnect();
|
|
@@ -691,8 +668,6 @@ class WebSocketSyncProvider {
|
|
|
691
668
|
this.provider.destroy();
|
|
692
669
|
}
|
|
693
670
|
this.isConnected = false;
|
|
694
|
-
this._isSynced = false;
|
|
695
|
-
this.releaseSyncedWaiters();
|
|
696
671
|
}
|
|
697
672
|
}
|
|
698
673
|
|
|
@@ -714,12 +689,10 @@ class HocuspocusSyncProvider {
|
|
|
714
689
|
_connectionStatus = 'disconnected';
|
|
715
690
|
visibilityHandler = null;
|
|
716
691
|
onlineHandler = null;
|
|
717
|
-
syncedResolvers = [];
|
|
718
692
|
get awareness() {
|
|
719
693
|
return this.provider.awareness;
|
|
720
694
|
}
|
|
721
|
-
|
|
722
|
-
get updateOrigin() {
|
|
695
|
+
get rawProvider() {
|
|
723
696
|
return this.provider;
|
|
724
697
|
}
|
|
725
698
|
get connectionStatus() {
|
|
@@ -778,7 +751,6 @@ class HocuspocusSyncProvider {
|
|
|
778
751
|
}
|
|
779
752
|
this.isSynced = true;
|
|
780
753
|
this._connectionStatus = 'synced';
|
|
781
|
-
this.releaseSyncedWaiters();
|
|
782
754
|
if (!options?.quiet) {
|
|
783
755
|
console.info(`Hocuspocus synced: ${name}`);
|
|
784
756
|
}
|
|
@@ -989,19 +961,6 @@ class HocuspocusSyncProvider {
|
|
|
989
961
|
this.disconnect();
|
|
990
962
|
return this.connect();
|
|
991
963
|
}
|
|
992
|
-
releaseSyncedWaiters() {
|
|
993
|
-
const resolvers = this.syncedResolvers;
|
|
994
|
-
this.syncedResolvers = [];
|
|
995
|
-
resolvers.forEach(resolve => resolve());
|
|
996
|
-
}
|
|
997
|
-
async whenSynced() {
|
|
998
|
-
if (this.isSynced || this.isDestroyed || this.provider.isSynced) {
|
|
999
|
-
return;
|
|
1000
|
-
}
|
|
1001
|
-
return new Promise(resolve => {
|
|
1002
|
-
this.syncedResolvers.push(resolve);
|
|
1003
|
-
});
|
|
1004
|
-
}
|
|
1005
964
|
disconnect() {
|
|
1006
965
|
// Cancel any pending connection attempt
|
|
1007
966
|
if (this.connectTimeout) {
|
|
@@ -1023,7 +982,6 @@ class HocuspocusSyncProvider {
|
|
|
1023
982
|
this.isConnected = false;
|
|
1024
983
|
this.isSynced = false;
|
|
1025
984
|
this._connectionStatus = 'disconnected';
|
|
1026
|
-
this.releaseSyncedWaiters();
|
|
1027
985
|
}
|
|
1028
986
|
destroy() {
|
|
1029
987
|
// Mark as destroyed first to prevent any callbacks from doing work
|
|
@@ -1043,7 +1001,6 @@ class HocuspocusSyncProvider {
|
|
|
1043
1001
|
this.isConnected = false;
|
|
1044
1002
|
this.isSynced = false;
|
|
1045
1003
|
this._connectionStatus = 'disconnected';
|
|
1046
|
-
this.releaseSyncedWaiters();
|
|
1047
1004
|
}
|
|
1048
1005
|
}
|
|
1049
1006
|
|
|
@@ -2168,8 +2168,7 @@ const KritzelEditor = class {
|
|
|
2168
2168
|
this.login = index.createEvent(this, "login");
|
|
2169
2169
|
this.isPublicChange = index.createEvent(this, "isPublicChange");
|
|
2170
2170
|
this.awarenessChange = index.createEvent(this, "awarenessChange");
|
|
2171
|
-
this.
|
|
2172
|
-
this.loadingChange = index.createEvent(this, "loadingChange");
|
|
2171
|
+
this.isSyncing = index.createEvent(this, "isSyncing");
|
|
2173
2172
|
}
|
|
2174
2173
|
get host() { return index.getElement(this); }
|
|
2175
2174
|
scaleMax = ABSOLUTE_SCALE_MAX;
|
|
@@ -2409,9 +2408,7 @@ const KritzelEditor = class {
|
|
|
2409
2408
|
login;
|
|
2410
2409
|
isPublicChange;
|
|
2411
2410
|
awarenessChange;
|
|
2412
|
-
|
|
2413
|
-
syncingChange;
|
|
2414
|
-
loadingChange;
|
|
2411
|
+
isSyncing;
|
|
2415
2412
|
isEngineReady = false;
|
|
2416
2413
|
isControlsReady = false;
|
|
2417
2414
|
isWorkspaceManagerReady = false;
|
|
@@ -2433,8 +2430,8 @@ const KritzelEditor = class {
|
|
|
2433
2430
|
contextMenuState;
|
|
2434
2431
|
normalizedControls = [];
|
|
2435
2432
|
resolvedMoreMenuItems = [];
|
|
2436
|
-
isSyncing = false;
|
|
2437
2433
|
isLoadingOverlayVisible = false;
|
|
2434
|
+
isSyncingIndicatorVisible = false;
|
|
2438
2435
|
notificationDismissTimeout;
|
|
2439
2436
|
notificationDismissAnimationTimeout;
|
|
2440
2437
|
notificationDisplayDurationMs = 5000;
|
|
@@ -2917,6 +2914,11 @@ const KritzelEditor = class {
|
|
|
2917
2914
|
event.stopPropagation();
|
|
2918
2915
|
this.awarenessChange.emit(event.detail);
|
|
2919
2916
|
}
|
|
2917
|
+
handleIsSyncingChange(event) {
|
|
2918
|
+
event.stopPropagation();
|
|
2919
|
+
this.isSyncingIndicatorVisible = event.detail;
|
|
2920
|
+
this.isSyncing.emit(event.detail);
|
|
2921
|
+
}
|
|
2920
2922
|
handleNotificationsChange(event) {
|
|
2921
2923
|
event.stopPropagation();
|
|
2922
2924
|
this.clearNotificationDismissAnimationTimer();
|
|
@@ -3230,40 +3232,40 @@ const KritzelEditor = class {
|
|
|
3230
3232
|
const isLoggedIn = this.isLoggedIn;
|
|
3231
3233
|
const shouldShowCurrentUser = isLoggedIn;
|
|
3232
3234
|
const shouldShowLoginButton = this.isReady && !!this.loginConfig && !isLoggedIn;
|
|
3233
|
-
return (index.h(index.Host, { key: '
|
|
3235
|
+
return (index.h(index.Host, { key: 'a24350a0c12d99ccb0d0ec3ab5975d0f1bf7f861' }, index.h("div", { key: 'bd7029567aeef8cba5290c2bf9937db1af113475', class: "editor-content", style: {
|
|
3234
3236
|
opacity: this.isEditorVisible ? '1' : '0',
|
|
3235
3237
|
visibility: this.isEditorVisible ? 'visible' : 'hidden',
|
|
3236
3238
|
transition: 'opacity 0.2s ease-in-out, visibility 0.2s ease-in-out',
|
|
3237
|
-
} }, index.h("div", { key: '
|
|
3239
|
+
} }, index.h("div", { key: 'f628dbd94d88c9bdb313a59d73ce86302c90e375', class: "top-left-buttons" }, index.h("kritzel-workspace-manager", { key: '5a82d054da31e47d3f8b5c6c403949a5fb97b9dd', visible: this.isWorkspaceManagerVisible, workspaces: this.workspaces, activeWorkspace: this.activeWorkspace, terms: this.resolvedTerms, onWorkspaceChange: event => (this.activeWorkspace = event.detail), onIsWorkspaceManagerReady: () => (this.isWorkspaceManagerReady = true) }), index.h("kritzel-back-to-content", { key: 'a5bccef36c8a49ef2cb7ec029def1c7ba71d1c31', visible: this.isBackToContentButtonVisible, text: this.resolvedTerms['backToContent.label'] ?? 'Back to content', onBackToContent: () => this.backToContent() })), this.activeNotification && (index.h("div", { key: 'c5c359b199528dd7b1b64a6a32ef349037357c5a', class: "top-center-notification-layer", role: "presentation" }, index.h("div", { key: 'a41cd6c67c56626c2b6f0eb12193af1f80d6a254', class: { 'top-center-notification-container': true, 'is-dismissing': this.isNotificationDismissing }, role: "presentation" }, index.h("kritzel-notification-card", { key: 'fb49769368ddf0fc74998a96dd26dc446ff2b386', notification: this.activeNotification, locale: this.locale, onDismiss: this.dismissNotification, onHoverChange: event => this.handleNotificationHoverChange(event) })))), this.contextMenuState && this.contextMenuState.items.length > 0 && (index.h("kritzel-context-menu", { key: '56f38790f477d08761d7542ed3794c52f1f73815', class: "context-menu", items: this.contextMenuState.items, objects: this.contextMenuState.objects, style: {
|
|
3238
3240
|
position: 'absolute',
|
|
3239
3241
|
left: `${this.contextMenuState.position.x}px`,
|
|
3240
3242
|
top: `${this.contextMenuState.position.y}px`,
|
|
3241
3243
|
zIndex: '10002',
|
|
3242
|
-
}, onActionSelected: event => this.handleContextMenuActionSelected(event), onClose: () => this.hideContextMenu() })), index.h("kritzel-sync-indicator", { key: '
|
|
3244
|
+
}, onActionSelected: event => this.handleContextMenuActionSelected(event), onClose: () => this.hideContextMenu() })), index.h("kritzel-sync-indicator", { key: '4957b8bae0d7087d586c9d0c6da82cae905d7d08', visible: this.isSyncingIndicatorVisible, text: "Syncing..." }), index.h("kritzel-loading-overlay", { key: 'e2e99dc452245a2edf7a575ea5fb60aa91be20df', visible: this.isLoadingOverlayVisible, text: this.resolvedTerms['editor.loading'] ?? 'Loading...' }), index.h("kritzel-engine", { key: 'fcebe1cc1237c8649461f03679f9c76c05dde9c4', ref: el => {
|
|
3243
3245
|
if (el) {
|
|
3244
3246
|
this.engineRef = el;
|
|
3245
3247
|
}
|
|
3246
|
-
}, workspace: this.activeWorkspace, activeWorkspaceId: this.activeWorkspaceId, editorId: this.editorId, syncConfig: this.syncConfig, assetStorageConfig: this.assetStorageConfig, user: this.user, scaleMax: this.scaleMax, lockDrawingScale: this.lockDrawingScale, isObjectDistanceFadingActive: this.isObjectDistanceFadingActive, scaleMin: this.scaleMin, cursorTarget: this.cursorTarget, isLoading: this.isLoading, viewportBoundaryLeft: this.viewportBoundaryLeft, viewportBoundaryRight: this.viewportBoundaryRight, viewportBoundaryTop: this.viewportBoundaryTop, viewportBoundaryBottom: this.viewportBoundaryBottom, isPanningEnabled: this.isPanningEnabled, isZoomingEnabled: this.isZoomingEnabled, theme: this.theme, themes: this.themes, licenseKey: this.licenseKey, locale: this.locale, locales: this.locales, fallbackLocale: this.fallbackLocale, debugInfo: this.debugInfo, globalContextMenuItems: this.globalContextMenuItems, objectContextMenuItems: this.objectContextMenuItems, onIsEngineReady: event => this.onEngineReady(event), onWorkspacesChange: event => this.handleWorkspacesChange(event), onActiveWorkspaceChange: event => this.handleActiveWorkspaceChange(event), onObjectsChange: event => this.handleObjectsChange(event), onObjectsAdded: event => this.handleObjectsAdded(event), onObjectsRemoved: event => this.handleObjectsRemoved(event), onObjectsUpdated: event => this.handleObjectsUpdated(event), onUndoStateChange: event => this.handleUndoStateChange(event), onObjectsInViewportChange: event => this.handleObjectsInViewportChange(event), onViewportChange: event => this.handleViewportChange(event), onAwarenessChange: event => this.handleAwarenessChange(event),
|
|
3248
|
+
}, workspace: this.activeWorkspace, activeWorkspaceId: this.activeWorkspaceId, editorId: this.editorId, syncConfig: this.syncConfig, assetStorageConfig: this.assetStorageConfig, user: this.user, scaleMax: this.scaleMax, lockDrawingScale: this.lockDrawingScale, isObjectDistanceFadingActive: this.isObjectDistanceFadingActive, scaleMin: this.scaleMin, cursorTarget: this.cursorTarget, isLoading: this.isLoading, viewportBoundaryLeft: this.viewportBoundaryLeft, viewportBoundaryRight: this.viewportBoundaryRight, viewportBoundaryTop: this.viewportBoundaryTop, viewportBoundaryBottom: this.viewportBoundaryBottom, isPanningEnabled: this.isPanningEnabled, isZoomingEnabled: this.isZoomingEnabled, theme: this.theme, themes: this.themes, licenseKey: this.licenseKey, locale: this.locale, locales: this.locales, fallbackLocale: this.fallbackLocale, debugInfo: this.debugInfo, globalContextMenuItems: this.globalContextMenuItems, objectContextMenuItems: this.objectContextMenuItems, onIsEngineReady: event => this.onEngineReady(event), onWorkspacesChange: event => this.handleWorkspacesChange(event), onActiveWorkspaceChange: event => this.handleActiveWorkspaceChange(event), onObjectsChange: event => this.handleObjectsChange(event), onObjectsAdded: event => this.handleObjectsAdded(event), onObjectsRemoved: event => this.handleObjectsRemoved(event), onObjectsUpdated: event => this.handleObjectsUpdated(event), onUndoStateChange: event => this.handleUndoStateChange(event), onObjectsInViewportChange: event => this.handleObjectsInViewportChange(event), onViewportChange: event => this.handleViewportChange(event), onAwarenessChange: event => this.handleAwarenessChange(event), onIsSyncing: event => this.handleIsSyncingChange(event), onNotificationsChange: event => this.handleNotificationsChange(event), onContextMenuStateChange: event => this.handleContextMenuStateChange(event), onLoadingChange: event => (this.isLoadingOverlayVisible = event.detail) }), index.h("kritzel-controls", { key: '72b1a3f80bfedb3843d0d54159ad47793db69977', visible: this.isControlsVisible, class: { 'keyboard-open': this.isVirtualKeyboardOpen }, ref: el => {
|
|
3247
3249
|
if (el) {
|
|
3248
3250
|
this.controlsRef = el;
|
|
3249
3251
|
}
|
|
3250
|
-
}, controls: this.normalizedControls, isUtilityPanelVisible: this.isUtilityPanelVisible, undoState: this.undoState ?? undefined, theme: this.theme, terms: this.resolvedTerms, onIsControlsReady: () => (this.isControlsReady = true) }), index.h("div", { key: '
|
|
3252
|
+
}, controls: this.normalizedControls, isUtilityPanelVisible: this.isUtilityPanelVisible, undoState: this.undoState ?? undefined, theme: this.theme, terms: this.resolvedTerms, onIsControlsReady: () => (this.isControlsReady = true) }), index.h("div", { key: '1684a320f1806ae9fdfcfcff115d01f5788737e7', class: "bottom-left-buttons" }, index.h("kritzel-zoom-panel", { key: '8e85652ded70df043d79c9cd73b226aaefa5d6d4', visible: this.isZoomPanelVisible, disabled: !this.isZoomingEnabled, zoomPercent: this.currentZoomPercent, terms: this.resolvedTerms, onZoomIn: () => this.zoomIn(), onZoomOut: () => this.zoomOut() })), index.h("div", { key: 'a836056bdae11324f4ce79da4b991281c1985358', class: "top-right-buttons" }, index.h("kritzel-settings", { key: 'e68f4e79bc053e03dc37c18ee153758d284b0d34', ref: el => {
|
|
3251
3253
|
if (el) {
|
|
3252
3254
|
this.settingsRef = el;
|
|
3253
3255
|
}
|
|
3254
|
-
}, shortcuts: this.shortcuts, availableThemes: this.themes && this.themes.length > 0 ? this.themes.map(t => t.name) : ['light', 'dark'], availableLocales: this.availableLocaleOptions, settings: this.currentSettingsConfig, terms: this.resolvedTerms, onSettingsChange: event => this.handleSettingsChange(event) }), index.h("kritzel-export", { key: '
|
|
3256
|
+
}, shortcuts: this.shortcuts, availableThemes: this.themes && this.themes.length > 0 ? this.themes.map(t => t.name) : ['light', 'dark'], availableLocales: this.availableLocaleOptions, settings: this.currentSettingsConfig, terms: this.resolvedTerms, onSettingsChange: event => this.handleSettingsChange(event) }), index.h("kritzel-export", { key: 'f1e9ea467d11b55dbe75d8b0252fd7f5ed37a1a2', ref: el => {
|
|
3255
3257
|
if (el) {
|
|
3256
3258
|
this.exportRef = el;
|
|
3257
3259
|
}
|
|
3258
|
-
}, workspaceName: this.activeWorkspace?.name || 'workspace', terms: this.resolvedTerms, onExportPng: () => this.engineRef.exportViewportAsPng(), onExportSvg: () => this.engineRef.exportViewportAsSvg(), onExportJson: event => this.engineRef.downloadAsJson(event.detail) }), index.h("kritzel-active-users", { key: '
|
|
3260
|
+
}, workspaceName: this.activeWorkspace?.name || 'workspace', terms: this.resolvedTerms, onExportPng: () => this.engineRef.exportViewportAsPng(), onExportSvg: () => this.engineRef.exportViewportAsSvg(), onExportJson: event => this.engineRef.downloadAsJson(event.detail) }), index.h("kritzel-active-users", { key: '01bb56bd37bc22e82be5a1175f597cdf724c4834', users: this.activeUsers }), shouldShowCurrentUser && index.h("kritzel-current-user", { key: '5470ef356a4d6332b380e8c75f02f0fccbe861cc', user: this.user, terms: this.resolvedTerms, onClick: () => this.currentUserDialogRef?.open() }), shouldShowCurrentUser && (index.h("kritzel-current-user-dialog", { key: '229551b18f0443944a96f7b8e833ff1aefb001f4', ref: el => {
|
|
3259
3261
|
if (el) {
|
|
3260
3262
|
this.currentUserDialogRef = el;
|
|
3261
3263
|
}
|
|
3262
|
-
}, user: this.user, terms: this.resolvedTerms, onLogoutRequest: this.handleCurrentUserLogout })), shouldShowLoginButton && index.h("kritzel-button", { key: '
|
|
3264
|
+
}, user: this.user, terms: this.resolvedTerms, onLogoutRequest: this.handleCurrentUserLogout })), shouldShowLoginButton && index.h("kritzel-button", { key: '3d9a8ebbe62084e94348265f1f883bc80e625d9c', onButtonClick: () => this.loginDialogRef?.open() }, this.resolvedTerms['login.dialogTitle'] ?? 'Sign in'), index.h("kritzel-more-menu", { key: '9f7f763c330b27068bc371d98eb22a80adbf359e', items: this.resolvedMoreMenuItems, visible: this.isMoreMenuVisible, terms: this.resolvedTerms }), index.h("kritzel-share-dialog", { key: 'c60b860e22394a44270285dea45f02305a05c545', ref: el => {
|
|
3263
3265
|
if (el) {
|
|
3264
3266
|
this.shareDialogRef = el;
|
|
3265
3267
|
}
|
|
3266
|
-
}, isPublic: this.currentIsPublic, workspaceId: this.activeWorkspace?.id, terms: this.resolvedTerms, onToggleIsPublic: this.handleToggleIsPublic }), this.loginConfig && (index.h("kritzel-login-dialog", { key: '
|
|
3268
|
+
}, isPublic: this.currentIsPublic, workspaceId: this.activeWorkspace?.id, terms: this.resolvedTerms, onToggleIsPublic: this.handleToggleIsPublic }), this.loginConfig && (index.h("kritzel-login-dialog", { key: '84d0fab11722a7be1d5824b3284f000502277dfc', ref: el => {
|
|
3267
3269
|
if (el) {
|
|
3268
3270
|
this.loginDialogRef = el;
|
|
3269
3271
|
}
|
|
@@ -22306,13 +22308,17 @@ class KritzelObjectMap {
|
|
|
22306
22308
|
_awarenessChangeHandler = null;
|
|
22307
22309
|
_awarenessChangeCallbacks = [];
|
|
22308
22310
|
_objectsChangeCallbacks = [];
|
|
22309
|
-
_remoteChangesCallbacks = [];
|
|
22310
|
-
_docUpdateHandler = null;
|
|
22311
|
-
_remoteOrigins = new Set();
|
|
22312
|
-
_appliedRemoteChanges = false;
|
|
22313
22311
|
_lastAwarenessEmitTime = 0;
|
|
22314
22312
|
_awarenessEmitTimeout = null;
|
|
22315
22313
|
AWARENESS_THROTTLE_INTERVAL = 100; // milliseconds
|
|
22314
|
+
// Identities of the raw network-provider instances (e.g. WebsocketProvider, HocuspocusProvider)
|
|
22315
|
+
// that Yjs tags as transaction origin for remote updates; local providers (IndexedDB,
|
|
22316
|
+
// BroadcastChannel) never appear here, so their transactions never toggle isSyncing.
|
|
22317
|
+
_networkTransactionOrigins = new Set();
|
|
22318
|
+
_isSyncing = false;
|
|
22319
|
+
_syncingChangeCallbacks = [];
|
|
22320
|
+
_beforeTransactionHandler = null;
|
|
22321
|
+
_afterAllTransactionsHandler = null;
|
|
22316
22322
|
/**
|
|
22317
22323
|
* When true, update() only modifies local state (quadtree + idMap)
|
|
22318
22324
|
* without writing to Yjs. Used during drag operations to avoid
|
|
@@ -22333,44 +22339,12 @@ class KritzelObjectMap {
|
|
|
22333
22339
|
return this._isReady;
|
|
22334
22340
|
}
|
|
22335
22341
|
/**
|
|
22336
|
-
* Promise that settles when network providers finish connecting
|
|
22337
|
-
*
|
|
22342
|
+
* Promise that settles when network providers finish connecting.
|
|
22343
|
+
* Resolves immediately if no network providers. Awaited by the loading overlay.
|
|
22338
22344
|
*/
|
|
22339
22345
|
whenNetworkSynced() {
|
|
22340
22346
|
return this._networkSyncPromise ?? Promise.resolve();
|
|
22341
22347
|
}
|
|
22342
|
-
/**
|
|
22343
|
-
* Whether any configured provider synchronizes over the network.
|
|
22344
|
-
*/
|
|
22345
|
-
get hasNetworkSyncProvider() {
|
|
22346
|
-
return this._providers.some(provider => provider.type === 'network');
|
|
22347
|
-
}
|
|
22348
|
-
/**
|
|
22349
|
-
* Whether remote-originated changes can be told apart from local writes.
|
|
22350
|
-
* Requires every network provider to expose its Yjs update origin.
|
|
22351
|
-
*/
|
|
22352
|
-
get supportsRemoteChangeDetection() {
|
|
22353
|
-
const networkProviders = this._providers.filter(provider => provider.type === 'network');
|
|
22354
|
-
return networkProviders.length > 0 && networkProviders.every(provider => provider.updateOrigin !== undefined);
|
|
22355
|
-
}
|
|
22356
|
-
/**
|
|
22357
|
-
* Whether at least one update originating from a network provider has been
|
|
22358
|
-
* applied to this document. Stays `false` when the remote held no data the
|
|
22359
|
-
* local document was missing, because Yjs suppresses empty updates.
|
|
22360
|
-
*/
|
|
22361
|
-
get hasAppliedRemoteChanges() {
|
|
22362
|
-
return this._appliedRemoteChanges;
|
|
22363
|
-
}
|
|
22364
|
-
/**
|
|
22365
|
-
* Registers a callback invoked whenever a network provider applies changes to this document.
|
|
22366
|
-
* @returns A function that unregisters the callback.
|
|
22367
|
-
*/
|
|
22368
|
-
onRemoteChangesApplied(callback) {
|
|
22369
|
-
this._remoteChangesCallbacks.push(callback);
|
|
22370
|
-
return () => {
|
|
22371
|
-
this._remoteChangesCallbacks = this._remoteChangesCallbacks.filter(registered => registered !== callback);
|
|
22372
|
-
};
|
|
22373
|
-
}
|
|
22374
22348
|
/**
|
|
22375
22349
|
* Returns the Yjs Awareness instance, if a network provider is available.
|
|
22376
22350
|
*/
|
|
@@ -22520,6 +22494,22 @@ class KritzelObjectMap {
|
|
|
22520
22494
|
this._objectsChangeCallbacks = this._objectsChangeCallbacks.filter(existingCallback => existingCallback !== callback);
|
|
22521
22495
|
};
|
|
22522
22496
|
}
|
|
22497
|
+
/**
|
|
22498
|
+
* Whether the local copy currently differs from data a remote peer is in the process of merging in.
|
|
22499
|
+
*/
|
|
22500
|
+
get isSyncing() {
|
|
22501
|
+
return this._isSyncing;
|
|
22502
|
+
}
|
|
22503
|
+
/**
|
|
22504
|
+
* Registers a callback invoked when a remote sync starts (`true`) or finishes (`false`).
|
|
22505
|
+
* "Starts" fires from `beforeTransaction`, before the incoming remote update is merged.
|
|
22506
|
+
*/
|
|
22507
|
+
onSyncingChange(callback) {
|
|
22508
|
+
this._syncingChangeCallbacks.push(callback);
|
|
22509
|
+
return () => {
|
|
22510
|
+
this._syncingChangeCallbacks = this._syncingChangeCallbacks.filter(existingCallback => existingCallback !== callback);
|
|
22511
|
+
};
|
|
22512
|
+
}
|
|
22523
22513
|
/**
|
|
22524
22514
|
* Returns the Yjs UndoManager instance for managing undo/redo operations.
|
|
22525
22515
|
* @returns The UndoManager instance, or `null` if not initialized
|
|
@@ -22613,22 +22603,36 @@ class KritzelObjectMap {
|
|
|
22613
22603
|
const providerList = this._providers.map(p => `${p.constructor.name} (${p.type})`).join(', ');
|
|
22614
22604
|
console.info(`[Kritzel] Workspace sync providers initialized for ${docName}: ${providerList || 'none'}`);
|
|
22615
22605
|
}
|
|
22616
|
-
//
|
|
22617
|
-
|
|
22618
|
-
|
|
22619
|
-
|
|
22606
|
+
// Only network providers (WebSocket, Hocuspocus) represent a genuine remote peer;
|
|
22607
|
+
// local providers (IndexedDB, BroadcastChannel) never appear as a transaction origin here,
|
|
22608
|
+
// so loading from IndexedDB or a same-device tab never toggles isSyncing.
|
|
22609
|
+
this._networkTransactionOrigins = new Set(this._providers
|
|
22610
|
+
.filter(p => p.type === 'network')
|
|
22611
|
+
.map(p => p.rawProvider)
|
|
22612
|
+
.filter((origin) => origin != null));
|
|
22613
|
+
// Fires before a remote-origin transaction integrates its update, so this always
|
|
22614
|
+
// precedes any local/remote reconciliation for that update.
|
|
22615
|
+
this._beforeTransactionHandler = transaction => {
|
|
22616
|
+
if (this._isSyncing || !this._networkTransactionOrigins.has(transaction.origin)) {
|
|
22617
|
+
return;
|
|
22620
22618
|
}
|
|
22621
|
-
|
|
22622
|
-
|
|
22623
|
-
|
|
22619
|
+
this._isSyncing = true;
|
|
22620
|
+
this._syncingChangeCallbacks.forEach(callback => callback(true));
|
|
22621
|
+
};
|
|
22622
|
+
// Fires once a batch of transactions (possibly several remote updates) has fully settled.
|
|
22623
|
+
this._afterAllTransactionsHandler = (_doc, transactions) => {
|
|
22624
|
+
if (!this._isSyncing) {
|
|
22624
22625
|
return;
|
|
22625
22626
|
}
|
|
22626
|
-
|
|
22627
|
-
|
|
22628
|
-
|
|
22627
|
+
const hadRemoteTransaction = transactions.some(transaction => this._networkTransactionOrigins.has(transaction.origin));
|
|
22628
|
+
if (!hadRemoteTransaction) {
|
|
22629
|
+
return;
|
|
22629
22630
|
}
|
|
22631
|
+
this._isSyncing = false;
|
|
22632
|
+
this._syncingChangeCallbacks.forEach(callback => callback(false));
|
|
22630
22633
|
};
|
|
22631
|
-
this._ydoc.on('
|
|
22634
|
+
this._ydoc.on('beforeTransaction', this._beforeTransactionHandler);
|
|
22635
|
+
this._ydoc.on('afterAllTransactions', this._afterAllTransactionsHandler);
|
|
22632
22636
|
// captureTimeout is effectively infinite — undo-step boundaries are
|
|
22633
22637
|
// marked explicitly via markUndoBoundary() in insert/remove/reset and
|
|
22634
22638
|
// at stroke/gesture boundaries in the tools. This prevents a single
|
|
@@ -22682,15 +22686,12 @@ class KritzelObjectMap {
|
|
|
22682
22686
|
if (showSyncProviderInfo && networkProviders.length > 0) {
|
|
22683
22687
|
console.info(`[Kritzel] Workspace network providers connecting in background: ${networkProviders.length}`);
|
|
22684
22688
|
}
|
|
22685
|
-
const networkConnectPromises = networkProviders.map(provider => provider
|
|
22686
|
-
.connect()
|
|
22687
|
-
.then(() => provider.whenSynced?.())
|
|
22688
|
-
.catch(err => {
|
|
22689
|
+
const networkConnectPromises = networkProviders.map(provider => provider.connect().catch(err => {
|
|
22689
22690
|
if (showSyncProviderInfo) {
|
|
22690
22691
|
console.error(`[Kritzel] Network sync provider "${provider.constructor.name}" failed to connect:`, err);
|
|
22691
22692
|
}
|
|
22692
22693
|
}));
|
|
22693
|
-
//
|
|
22694
|
+
// Network sync awaited by loading overlay to show remote workspace hydration
|
|
22694
22695
|
this._networkSyncPromise = networkConnectPromises.length > 0 ? Promise.allSettled(networkConnectPromises).then(() => undefined) : null;
|
|
22695
22696
|
this._isReady = true;
|
|
22696
22697
|
// Find the first provider that exposes awareness (network providers)
|
|
@@ -23348,13 +23349,6 @@ class KritzelObjectMap {
|
|
|
23348
23349
|
this._objectsMap.unobserve(this._objectsObserver);
|
|
23349
23350
|
this._objectsObserver = null;
|
|
23350
23351
|
}
|
|
23351
|
-
if (this._ydoc && this._docUpdateHandler) {
|
|
23352
|
-
this._ydoc.off('update', this._docUpdateHandler);
|
|
23353
|
-
}
|
|
23354
|
-
this._docUpdateHandler = null;
|
|
23355
|
-
this._remoteOrigins.clear();
|
|
23356
|
-
this._remoteChangesCallbacks = [];
|
|
23357
|
-
this._appliedRemoteChanges = false;
|
|
23358
23352
|
// Remove undo manager event listeners
|
|
23359
23353
|
if (this._undoManager) {
|
|
23360
23354
|
if (this._stackItemAddedHandler) {
|
|
@@ -23387,11 +23381,20 @@ class KritzelObjectMap {
|
|
|
23387
23381
|
p.destroy();
|
|
23388
23382
|
});
|
|
23389
23383
|
this._providers = [];
|
|
23384
|
+
this._networkTransactionOrigins = new Set();
|
|
23390
23385
|
// Clear object map references
|
|
23391
23386
|
this._objectsMap = null;
|
|
23392
23387
|
this._metadataMap = null;
|
|
23393
23388
|
// Destroy Y.Doc
|
|
23394
23389
|
if (this._ydoc) {
|
|
23390
|
+
if (this._beforeTransactionHandler) {
|
|
23391
|
+
this._ydoc.off('beforeTransaction', this._beforeTransactionHandler);
|
|
23392
|
+
this._beforeTransactionHandler = null;
|
|
23393
|
+
}
|
|
23394
|
+
if (this._afterAllTransactionsHandler) {
|
|
23395
|
+
this._ydoc.off('afterAllTransactions', this._afterAllTransactionsHandler);
|
|
23396
|
+
this._afterAllTransactionsHandler = null;
|
|
23397
|
+
}
|
|
23395
23398
|
this._ydoc.destroy();
|
|
23396
23399
|
this._ydoc = null;
|
|
23397
23400
|
}
|
|
@@ -23401,6 +23404,8 @@ class KritzelObjectMap {
|
|
|
23401
23404
|
this._workspaceId = null;
|
|
23402
23405
|
this._isReady = false;
|
|
23403
23406
|
this._temporaryItemsCount = 0;
|
|
23407
|
+
this._isSyncing = false;
|
|
23408
|
+
this._syncingChangeCallbacks = [];
|
|
23404
23409
|
}
|
|
23405
23410
|
}
|
|
23406
23411
|
|
|
@@ -23850,10 +23855,7 @@ class KritzelAppStateMap {
|
|
|
23850
23855
|
if (showSyncProviderInfo && networkProviders.length > 0) {
|
|
23851
23856
|
console.info(`[Kritzel] App-state network providers connecting in background: ${networkProviders.length}`);
|
|
23852
23857
|
}
|
|
23853
|
-
const networkConnectPromises = networkProviders.map(provider => provider
|
|
23854
|
-
.connect()
|
|
23855
|
-
.then(() => provider.whenSynced?.())
|
|
23856
|
-
.catch(err => {
|
|
23858
|
+
const networkConnectPromises = networkProviders.map(provider => provider.connect().catch(err => {
|
|
23857
23859
|
if (showSyncProviderInfo) {
|
|
23858
23860
|
console.error(`[Kritzel] Network sync provider "${provider.constructor.name}" failed to connect:`, err);
|
|
23859
23861
|
}
|
|
@@ -25254,6 +25256,10 @@ class KritzelCore {
|
|
|
25254
25256
|
objectsMap.onAwarenessChange(states => {
|
|
25255
25257
|
this.engine.emitAwarenessChange(states);
|
|
25256
25258
|
});
|
|
25259
|
+
// Forward remote sync start/finish to the engine as events
|
|
25260
|
+
objectsMap.onSyncingChange(isSyncing => {
|
|
25261
|
+
this.engine.emitIsSyncing(isSyncing);
|
|
25262
|
+
});
|
|
25257
25263
|
// Rebuild anchor index after loading objects
|
|
25258
25264
|
this._anchorManager.rebuildIndex();
|
|
25259
25265
|
this.engine.emitObjectsChange();
|
|
@@ -27951,16 +27957,15 @@ const KritzelEngine = class {
|
|
|
27951
27957
|
viewportChange;
|
|
27952
27958
|
/** Emitted when the awareness state changes (remote user cursors, presence). */
|
|
27953
27959
|
awarenessChange;
|
|
27960
|
+
/** Emitted when a remote sync starts (`true`, data differs from the local copy) or finishes (`false`). */
|
|
27961
|
+
isSyncing;
|
|
27954
27962
|
/** Emitted when notifications change. */
|
|
27955
27963
|
notificationsChange;
|
|
27956
27964
|
/** Emitted when context-menu visibility, items, or position changes. */
|
|
27957
27965
|
contextMenuStateChange;
|
|
27958
27966
|
/** Emitted when the combined loading state (external `isLoading` prop or internal workspace loading) changes. */
|
|
27959
27967
|
loadingChange;
|
|
27960
|
-
/** Emitted while remote changes are being applied to the active workspace. Stays silent when the remote holds nothing new. */
|
|
27961
|
-
syncingChange;
|
|
27962
27968
|
forceUpdate = 0;
|
|
27963
|
-
isSyncing = false;
|
|
27964
27969
|
/** Manually triggers the `objectsSelectionChange` event. */
|
|
27965
27970
|
async triggerSelectionChange() {
|
|
27966
27971
|
this.objectsSelectionChange.emit();
|
|
@@ -29544,7 +29549,6 @@ const KritzelEngine = class {
|
|
|
29544
29549
|
_sceneBootstrapOpacity = 1;
|
|
29545
29550
|
_sceneBootstrapTransitionEnabled = false;
|
|
29546
29551
|
_sceneBootstrapTransitionTimer = null;
|
|
29547
|
-
_remoteChangesUnsubscribe = null;
|
|
29548
29552
|
_defaultUndoState = {
|
|
29549
29553
|
canUndo: false,
|
|
29550
29554
|
canRedo: false,
|
|
@@ -29561,17 +29565,6 @@ const KritzelEngine = class {
|
|
|
29561
29565
|
this.core.store.state.isLoading = this._isWorkspaceLoading || this.isLoading;
|
|
29562
29566
|
this.loadingChange.emit(this.core.store.state.isLoading);
|
|
29563
29567
|
}
|
|
29564
|
-
syncSyncingState(isSyncing) {
|
|
29565
|
-
if (this.isSyncing === isSyncing) {
|
|
29566
|
-
return;
|
|
29567
|
-
}
|
|
29568
|
-
this.isSyncing = isSyncing;
|
|
29569
|
-
this.syncingChange.emit(isSyncing);
|
|
29570
|
-
}
|
|
29571
|
-
clearRemoteChangesSubscription() {
|
|
29572
|
-
this._remoteChangesUnsubscribe?.();
|
|
29573
|
-
this._remoteChangesUnsubscribe = null;
|
|
29574
|
-
}
|
|
29575
29568
|
isNetworkAvailable() {
|
|
29576
29569
|
return typeof navigator !== 'undefined' && navigator.onLine;
|
|
29577
29570
|
}
|
|
@@ -29674,16 +29667,15 @@ const KritzelEngine = class {
|
|
|
29674
29667
|
this.objectsInViewportChange = index.createEvent(this, "objectsInViewportChange");
|
|
29675
29668
|
this.viewportChange = index.createEvent(this, "viewportChange");
|
|
29676
29669
|
this.awarenessChange = index.createEvent(this, "awarenessChange");
|
|
29670
|
+
this.isSyncing = index.createEvent(this, "isSyncing");
|
|
29677
29671
|
this.notificationsChange = index.createEvent(this, "notificationsChange");
|
|
29678
29672
|
this.contextMenuStateChange = index.createEvent(this, "contextMenuStateChange");
|
|
29679
29673
|
this.loadingChange = index.createEvent(this, "loadingChange");
|
|
29680
|
-
this.syncingChange = index.createEvent(this, "syncingChange");
|
|
29681
29674
|
this.core = new KritzelCore(this);
|
|
29682
29675
|
}
|
|
29683
29676
|
disconnectedCallback() {
|
|
29684
29677
|
this.throttledPointerMoveMulti.cancel();
|
|
29685
29678
|
this._revealedImageKeys.clear();
|
|
29686
|
-
this.clearRemoteChangesSubscription();
|
|
29687
29679
|
if (this._sceneBootstrapTransitionTimer !== null) {
|
|
29688
29680
|
clearTimeout(this._sceneBootstrapTransitionTimer);
|
|
29689
29681
|
this._sceneBootstrapTransitionTimer = null;
|
|
@@ -29938,7 +29930,6 @@ const KritzelEngine = class {
|
|
|
29938
29930
|
this._workspaceInitializationTargetKey = targetKey;
|
|
29939
29931
|
try {
|
|
29940
29932
|
await initializationPromise;
|
|
29941
|
-
this.trackRemoteSynchronization();
|
|
29942
29933
|
}
|
|
29943
29934
|
finally {
|
|
29944
29935
|
// Only the most recent init clears loading state to prevent race conditions
|
|
@@ -29950,45 +29941,6 @@ const KritzelEngine = class {
|
|
|
29950
29941
|
}
|
|
29951
29942
|
}
|
|
29952
29943
|
}
|
|
29953
|
-
/**
|
|
29954
|
-
* Reports syncing only while remote data is actually being reconciled into the
|
|
29955
|
-
* active workspace. Yjs suppresses updates that carry nothing new, so a workspace
|
|
29956
|
-
* that already matches the remote never reports syncing at all.
|
|
29957
|
-
*/
|
|
29958
|
-
trackRemoteSynchronization() {
|
|
29959
|
-
this.clearRemoteChangesSubscription();
|
|
29960
|
-
this.syncSyncingState(false);
|
|
29961
|
-
const initializedObjects = this.core.store.objects;
|
|
29962
|
-
if (!initializedObjects?.hasNetworkSyncProvider || !this.isNetworkAvailable()) {
|
|
29963
|
-
return;
|
|
29964
|
-
}
|
|
29965
|
-
if (initializedObjects.supportsRemoteChangeDetection) {
|
|
29966
|
-
this._remoteChangesUnsubscribe = initializedObjects.onRemoteChangesApplied(() => {
|
|
29967
|
-
if (this.core.store.objects !== initializedObjects) {
|
|
29968
|
-
return;
|
|
29969
|
-
}
|
|
29970
|
-
this.syncSyncingState(true);
|
|
29971
|
-
});
|
|
29972
|
-
// The network provider may have already applied remote changes between
|
|
29973
|
-
// object-map initialization and this subscription (e.g. an already-connected
|
|
29974
|
-
// shared socket resolves the sync handshake almost immediately). Without this
|
|
29975
|
-
// check that update is missed entirely and the indicator never appears.
|
|
29976
|
-
if (initializedObjects.hasAppliedRemoteChanges) {
|
|
29977
|
-
this.syncSyncingState(true);
|
|
29978
|
-
}
|
|
29979
|
-
}
|
|
29980
|
-
else {
|
|
29981
|
-
// Custom providers without an update origin cannot be diffed, so fall back to reporting the whole handshake.
|
|
29982
|
-
this.syncSyncingState(true);
|
|
29983
|
-
}
|
|
29984
|
-
void initializedObjects.whenNetworkSynced().finally(() => {
|
|
29985
|
-
if (this.core.store.objects !== initializedObjects) {
|
|
29986
|
-
return;
|
|
29987
|
-
}
|
|
29988
|
-
this.clearRemoteChangesSubscription();
|
|
29989
|
-
this.syncSyncingState(false);
|
|
29990
|
-
});
|
|
29991
|
-
}
|
|
29992
29944
|
emitObjectsChange() {
|
|
29993
29945
|
const objectsMap = this.core.store.objects;
|
|
29994
29946
|
if (!objectsMap) {
|
|
@@ -30022,6 +29974,9 @@ const KritzelEngine = class {
|
|
|
30022
29974
|
emitAwarenessChange(states) {
|
|
30023
29975
|
this.awarenessChange.emit(states);
|
|
30024
29976
|
}
|
|
29977
|
+
emitIsSyncing(isSyncing) {
|
|
29978
|
+
this.isSyncing.emit(isSyncing);
|
|
29979
|
+
}
|
|
30025
29980
|
emitObjectsInViewportChange() {
|
|
30026
29981
|
const visibleObjects = this.core.store.objectsInViewport;
|
|
30027
29982
|
this.objectsInViewportChange.emit(visibleObjects);
|
|
@@ -32133,7 +32088,7 @@ const KritzelPortal = class {
|
|
|
32133
32088
|
* This file is auto-generated by the version bump scripts.
|
|
32134
32089
|
* Do not modify manually.
|
|
32135
32090
|
*/
|
|
32136
|
-
const KRITZEL_VERSION = '0.4.
|
|
32091
|
+
const KRITZEL_VERSION = '0.4.25';
|
|
32137
32092
|
|
|
32138
32093
|
const kritzelSettingsCss = () => `:host{display:contents}kritzel-dialog{--kritzel-dialog-body-padding:0;--kritzel-dialog-width-large:800px;--kritzel-dialog-height-large:500px}.footer-button{padding:8px 16px;border-radius:6px;cursor:pointer;font-size:14px}.cancel-button{border:1px solid #ebebeb;background:#fff;color:inherit}.cancel-button:hover{background:#f5f5f5}.settings-tab-panel{display:none}.settings-tab-panel.is-active{display:block}.settings-content{padding:0}.settings-content h3{margin:0 0 16px 0;font-size:18px;font-weight:600;color:var(--kritzel-settings-content-heading-color, #333333)}.settings-content p{margin:0;font-size:14px;color:var(--kritzel-settings-content-text-color, #666666);line-height:1.5}.settings-group{display:flex;flex-direction:column;gap:24px}.settings-item{display:flex;flex-direction:column;gap:8px}.settings-row{display:flex;align-items:center;justify-content:space-between;gap:16px}.settings-label{font-size:14px;font-weight:600;color:var(--kritzel-settings-label-color, #333333);margin:0 0 4px 0}.settings-description{font-size:12px;color:var(--kritzel-settings-description-color, #888888);margin:0;line-height:1.4}.shortcuts-list{display:flex;flex-direction:column;gap:24px}.shortcuts-category{display:flex;flex-direction:column;gap:8px}.shortcuts-category-title{font-size:14px;font-weight:600;color:var(--kritzel-settings-label-color, #333333);margin:0 0 4px 0}.shortcuts-group{display:flex;flex-direction:column;gap:4px}.shortcut-item{display:flex;justify-content:space-between;align-items:center;padding:6px 8px;border-radius:4px;background:var(--kritzel-settings-shortcut-item-bg, rgba(0, 0, 0, 0.02))}.shortcut-label{font-size:14px;color:var(--kritzel-settings-content-text-color, #666666)}.shortcut-key{font-family:monospace;font-size:12px;padding:2px 8px;border-radius:4px;background:var(--kritzel-settings-shortcut-key-bg, #f0f0f0);color:var(--kritzel-settings-shortcut-key-color, #333333);border:1px solid var(--kritzel-settings-shortcut-key-border, #ddd)}`;
|
|
32139
32094
|
|