kritzel-stencil 0.3.17 → 0.3.19
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-Xav9JFHg.js +2 -2
- package/dist/cjs/index.cjs.js +1 -1
- package/dist/cjs/{kritzel-active-users_44.cjs.entry.js → kritzel-active-users_45.cjs.entry.js} +739 -310
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/{schema.constants-DrHO_CYF.js → schema.constants-IBG5VW_J.js} +116 -59
- package/dist/cjs/stencil.cjs.js +1 -1
- package/dist/collection/classes/core/core.class.js +22 -210
- package/dist/collection/classes/handlers/key.handler.js +1 -22
- package/dist/collection/classes/managers/browser-permission.manager.js +64 -0
- package/dist/collection/classes/managers/clipboard.manager.js +401 -0
- package/dist/collection/classes/objects/image.class.js +42 -0
- package/dist/collection/classes/tools/image-tool.class.js +1 -59
- package/dist/collection/collection-manifest.json +1 -0
- package/dist/collection/components/core/kritzel-editor/kritzel-editor.css +53 -0
- package/dist/collection/components/core/kritzel-editor/kritzel-editor.js +133 -53
- package/dist/collection/components/core/kritzel-engine/kritzel-engine.js +101 -43
- package/dist/collection/components/core/kritzel-watermark/kritzel-watermark.js +1 -1
- package/dist/collection/components/shared/kritzel-avatar/kritzel-avatar.js +3 -3
- package/dist/collection/components/shared/kritzel-button/kritzel-button.js +2 -2
- package/dist/collection/components/shared/kritzel-color/kritzel-color.js +2 -2
- package/dist/collection/components/shared/kritzel-color-palette/kritzel-color-palette.js +1 -1
- package/dist/collection/components/shared/kritzel-font/kritzel-font.js +1 -1
- package/dist/collection/components/shared/kritzel-font-size/kritzel-font-size.js +1 -1
- package/dist/collection/components/shared/kritzel-input/kritzel-input.js +1 -1
- package/dist/collection/components/shared/kritzel-master-detail/kritzel-master-detail.js +3 -3
- package/dist/collection/components/shared/kritzel-menu/kritzel-menu.js +1 -1
- package/dist/collection/components/shared/kritzel-menu-item/kritzel-menu-item.js +2 -2
- package/dist/collection/components/shared/kritzel-numeric-input/kritzel-numeric-input.js +1 -1
- package/dist/collection/components/shared/kritzel-opacity-slider/kritzel-opacity-slider.js +1 -1
- package/dist/collection/components/shared/kritzel-portal/kritzel-portal.js +1 -1
- package/dist/collection/components/shared/kritzel-slide-toggle/kritzel-slide-toggle.js +1 -1
- package/dist/collection/components/shared/kritzel-split-button/kritzel-split-button.js +1 -1
- package/dist/collection/components/shared/kritzel-stroke-size/kritzel-stroke-size.js +1 -1
- package/dist/collection/components/shared/kritzel-tooltip/kritzel-tooltip.js +2 -2
- package/dist/collection/components/ui/kritzel-back-to-content/kritzel-back-to-content.js +1 -1
- package/dist/collection/components/ui/kritzel-controls/kritzel-controls.js +6 -6
- package/dist/collection/components/ui/kritzel-current-user/kritzel-current-user.js +1 -1
- package/dist/collection/components/ui/kritzel-current-user-dialog/kritzel-current-user-dialog.js +1 -1
- package/dist/collection/components/ui/kritzel-export/kritzel-export.js +1 -1
- package/dist/collection/components/ui/kritzel-login-dialog/kritzel-login-dialog.js +1 -1
- package/dist/collection/components/ui/kritzel-more-menu/kritzel-more-menu.js +1 -1
- package/dist/collection/components/ui/kritzel-notification-card/kritzel-notification-card.css +101 -0
- package/dist/collection/components/ui/kritzel-notification-card/kritzel-notification-card.js +173 -0
- package/dist/collection/components/ui/kritzel-settings/kritzel-settings.js +1 -1
- package/dist/collection/components/ui/kritzel-share-dialog/kritzel-share-dialog.js +2 -2
- package/dist/collection/components/ui/kritzel-utility-panel/kritzel-utility-panel.js +1 -1
- package/dist/collection/components/ui/kritzel-zoom-panel/kritzel-zoom-panel.js +1 -1
- package/dist/collection/configs/default-engine-config.js +0 -1
- package/dist/collection/constants/version.js +1 -1
- package/dist/collection/interfaces/notification.interface.js +1 -0
- package/dist/collection/themes/dark-theme.js +36 -0
- package/dist/collection/themes/light-theme.js +36 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.js +1 -1
- package/dist/components/kritzel-active-users.js +1 -1
- package/dist/components/kritzel-avatar.js +1 -1
- package/dist/components/kritzel-awareness-cursors.js +1 -1
- package/dist/components/kritzel-back-to-content.js +1 -1
- package/dist/components/kritzel-button.js +1 -1
- package/dist/components/kritzel-color-palette.js +1 -1
- package/dist/components/kritzel-color.js +1 -1
- package/dist/components/kritzel-controls.js +1 -1
- package/dist/components/kritzel-current-user-dialog.js +1 -1
- package/dist/components/kritzel-current-user.js +1 -1
- package/dist/components/kritzel-editor.js +1 -1
- package/dist/components/kritzel-engine.js +1 -1
- package/dist/components/kritzel-export.js +1 -1
- package/dist/components/kritzel-font-size.js +1 -1
- package/dist/components/kritzel-font.js +1 -1
- package/dist/components/kritzel-input.js +1 -1
- package/dist/components/kritzel-login-dialog.js +1 -1
- package/dist/components/kritzel-master-detail.js +1 -1
- package/dist/components/kritzel-menu-item.js +1 -1
- package/dist/components/kritzel-menu.js +1 -1
- package/dist/components/kritzel-more-menu.js +1 -1
- package/dist/components/kritzel-notification-card.d.ts +11 -0
- package/dist/components/kritzel-notification-card.js +1 -0
- package/dist/components/kritzel-numeric-input.js +1 -1
- package/dist/components/kritzel-opacity-slider.js +1 -1
- package/dist/components/kritzel-portal.js +1 -1
- package/dist/components/kritzel-settings.js +1 -1
- package/dist/components/kritzel-share-dialog.js +1 -1
- package/dist/components/kritzel-slide-toggle.js +1 -1
- package/dist/components/kritzel-split-button.js +1 -1
- package/dist/components/kritzel-stroke-size.js +1 -1
- package/dist/components/kritzel-tool-config.js +1 -1
- package/dist/components/kritzel-tooltip.js +1 -1
- package/dist/components/kritzel-utility-panel.js +1 -1
- package/dist/components/kritzel-watermark.js +1 -1
- package/dist/components/kritzel-workspace-manager.js +1 -1
- package/dist/components/kritzel-zoom-panel.js +1 -1
- package/dist/components/{p-BvRrA4hN.js → p-6Ca7Eolf.js} +1 -1
- package/dist/components/{p-BpnIvNvq.js → p-BO1CnEOT.js} +1 -1
- package/dist/components/{p-CyqRcqsO.js → p-BPoDE87Q.js} +1 -1
- package/dist/components/p-BX-nQAyH.js +1 -0
- package/dist/components/{p-DNdXJp8F.js → p-Bg0xIZiR.js} +1 -1
- package/dist/components/{p-DmWSRsjK.js → p-BhODnvMO.js} +1 -1
- package/dist/components/{p-3HxnBrCM.js → p-BrAeYciD.js} +1 -1
- package/dist/components/{p-f8aW1ye7.js → p-BwuemYET.js} +1 -1
- package/dist/components/{p-U4oawa1x.js → p-C-RiEw9X.js} +1 -1
- package/dist/components/{p-DdsSSqFY.js → p-C-Zrxv7T.js} +1 -1
- package/dist/components/{p-DdH1cKED.js → p-C1jg5IQi.js} +1 -1
- package/dist/components/{p-SDZNC8GF.js → p-C4-Som48.js} +1 -1
- package/dist/components/{p-C9HGoDHE.js → p-C5TZjIE1.js} +1 -1
- package/dist/components/{p-7NsK0uHu.js → p-CC0J_kEP.js} +1 -1
- package/dist/components/{p-CIcLzcfA.js → p-CJEIUs0x.js} +1 -1
- package/dist/components/{p-Bzv9Px8v.js → p-CO0eEzos.js} +1 -1
- package/dist/components/{p-DDkmsPpV.js → p-COdwK_mi.js} +1 -1
- package/dist/components/{p-CPtDfadX.js → p-COj8EVzL.js} +1 -1
- package/dist/components/{p-CEnEDaix.js → p-CVV-HzFR.js} +1 -1
- package/dist/components/{p-6RjeGuvH.js → p-Cb5YwXbC.js} +1 -1
- package/dist/components/{p-DX5K8xnh.js → p-CbMLbDou.js} +1 -1
- package/dist/components/{p-DZdgXCAx.js → p-CdkNxxut.js} +1 -1
- package/dist/components/{p-BKJSh8qQ.js → p-CpR9lc-o.js} +1 -1
- package/dist/components/p-CpzicliK.js +1 -0
- package/dist/components/{p-IpoC5EEY.js → p-D0RYktBV.js} +1 -1
- package/dist/components/{p-DI4vQRE3.js → p-D0v9WP5w.js} +1 -1
- package/dist/components/{p-DgmtCdnL.js → p-D28ZylHn.js} +1 -1
- package/dist/components/{p-F5_X4dZG.js → p-DEpnJBA3.js} +1 -1
- package/dist/components/{p-BCNyR5Sw.js → p-DRsD38Nl.js} +1 -1
- package/dist/components/p-DWhWFDcC.js +9 -0
- package/dist/components/{p-Dz-Ti24X.js → p-DeqALrzV.js} +1 -1
- package/dist/components/{p-BKvHg9cv.js → p-Ndib1Jb3.js} +1 -1
- package/dist/components/{p-vAeiXe6c.js → p-NwN6r0N0.js} +1 -1
- package/dist/components/{p-NuLP1xHe.js → p-W1ZwImdd.js} +1 -1
- package/dist/components/{p-Jn6TNdfe.js → p-YFR180v-.js} +1 -1
- package/dist/components/p-pagW8YF7.js +1 -0
- package/dist/components/{p-v7dxxrL5.js → p-vf28uSsc.js} +1 -1
- package/dist/esm/index-Dhio9uis.js +2 -2
- package/dist/esm/index.js +2 -2
- package/dist/esm/{kritzel-active-users_44.entry.js → kritzel-active-users_45.entry.js} +739 -311
- package/dist/esm/loader.js +1 -1
- package/dist/esm/{schema.constants-DchTXG3V.js → schema.constants-D35cwCYd.js} +116 -60
- package/dist/esm/stencil.js +1 -1
- package/dist/stencil/index.esm.js +1 -1
- package/dist/stencil/p-207942fe.entry.js +9 -0
- package/dist/stencil/p-D35cwCYd.js +1 -0
- package/dist/stencil/stencil.esm.js +1 -1
- package/dist/types/classes/core/core.class.d.ts +16 -19
- package/dist/types/classes/handlers/key.handler.d.ts +1 -1
- package/dist/types/classes/managers/browser-permission.manager.d.ts +41 -0
- package/dist/types/classes/managers/clipboard.manager.d.ts +86 -0
- package/dist/types/classes/objects/image.class.d.ts +10 -0
- package/dist/types/classes/tools/image-tool.class.d.ts +0 -14
- package/dist/types/components/core/kritzel-editor/kritzel-editor.d.ts +20 -1
- package/dist/types/components/core/kritzel-engine/kritzel-engine.d.ts +8 -4
- package/dist/types/components/ui/kritzel-notification-card/kritzel-notification-card.d.ts +22 -0
- package/dist/types/components.d.ts +83 -9
- package/dist/types/constants/version.d.ts +1 -1
- package/dist/types/interfaces/engine-state.interface.d.ts +0 -3
- package/dist/types/interfaces/notification.interface.d.ts +10 -0
- package/dist/types/interfaces/theme.interface.d.ts +43 -0
- package/package.json +2 -2
- package/dist/components/p-Bc55X65h.js +0 -1
- package/dist/components/p-C_fKgKHu.js +0 -9
- package/dist/components/p-Cu9KYyoq.js +0 -1
- package/dist/stencil/p-DchTXG3V.js +0 -1
- package/dist/stencil/p-c9a3807b.entry.js +0 -9
package/dist/cjs/{kritzel-active-users_44.cjs.entry.js → kritzel-active-users_45.cjs.entry.js}
RENAMED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var index = require('./index-Xav9JFHg.js');
|
|
4
|
-
var schema_constants = require('./schema.constants-
|
|
4
|
+
var schema_constants = require('./schema.constants-IBG5VW_J.js');
|
|
5
5
|
var Y = require('yjs');
|
|
6
6
|
require('y-indexeddb');
|
|
7
7
|
require('y-websocket');
|
|
@@ -154,16 +154,16 @@ const KritzelAvatar = class {
|
|
|
154
154
|
height: `${this.size}px`,
|
|
155
155
|
fontSize: `${Math.round(this.size * 0.4)}px`,
|
|
156
156
|
};
|
|
157
|
-
return (index.h(index.Host, { key: '
|
|
157
|
+
return (index.h(index.Host, { key: '4bdbe2c1d5d3a1708189166498ae4e36c19c46ff', style: containerStyles, class: {
|
|
158
158
|
'has-image': !!showImage,
|
|
159
159
|
'has-initials': !!showInitials,
|
|
160
160
|
'has-default': !!showDefaultIcon,
|
|
161
|
-
}, role: "img", "aria-label": this.getDisplayName() || 'User avatar' }, showImage && (index.h("img", { key: '
|
|
161
|
+
}, role: "img", "aria-label": this.getDisplayName() || 'User avatar' }, showImage && (index.h("img", { key: '55c3a13c9d514ea700c6b1a9339cd0dff1828b2b', src: imageUrl, alt: "", class: "avatar-image", ref: (el) => {
|
|
162
162
|
if (el) {
|
|
163
163
|
el.referrerPolicy = 'no-referrer';
|
|
164
164
|
el.crossOrigin = 'anonymous';
|
|
165
165
|
}
|
|
166
|
-
}, onError: this.handleImageError })), showInitials && (index.h("span", { key: '
|
|
166
|
+
}, onError: this.handleImageError })), showInitials && (index.h("span", { key: 'b60cbe2b94ea1d2cd2a09d10c928290fc1469a4a', class: "avatar-initials", style: { backgroundColor: this.getBackgroundColor() } }, initials)), showDefaultIcon && (index.h("span", { key: 'e8a0f49952b5b7e5e4a1fe3d67e68a56081d5e4c', class: "avatar-default" }, index.h("svg", { key: '1fdc256fd53aa5c866bb0e81fdd40393c8a7d69d', viewBox: "0 0 24 24", fill: "currentColor" }, index.h("path", { key: '8f3a5a6775154e46a2f331534fe75671b9ad081a', d: "M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z" }))))));
|
|
167
167
|
}
|
|
168
168
|
static get watchers() { return {
|
|
169
169
|
"user": [{
|
|
@@ -473,7 +473,7 @@ const KritzelBackToContent = class {
|
|
|
473
473
|
this.backToContent.emit();
|
|
474
474
|
};
|
|
475
475
|
render() {
|
|
476
|
-
return (index.h(index.Host, { key: '
|
|
476
|
+
return (index.h(index.Host, { key: 'a7d52616642f45a0c0e7b76deb3cc5994184b968' }, index.h("button", { key: '9e7acae2b62f7f66ee0127545ee8ab115f9d340e', class: { 'back-to-content-button': true, visible: this.visible }, onClick: this.handleClick, "aria-label": this.text }, index.h("kritzel-icon", { key: '6c404376643554cdb86c33957c066dd4580f19f1', name: "chevrons-left" }))));
|
|
477
477
|
}
|
|
478
478
|
};
|
|
479
479
|
KritzelBackToContent.style = kritzelBackToContentCss();
|
|
@@ -500,11 +500,11 @@ const KritzelButton = class {
|
|
|
500
500
|
this.buttonClick.emit();
|
|
501
501
|
};
|
|
502
502
|
render() {
|
|
503
|
-
return (index.h(index.Host, { key: '
|
|
503
|
+
return (index.h(index.Host, { key: '0de2b5dcf75de9f5b7de0c6b876bd18733bf21b9' }, index.h("button", { key: '5ab9d80167c6b90add7779d4b1c3ebb80fafaed5', type: this.type, class: {
|
|
504
504
|
'kritzel-button': true,
|
|
505
505
|
[this.variant]: true,
|
|
506
506
|
'disabled': this.disabled,
|
|
507
|
-
}, disabled: this.disabled, onClick: this.handleClick }, index.h("slot", { key: '
|
|
507
|
+
}, disabled: this.disabled, onClick: this.handleClick }, index.h("slot", { key: 'dc105f7d1f87aa55c314d942a1cc6522b272526a' }))));
|
|
508
508
|
}
|
|
509
509
|
};
|
|
510
510
|
KritzelButton.style = kritzelButtonCss();
|
|
@@ -552,13 +552,13 @@ const KritzelColorComponent = class {
|
|
|
552
552
|
render() {
|
|
553
553
|
const resolvedColor = this.resolveColor();
|
|
554
554
|
const isColorVeryLight = this.isLightColor(resolvedColor);
|
|
555
|
-
return (index.h(index.Host, { key: '
|
|
555
|
+
return (index.h(index.Host, { key: '0d56c7ad01eddd523ebcf11a32e68367c96090bd' }, index.h("div", { key: '0bef4cb73804b98e6eea6b3cf006c19c8786bdb9', class: "checkerboard-bg", style: {
|
|
556
556
|
width: `${this.size}px`,
|
|
557
557
|
height: `${this.size}px`,
|
|
558
558
|
borderRadius: '50%',
|
|
559
559
|
display: 'inline-block',
|
|
560
560
|
position: 'relative',
|
|
561
|
-
} }, index.h("div", { key: '
|
|
561
|
+
} }, index.h("div", { key: '5be9714c3ddd56ae77c2870333ff97a59b58bd45', class: {
|
|
562
562
|
'color-circle': true,
|
|
563
563
|
'white': isColorVeryLight,
|
|
564
564
|
}, style: {
|
|
@@ -614,7 +614,7 @@ const KritzelColorPalette = class {
|
|
|
614
614
|
render() {
|
|
615
615
|
const displayedColors = this.isExpanded ? this.colors : this.colors.slice(0, 6);
|
|
616
616
|
const expandedHeight = this.isExpanded ? this.calculateHeight() : '32px';
|
|
617
|
-
return (index.h(index.Host, { key: '
|
|
617
|
+
return (index.h(index.Host, { key: '6d003ec5b92f586532782144c25ca5a733741f20' }, index.h("div", { key: '031838b45da4916aa91d87c066ac950cfe3a1ddc', class: {
|
|
618
618
|
'color-grid': true,
|
|
619
619
|
'expanded': this.isExpanded,
|
|
620
620
|
}, style: {
|
|
@@ -1182,13 +1182,13 @@ const KritzelControls = class {
|
|
|
1182
1182
|
// Separate tool controls from config control
|
|
1183
1183
|
const toolControls = this.internalControls.filter(c => c.type === 'tool' || c.type === 'separator');
|
|
1184
1184
|
const configControl = this.internalControls.find(c => c.type === 'config' && c.name === this.firstConfig?.name);
|
|
1185
|
-
return (index.h(index.Host, { key: '
|
|
1185
|
+
return (index.h(index.Host, { key: '266e38cdeffb8c22a7f778e865e5fab6b461f5b6', style: { display: this.visible ? '' : 'none' }, class: {
|
|
1186
1186
|
mobile: this.isTouchDevice,
|
|
1187
|
-
} }, this.isUtilityPanelVisible && (index.h("kritzel-utility-panel", { key: '
|
|
1187
|
+
} }, this.isUtilityPanelVisible && (index.h("kritzel-utility-panel", { key: '5e75ece000ac02675d3d226461b7f522dcf5ead9', style: {
|
|
1188
1188
|
position: 'absolute',
|
|
1189
1189
|
bottom: '56px',
|
|
1190
1190
|
left: '12px',
|
|
1191
|
-
}, undoState: this.undoState, terms: this.terms, onUndo: () => this.kritzelEngine?.undo(), onRedo: () => this.kritzelEngine?.redo(), onDelete: () => this.kritzelEngine?.delete() })), index.h("div", { key: '
|
|
1191
|
+
}, undoState: this.undoState, terms: this.terms, onUndo: () => this.kritzelEngine?.undo(), onRedo: () => this.kritzelEngine?.redo(), onDelete: () => this.kritzelEngine?.delete() })), index.h("div", { key: 'fc98b1675afe1abb6a8d391c4ace34c7f0e46677', class: "kritzel-controls" }, index.h("div", { key: 'b17bc9e9a65646735c56f78a326a281229fa9790', class: { 'scroll-indicator-left': true, 'visible': this.canScrollLeft } }), index.h("div", { key: '9ab9d5c44e515551d75f27c31875de72e9d3407c', class: "kritzel-tools-scroll", ref: el => (this.toolsScrollRef = el), onScroll: this.handleToolsScroll }, toolControls.map(control => {
|
|
1192
1192
|
// Check if this control has sub-options (split-button)
|
|
1193
1193
|
if (control.subOptions?.length) {
|
|
1194
1194
|
const selectedSubOption = this.getSelectedSubOption(control);
|
|
@@ -1218,10 +1218,10 @@ const KritzelControls = class {
|
|
|
1218
1218
|
'kritzel-control': true,
|
|
1219
1219
|
'selected': this.activeControl?.name === control?.name,
|
|
1220
1220
|
}, key: control.name, "data-testid": `tool-${control.name}`, onClick: _event => this.handleControlClick?.(control), "aria-label": control.name.charAt(0).toUpperCase() + control.name.slice(1) }, index.h("kritzel-icon", { name: control.icon })));
|
|
1221
|
-
})), index.h("div", { key: '
|
|
1221
|
+
})), index.h("div", { key: 'fad7512f5d1aa68905a56b8f22d498380f166f9f', class: { 'scroll-indicator-right': true, 'visible': this.canScrollRight && !(configControl && this.activeControl && hasConfigUI) } }), configControl && this.activeControl && (index.h("div", { class: {
|
|
1222
1222
|
'kritzel-config-container': true,
|
|
1223
1223
|
'visible': hasConfigUI,
|
|
1224
|
-
}, key: configControl.name }, index.h("div", { key: '
|
|
1224
|
+
}, key: configControl.name }, index.h("div", { key: '2ff7cb3ad18608102f3d8188b5936cf00b00451f', class: { 'config-gradient-left': true, 'visible': this.needsScrolling } }), index.h("kritzel-tooltip", { key: '10f15f717c8573cbad6ea53b412ad56254099ad1', anchorElement: this.host.shadowRoot?.querySelector('.kritzel-config-container'), triggerElement: this.configTriggerRef }, index.h("kritzel-tool-config", { key: 'a1b0ed8ecc2696a591e32add642a3d5cb2bf7f4a', tool: this.activeControl.tool, theme: this.theme, engine: this.kritzelEngine, terms: this.terms, onToolChange: event => this.handleToolChange?.(event), onDisplayValuesChange: this.handleDisplayValuesChange, style: { width: '100%', height: '100%' } })), index.h("div", { key: '7ac8214a3dbad5323a38cad3ff7324b57f9dbfb5', tabIndex: hasConfigUI ? 0 : -1, class: "kritzel-config", "data-testid": "tool-config", ref: el => {
|
|
1225
1225
|
if (el)
|
|
1226
1226
|
this.configTriggerRef = el;
|
|
1227
1227
|
}, onKeyDown: event => {
|
|
@@ -1230,7 +1230,7 @@ const KritzelControls = class {
|
|
|
1230
1230
|
}
|
|
1231
1231
|
}, style: {
|
|
1232
1232
|
cursor: 'pointer',
|
|
1233
|
-
} }, this.displayValues && (index.h("div", { key: '
|
|
1233
|
+
} }, this.displayValues && (index.h("div", { key: '7e64f79859f7f2b03d72bb7a93fb295e7d2b2ac0', class: "color-container" }, index.h("kritzel-color", { key: 'b87d9861949379d84954ef1ecb554e13317b3287', value: this.displayValues.color, theme: this.theme, size: 18, style: {
|
|
1234
1234
|
borderRadius: '50%',
|
|
1235
1235
|
border: 'none',
|
|
1236
1236
|
} })))))))));
|
|
@@ -1270,7 +1270,7 @@ const KritzelCurrentUser = class {
|
|
|
1270
1270
|
this.dialogRef?.open();
|
|
1271
1271
|
};
|
|
1272
1272
|
render() {
|
|
1273
|
-
return (index.h(index.Host, { key: '
|
|
1273
|
+
return (index.h(index.Host, { key: 'bdee6b71c08d6ea22aec40e88ba56077882b301d' }, index.h("kritzel-avatar", { key: '97bcaaa6b683c0d26d547ac5cbd9df7814f0cd80', user: this.user, size: this.avatarSize, onClick: this.handleAvatarClick }), index.h("kritzel-current-user-dialog", { key: 'c984ea1803bcf2b06569fd66d12e4e7054235225', ref: el => (this.dialogRef = el), user: this.user, terms: this.terms })));
|
|
1274
1274
|
}
|
|
1275
1275
|
};
|
|
1276
1276
|
KritzelCurrentUser.style = kritzelCurrentUserCss();
|
|
@@ -1304,7 +1304,7 @@ const KritzelCurrentUserDialog = class {
|
|
|
1304
1304
|
}
|
|
1305
1305
|
render() {
|
|
1306
1306
|
const displayName = this.getDisplayName();
|
|
1307
|
-
return (index.h(index.Host, { key: '
|
|
1307
|
+
return (index.h(index.Host, { key: '042455d68a432e0e218d5b8750fb1d22b0d202fc' }, index.h("kritzel-dialog", { key: '058abbc8e1c38c647cc02e85c272e89693cab22a', dialogTitle: this.terms['currentUser.dialogTitle'] ?? 'Account', isOpen: this.isDialogOpen, onDialogClose: this.closeDialog, size: "small", contained: true }, index.h("div", { key: 'ee141b2e91f093527e2d8f6649bade8e1a14f130', class: "user-info" }, index.h("kritzel-avatar", { key: '2734bb0d3c69df14d26c204eeaf726174afaabc0', user: this.user, size: 80 }), displayName && index.h("div", { key: '56cbad7a51264ebada0cb029e6455aabb9cb4ae9', class: "user-name" }, displayName), this.user?.email && index.h("div", { key: 'ef9075dfdeb52ce6f90bb41d1348fbdf7dbb93ee', class: "user-email" }, this.user.email)))));
|
|
1308
1308
|
}
|
|
1309
1309
|
};
|
|
1310
1310
|
KritzelCurrentUserDialog.style = kritzelCurrentUserDialogCss();
|
|
@@ -2193,7 +2193,7 @@ const DEFAULT_SYNC_CONFIG = {
|
|
|
2193
2193
|
providers: [],
|
|
2194
2194
|
};
|
|
2195
2195
|
|
|
2196
|
-
const kritzelEditorCss = () => `kritzel-editor{display:flex;margin:0;position:relative;container-type:inline-size;overflow:hidden;width:100%;height:100%;align-items:center;justify-content:center;touch-action:manipulation;user-select:none;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;text-align:start;line-height:normal}kritzel-controls{position:absolute;left:0;right:0;margin-inline:auto;width:max-content;max-width:calc(100% - 16px);bottom:var(--kritzel-editor-controls-bottom, 14px);transition:transform var(--kritzel-editor-controls-transition-duration, 0.1s) var(--kritzel-editor-controls-transition, ease-in-out)}kritzel-controls.keyboard-open{transform:var(--kritzel-editor-controls-transform, translateY(300%))}.top-left-buttons{position:absolute;top:var(--kritzel-editor-top-left-buttons-top, 14px);left:var(--kritzel-editor-top-left-buttons-left, 14px);display:flex;align-items:flex-start;gap:8px}.top-right-buttons{position:absolute;top:var(--kritzel-editor-top-right-buttons-top, 14px);right:var(--kritzel-editor-top-right-buttons-right, 14px);display:flex;align-items:center;gap:8px}.bottom-left-buttons{position:absolute;left:var(--kritzel-editor-top-left-buttons-left, 14px);bottom:var(--kritzel-editor-controls-bottom, 14px);display:flex;align-items:flex-end}@container (max-width: 767px){.bottom-left-buttons{display:none}}.top-right-button{display:flex;align-items:center;justify-content:center;width:50px;height:50px;padding:0;border:var(--kritzel-split-button-border, 1px solid #ebebeb);border-radius:var(--kritzel-split-button-border-radius, 12px);background-color:var(--kritzel-split-button-background-color, #ffffff);cursor:var(--kritzel-global-pointer-cursor, pointer);box-shadow:var(--kritzel-split-button-box-shadow, 0 0 3px rgba(0, 0, 0, 0.08));transition:background-color 150ms ease;-webkit-tap-highlight-color:transparent}.top-right-button:hover{background-color:#f5f5f5}.top-right-button:active{background-color:#ebebeb}`;
|
|
2196
|
+
const kritzelEditorCss = () => `kritzel-editor{display:flex;margin:0;position:relative;container-type:inline-size;overflow:hidden;width:100%;height:100%;align-items:center;justify-content:center;touch-action:manipulation;user-select:none;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;text-align:start;line-height:normal}kritzel-controls{position:absolute;left:0;right:0;margin-inline:auto;width:max-content;max-width:calc(100% - 16px);bottom:var(--kritzel-editor-controls-bottom, 14px);transition:transform var(--kritzel-editor-controls-transition-duration, 0.1s) var(--kritzel-editor-controls-transition, ease-in-out)}kritzel-controls.keyboard-open{transform:var(--kritzel-editor-controls-transform, translateY(300%))}.top-left-buttons{position:absolute;top:var(--kritzel-editor-top-left-buttons-top, 14px);left:var(--kritzel-editor-top-left-buttons-left, 14px);display:flex;align-items:flex-start;gap:8px}.top-center-notification-layer{position:absolute;top:var(--kritzel-editor-top-center-notification-top, 14px);left:0;right:0;z-index:var(--kritzel-editor-top-center-notification-z-index, 10001);display:flex;justify-content:center;pointer-events:none}.top-center-notification-container{width:min(90vw, 420px);pointer-events:auto;animation:kritzel-notification-slide-in var(--kritzel-editor-notification-animation-duration, 220ms) var(--kritzel-editor-notification-animation-easing, cubic-bezier(0.22, 1, 0.36, 1))}.top-center-notification-container.is-dismissing{animation:kritzel-notification-fade-out var(--kritzel-editor-notification-dismiss-animation-duration, 180ms) var(--kritzel-editor-notification-dismiss-animation-easing, ease-in) forwards}@keyframes kritzel-notification-slide-in{from{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}@keyframes kritzel-notification-fade-out{from{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(-6px)}}@media (prefers-reduced-motion: reduce){.top-center-notification-container{animation:none}}.top-right-buttons{position:absolute;top:var(--kritzel-editor-top-right-buttons-top, 14px);right:var(--kritzel-editor-top-right-buttons-right, 14px);display:flex;align-items:center;gap:8px}.bottom-left-buttons{position:absolute;left:var(--kritzel-editor-top-left-buttons-left, 14px);bottom:var(--kritzel-editor-controls-bottom, 14px);display:flex;align-items:flex-end}@container (max-width: 767px){.bottom-left-buttons{display:none}}.top-right-button{display:flex;align-items:center;justify-content:center;width:50px;height:50px;padding:0;border:var(--kritzel-split-button-border, 1px solid #ebebeb);border-radius:var(--kritzel-split-button-border-radius, 12px);background-color:var(--kritzel-split-button-background-color, #ffffff);cursor:var(--kritzel-global-pointer-cursor, pointer);box-shadow:var(--kritzel-split-button-box-shadow, 0 0 3px rgba(0, 0, 0, 0.08));transition:background-color 150ms ease;-webkit-tap-highlight-color:transparent}.top-right-button:hover{background-color:#f5f5f5}.top-right-button:active{background-color:#ebebeb}`;
|
|
2197
2197
|
|
|
2198
2198
|
const KritzelEditor = class {
|
|
2199
2199
|
constructor(hostRef) {
|
|
@@ -2291,13 +2291,11 @@ const KritzelEditor = class {
|
|
|
2291
2291
|
{
|
|
2292
2292
|
label: 'menu.paste',
|
|
2293
2293
|
icon: 'paste',
|
|
2294
|
-
disabled: async () => (await this.engineRef.getCopiedObjects()).length === 0,
|
|
2295
2294
|
action: menu => this.engineRef.paste(menu.x, menu.y),
|
|
2296
2295
|
},
|
|
2297
2296
|
{
|
|
2298
2297
|
label: 'menu.selectAll',
|
|
2299
2298
|
icon: 'select-all',
|
|
2300
|
-
disabled: async () => (await this.engineRef.getObjectsInViewport()).length === 0,
|
|
2301
2299
|
action: () => this.selectAllObjectsInViewport(),
|
|
2302
2300
|
},
|
|
2303
2301
|
];
|
|
@@ -2308,7 +2306,6 @@ const KritzelEditor = class {
|
|
|
2308
2306
|
label: 'menu.paste',
|
|
2309
2307
|
icon: 'paste',
|
|
2310
2308
|
group: 'clipboard',
|
|
2311
|
-
disabled: async () => (await this.engineRef.getCopiedObjects()).length === 0,
|
|
2312
2309
|
action: (menu, _) => this.engineRef.paste(menu.x, menu.y),
|
|
2313
2310
|
},
|
|
2314
2311
|
{
|
|
@@ -2326,7 +2323,6 @@ const KritzelEditor = class {
|
|
|
2326
2323
|
label: 'menu.align',
|
|
2327
2324
|
icon: 'align',
|
|
2328
2325
|
group: 'other',
|
|
2329
|
-
disabled: async () => (await this.engineRef.getSelectedObjects()).length < 2,
|
|
2330
2326
|
children: [
|
|
2331
2327
|
{ label: 'menu.alignLeft', icon: 'align-start-vertical', action: () => this.engineRef.alignObjects(schema_constants.KritzelAlignment.StartHorizontal) },
|
|
2332
2328
|
{ label: 'menu.alignCenterHorizontal', icon: 'align-center-horizontal', action: () => this.engineRef.alignObjects(schema_constants.KritzelAlignment.CenterHorizontal) },
|
|
@@ -2344,16 +2340,11 @@ const KritzelEditor = class {
|
|
|
2344
2340
|
{
|
|
2345
2341
|
label: 'menu.group',
|
|
2346
2342
|
icon: 'group',
|
|
2347
|
-
disabled: async () => (await this.engineRef.getSelectedObjects()).length < 2,
|
|
2348
2343
|
action: () => this.engineRef.group(),
|
|
2349
2344
|
},
|
|
2350
2345
|
{
|
|
2351
2346
|
label: 'menu.ungroup',
|
|
2352
2347
|
icon: 'ungroup',
|
|
2353
|
-
disabled: async () => {
|
|
2354
|
-
const selectedObjects = await this.engineRef.getSelectedObjects();
|
|
2355
|
-
return !selectedObjects.some(obj => obj.__class__ === 'KritzelGroup');
|
|
2356
|
-
},
|
|
2357
2348
|
action: () => this.engineRef.ungroup(),
|
|
2358
2349
|
},
|
|
2359
2350
|
],
|
|
@@ -2430,6 +2421,13 @@ const KritzelEditor = class {
|
|
|
2430
2421
|
shortcuts = [];
|
|
2431
2422
|
currentIsPublic = false;
|
|
2432
2423
|
isEditorVisible = false;
|
|
2424
|
+
activeNotification;
|
|
2425
|
+
isNotificationDismissing = false;
|
|
2426
|
+
notificationDismissTimeout;
|
|
2427
|
+
notificationDismissAnimationTimeout;
|
|
2428
|
+
notificationDisplayDurationMs = 5000;
|
|
2429
|
+
notificationDismissAnimationDurationMs = 180;
|
|
2430
|
+
isNotificationHovered = false;
|
|
2433
2431
|
onIsEngineReady(newValue) {
|
|
2434
2432
|
if (newValue && this.isControlsReady) {
|
|
2435
2433
|
this.checkIsReady();
|
|
@@ -2692,9 +2690,6 @@ const KritzelEditor = class {
|
|
|
2692
2690
|
async findObjects(predicate) {
|
|
2693
2691
|
return this.engineRef.findObjects(predicate);
|
|
2694
2692
|
}
|
|
2695
|
-
async getCopiedObjects() {
|
|
2696
|
-
return this.engineRef.getCopiedObjects();
|
|
2697
|
-
}
|
|
2698
2693
|
async getObjectsInViewport() {
|
|
2699
2694
|
return this.engineRef.getObjectsInViewport();
|
|
2700
2695
|
}
|
|
@@ -2710,6 +2705,22 @@ const KritzelEditor = class {
|
|
|
2710
2705
|
async getDisplayableShortcuts() {
|
|
2711
2706
|
return this.engineRef.getDisplayableShortcuts();
|
|
2712
2707
|
}
|
|
2708
|
+
/**
|
|
2709
|
+
* Triggers a UI notification programmatically.
|
|
2710
|
+
* @param notification - Notification payload. `id` and `timestamp` are optional.
|
|
2711
|
+
*/
|
|
2712
|
+
async triggerNotification(notification) {
|
|
2713
|
+
const normalizedNotification = {
|
|
2714
|
+
...notification,
|
|
2715
|
+
id: notification.id ?? schema_constants.ObjectHelper.generateUUID(),
|
|
2716
|
+
timestamp: notification.timestamp ?? new Date(),
|
|
2717
|
+
};
|
|
2718
|
+
this.clearNotificationDismissAnimationTimer();
|
|
2719
|
+
this.isNotificationDismissing = false;
|
|
2720
|
+
this.isNotificationHovered = false;
|
|
2721
|
+
this.activeNotification = normalizedNotification;
|
|
2722
|
+
this.scheduleNotificationDismiss();
|
|
2723
|
+
}
|
|
2713
2724
|
engineRef;
|
|
2714
2725
|
controlsRef;
|
|
2715
2726
|
settingsRef;
|
|
@@ -2734,6 +2745,10 @@ const KritzelEditor = class {
|
|
|
2734
2745
|
this.listenForMobileKeyboard();
|
|
2735
2746
|
this.setOsSpecificCssVariables();
|
|
2736
2747
|
}
|
|
2748
|
+
disconnectedCallback() {
|
|
2749
|
+
this.clearNotificationDismissTimer();
|
|
2750
|
+
this.clearNotificationDismissAnimationTimer();
|
|
2751
|
+
}
|
|
2737
2752
|
async checkIsReady() {
|
|
2738
2753
|
await customElements.whenDefined('kritzel-editor');
|
|
2739
2754
|
await customElements.whenDefined('kritzel-workspace-manager');
|
|
@@ -2833,6 +2848,57 @@ const KritzelEditor = class {
|
|
|
2833
2848
|
event.stopPropagation();
|
|
2834
2849
|
this.awarenessChange.emit(event.detail);
|
|
2835
2850
|
}
|
|
2851
|
+
handleNotificationsChange(event) {
|
|
2852
|
+
event.stopPropagation();
|
|
2853
|
+
this.clearNotificationDismissAnimationTimer();
|
|
2854
|
+
this.isNotificationDismissing = false;
|
|
2855
|
+
this.isNotificationHovered = false;
|
|
2856
|
+
this.activeNotification = event.detail;
|
|
2857
|
+
this.scheduleNotificationDismiss();
|
|
2858
|
+
}
|
|
2859
|
+
handleNotificationHoverChange(event) {
|
|
2860
|
+
event.stopPropagation();
|
|
2861
|
+
this.isNotificationHovered = event.detail;
|
|
2862
|
+
if (this.isNotificationHovered) {
|
|
2863
|
+
this.clearNotificationDismissTimer();
|
|
2864
|
+
return;
|
|
2865
|
+
}
|
|
2866
|
+
if (this.activeNotification && !this.isNotificationDismissing) {
|
|
2867
|
+
this.scheduleNotificationDismiss();
|
|
2868
|
+
}
|
|
2869
|
+
}
|
|
2870
|
+
scheduleNotificationDismiss() {
|
|
2871
|
+
this.clearNotificationDismissTimer();
|
|
2872
|
+
this.notificationDismissTimeout = setTimeout(() => {
|
|
2873
|
+
this.dismissNotification();
|
|
2874
|
+
}, this.notificationDisplayDurationMs);
|
|
2875
|
+
}
|
|
2876
|
+
clearNotificationDismissTimer() {
|
|
2877
|
+
if (this.notificationDismissTimeout) {
|
|
2878
|
+
clearTimeout(this.notificationDismissTimeout);
|
|
2879
|
+
this.notificationDismissTimeout = undefined;
|
|
2880
|
+
}
|
|
2881
|
+
}
|
|
2882
|
+
clearNotificationDismissAnimationTimer() {
|
|
2883
|
+
if (this.notificationDismissAnimationTimeout) {
|
|
2884
|
+
clearTimeout(this.notificationDismissAnimationTimeout);
|
|
2885
|
+
this.notificationDismissAnimationTimeout = undefined;
|
|
2886
|
+
}
|
|
2887
|
+
}
|
|
2888
|
+
dismissNotification = () => {
|
|
2889
|
+
this.clearNotificationDismissTimer();
|
|
2890
|
+
this.isNotificationHovered = false;
|
|
2891
|
+
if (!this.activeNotification || this.isNotificationDismissing) {
|
|
2892
|
+
return;
|
|
2893
|
+
}
|
|
2894
|
+
this.isNotificationDismissing = true;
|
|
2895
|
+
this.clearNotificationDismissAnimationTimer();
|
|
2896
|
+
this.notificationDismissAnimationTimeout = setTimeout(() => {
|
|
2897
|
+
this.activeNotification = undefined;
|
|
2898
|
+
this.isNotificationDismissing = false;
|
|
2899
|
+
this.notificationDismissAnimationTimeout = undefined;
|
|
2900
|
+
}, this.notificationDismissAnimationDurationMs);
|
|
2901
|
+
};
|
|
2836
2902
|
handleSettingsChange(event) {
|
|
2837
2903
|
this.scaleMin = event.detail.scaleMin;
|
|
2838
2904
|
this.scaleMax = event.detail.scaleMax;
|
|
@@ -3071,31 +3137,31 @@ const KritzelEditor = class {
|
|
|
3071
3137
|
const isLoggedIn = this.isLoggedIn;
|
|
3072
3138
|
const shouldShowCurrentUser = isLoggedIn;
|
|
3073
3139
|
const shouldShowLoginButton = this.isReady && !!this.loginConfig && !isLoggedIn;
|
|
3074
|
-
return (index.h(index.Host, { key: '
|
|
3140
|
+
return (index.h(index.Host, { key: '07fe246b722ca64cfbdd8cc3474e6288c39d1128', style: {
|
|
3075
3141
|
opacity: this.isEditorVisible ? '1' : '0',
|
|
3076
3142
|
visibility: this.isEditorVisible ? 'visible' : 'hidden',
|
|
3077
3143
|
transition: 'opacity 0.2s ease-in-out, visibility 0.2s ease-in-out',
|
|
3078
|
-
} }, index.h("div", { key: '
|
|
3144
|
+
} }, index.h("div", { key: '2d0db1e78161edb061779b5875114e901f8e79f8', class: "top-left-buttons" }, index.h("kritzel-workspace-manager", { key: '8fee1d57b0b868b673c41015453fd39a19f8cb43', 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: 'f2a0305bf73bd14d7522974b7956a289a0a44258', visible: this.isBackToContentButtonVisible, text: this.resolvedTerms['backToContent.label'] ?? 'Back to content', onBackToContent: () => this.backToContent() })), this.activeNotification && (index.h("div", { key: '918fe80193999ec072042500cd1eaf3670f5ed3c', class: "top-center-notification-layer", role: "presentation" }, index.h("div", { key: '0a5609b2b32f9f04bac03618803c14d9a891742c', class: { 'top-center-notification-container': true, 'is-dismissing': this.isNotificationDismissing }, role: "presentation" }, index.h("kritzel-notification-card", { key: 'eb1ff7aeaee3a237baf3ba2d96a10ba03a8bf7fb', notification: this.activeNotification, locale: this.locale, onDismiss: this.dismissNotification, onHoverChange: event => this.handleNotificationHoverChange(event) })))), index.h("kritzel-engine", { key: '8783a87101f308029482ced926a8d2163aae1428', ref: el => {
|
|
3079
3145
|
if (el) {
|
|
3080
3146
|
this.engineRef = el;
|
|
3081
3147
|
}
|
|
3082
|
-
}, 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) }), index.h("kritzel-controls", { key: '
|
|
3148
|
+
}, 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), onNotificationsChange: event => this.handleNotificationsChange(event) }), index.h("kritzel-controls", { key: '73a94f6baef4e0e26be4540ecd44d24588f5761b', visible: this.isControlsVisible, class: { 'keyboard-open': this.isVirtualKeyboardOpen }, ref: el => {
|
|
3083
3149
|
if (el) {
|
|
3084
3150
|
this.controlsRef = el;
|
|
3085
3151
|
}
|
|
3086
|
-
}, controls: this.controls, isUtilityPanelVisible: this.isUtilityPanelVisible, undoState: this.undoState ?? undefined, theme: this.theme, terms: this.resolvedTerms, onIsControlsReady: () => (this.isControlsReady = true) }), index.h("div", { key: '
|
|
3152
|
+
}, controls: this.controls, isUtilityPanelVisible: this.isUtilityPanelVisible, undoState: this.undoState ?? undefined, theme: this.theme, terms: this.resolvedTerms, onIsControlsReady: () => (this.isControlsReady = true) }), index.h("div", { key: 'b0653098e5e15b81f453a7f3c2b27f137eb38f2e', class: "bottom-left-buttons" }, index.h("kritzel-zoom-panel", { key: '33384aeb6bd32d17fb428bd9ed48e5d588ac60c0', visible: this.isZoomPanelVisible, disabled: !this.isZoomingEnabled, zoomPercent: this.currentZoomPercent, terms: this.resolvedTerms, onZoomIn: () => this.zoomIn(), onZoomOut: () => this.zoomOut() })), index.h("div", { key: '37bed04c062b63a99c930362fb8ce30b58ed8872', class: "top-right-buttons" }, index.h("kritzel-settings", { key: '4e339573e3d8d48bc9803b9dd40a549bd056d147', ref: el => {
|
|
3087
3153
|
if (el) {
|
|
3088
3154
|
this.settingsRef = el;
|
|
3089
3155
|
}
|
|
3090
|
-
}, 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: '
|
|
3156
|
+
}, 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: '2a726ea5b56cd36ecf92bbab17d69d04baf73009', ref: el => {
|
|
3091
3157
|
if (el) {
|
|
3092
3158
|
this.exportRef = el;
|
|
3093
3159
|
}
|
|
3094
|
-
}, 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: '
|
|
3160
|
+
}, 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: '26d9bbf922b1d4158a0875ba42e7b598011973d5', users: this.activeUsers }), shouldShowCurrentUser && index.h("kritzel-current-user", { key: '8179cc3e940c9fd8d97978af2bf52543f661a0fd', user: this.user, terms: this.resolvedTerms }), shouldShowLoginButton && (index.h("kritzel-button", { key: 'd4aa5bc108043eb103754d14f1b5df42ab73f8c4', onButtonClick: () => this.loginDialogRef?.open() }, this.resolvedTerms['login.dialogTitle'] ?? 'Sign in')), index.h("kritzel-more-menu", { key: '17ac617bde379d7484dbeed39ac7168349b634a1', items: this.moreMenuItems, visible: this.isMoreMenuVisible, terms: this.resolvedTerms }), index.h("kritzel-share-dialog", { key: '881729b36d34ef3ac3d87fc51ad828fc20fa36cd', ref: el => {
|
|
3095
3161
|
if (el) {
|
|
3096
3162
|
this.shareDialogRef = el;
|
|
3097
3163
|
}
|
|
3098
|
-
}, isPublic: this.currentIsPublic, workspaceId: this.activeWorkspace?.id, terms: this.resolvedTerms, onToggleIsPublic: this.handleToggleIsPublic }), this.loginConfig && (index.h("kritzel-login-dialog", { key: '
|
|
3164
|
+
}, isPublic: this.currentIsPublic, workspaceId: this.activeWorkspace?.id, terms: this.resolvedTerms, onToggleIsPublic: this.handleToggleIsPublic }), this.loginConfig && (index.h("kritzel-login-dialog", { key: '5e34b647ac4c3e18981042d765b4d443422c5db3', ref: el => {
|
|
3099
3165
|
if (el) {
|
|
3100
3166
|
this.loginDialogRef = el;
|
|
3101
3167
|
}
|
|
@@ -21174,7 +21240,7 @@ class KritzelViewport {
|
|
|
21174
21240
|
const NUDGE_AMOUNT = 10;
|
|
21175
21241
|
/**
|
|
21176
21242
|
* Handles keyboard events and manages keyboard shortcuts for the Kritzel canvas.
|
|
21177
|
-
* Provides functionality for tool switching,
|
|
21243
|
+
* Provides functionality for tool switching, object manipulation,
|
|
21178
21244
|
* undo/redo, and navigation via keyboard input.
|
|
21179
21245
|
*/
|
|
21180
21246
|
class KritzelKeyHandler extends schema_constants.KritzelBaseHandler {
|
|
@@ -21217,27 +21283,6 @@ class KritzelKeyHandler extends schema_constants.KritzelBaseHandler {
|
|
|
21217
21283
|
{ key: '7', ctrl: true, label: 'Tool 7', category: 'Tool Selection', action: () => this.switchToolByIndex(6) },
|
|
21218
21284
|
{ key: '8', ctrl: true, label: 'Tool 8', category: 'Tool Selection', action: () => this.switchToolByIndex(7) },
|
|
21219
21285
|
{ key: '9', ctrl: true, label: 'Tool 9', category: 'Tool Selection', action: () => this.switchToolByIndex(8) },
|
|
21220
|
-
// Clipboard
|
|
21221
|
-
{
|
|
21222
|
-
key: 'c',
|
|
21223
|
-
ctrl: true,
|
|
21224
|
-
label: 'Copy',
|
|
21225
|
-
category: 'Clipboard',
|
|
21226
|
-
condition: c => !!c.store.selectionGroup,
|
|
21227
|
-
action: c => {
|
|
21228
|
-
c.copy();
|
|
21229
|
-
c.rerender();
|
|
21230
|
-
},
|
|
21231
|
-
},
|
|
21232
|
-
{ key: 'x', ctrl: true, label: 'Cut', category: 'Clipboard', condition: c => !!c.store.selectionGroup, action: c => c.cut() },
|
|
21233
|
-
{
|
|
21234
|
-
key: 'v',
|
|
21235
|
-
ctrl: true,
|
|
21236
|
-
label: 'Paste',
|
|
21237
|
-
category: 'Clipboard',
|
|
21238
|
-
condition: c => !!c.store.state.copiedObjects && !c.store.activeText && !c.store.activeShape,
|
|
21239
|
-
action: c => c.paste(),
|
|
21240
|
-
},
|
|
21241
21286
|
// Object layering
|
|
21242
21287
|
{ key: '+', ctrl: true, label: 'Bring Forward', category: 'Object Layering', condition: c => !!c.store.selectionGroup, action: c => c.bringForward() },
|
|
21243
21288
|
{ key: '-', ctrl: true, label: 'Send Backward', category: 'Object Layering', condition: c => !!c.store.selectionGroup, action: c => c.sendBackward() },
|
|
@@ -21747,7 +21792,6 @@ class KritzelReviver {
|
|
|
21747
21792
|
const DEFAULT_ENGINE_CONFIG = {
|
|
21748
21793
|
activeWorkspace: undefined,
|
|
21749
21794
|
activeTool: null,
|
|
21750
|
-
copiedObjects: null,
|
|
21751
21795
|
objects: null,
|
|
21752
21796
|
snapCandidate: null,
|
|
21753
21797
|
resizeHandleType: null,
|
|
@@ -24090,6 +24134,467 @@ class KritzelCursorManager {
|
|
|
24090
24134
|
}
|
|
24091
24135
|
}
|
|
24092
24136
|
|
|
24137
|
+
/**
|
|
24138
|
+
* Manages browser permission checks and prompts for a core instance.
|
|
24139
|
+
*
|
|
24140
|
+
* Permission-specific prompt logic is routed through a handler registry so new
|
|
24141
|
+
* permissions can be added without changing the core control flow.
|
|
24142
|
+
*/
|
|
24143
|
+
class KritzelBrowserPermissionManager {
|
|
24144
|
+
_isFirefox = /firefox|fxios/i.test(navigator.userAgent);
|
|
24145
|
+
_isSafari = /safari/i.test(navigator.userAgent) && !/chrome|chromium|crios|android|edg/i.test(navigator.userAgent);
|
|
24146
|
+
_requestHandlers = new Map();
|
|
24147
|
+
/**
|
|
24148
|
+
* Creates a new KritzelBrowserPermissionManager instance.
|
|
24149
|
+
* @param core - The KritzelCore instance this manager belongs to
|
|
24150
|
+
*/
|
|
24151
|
+
constructor(_core) {
|
|
24152
|
+
this.registerRequestPermissionHandler('clipboard-read', async () => {
|
|
24153
|
+
// Firefox and Safari open native paste menus when readText() is called
|
|
24154
|
+
// proactively, so rely on the permission state instead of an eager read.
|
|
24155
|
+
if (this._isFirefox || this._isSafari) {
|
|
24156
|
+
return 'granted';
|
|
24157
|
+
}
|
|
24158
|
+
try {
|
|
24159
|
+
await navigator.clipboard.readText();
|
|
24160
|
+
return 'granted';
|
|
24161
|
+
}
|
|
24162
|
+
catch {
|
|
24163
|
+
return 'denied';
|
|
24164
|
+
}
|
|
24165
|
+
});
|
|
24166
|
+
}
|
|
24167
|
+
/**
|
|
24168
|
+
* Registers a custom request handler for a browser permission name.
|
|
24169
|
+
* Existing handlers are replaced, which makes the registry easy to extend.
|
|
24170
|
+
*
|
|
24171
|
+
* @param permissionName - The browser permission name to handle
|
|
24172
|
+
* @param handler - The request implementation for that permission
|
|
24173
|
+
*/
|
|
24174
|
+
registerRequestPermissionHandler(permissionName, handler) {
|
|
24175
|
+
this._requestHandlers.set(permissionName, handler);
|
|
24176
|
+
}
|
|
24177
|
+
/**
|
|
24178
|
+
* Checks the current state for a browser permission via the Permissions API.
|
|
24179
|
+
*
|
|
24180
|
+
* @param permissionName - The browser permission name to inspect
|
|
24181
|
+
*/
|
|
24182
|
+
async checkPermission(permissionName) {
|
|
24183
|
+
const status = await navigator.permissions.query({ name: permissionName });
|
|
24184
|
+
return status.state;
|
|
24185
|
+
}
|
|
24186
|
+
/**
|
|
24187
|
+
* Requests a browser permission using the registered handler for the given
|
|
24188
|
+
* permission name, then falls back to a permission check when no handler is
|
|
24189
|
+
* registered.
|
|
24190
|
+
*
|
|
24191
|
+
* @param permissionName - The browser permission name to request
|
|
24192
|
+
*/
|
|
24193
|
+
async requestPermission(permissionName) {
|
|
24194
|
+
const handler = this._requestHandlers.get(permissionName);
|
|
24195
|
+
if (handler) {
|
|
24196
|
+
return handler();
|
|
24197
|
+
}
|
|
24198
|
+
return this.checkPermission(permissionName);
|
|
24199
|
+
}
|
|
24200
|
+
}
|
|
24201
|
+
|
|
24202
|
+
const CLIPBOARD_PAYLOAD_PREFIX = 'kritzel-clipboard/v1:';
|
|
24203
|
+
/**
|
|
24204
|
+
* Manages clipboard operations (copy/cut/paste) for a core instance.
|
|
24205
|
+
*
|
|
24206
|
+
* The system clipboard is the single source of truth: copy serializes the current
|
|
24207
|
+
* selection into a Kritzel payload, paste reads + revives it. No copied objects are
|
|
24208
|
+
* cached on the engine state.
|
|
24209
|
+
*/
|
|
24210
|
+
class KritzelClipboardManager {
|
|
24211
|
+
_core;
|
|
24212
|
+
/**
|
|
24213
|
+
* In-memory cascade offset (world units) applied to successive pastes of the same
|
|
24214
|
+
* clipboard content so they don't stack exactly on top of each other. Reset on copy/cut.
|
|
24215
|
+
*/
|
|
24216
|
+
_pasteOffset = 0;
|
|
24217
|
+
constructor(core) {
|
|
24218
|
+
this._core = core;
|
|
24219
|
+
}
|
|
24220
|
+
/**
|
|
24221
|
+
* Serializes an object for the clipboard payload. Groups additionally embed their
|
|
24222
|
+
* (recursively serialized) children under `__children__` so the payload is self-contained.
|
|
24223
|
+
*/
|
|
24224
|
+
serializeForClipboard(object) {
|
|
24225
|
+
const serialized = (typeof object.serialize === 'function' ? object.serialize() : object);
|
|
24226
|
+
if (schema_constants.KritzelClassHelper.isInstanceOf(object, 'KritzelGroup')) {
|
|
24227
|
+
serialized.__children__ = object.children.map(child => this.serializeForClipboard(child));
|
|
24228
|
+
}
|
|
24229
|
+
return serialized;
|
|
24230
|
+
}
|
|
24231
|
+
serializeClipboardPayload(payload) {
|
|
24232
|
+
return `${CLIPBOARD_PAYLOAD_PREFIX}${JSON.stringify(payload)}`;
|
|
24233
|
+
}
|
|
24234
|
+
parseClipboardPayload(text) {
|
|
24235
|
+
if (!text || !text.startsWith(CLIPBOARD_PAYLOAD_PREFIX)) {
|
|
24236
|
+
return null;
|
|
24237
|
+
}
|
|
24238
|
+
try {
|
|
24239
|
+
const parsed = JSON.parse(text.slice(CLIPBOARD_PAYLOAD_PREFIX.length));
|
|
24240
|
+
if (parsed?.version !== 1 || !Array.isArray(parsed.objects)) {
|
|
24241
|
+
return null;
|
|
24242
|
+
}
|
|
24243
|
+
return parsed;
|
|
24244
|
+
}
|
|
24245
|
+
catch {
|
|
24246
|
+
return null;
|
|
24247
|
+
}
|
|
24248
|
+
}
|
|
24249
|
+
determineTextPasteIntent(text) {
|
|
24250
|
+
const payload = this.parseClipboardPayload(text);
|
|
24251
|
+
if (payload) {
|
|
24252
|
+
return { type: 'kritzel_objects', payload };
|
|
24253
|
+
}
|
|
24254
|
+
if (text && text.trim().length > 0) {
|
|
24255
|
+
return { type: 'plain_text', text };
|
|
24256
|
+
}
|
|
24257
|
+
return null;
|
|
24258
|
+
}
|
|
24259
|
+
async writeBrowserClipboardPayload(payload, event) {
|
|
24260
|
+
const serialized = this.serializeClipboardPayload(payload);
|
|
24261
|
+
if (event?.clipboardData) {
|
|
24262
|
+
event.clipboardData.setData('text/plain', serialized);
|
|
24263
|
+
return;
|
|
24264
|
+
}
|
|
24265
|
+
if (typeof navigator === 'undefined' || !navigator.clipboard?.writeText) {
|
|
24266
|
+
return;
|
|
24267
|
+
}
|
|
24268
|
+
try {
|
|
24269
|
+
await navigator.clipboard.writeText(serialized);
|
|
24270
|
+
}
|
|
24271
|
+
catch {
|
|
24272
|
+
// Ignore clipboard permission failures and keep the local clipboard working.
|
|
24273
|
+
}
|
|
24274
|
+
}
|
|
24275
|
+
/**
|
|
24276
|
+
* Revives a single serialized clipboard object (and its embedded group children).
|
|
24277
|
+
* IDs are NOT regenerated here; see regenerateIdsAndRemapAnchors.
|
|
24278
|
+
*/
|
|
24279
|
+
reviveClipboardObject(serialized) {
|
|
24280
|
+
const reviver = new KritzelReviver(this._core);
|
|
24281
|
+
const { __children__, ...objectData } = serialized;
|
|
24282
|
+
const revived = reviver.revive(objectData);
|
|
24283
|
+
if (!revived) {
|
|
24284
|
+
return null;
|
|
24285
|
+
}
|
|
24286
|
+
if (__children__ && schema_constants.KritzelClassHelper.isInstanceOf(revived, 'KritzelGroup')) {
|
|
24287
|
+
const children = __children__.map(child => this.reviveClipboardObject(child)).filter((child) => child != null);
|
|
24288
|
+
revived._pendingChildren = children;
|
|
24289
|
+
revived.childIds = children.map(child => child.id);
|
|
24290
|
+
}
|
|
24291
|
+
return revived;
|
|
24292
|
+
}
|
|
24293
|
+
/**
|
|
24294
|
+
* Assigns fresh unique IDs to every revived object (including nested group children),
|
|
24295
|
+
* keeping group.childIds in sync and remapping line anchors that reference copied
|
|
24296
|
+
* siblings to their new IDs. Anchors pointing at objects outside the pasted set are
|
|
24297
|
+
* left untouched so they stay connected to the existing object.
|
|
24298
|
+
*/
|
|
24299
|
+
regenerateIdsAndRemapAnchors(topLevel) {
|
|
24300
|
+
const all = [];
|
|
24301
|
+
const collect = (objects) => {
|
|
24302
|
+
for (const object of objects) {
|
|
24303
|
+
all.push(object);
|
|
24304
|
+
if (schema_constants.KritzelClassHelper.isInstanceOf(object, 'KritzelGroup')) {
|
|
24305
|
+
collect(object._pendingChildren);
|
|
24306
|
+
}
|
|
24307
|
+
}
|
|
24308
|
+
};
|
|
24309
|
+
collect(topLevel);
|
|
24310
|
+
const idMap = new Map();
|
|
24311
|
+
for (const object of all) {
|
|
24312
|
+
const newId = object.generateId();
|
|
24313
|
+
idMap.set(object.id, newId);
|
|
24314
|
+
object.id = newId;
|
|
24315
|
+
object.isMounted = false;
|
|
24316
|
+
}
|
|
24317
|
+
for (const object of all) {
|
|
24318
|
+
if (schema_constants.KritzelClassHelper.isInstanceOf(object, 'KritzelGroup')) {
|
|
24319
|
+
object.childIds = object.childIds.map(id => idMap.get(id) ?? id);
|
|
24320
|
+
}
|
|
24321
|
+
if (schema_constants.KritzelClassHelper.isInstanceOf(object, 'KritzelLine')) {
|
|
24322
|
+
if (object.startAnchor && idMap.has(object.startAnchor.objectId)) {
|
|
24323
|
+
object.startAnchor = { objectId: idMap.get(object.startAnchor.objectId) };
|
|
24324
|
+
}
|
|
24325
|
+
if (object.endAnchor && idMap.has(object.endAnchor.objectId)) {
|
|
24326
|
+
object.endAnchor = { objectId: idMap.get(object.endAnchor.objectId) };
|
|
24327
|
+
}
|
|
24328
|
+
}
|
|
24329
|
+
}
|
|
24330
|
+
}
|
|
24331
|
+
/**
|
|
24332
|
+
* Evaluates the clipboard event to determine exactly what the user is trying to paste.
|
|
24333
|
+
* Returns a PasteIntent covering the 3 main cases: Kritzel objects, Images, or Plain text.
|
|
24334
|
+
*/
|
|
24335
|
+
async determinePasteIntent(event) {
|
|
24336
|
+
if (event?.clipboardData) {
|
|
24337
|
+
const data = event.clipboardData;
|
|
24338
|
+
const imageFiles = Array.from(data.files ?? []).filter(file => file.type.startsWith('image/'));
|
|
24339
|
+
if (imageFiles.length > 0) {
|
|
24340
|
+
return { type: 'image_files', files: imageFiles };
|
|
24341
|
+
}
|
|
24342
|
+
if (data.types.includes('text/plain')) {
|
|
24343
|
+
const textIntent = this.determineTextPasteIntent(data.getData('text/plain'));
|
|
24344
|
+
if (textIntent)
|
|
24345
|
+
return textIntent;
|
|
24346
|
+
}
|
|
24347
|
+
return { type: 'unknown' };
|
|
24348
|
+
}
|
|
24349
|
+
if (typeof navigator === 'undefined' || !navigator.clipboard) {
|
|
24350
|
+
return { type: 'unknown' };
|
|
24351
|
+
}
|
|
24352
|
+
const { clipboard } = navigator;
|
|
24353
|
+
const permissionState = await this._core.permissionManager.checkPermission('clipboard-read');
|
|
24354
|
+
if (permissionState !== 'granted') {
|
|
24355
|
+
const requestedState = await this._core.permissionManager.requestPermission('clipboard-read');
|
|
24356
|
+
if (requestedState !== 'granted') {
|
|
24357
|
+
return { type: 'unknown' };
|
|
24358
|
+
}
|
|
24359
|
+
}
|
|
24360
|
+
if (clipboard.read) {
|
|
24361
|
+
try {
|
|
24362
|
+
const items = await clipboard.read();
|
|
24363
|
+
const { imageFiles, text } = await this.processClipboardItems(items);
|
|
24364
|
+
if (imageFiles.length > 0) {
|
|
24365
|
+
return { type: 'image_files', files: imageFiles };
|
|
24366
|
+
}
|
|
24367
|
+
if (text !== null) {
|
|
24368
|
+
const textIntent = this.determineTextPasteIntent(text);
|
|
24369
|
+
if (textIntent)
|
|
24370
|
+
return textIntent;
|
|
24371
|
+
}
|
|
24372
|
+
}
|
|
24373
|
+
catch {
|
|
24374
|
+
// Fall back to readText below when read() is denied or unavailable at runtime.
|
|
24375
|
+
}
|
|
24376
|
+
}
|
|
24377
|
+
if (clipboard.readText) {
|
|
24378
|
+
const textIntent = this.determineTextPasteIntent(await clipboard.readText());
|
|
24379
|
+
if (textIntent)
|
|
24380
|
+
return textIntent;
|
|
24381
|
+
}
|
|
24382
|
+
return { type: 'unknown' };
|
|
24383
|
+
}
|
|
24384
|
+
/**
|
|
24385
|
+
* Helper to parse clipboard items in parallel
|
|
24386
|
+
*/
|
|
24387
|
+
async processClipboardItems(items) {
|
|
24388
|
+
const imageFiles = [];
|
|
24389
|
+
let text = null;
|
|
24390
|
+
// Process items concurrently
|
|
24391
|
+
await Promise.all(items.map(async (item) => {
|
|
24392
|
+
const imageType = item.types.find(type => type.startsWith('image/'));
|
|
24393
|
+
if (imageType) {
|
|
24394
|
+
const blob = await item.getType(imageType);
|
|
24395
|
+
imageFiles.push(new File([blob], 'pasted-image', { type: imageType }));
|
|
24396
|
+
return;
|
|
24397
|
+
}
|
|
24398
|
+
if (text === null && item.types.includes('text/plain')) {
|
|
24399
|
+
const blob = await item.getType('text/plain');
|
|
24400
|
+
text = await blob.text();
|
|
24401
|
+
}
|
|
24402
|
+
}));
|
|
24403
|
+
return { imageFiles, text };
|
|
24404
|
+
}
|
|
24405
|
+
/**
|
|
24406
|
+
* Copies currently selected objects into internal clipboard state.
|
|
24407
|
+
*/
|
|
24408
|
+
copy(event) {
|
|
24409
|
+
const selectionGroup = this._core.store.selectionGroup;
|
|
24410
|
+
if (!selectionGroup) {
|
|
24411
|
+
return;
|
|
24412
|
+
}
|
|
24413
|
+
const payload = {
|
|
24414
|
+
version: 1,
|
|
24415
|
+
sourceWorkspaceId: this._core.store.state.activeWorkspace?.id,
|
|
24416
|
+
objects: selectionGroup.objects.sort((a, b) => a.zIndex - b.zIndex).map(obj => this.serializeForClipboard(obj)),
|
|
24417
|
+
};
|
|
24418
|
+
// A fresh copy resets the cascade so the first paste lands at the default offset.
|
|
24419
|
+
this._pasteOffset = 0;
|
|
24420
|
+
void this.writeBrowserClipboardPayload(payload, event);
|
|
24421
|
+
}
|
|
24422
|
+
/**
|
|
24423
|
+
* Cuts currently selected objects (copy then delete).
|
|
24424
|
+
*/
|
|
24425
|
+
cut(event) {
|
|
24426
|
+
const selectionGroup = this._core.store.selectionGroup;
|
|
24427
|
+
if (!selectionGroup) {
|
|
24428
|
+
return;
|
|
24429
|
+
}
|
|
24430
|
+
this.copy(event);
|
|
24431
|
+
this._core.delete();
|
|
24432
|
+
}
|
|
24433
|
+
materializeKritzelObjects(intent) {
|
|
24434
|
+
const objects = intent.payload.objects.map(object => this.reviveClipboardObject(object)).filter((object) => object != null);
|
|
24435
|
+
this.regenerateIdsAndRemapAnchors(objects);
|
|
24436
|
+
return objects;
|
|
24437
|
+
}
|
|
24438
|
+
async materializeImageFiles(intent) {
|
|
24439
|
+
try {
|
|
24440
|
+
const scale = this._core.store.state.scale;
|
|
24441
|
+
const offset = 25 / scale;
|
|
24442
|
+
const preparePromises = intent.files.map(async (file, index) => {
|
|
24443
|
+
// Use the default image compression size of 1200
|
|
24444
|
+
const compressed = await schema_constants.imageCompression(file, { maxWidthOrHeight: 1200 });
|
|
24445
|
+
return schema_constants.KritzelImage.fromBlob(this._core, compressed, {
|
|
24446
|
+
translateX: index * offset,
|
|
24447
|
+
translateY: index * offset,
|
|
24448
|
+
});
|
|
24449
|
+
});
|
|
24450
|
+
return await Promise.all(preparePromises);
|
|
24451
|
+
}
|
|
24452
|
+
catch (err) {
|
|
24453
|
+
console.error('Failed to import pasted image files:', err);
|
|
24454
|
+
return null;
|
|
24455
|
+
}
|
|
24456
|
+
}
|
|
24457
|
+
async materializePlainText(intent) {
|
|
24458
|
+
const textObject = schema_constants.KritzelText.create(this._core);
|
|
24459
|
+
const paragraphs = intent.text.split('\n').map(line => {
|
|
24460
|
+
if (line.length === 0) {
|
|
24461
|
+
return { type: 'paragraph' }; // Empty paragraph
|
|
24462
|
+
}
|
|
24463
|
+
return {
|
|
24464
|
+
type: 'paragraph',
|
|
24465
|
+
content: [{ type: 'text', text: line }],
|
|
24466
|
+
};
|
|
24467
|
+
});
|
|
24468
|
+
textObject.setContent({
|
|
24469
|
+
type: 'doc',
|
|
24470
|
+
content: paragraphs,
|
|
24471
|
+
});
|
|
24472
|
+
return [textObject];
|
|
24473
|
+
}
|
|
24474
|
+
/**
|
|
24475
|
+
* Pastes objects from clipboard with optional explicit world coordinates.
|
|
24476
|
+
*/
|
|
24477
|
+
async paste(x, y, event) {
|
|
24478
|
+
const pasteIntent = await this.determinePasteIntent(event);
|
|
24479
|
+
let objects = null;
|
|
24480
|
+
if (pasteIntent.type === 'kritzel_objects') {
|
|
24481
|
+
objects = this.materializeKritzelObjects(pasteIntent);
|
|
24482
|
+
}
|
|
24483
|
+
else if (pasteIntent.type === 'image_files') {
|
|
24484
|
+
objects = await this.materializeImageFiles(pasteIntent);
|
|
24485
|
+
}
|
|
24486
|
+
else if (pasteIntent.type === 'plain_text') {
|
|
24487
|
+
objects = await this.materializePlainText(pasteIntent);
|
|
24488
|
+
}
|
|
24489
|
+
if (!objects || objects.length === 0) {
|
|
24490
|
+
return;
|
|
24491
|
+
}
|
|
24492
|
+
await this.insertMaterializedObjects(objects, pasteIntent, x, y);
|
|
24493
|
+
}
|
|
24494
|
+
async insertMaterializedObjects(copiedObjects, pasteIntent, x, y) {
|
|
24495
|
+
const activeWorkspace = this._core.store.state.activeWorkspace;
|
|
24496
|
+
if (!activeWorkspace) {
|
|
24497
|
+
return;
|
|
24498
|
+
}
|
|
24499
|
+
// Determine if we should center the objects in the viewport.
|
|
24500
|
+
// This happens if the user specifically pasted from a different workspace,
|
|
24501
|
+
// OR if we're inserting brand new external items (like images or text).
|
|
24502
|
+
const isDifferentWorkspace = copiedObjects.some(obj => obj.workspaceId !== activeWorkspace.id);
|
|
24503
|
+
const isNewExternalContent = pasteIntent.type !== 'kritzel_objects';
|
|
24504
|
+
const shouldCenterInViewport = isDifferentWorkspace || isNewExternalContent;
|
|
24505
|
+
const hasExplicitPastePosition = x !== undefined && y !== undefined;
|
|
24506
|
+
const minX = Math.min(...copiedObjects.map(obj => obj.translateX));
|
|
24507
|
+
const minY = Math.min(...copiedObjects.map(obj => obj.translateY));
|
|
24508
|
+
let pasteX;
|
|
24509
|
+
let pasteY;
|
|
24510
|
+
const step = 25 / this._core.store.state.scale;
|
|
24511
|
+
if (x !== undefined && y !== undefined) {
|
|
24512
|
+
pasteX = x;
|
|
24513
|
+
pasteY = y;
|
|
24514
|
+
}
|
|
24515
|
+
else if (shouldCenterInViewport) {
|
|
24516
|
+
pasteX = minX;
|
|
24517
|
+
pasteY = minY;
|
|
24518
|
+
}
|
|
24519
|
+
else {
|
|
24520
|
+
pasteX = minX + step + this._pasteOffset;
|
|
24521
|
+
pasteY = minY + step + this._pasteOffset;
|
|
24522
|
+
// Advance the cascade so the next same-content paste is offset further.
|
|
24523
|
+
this._pasteOffset += step;
|
|
24524
|
+
}
|
|
24525
|
+
const offsetX = pasteX - minX;
|
|
24526
|
+
const offsetY = pasteY - minY;
|
|
24527
|
+
this._core.removeSelectionGroup();
|
|
24528
|
+
this._core.removeSelectionBox();
|
|
24529
|
+
const selectionGroup = schema_constants.KritzelSelectionGroup.create(this._core);
|
|
24530
|
+
const baseZIndex = this._core.store.currentZIndex;
|
|
24531
|
+
this._core.store.objects.transaction(() => {
|
|
24532
|
+
const flushPendingChildren = (group, parentZIndex) => {
|
|
24533
|
+
if (group._pendingChildren.length === 0) {
|
|
24534
|
+
return;
|
|
24535
|
+
}
|
|
24536
|
+
const pendingChildren = group._pendingChildren;
|
|
24537
|
+
group._pendingChildren = [];
|
|
24538
|
+
pendingChildren.forEach((child, childIndex) => {
|
|
24539
|
+
if (child.workspaceId !== activeWorkspace.id) {
|
|
24540
|
+
child.workspaceId = activeWorkspace.id;
|
|
24541
|
+
}
|
|
24542
|
+
child.updatePosition(child.translateX + offsetX, child.translateY + offsetY);
|
|
24543
|
+
child.zIndex = parentZIndex + childIndex + 1;
|
|
24544
|
+
if (schema_constants.KritzelClassHelper.isInstanceOf(child, 'KritzelGroup')) {
|
|
24545
|
+
flushPendingChildren(child, child.zIndex);
|
|
24546
|
+
}
|
|
24547
|
+
this._core.addObject(child);
|
|
24548
|
+
});
|
|
24549
|
+
group.finalize();
|
|
24550
|
+
};
|
|
24551
|
+
const newlyAddedObjects = [];
|
|
24552
|
+
copiedObjects.forEach((obj, i) => {
|
|
24553
|
+
if (obj.workspaceId !== activeWorkspace.id) {
|
|
24554
|
+
obj.workspaceId = activeWorkspace.id;
|
|
24555
|
+
}
|
|
24556
|
+
obj.updatePosition(obj.translateX + offsetX, obj.translateY + offsetY);
|
|
24557
|
+
obj.zIndex = baseZIndex + i;
|
|
24558
|
+
if (schema_constants.KritzelClassHelper.isInstanceOf(obj, 'KritzelGroup')) {
|
|
24559
|
+
flushPendingChildren(obj, obj.zIndex);
|
|
24560
|
+
}
|
|
24561
|
+
this._core.addObject(obj);
|
|
24562
|
+
newlyAddedObjects.push(obj);
|
|
24563
|
+
selectionGroup.addOrRemove(obj);
|
|
24564
|
+
});
|
|
24565
|
+
this._core.engine.emitObjectsAdded(newlyAddedObjects);
|
|
24566
|
+
});
|
|
24567
|
+
this._core.anchorManager.rebuildIndex();
|
|
24568
|
+
selectionGroup.isSelected = true;
|
|
24569
|
+
if (copiedObjects.length === 1) {
|
|
24570
|
+
selectionGroup.rotation = copiedObjects[0].rotation;
|
|
24571
|
+
}
|
|
24572
|
+
if (shouldCenterInViewport && !hasExplicitPastePosition) {
|
|
24573
|
+
selectionGroup.centerInViewport();
|
|
24574
|
+
}
|
|
24575
|
+
this._core.addSelectionGroup(selectionGroup);
|
|
24576
|
+
this._core.engine.viewport?.bringIntoViewIfNeeded(selectionGroup);
|
|
24577
|
+
this._core.store.state.isSelecting = false;
|
|
24578
|
+
// Use a double requestAnimationFrame to ensure the browser has fully rendered the DOM,
|
|
24579
|
+
// and objects like KritzelText have executed their own internal size-adjustment rAF calls.
|
|
24580
|
+
await new Promise(resolve => {
|
|
24581
|
+
requestAnimationFrame(() => requestAnimationFrame(() => resolve()));
|
|
24582
|
+
});
|
|
24583
|
+
// Re-evaluate bounding box dimensions now that any DOM nodes (like ProseMirror text editors)
|
|
24584
|
+
// have mounted and calculated their actual bounds.
|
|
24585
|
+
selectionGroup.refreshObjectDimensions();
|
|
24586
|
+
// We should update it if the centerInViewport or width adjustments changed it significantly
|
|
24587
|
+
if (shouldCenterInViewport && !hasExplicitPastePosition) {
|
|
24588
|
+
selectionGroup.centerInViewport();
|
|
24589
|
+
}
|
|
24590
|
+
this._core.engine.emitObjectsChange();
|
|
24591
|
+
this._core.rerender();
|
|
24592
|
+
this._core.store.setState('activeTool', this._core.toolRegistry.getTool('selection'));
|
|
24593
|
+
this._core.engine.emitObjectsChange();
|
|
24594
|
+
this._core.rerender();
|
|
24595
|
+
}
|
|
24596
|
+
}
|
|
24597
|
+
|
|
24093
24598
|
/**
|
|
24094
24599
|
* Central orchestrator class for the Kritzel canvas system.
|
|
24095
24600
|
* Manages workspaces, objects, selection, clipboard operations, and coordinates
|
|
@@ -24118,6 +24623,10 @@ class KritzelCore {
|
|
|
24118
24623
|
_localizationManager;
|
|
24119
24624
|
/** Manager for license validation and watermark gating */
|
|
24120
24625
|
_licenseManager;
|
|
24626
|
+
/** Manager for browser permission checks and permission prompts */
|
|
24627
|
+
_permissionManager;
|
|
24628
|
+
/** Manager for clipboard copy/cut/paste orchestration */
|
|
24629
|
+
_clipboardManager;
|
|
24121
24630
|
/** Per-core registry of drawing tools (one instance per editor). */
|
|
24122
24631
|
_toolRegistry;
|
|
24123
24632
|
/** Optional unique identifier for namespacing storage keys across multiple editor instances */
|
|
@@ -24180,6 +24689,13 @@ class KritzelCore {
|
|
|
24180
24689
|
get licenseManager() {
|
|
24181
24690
|
return this._licenseManager;
|
|
24182
24691
|
}
|
|
24692
|
+
/**
|
|
24693
|
+
* Gets the browser permission manager.
|
|
24694
|
+
* @returns The KritzelBrowserPermissionManager for browser permission checks and requests
|
|
24695
|
+
*/
|
|
24696
|
+
get permissionManager() {
|
|
24697
|
+
return this._permissionManager;
|
|
24698
|
+
}
|
|
24183
24699
|
/**
|
|
24184
24700
|
* Gets the tool registry scoped to this core instance.
|
|
24185
24701
|
* @returns The KritzelToolRegistry owned by this core
|
|
@@ -24187,6 +24703,13 @@ class KritzelCore {
|
|
|
24187
24703
|
get toolRegistry() {
|
|
24188
24704
|
return this._toolRegistry;
|
|
24189
24705
|
}
|
|
24706
|
+
/**
|
|
24707
|
+
* Gets the clipboard manager scoped to this core instance.
|
|
24708
|
+
* @returns The KritzelClipboardManager owned by this core
|
|
24709
|
+
*/
|
|
24710
|
+
get clipboardManager() {
|
|
24711
|
+
return this._clipboardManager;
|
|
24712
|
+
}
|
|
24190
24713
|
/**
|
|
24191
24714
|
* Gets the editor ID used for namespacing storage keys.
|
|
24192
24715
|
* @returns The editor ID or undefined if not set
|
|
@@ -24234,6 +24757,8 @@ class KritzelCore {
|
|
|
24234
24757
|
this._themeManager = new schema_constants.KritzelThemeManager(this);
|
|
24235
24758
|
this._localizationManager = new schema_constants.KritzelLocalizationManager(this);
|
|
24236
24759
|
this._licenseManager = new schema_constants.KritzelLicenseManager(this);
|
|
24760
|
+
this._permissionManager = new KritzelBrowserPermissionManager(this);
|
|
24761
|
+
this._clipboardManager = new KritzelClipboardManager(this);
|
|
24237
24762
|
this._toolRegistry = new KritzelToolRegistry(this);
|
|
24238
24763
|
this._assetResolver = new schema_constants.KritzelAssetResolver();
|
|
24239
24764
|
}
|
|
@@ -24731,216 +25256,6 @@ class KritzelCore {
|
|
|
24731
25256
|
this.rerender();
|
|
24732
25257
|
}
|
|
24733
25258
|
}
|
|
24734
|
-
/**
|
|
24735
|
-
* Copies the currently selected objects to the clipboard.
|
|
24736
|
-
* Creates deep copies of objects and tracks ID mappings for anchor remapping.
|
|
24737
|
-
*/
|
|
24738
|
-
copy() {
|
|
24739
|
-
const selectionGroup = this._store.selectionGroup;
|
|
24740
|
-
if (selectionGroup) {
|
|
24741
|
-
// Copy each object and store them in an array, also track the ID mapping
|
|
24742
|
-
const idMapping = new Map();
|
|
24743
|
-
const copiedObjects = selectionGroup.objects
|
|
24744
|
-
.sort((a, b) => a.zIndex - b.zIndex)
|
|
24745
|
-
.map(obj => {
|
|
24746
|
-
const copiedObj = obj.copy();
|
|
24747
|
-
// Map: newId -> originalId
|
|
24748
|
-
idMapping.set(copiedObj.id, obj.id);
|
|
24749
|
-
return copiedObj;
|
|
24750
|
-
});
|
|
24751
|
-
this._store.state.copiedObjects = copiedObjects;
|
|
24752
|
-
this._store.state.copiedObjectIdMapping = idMapping;
|
|
24753
|
-
}
|
|
24754
|
-
}
|
|
24755
|
-
/**
|
|
24756
|
-
* Cuts the currently selected objects (copy then delete).
|
|
24757
|
-
* Objects are copied to clipboard and then removed from the canvas.
|
|
24758
|
-
*/
|
|
24759
|
-
cut() {
|
|
24760
|
-
const selectionGroup = this._store.selectionGroup;
|
|
24761
|
-
if (!selectionGroup) {
|
|
24762
|
-
return;
|
|
24763
|
-
}
|
|
24764
|
-
// Copy first, then delete
|
|
24765
|
-
this.copy();
|
|
24766
|
-
this.delete();
|
|
24767
|
-
}
|
|
24768
|
-
/**
|
|
24769
|
-
* Pastes objects from the clipboard to the canvas.
|
|
24770
|
-
* Handles positioning (explicit, offset, or centered for cross-workspace paste),
|
|
24771
|
-
* workspace assignment, z-index ordering, group children, and anchor remapping.
|
|
24772
|
-
* Creates a selection group containing the pasted objects.
|
|
24773
|
-
* @param x - Optional explicit X position for paste
|
|
24774
|
-
* @param y - Optional explicit Y position for paste
|
|
24775
|
-
*/
|
|
24776
|
-
paste(x, y) {
|
|
24777
|
-
const copiedObjects = this._store.state.copiedObjects;
|
|
24778
|
-
if (!copiedObjects || copiedObjects.length === 0) {
|
|
24779
|
-
return;
|
|
24780
|
-
}
|
|
24781
|
-
const activeWorkspace = this._store.state.activeWorkspace;
|
|
24782
|
-
const originalIdMapping = this._store.state.copiedObjectIdMapping;
|
|
24783
|
-
// Check if we're pasting from a different workspace
|
|
24784
|
-
const isDifferentWorkspace = copiedObjects.some(obj => obj.workspaceId !== activeWorkspace.id);
|
|
24785
|
-
// Calculate the bounding box of all copied objects
|
|
24786
|
-
const minX = Math.min(...copiedObjects.map(obj => obj.translateX));
|
|
24787
|
-
const minY = Math.min(...copiedObjects.map(obj => obj.translateY));
|
|
24788
|
-
// Determine the paste position
|
|
24789
|
-
let pasteX;
|
|
24790
|
-
let pasteY;
|
|
24791
|
-
if (x !== undefined && y !== undefined) {
|
|
24792
|
-
// Explicit position provided (e.g., right-click paste)
|
|
24793
|
-
pasteX = x;
|
|
24794
|
-
pasteY = y;
|
|
24795
|
-
}
|
|
24796
|
-
else if (isDifferentWorkspace) {
|
|
24797
|
-
// Pasting to different workspace without explicit position
|
|
24798
|
-
// Keep original position; will be centered by centerInViewport() later
|
|
24799
|
-
pasteX = minX;
|
|
24800
|
-
pasteY = minY;
|
|
24801
|
-
}
|
|
24802
|
-
else {
|
|
24803
|
-
// Same workspace paste: offset by 25 pixels from original position
|
|
24804
|
-
pasteX = minX + 25 / this._store.state.scale;
|
|
24805
|
-
pasteY = minY + 25 / this._store.state.scale;
|
|
24806
|
-
}
|
|
24807
|
-
// Calculate the offset to apply to all objects
|
|
24808
|
-
const offsetX = pasteX - minX;
|
|
24809
|
-
const offsetY = pasteY - minY;
|
|
24810
|
-
this.removeSelectionGroup();
|
|
24811
|
-
this.removeSelectionBox();
|
|
24812
|
-
// Create a new selection group for the pasted objects
|
|
24813
|
-
const selectionGroup = schema_constants.KritzelSelectionGroup.create(this);
|
|
24814
|
-
// Build a reverse mapping: originalId -> newCopiedObjectId
|
|
24815
|
-
// This is used to remap anchor references from original IDs to the copied object IDs
|
|
24816
|
-
const originalToNewIdMap = new Map();
|
|
24817
|
-
if (originalIdMapping) {
|
|
24818
|
-
originalIdMapping.forEach((originalId, copiedId) => {
|
|
24819
|
-
originalToNewIdMap.set(originalId, copiedId);
|
|
24820
|
-
});
|
|
24821
|
-
}
|
|
24822
|
-
// Precompute zIndex once to avoid O(N * total_objects) repeated scans
|
|
24823
|
-
const baseZIndex = this._store.currentZIndex;
|
|
24824
|
-
// Batch all inserts and updates in a single Y.js transaction to avoid
|
|
24825
|
-
// N separate observer callbacks and N rerenders (fires only once at commit)
|
|
24826
|
-
this._store.objects.transaction(() => {
|
|
24827
|
-
// Recursively flush a group's pending children (and any nested groups'
|
|
24828
|
-
// pending children) into the store. Without recursion, nested groups
|
|
24829
|
-
// would have their grandchildren stranded in `_pendingChildren` and they
|
|
24830
|
-
// would never appear on the canvas, even though the parent group's
|
|
24831
|
-
// bounding box looks correct.
|
|
24832
|
-
const flushPendingChildren = (group, parentZIndex) => {
|
|
24833
|
-
if (group._pendingChildren.length === 0) {
|
|
24834
|
-
return;
|
|
24835
|
-
}
|
|
24836
|
-
const pendingChildren = group._pendingChildren;
|
|
24837
|
-
group._pendingChildren = [];
|
|
24838
|
-
pendingChildren.forEach((child, childIndex) => {
|
|
24839
|
-
if (child.workspaceId !== activeWorkspace.id) {
|
|
24840
|
-
child.workspaceId = activeWorkspace.id;
|
|
24841
|
-
}
|
|
24842
|
-
child.updatePosition(child.translateX + offsetX, child.translateY + offsetY);
|
|
24843
|
-
child.zIndex = parentZIndex + childIndex + 1;
|
|
24844
|
-
// Recurse before adding so grandchildren are inserted as well
|
|
24845
|
-
if (schema_constants.KritzelClassHelper.isInstanceOf(child, 'KritzelGroup')) {
|
|
24846
|
-
flushPendingChildren(child, child.zIndex);
|
|
24847
|
-
}
|
|
24848
|
-
this.addObject(child);
|
|
24849
|
-
});
|
|
24850
|
-
group.finalize();
|
|
24851
|
-
};
|
|
24852
|
-
const newlyAddedObjects = [];
|
|
24853
|
-
// First add all copied objects to the objectsMap with updated positions
|
|
24854
|
-
copiedObjects.forEach((obj, i) => {
|
|
24855
|
-
// Update workspace if pasting to a different workspace
|
|
24856
|
-
if (obj.workspaceId !== activeWorkspace.id) {
|
|
24857
|
-
obj.workspaceId = activeWorkspace.id;
|
|
24858
|
-
}
|
|
24859
|
-
// Update position
|
|
24860
|
-
obj.updatePosition(obj.translateX + offsetX, obj.translateY + offsetY);
|
|
24861
|
-
// Update z-index
|
|
24862
|
-
obj.zIndex = baseZIndex + i;
|
|
24863
|
-
// Handle KritzelGroup: also add pending children (and grandchildren) with offset
|
|
24864
|
-
if (schema_constants.KritzelClassHelper.isInstanceOf(obj, 'KritzelGroup')) {
|
|
24865
|
-
flushPendingChildren(obj, obj.zIndex);
|
|
24866
|
-
}
|
|
24867
|
-
// Add to objectsMap
|
|
24868
|
-
this.addObject(obj);
|
|
24869
|
-
newlyAddedObjects.push(obj);
|
|
24870
|
-
// Add to selection group
|
|
24871
|
-
selectionGroup.addOrRemove(obj);
|
|
24872
|
-
});
|
|
24873
|
-
this.engine.emitObjectsAdded(newlyAddedObjects);
|
|
24874
|
-
// Update line anchors to point to the newly pasted objects
|
|
24875
|
-
// Only remap if the anchor target was also part of the copied selection
|
|
24876
|
-
copiedObjects.forEach(obj => {
|
|
24877
|
-
if (schema_constants.KritzelClassHelper.isInstanceOf(obj, 'KritzelLine')) {
|
|
24878
|
-
let updated = false;
|
|
24879
|
-
if (obj.startAnchor && originalToNewIdMap.has(obj.startAnchor.objectId)) {
|
|
24880
|
-
obj.startAnchor = { objectId: originalToNewIdMap.get(obj.startAnchor.objectId) };
|
|
24881
|
-
updated = true;
|
|
24882
|
-
}
|
|
24883
|
-
if (obj.endAnchor && originalToNewIdMap.has(obj.endAnchor.objectId)) {
|
|
24884
|
-
obj.endAnchor = { objectId: originalToNewIdMap.get(obj.endAnchor.objectId) };
|
|
24885
|
-
updated = true;
|
|
24886
|
-
}
|
|
24887
|
-
// If anchors were updated, rebuild the anchor index and persist the change
|
|
24888
|
-
if (updated) {
|
|
24889
|
-
this._store.objects.update(obj);
|
|
24890
|
-
}
|
|
24891
|
-
}
|
|
24892
|
-
});
|
|
24893
|
-
});
|
|
24894
|
-
// Rebuild anchor index after all anchor updates
|
|
24895
|
-
this._anchorManager.rebuildIndex();
|
|
24896
|
-
// Mark selection group as selected
|
|
24897
|
-
selectionGroup.isSelected = true;
|
|
24898
|
-
// Set rotation for single object
|
|
24899
|
-
if (copiedObjects.length === 1) {
|
|
24900
|
-
selectionGroup.rotation = copiedObjects[0].rotation;
|
|
24901
|
-
}
|
|
24902
|
-
// For cross-workspace paste, set the selection group's position before inserting
|
|
24903
|
-
// it into the store. This mirrors the existing pattern where objects have
|
|
24904
|
-
// updatePosition called before addObject, so the correct position is captured
|
|
24905
|
-
// in the single initial insert with no separate Yjs update (and no extra undo step).
|
|
24906
|
-
if (isDifferentWorkspace) {
|
|
24907
|
-
if (x !== undefined && y !== undefined) {
|
|
24908
|
-
// Explicit cursor position provided (e.g. right-click paste)
|
|
24909
|
-
selectionGroup.updatePosition(x, y);
|
|
24910
|
-
}
|
|
24911
|
-
else {
|
|
24912
|
-
// Ctrl+V paste: center objects in the current viewport
|
|
24913
|
-
selectionGroup.centerInViewport();
|
|
24914
|
-
}
|
|
24915
|
-
}
|
|
24916
|
-
// Add the selection group (inserts with the already-adjusted position)
|
|
24917
|
-
this.addSelectionGroup(selectionGroup);
|
|
24918
|
-
// Bring pasted objects into view with a smooth animation if they are not
|
|
24919
|
-
// fully visible. These only mutate in-memory viewport state (scale, translateX/Y)
|
|
24920
|
-
// and do not produce any Yjs writes, so they have no impact on the undo history.
|
|
24921
|
-
this.engine.viewport.bringIntoViewIfNeeded(selectionGroup);
|
|
24922
|
-
this._store.state.isSelecting = false;
|
|
24923
|
-
// Defer creating copies for future pastes to next frame to avoid
|
|
24924
|
-
// doubling the object creation cost in the current paste frame
|
|
24925
|
-
requestAnimationFrame(() => {
|
|
24926
|
-
const newSelectionGroup = this._store.selectionGroup;
|
|
24927
|
-
if (newSelectionGroup) {
|
|
24928
|
-
const newIdMapping = new Map();
|
|
24929
|
-
const newCopiedObjects = newSelectionGroup.objects
|
|
24930
|
-
.sort((a, b) => a.zIndex - b.zIndex)
|
|
24931
|
-
.map(obj => {
|
|
24932
|
-
const copiedObj = obj.copy();
|
|
24933
|
-
newIdMapping.set(copiedObj.id, obj.id);
|
|
24934
|
-
return copiedObj;
|
|
24935
|
-
});
|
|
24936
|
-
this._store.state.copiedObjects = newCopiedObjects;
|
|
24937
|
-
this._store.state.copiedObjectIdMapping = newIdMapping;
|
|
24938
|
-
}
|
|
24939
|
-
});
|
|
24940
|
-
this._store.setState('activeTool', this._toolRegistry.getTool('selection'));
|
|
24941
|
-
this.engine.emitObjectsChange();
|
|
24942
|
-
this.rerender();
|
|
24943
|
-
}
|
|
24944
25259
|
/**
|
|
24945
25260
|
* Moves objects one step forward in the z-order stack.
|
|
24946
25261
|
* @param object - Optional specific object to move; defaults to all selected objects
|
|
@@ -27086,6 +27401,8 @@ const KritzelEngine = class {
|
|
|
27086
27401
|
viewportChange;
|
|
27087
27402
|
/** Emitted when the awareness state changes (remote user cursors, presence). */
|
|
27088
27403
|
awarenessChange;
|
|
27404
|
+
/** Emitted when notifications change. */
|
|
27405
|
+
notificationsChange;
|
|
27089
27406
|
forceUpdate = 0;
|
|
27090
27407
|
/** Manually triggers the `objectsSelectionChange` event. */
|
|
27091
27408
|
async triggerSelectionChange() {
|
|
@@ -27200,19 +27517,56 @@ const KritzelEngine = class {
|
|
|
27200
27517
|
this.viewport.handleResize();
|
|
27201
27518
|
}
|
|
27202
27519
|
handleKeyDown(ev) {
|
|
27203
|
-
if (this.core.store.isDisabled || !this.
|
|
27520
|
+
if (this.core.store.isDisabled || !this.shouldHandleGlobalShortcutEvent(ev)) {
|
|
27204
27521
|
return;
|
|
27205
27522
|
}
|
|
27206
27523
|
this.keyHandler.handleKeyDown(ev);
|
|
27207
27524
|
}
|
|
27208
27525
|
handleKeyUp(ev) {
|
|
27209
|
-
if (this.core.store.isDisabled || !this.
|
|
27526
|
+
if (this.core.store.isDisabled || !this.shouldHandleGlobalShortcutEvent(ev)) {
|
|
27210
27527
|
return;
|
|
27211
27528
|
}
|
|
27212
27529
|
this.keyHandler.handleKeyUp(ev);
|
|
27213
27530
|
}
|
|
27531
|
+
handleCopy(ev) {
|
|
27532
|
+
if (this.core.store.isDisabled || !this.shouldHandleGlobalShortcutEvent(ev)) {
|
|
27533
|
+
return;
|
|
27534
|
+
}
|
|
27535
|
+
if (!this.core.store.selectionGroup || this.core.store.activeText || this.core.store.activeShape) {
|
|
27536
|
+
return;
|
|
27537
|
+
}
|
|
27538
|
+
if (ev.cancelable) {
|
|
27539
|
+
ev.preventDefault();
|
|
27540
|
+
}
|
|
27541
|
+
this.core.clipboardManager.copy(ev);
|
|
27542
|
+
this.core.rerender();
|
|
27543
|
+
}
|
|
27544
|
+
handleCut(ev) {
|
|
27545
|
+
if (this.core.store.isDisabled || !this.shouldHandleGlobalShortcutEvent(ev)) {
|
|
27546
|
+
return;
|
|
27547
|
+
}
|
|
27548
|
+
if (!this.core.store.selectionGroup || this.core.store.activeText || this.core.store.activeShape) {
|
|
27549
|
+
return;
|
|
27550
|
+
}
|
|
27551
|
+
if (ev.cancelable) {
|
|
27552
|
+
ev.preventDefault();
|
|
27553
|
+
}
|
|
27554
|
+
this.core.clipboardManager.cut(ev);
|
|
27555
|
+
}
|
|
27556
|
+
handlePaste(ev) {
|
|
27557
|
+
if (this.core.store.isDisabled || !this.shouldHandleGlobalShortcutEvent(ev)) {
|
|
27558
|
+
return;
|
|
27559
|
+
}
|
|
27560
|
+
if (this.core.store.activeText || this.core.store.activeShape) {
|
|
27561
|
+
return;
|
|
27562
|
+
}
|
|
27563
|
+
if (ev.cancelable) {
|
|
27564
|
+
ev.preventDefault();
|
|
27565
|
+
}
|
|
27566
|
+
void this.core.clipboardManager.paste(undefined, undefined, ev);
|
|
27567
|
+
}
|
|
27214
27568
|
/**
|
|
27215
|
-
|
|
27569
|
+
* Determines if the engine should handle a keyboard/clipboard shortcut event.
|
|
27216
27570
|
* Returns true only if:
|
|
27217
27571
|
* - The event originates from within the engine component, OR
|
|
27218
27572
|
* - The event target is not an interactive element that needs keyboard input
|
|
@@ -27220,7 +27574,7 @@ const KritzelEngine = class {
|
|
|
27220
27574
|
* This prevents conflicts with inputs, textareas, dialogs, or other
|
|
27221
27575
|
* interactive elements that need their own keyboard handling.
|
|
27222
27576
|
*/
|
|
27223
|
-
|
|
27577
|
+
shouldHandleGlobalShortcutEvent(ev) {
|
|
27224
27578
|
const path = ev.composedPath();
|
|
27225
27579
|
// Check if event path includes our host - works reliably with Shadow DOM
|
|
27226
27580
|
if (path.includes(this.host)) {
|
|
@@ -27316,11 +27670,11 @@ const KritzelEngine = class {
|
|
|
27316
27670
|
}
|
|
27317
27671
|
/** Copies the currently selected objects to the internal clipboard. */
|
|
27318
27672
|
async copy() {
|
|
27319
|
-
this.core.copy();
|
|
27673
|
+
this.core.clipboardManager.copy();
|
|
27320
27674
|
}
|
|
27321
27675
|
/** Cuts the currently selected objects to the internal clipboard (deletes them from the canvas). */
|
|
27322
27676
|
async cut() {
|
|
27323
|
-
this.core.cut();
|
|
27677
|
+
this.core.clipboardManager.cut();
|
|
27324
27678
|
}
|
|
27325
27679
|
/**
|
|
27326
27680
|
* Pastes previously copied objects at the specified world coordinates.
|
|
@@ -27328,7 +27682,16 @@ const KritzelEngine = class {
|
|
|
27328
27682
|
* @param y - Y position in world coordinates.
|
|
27329
27683
|
*/
|
|
27330
27684
|
async paste(x, y) {
|
|
27331
|
-
this.core.
|
|
27685
|
+
const hasPermission = await this.core.permissionManager.requestPermission('clipboard-read');
|
|
27686
|
+
if (hasPermission !== 'granted') {
|
|
27687
|
+
this.notificationsChange.emit({
|
|
27688
|
+
type: 'error',
|
|
27689
|
+
message: 'Clipboard read permission is required to paste content. Please grant permission and try again.',
|
|
27690
|
+
id: schema_constants.ObjectHelper.generateUUID(),
|
|
27691
|
+
});
|
|
27692
|
+
return;
|
|
27693
|
+
}
|
|
27694
|
+
this.core.clipboardManager.paste(x, y);
|
|
27332
27695
|
}
|
|
27333
27696
|
/**
|
|
27334
27697
|
* Moves an object one layer forward in the z-order.
|
|
@@ -27819,10 +28182,6 @@ const KritzelEngine = class {
|
|
|
27819
28182
|
async worldToScreen(x, y) {
|
|
27820
28183
|
return this.viewport.worldToScreen(x, y);
|
|
27821
28184
|
}
|
|
27822
|
-
/** Returns the objects currently stored in the internal clipboard from a prior `copy()` call. */
|
|
27823
|
-
async getCopiedObjects() {
|
|
27824
|
-
return this.core.store.state.copiedObjects || [];
|
|
27825
|
-
}
|
|
27826
28185
|
/** Returns all objects currently visible within the viewport bounds. */
|
|
27827
28186
|
async getObjectsInViewport() {
|
|
27828
28187
|
return this.core.getObjectsInViewport();
|
|
@@ -28479,6 +28838,7 @@ const KritzelEngine = class {
|
|
|
28479
28838
|
this.objectsInViewportChange = index.createEvent(this, "objectsInViewportChange");
|
|
28480
28839
|
this.viewportChange = index.createEvent(this, "viewportChange");
|
|
28481
28840
|
this.awarenessChange = index.createEvent(this, "awarenessChange");
|
|
28841
|
+
this.notificationsChange = index.createEvent(this, "notificationsChange");
|
|
28482
28842
|
this.core = new KritzelCore(this);
|
|
28483
28843
|
}
|
|
28484
28844
|
disconnectedCallback() {
|
|
@@ -28757,7 +29117,6 @@ const KritzelEngine = class {
|
|
|
28757
29117
|
this.core.resetActiveShape();
|
|
28758
29118
|
}
|
|
28759
29119
|
this.core.store.state.skipContextMenu = false;
|
|
28760
|
-
this.core.store.state.copiedObjects = undefined;
|
|
28761
29120
|
if (activeTool) {
|
|
28762
29121
|
this.activeToolChange.emit(activeTool);
|
|
28763
29122
|
}
|
|
@@ -29409,7 +29768,7 @@ const KritzelExport = class {
|
|
|
29409
29768
|
return (index.h("div", { class: "export-tab-content" }, index.h("kritzel-input", { label: this.terms['export.filename.label'] ?? 'Filename', value: this.exportFilename, placeholder: this.terms['export.filename.placeholder'] ?? 'Enter filename', suffix: ".json", onValueChange: this.handleFilenameChange })));
|
|
29410
29769
|
}
|
|
29411
29770
|
render() {
|
|
29412
|
-
return (index.h(index.Host, { key: '
|
|
29771
|
+
return (index.h(index.Host, { key: 'fd219fffd4d8bb528e6a90055c2b43a5f5a73060' }, index.h("kritzel-dialog", { key: '9f4ba5b05f5ad31084aab457386a86cbc6d4f2bc', isOpen: this.isDialogOpen, dialogTitle: this.terms['export.dialogTitle'] ?? 'Export', closable: true, contained: true, onDialogClose: this.closeDialog }, index.h("div", { key: '920bb8f20b42897680084bde47270b3812e2f3e4', class: "export-content" }, index.h("kritzel-pill-tabs", { key: '7090bd0a371457adceaa4bd7461a616839a66349', tabs: this.tabs, value: this.activeTab, onValueChange: this.handleTabChange }), this.activeTab === 'viewport' && this.renderViewportExport(), this.activeTab === 'workspace' && this.renderWorkspaceExport(), index.h("button", { key: 'ddf36c1e7cb81409c2cecfa6585e0f1dd7aca2c3', class: "export-primary-button", onClick: this.handleExport }, this.terms['export.exportButton'] ?? 'Export')))));
|
|
29413
29772
|
}
|
|
29414
29773
|
};
|
|
29415
29774
|
KritzelExport.style = kritzelExportCss();
|
|
@@ -29424,7 +29783,7 @@ const KritzelFont = class {
|
|
|
29424
29783
|
size = 24;
|
|
29425
29784
|
color = '#000000';
|
|
29426
29785
|
render() {
|
|
29427
|
-
return (index.h(index.Host, { key: '
|
|
29786
|
+
return (index.h(index.Host, { key: 'e37350dd092fb7c81a5624bfdc39c3b9af66b894' }, index.h("div", { key: 'a962ccc23a48f62b86d49ae41b1c9c27bdc9a5b9', class: "font-preview", style: {
|
|
29428
29787
|
fontFamily: this.fontFamily,
|
|
29429
29788
|
fontSize: `${this.size}px`,
|
|
29430
29789
|
color: this.color
|
|
@@ -29500,7 +29859,7 @@ const KritzelFontSize = class {
|
|
|
29500
29859
|
render() {
|
|
29501
29860
|
const color = 'var(--kritzel-global-text-primary)';
|
|
29502
29861
|
const sizes = this.sizes ?? [];
|
|
29503
|
-
return (index.h(index.Host, { key: '
|
|
29862
|
+
return (index.h(index.Host, { key: 'a314e990b56cb4e819c4d83a139016b1658606b8' }, sizes.map(size => (index.h("div", { tabIndex: 0, class: {
|
|
29504
29863
|
'size-container': true,
|
|
29505
29864
|
'selected': this.selectedSize === size,
|
|
29506
29865
|
}, onClick: () => this.handleSizeClick(size), onKeyDown: event => this.handleKeyDown(event, size) }, index.h("kritzel-font", { fontFamily: this.fontFamily, size: size, color: color }))))));
|
|
@@ -29567,7 +29926,7 @@ const KritzelInput = class {
|
|
|
29567
29926
|
this.valueChange.emit(input.value);
|
|
29568
29927
|
};
|
|
29569
29928
|
render() {
|
|
29570
|
-
return (index.h(index.Host, { key: '
|
|
29929
|
+
return (index.h(index.Host, { key: '7e16272802a5485207721f4f01ddf8e956b56dac' }, index.h("div", { key: 'ab60dacd08c6199db507d896c00cd0c788ecf7fa', class: "input-container" }, this.label && index.h("label", { key: 'e2e5769ca2954442da5a0f2a2abb07847986eac8', class: "input-label" }, this.label), index.h("div", { key: 'e7131f6d1a770cf71de9f7086e3a8a092296b80e', class: { 'input-wrapper': true, 'has-suffix': !!this.suffix } }, index.h("input", { key: '565cb30ed36818badc148475c596b468cdd2a65b', type: this.type, class: "text-input", value: this.inputValue, placeholder: this.placeholder, disabled: this.disabled, onInput: this.handleInput }), this.suffix && index.h("span", { key: 'ec4afb63443b6c89a829e515df7d33066f0f8def', class: "input-suffix" }, this.suffix)))));
|
|
29571
29930
|
}
|
|
29572
29931
|
static get watchers() { return {
|
|
29573
29932
|
"value": [{
|
|
@@ -29707,7 +30066,7 @@ const KritzelLoginDialog = class {
|
|
|
29707
30066
|
this.dialogClosed.emit();
|
|
29708
30067
|
};
|
|
29709
30068
|
render() {
|
|
29710
|
-
return (index.h(index.Host, { key: '
|
|
30069
|
+
return (index.h(index.Host, { key: '6ef65077c95d32fee8da4b70ad2e832ad1bb78f7' }, index.h("kritzel-dialog", { key: '04f3d3350393475c7267d8ca90c0b3f0fce10c38', dialogTitle: this.dialogTitle, isOpen: this.isDialogOpen, onDialogClose: this.closeDialog, size: "small", contained: true }, index.h("div", { key: 'c2ed4e339d86dcea23b4a0778b8966a6ae36107a', class: "login-content" }, this.subtitle && (index.h("p", { key: 'ae46baa70526d057b3427459903287489e645e08', class: "login-subtitle" }, this.subtitle)), index.h("div", { key: '1055d5861e5281be234094a3c5c86a6aaf58935f', class: "login-providers" }, this.providers.map(provider => (index.h("button", { key: provider.name, class: {
|
|
29711
30070
|
'provider-button': true,
|
|
29712
30071
|
'is-loading': this.loadingProvider === provider.name,
|
|
29713
30072
|
'is-disabled': this.loadingProvider !== null && this.loadingProvider !== provider.name,
|
|
@@ -29813,15 +30172,15 @@ const KritzelMasterDetail = class {
|
|
|
29813
30172
|
const selectedItem = this.items.find(item => item.id === this.selectedItemId);
|
|
29814
30173
|
const panelId = 'master-detail-panel';
|
|
29815
30174
|
const selectedTabId = selectedItem ? `tab-${selectedItem.id}` : undefined;
|
|
29816
|
-
return (index.h(index.Host, { key: '
|
|
30175
|
+
return (index.h(index.Host, { key: 'e094bc3df0e0d1598e84c9a17a033079b1db33f6' }, index.h("div", { key: '79509ba5d63703fe36650b07b5172f77bd6eafde', class: {
|
|
29817
30176
|
'master-detail-container': true,
|
|
29818
30177
|
'is-mobile-detail-visible': this.showMobileDetail,
|
|
29819
|
-
} }, index.h("nav", { key: '
|
|
30178
|
+
} }, index.h("nav", { key: '79d200d8c2e54789a33fc88b07c48f034de140ad', class: "master-menu", role: "tablist", "aria-orientation": "vertical", "aria-label": "Settings categories" }, this.items.map((item, index$1) => (index.h("button", { key: item.id, id: `tab-${item.id}`, ref: el => this.setTabRef(el, index$1), class: {
|
|
29820
30179
|
'menu-item': true,
|
|
29821
30180
|
'is-selected': item.id === this.selectedItemId,
|
|
29822
30181
|
'is-disabled': !!item.disabled,
|
|
29823
30182
|
'is-focused': index$1 === this.focusedIndex,
|
|
29824
|
-
}, role: "tab", "aria-selected": item.id === this.selectedItemId ? 'true' : 'false', "aria-controls": panelId, "aria-disabled": item.disabled ? 'true' : undefined, tabIndex: this.getTabIndex(item, index$1), disabled: item.disabled, onClick: () => this.handleItemClick(item), onKeyDown: e => this.handleKeyDown(e, item, index$1), onFocus: () => this.handleFocus(index$1), onBlur: this.handleBlur }, item.icon && (index.h("kritzel-icon", { name: item.icon, size: 20, class: "menu-item-icon" })), index.h("span", { class: "menu-item-label" }, item.label), index.h("span", { class: "menu-item-chevron", "aria-hidden": "true" }, index.h("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "1.5", "stroke-linecap": "round", "stroke-linejoin": "round" }, index.h("path", { d: "m9 18 6-6-6-6" }))))))), index.h("div", { key: '
|
|
30183
|
+
}, role: "tab", "aria-selected": item.id === this.selectedItemId ? 'true' : 'false', "aria-controls": panelId, "aria-disabled": item.disabled ? 'true' : undefined, tabIndex: this.getTabIndex(item, index$1), disabled: item.disabled, onClick: () => this.handleItemClick(item), onKeyDown: e => this.handleKeyDown(e, item, index$1), onFocus: () => this.handleFocus(index$1), onBlur: this.handleBlur }, item.icon && (index.h("kritzel-icon", { name: item.icon, size: 20, class: "menu-item-icon" })), index.h("span", { class: "menu-item-label" }, item.label), index.h("span", { class: "menu-item-chevron", "aria-hidden": "true" }, index.h("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "1.5", "stroke-linecap": "round", "stroke-linejoin": "round" }, index.h("path", { d: "m9 18 6-6-6-6" }))))))), index.h("div", { key: '642b65781509d192330bb2602dd081585d16f76d', id: panelId, class: "detail-panel", role: "tabpanel", "aria-labelledby": selectedTabId }, index.h("button", { key: '18a922dbaad63f05bc3ca7de176de4996b5d7fcb', class: "mobile-back-button", onClick: this.handleBackClick, "aria-label": "Back to menu" }, index.h("kritzel-icon", { key: 'b31732cef2ffdb78e67be7ab793aaaf60e373763', name: "chevron-left", size: 20, class: "mobile-back-icon" }), "Back"), index.h("slot", { key: '48fe4ae631a8c0b2db9e4a232edb6300d603562c' })))));
|
|
29825
30184
|
}
|
|
29826
30185
|
static get watchers() { return {
|
|
29827
30186
|
"selectedItemId": [{
|
|
@@ -29894,7 +30253,7 @@ const KritzelMenu = class {
|
|
|
29894
30253
|
this.itemCloseChildMenu.emit(event.detail);
|
|
29895
30254
|
};
|
|
29896
30255
|
render() {
|
|
29897
|
-
return (index.h(index.Host, { key: '
|
|
30256
|
+
return (index.h(index.Host, { key: '6dfdc7928ae69aa191b2c64f9db79801e6978e92', tabIndex: 0, onClick: e => e.stopPropagation() }, this.openChildMenuItem && index.h("div", { key: 'ab8fa25f1b6ee0b7960cb0df84c40b1a7648c4e9', class: "has-open-child-overlay", onClick: this.onOverlayClick }), this.items.map(item => (index.h("kritzel-menu-item", { key: item.id, "data-testid": `menu-item-${item.id}`, item: item, parent: this.parent, style: { pointerEvents: this.editingMenuItem && !item.isEditing ? 'none' : 'auto' }, onItemSelect: this.handleItemSelect, onItemSave: this.handleSave, onItemCancel: this.handleCancel, onItemToggleChildMenu: this.handleToggleChildMenu, onItemCloseChildMenu: this.handleCloseChildMenu })))));
|
|
29898
30257
|
}
|
|
29899
30258
|
};
|
|
29900
30259
|
KritzelMenu.style = kritzelMenuCss();
|
|
@@ -29999,12 +30358,12 @@ const KritzelMenuItem = class {
|
|
|
29999
30358
|
];
|
|
30000
30359
|
}
|
|
30001
30360
|
render() {
|
|
30002
|
-
return (index.h(index.Host, { key: '
|
|
30361
|
+
return (index.h(index.Host, { key: 'dbdcfcee7fd36fe0b9c405dd3d1641aa62465e53', tabIndex: this.item.isDisabled ? -1 : 0, class: {
|
|
30003
30362
|
'selected': this.item.isSelected,
|
|
30004
30363
|
'editing': this.item.isEditing,
|
|
30005
30364
|
'disabled': this.item.isDisabled,
|
|
30006
30365
|
'child-open': this.item.isChildMenuOpen,
|
|
30007
|
-
}, onClick: this.handleItemSelect }, index.h("div", { key: '
|
|
30366
|
+
}, onClick: this.handleItemSelect }, index.h("div", { key: 'ef97c7cf48190c1bbdde0dd9011cc1d5674b7c94', class: "menu-item-overlay" }), this.item.isEditing ? this.renderEditMode() : this.renderViewMode()));
|
|
30008
30367
|
}
|
|
30009
30368
|
static get watchers() { return {
|
|
30010
30369
|
"item": [{
|
|
@@ -30077,11 +30436,80 @@ const KritzelMoreMenu = class {
|
|
|
30077
30436
|
this.closeMenu();
|
|
30078
30437
|
};
|
|
30079
30438
|
render() {
|
|
30080
|
-
return (index.h(index.Host, { key: '
|
|
30439
|
+
return (index.h(index.Host, { key: '3e7179c87713cb0087d2d2053f97db8f603f7321', class: { mobile: this.isTouchDevice }, style: { display: this.visible ? '' : 'none' } }, index.h("div", { key: '23d6be1ec2c25cd0335c1134f18aad7d5be25c85', class: { 'more-menu-wrapper': true, visible: this.visible } }, index.h("button", { key: 'e3064ba3f7b4c20e8447e16327b73d0f47f3842b', class: "more-menu-button", "data-testid": "more-menu-button", onClick: this.toggleMenu, "aria-label": this.terms['moreMenu.ariaLabel'] ?? 'More options' }, index.h("kritzel-icon", { key: 'feed090efe4f80c62a29c8146c2d7d8041624381', name: this.icon, size: this.iconSize })), index.h("kritzel-portal", { key: '7b1a5db932c7bfb5ea8f4d666571c4f7fbbcd238', anchor: this.menuAnchor, offsetY: this.offsetY, onClose: this.closeMenu }, index.h("kritzel-menu", { key: '65b1225b15a494d49712ad1d2d108e90f09507e9', items: this.visibleItems, onItemSelect: this.handleMenuItemSelect })))));
|
|
30081
30440
|
}
|
|
30082
30441
|
};
|
|
30083
30442
|
KritzelMoreMenu.style = kritzelMoreMenuCss();
|
|
30084
30443
|
|
|
30444
|
+
const kritzelNotificationCardCss = () => `:host{display:block}.card{box-sizing:border-box;width:100%;max-width:var(--kritzel-notification-card-max-width, 360px);margin-inline:auto;font-family:var(--kritzel-font-family, sans-serif);padding:var(--kritzel-notification-card-padding, 12px 14px);border:var(--kritzel-notification-card-border, 1px solid #e5e7eb);border-radius:var(--kritzel-notification-card-border-radius, 12px);background-color:var(--kritzel-notification-card-background-color, #ffffff);color:var(--kritzel-notification-card-color, #111827);box-shadow:var(--kritzel-notification-card-box-shadow, 0 8px 20px rgba(15, 23, 42, 0.08))}.card-header{display:flex;align-items:center;justify-content:space-between;gap:var(--kritzel-notification-card-header-gap, 8px);margin-bottom:var(--kritzel-notification-card-header-margin-bottom, 8px)}.header-right{display:inline-flex;align-items:center;gap:var(--kritzel-notification-card-header-right-gap, 6px)}.type-pill{display:inline-flex;align-items:center;justify-content:center;min-height:var(--kritzel-notification-card-pill-height, 22px);padding:var(--kritzel-notification-card-pill-padding, 0 8px);border-radius:var(--kritzel-notification-card-pill-border-radius, 999px);background-color:var(--kritzel-notification-card-pill-background-color, #eff6ff);color:var(--kritzel-notification-card-pill-color, #1d4ed8);font-size:var(--kritzel-notification-card-pill-font-size, 12px);font-weight:var(--kritzel-notification-card-pill-font-weight, 600);line-height:1}.card.type-info .type-pill{background-color:var(--kritzel-notification-card-info-pill-background-color, #eff6ff);color:var(--kritzel-notification-card-info-pill-color, #1d4ed8)}.card.type-warning .type-pill{background-color:var(--kritzel-notification-card-warning-pill-background-color, #fff7ed);color:var(--kritzel-notification-card-warning-pill-color, #b45309)}.card.type-error .type-pill{background-color:var(--kritzel-notification-card-error-pill-background-color, #fef2f2);color:var(--kritzel-notification-card-error-pill-color, #b91c1c)}.timestamp{color:var(--kritzel-notification-card-timestamp-color, #6b7280);font-size:var(--kritzel-notification-card-timestamp-font-size, 12px);white-space:nowrap}.dismiss-button{display:inline-flex;align-items:center;justify-content:center;width:var(--kritzel-notification-card-dismiss-button-size, 24px);height:var(--kritzel-notification-card-dismiss-button-size, 24px);padding:0;border:none;border-radius:var(--kritzel-notification-card-dismiss-button-border-radius, 6px);background:var(--kritzel-notification-card-dismiss-button-background-color, transparent);color:var(--kritzel-notification-card-dismiss-button-color, #4b5563);cursor:var(--kritzel-global-pointer-cursor, pointer);-webkit-tap-highlight-color:transparent}.dismiss-button:hover{background:var(--kritzel-notification-card-dismiss-button-hover-background-color, #f3f4f6)}.dismiss-button:active{background:var(--kritzel-notification-card-dismiss-button-active-background-color, #e5e7eb)}.dismiss-button:focus-visible{outline:revert}.message{margin:0;color:var(--kritzel-notification-card-message-color, inherit);font-size:var(--kritzel-notification-card-message-font-size, 14px);line-height:var(--kritzel-notification-card-message-line-height, 1.45);word-break:break-word}`;
|
|
30445
|
+
|
|
30446
|
+
const KritzelNotificationCard = class {
|
|
30447
|
+
constructor(hostRef) {
|
|
30448
|
+
index.registerInstance(this, hostRef);
|
|
30449
|
+
this.dismiss = index.createEvent(this, "dismiss");
|
|
30450
|
+
this.hoverChange = index.createEvent(this, "hoverChange");
|
|
30451
|
+
}
|
|
30452
|
+
/** Notification data rendered by this card. */
|
|
30453
|
+
notification;
|
|
30454
|
+
/** Whether a formatted timestamp should be displayed when available. */
|
|
30455
|
+
showTimestamp = true;
|
|
30456
|
+
/** Locale used for formatting the timestamp. */
|
|
30457
|
+
locale;
|
|
30458
|
+
/** Emitted when the notification should be dismissed manually. */
|
|
30459
|
+
dismiss;
|
|
30460
|
+
/** Emitted when pointer hover state changes. */
|
|
30461
|
+
hoverChange;
|
|
30462
|
+
handleDismissClick = (event) => {
|
|
30463
|
+
event.stopPropagation();
|
|
30464
|
+
this.dismiss.emit();
|
|
30465
|
+
};
|
|
30466
|
+
handleMouseEnter = () => {
|
|
30467
|
+
this.hoverChange.emit(true);
|
|
30468
|
+
};
|
|
30469
|
+
handleMouseLeave = () => {
|
|
30470
|
+
this.hoverChange.emit(false);
|
|
30471
|
+
};
|
|
30472
|
+
get type() {
|
|
30473
|
+
return this.notification?.type ?? 'info';
|
|
30474
|
+
}
|
|
30475
|
+
get role() {
|
|
30476
|
+
return this.type === 'error' ? 'alert' : 'status';
|
|
30477
|
+
}
|
|
30478
|
+
getTypeLabel(type) {
|
|
30479
|
+
switch (type) {
|
|
30480
|
+
case 'warning':
|
|
30481
|
+
return 'Warning';
|
|
30482
|
+
case 'error':
|
|
30483
|
+
return 'Error';
|
|
30484
|
+
default:
|
|
30485
|
+
return 'Info';
|
|
30486
|
+
}
|
|
30487
|
+
}
|
|
30488
|
+
formatTimestamp(timestamp) {
|
|
30489
|
+
if (!timestamp || !this.showTimestamp) {
|
|
30490
|
+
return null;
|
|
30491
|
+
}
|
|
30492
|
+
const date = timestamp instanceof Date ? timestamp : new Date(timestamp);
|
|
30493
|
+
if (Number.isNaN(date.getTime())) {
|
|
30494
|
+
return null;
|
|
30495
|
+
}
|
|
30496
|
+
return new Intl.DateTimeFormat(this.locale, {
|
|
30497
|
+
dateStyle: 'medium',
|
|
30498
|
+
timeStyle: 'short',
|
|
30499
|
+
}).format(date);
|
|
30500
|
+
}
|
|
30501
|
+
render() {
|
|
30502
|
+
const notification = this.notification;
|
|
30503
|
+
if (!notification) {
|
|
30504
|
+
return index.h(index.Host, null);
|
|
30505
|
+
}
|
|
30506
|
+
const type = this.type;
|
|
30507
|
+
const timestamp = this.formatTimestamp(notification.timestamp);
|
|
30508
|
+
return (index.h(index.Host, null, index.h("article", { class: { card: true, [`type-${type}`]: true }, role: this.role, "aria-live": "polite", onMouseEnter: this.handleMouseEnter, onMouseLeave: this.handleMouseLeave }, index.h("header", { class: "card-header" }, index.h("span", { class: "type-pill" }, this.getTypeLabel(type)), index.h("div", { class: "header-right" }, timestamp && (index.h("time", { class: "timestamp", dateTime: notification.timestamp?.toISOString() }, timestamp)), index.h("button", { class: "dismiss-button", type: "button", "aria-label": "Dismiss notification", onClick: this.handleDismissClick }, index.h("kritzel-icon", { name: "x", size: 16 })))), index.h("p", { class: "message" }, notification.message))));
|
|
30509
|
+
}
|
|
30510
|
+
};
|
|
30511
|
+
KritzelNotificationCard.style = kritzelNotificationCardCss();
|
|
30512
|
+
|
|
30085
30513
|
const kritzelNumericInputCss = () => `:host{display:block}.input-container{display:flex;flex-direction:column;gap:6px}.input-label{font-size:14px;font-weight:500;color:var(--kritzel-numeric-input-label-color, #333333)}.input-wrapper{display:flex;position:relative}.numeric-input{flex:1;padding:8px 36px 8px 12px;border:1px solid var(--kritzel-numeric-input-border-color, #ebebeb);border-radius:var(--kritzel-numeric-input-border-radius, 6px);font-size:14px;color:var(--kritzel-numeric-input-text-color, #333333);background-color:var(--kritzel-numeric-input-input-background, #ffffff);outline:none;transition:border-color 150ms ease;box-sizing:border-box}.numeric-input::-webkit-outer-spin-button,.numeric-input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.numeric-input[type='number']{-moz-appearance:textfield}.numeric-input::selection{background-color:var(--kritzel-numeric-input-selection-background, #007AFF);color:var(--kritzel-numeric-input-selection-color, #ffffff)}.numeric-input:hover{border-color:var(--kritzel-numeric-input-hover-border-color, #cccccc)}.numeric-input:focus{border-color:var(--kritzel-numeric-input-focus-border-color, #0066ff);border-width:2px;padding:7px 35px 7px 11px}.spinner-buttons{position:absolute;right:1px;top:1px;bottom:1px;display:flex;flex-direction:column;border-left:1px solid var(--kritzel-numeric-input-border-color, #ebebeb);border-radius:0 var(--kritzel-numeric-input-spinner-border-radius, 5px) var(--kritzel-numeric-input-spinner-border-radius, 5px) 0;overflow:hidden}.spinner-button{flex:1;display:flex;align-items:center;justify-content:center;width:24px;padding:0;border:none;background-color:var(--kritzel-numeric-input-spinner-background, #f5f5f5);color:var(--kritzel-numeric-input-spinner-color, #666666);cursor:pointer;transition:background-color 150ms ease}.spinner-button:hover{background-color:var(--kritzel-numeric-input-spinner-hover-background, #ebebeb)}.spinner-button:active{background-color:var(--kritzel-numeric-input-spinner-active-background, #dddddd)}.spinner-up{border-bottom:1px solid var(--kritzel-numeric-input-border-color, #ebebeb)}.spinner-icon{width:10px;height:6px}`;
|
|
30086
30514
|
|
|
30087
30515
|
const KritzelNumericInput = class {
|
|
@@ -30175,7 +30603,7 @@ const KritzelNumericInput = class {
|
|
|
30175
30603
|
this.valueChange.emit(newValue);
|
|
30176
30604
|
};
|
|
30177
30605
|
render() {
|
|
30178
|
-
return (index.h(index.Host, { key: '
|
|
30606
|
+
return (index.h(index.Host, { key: '008f18fc5ab81adcd82364706ca7d4c39ea39d77' }, index.h("div", { key: '5d91b2ec6e0458d186d923c422e8f6461ac7c51a', class: "input-container" }, this.label && index.h("label", { key: '45c911f1e11ff8289ab876192511f506eb65c940', class: "input-label" }, this.label), index.h("div", { key: 'f5e0bd1610a4085a291cc1d32787b68066757c69', class: "input-wrapper" }, index.h("input", { key: '897b1af7725f59df86a530836dda802e8cb04038', type: "number", class: "numeric-input", title: "", min: this.min === Number.MIN_SAFE_INTEGER ? undefined : this.min, max: this.max === Number.MAX_SAFE_INTEGER ? undefined : this.max, step: this.step, value: this.inputValue, placeholder: this.placeholder, onInput: this.handleInput, onBlur: this.handleBlur, onKeyDown: this.handleKeyDown, onInvalid: this.handleInvalid }), index.h("div", { key: '1acab70c82ff7431f916685084a6e5dd827cdca3', class: "spinner-buttons" }, index.h("button", { key: 'd93c4bec338d49ead87897baf61d2e036999a035', type: "button", class: "spinner-button spinner-up", onClick: this.handleIncrement, tabIndex: -1, "aria-label": "Increase value" }, index.h("svg", { key: '1e52d43c1eb1e9a43025302a7cd1f3d74c038c36', viewBox: "0 0 10 6", class: "spinner-icon" }, index.h("path", { key: '2a96516390bd9caf5b6a3617d07f7b10e2b42451', d: "M1 5L5 1L9 5", stroke: "currentColor", "stroke-width": "1.5", fill: "none", "stroke-linecap": "round", "stroke-linejoin": "round" }))), index.h("button", { key: '038cf61f4b8982a17bf5c279d78556872a03efea', type: "button", class: "spinner-button spinner-down", onClick: this.handleDecrement, tabIndex: -1, "aria-label": "Decrease value" }, index.h("svg", { key: '30110c2ad975b51049a902953c52be66c1b7b0af', viewBox: "0 0 10 6", class: "spinner-icon" }, index.h("path", { key: '5abe735234debfa80a983d2fb60eeeaedb1dbf9b', d: "M1 1L5 5L9 1", stroke: "currentColor", "stroke-width": "1.5", fill: "none", "stroke-linecap": "round", "stroke-linejoin": "round" }))))))));
|
|
30179
30607
|
}
|
|
30180
30608
|
static get watchers() { return {
|
|
30181
30609
|
"value": [{
|
|
@@ -30214,7 +30642,7 @@ const KritzelOpacitySlider = class {
|
|
|
30214
30642
|
}
|
|
30215
30643
|
render() {
|
|
30216
30644
|
const percentage = this.getPercentage();
|
|
30217
|
-
return (index.h(index.Host, { key: '
|
|
30645
|
+
return (index.h(index.Host, { key: 'e3a18981e5193ecd1ffaae5c807bdf6fa67e9695' }, index.h("div", { key: 'ee5ff0bb1355ca4f7e5d727ab8861933259c1a82', class: "opacity-container" }, index.h("div", { key: '6362fb3dba6910c55f5fe3b2a4245bcbb33dcdbb', class: "slider-wrapper" }, index.h("input", { key: 'f435f00fff7cc17ccdc181f39b29e032f6c5bf8d', type: "range", class: "opacity-slider", min: this.min, max: this.max, step: this.step, value: this.value, onInput: (e) => this.handleInput(e), style: {
|
|
30218
30646
|
'--slider-progress': `${percentage}%`,
|
|
30219
30647
|
'--kritzel-opacity-slider-thumb-border-color': this.previewColor,
|
|
30220
30648
|
} })))));
|
|
@@ -30567,7 +30995,7 @@ const KritzelPortal = class {
|
|
|
30567
30995
|
this.portal.style.visibility = 'visible';
|
|
30568
30996
|
}
|
|
30569
30997
|
render() {
|
|
30570
|
-
return (index.h(index.Host, { key: '
|
|
30998
|
+
return (index.h(index.Host, { key: '95fbfde070f33a7f1b59026de7c687a2f6d0119c', style: { display: this.anchor ? 'block' : 'none' } }, index.h("slot", { key: '14af59a35c5caf71079f7afb5ea6f4c5f13b05f8' })));
|
|
30571
30999
|
}
|
|
30572
31000
|
static get watchers() { return {
|
|
30573
31001
|
"anchor": [{
|
|
@@ -30581,7 +31009,7 @@ const KritzelPortal = class {
|
|
|
30581
31009
|
* This file is auto-generated by the version bump scripts.
|
|
30582
31010
|
* Do not modify manually.
|
|
30583
31011
|
*/
|
|
30584
|
-
const KRITZEL_VERSION = '0.3.
|
|
31012
|
+
const KRITZEL_VERSION = '0.3.19';
|
|
30585
31013
|
|
|
30586
31014
|
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-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)}`;
|
|
30587
31015
|
|
|
@@ -30805,7 +31233,7 @@ const KritzelSettings = class {
|
|
|
30805
31233
|
}
|
|
30806
31234
|
}
|
|
30807
31235
|
render() {
|
|
30808
|
-
return (index.h(index.Host, { key: '
|
|
31236
|
+
return (index.h(index.Host, { key: '6f26bd23bf7bb51653f09b96bafef221c51c2bfa' }, index.h("kritzel-dialog", { key: '49ffda0a422ae1c2c9c8e6e608bce532e7d4099e', isOpen: this.isDialogOpen, dialogTitle: this.t('settings.dialogTitle', 'Settings'), size: "large", contained: true, onDialogClose: this.closeDialog }, index.h("kritzel-master-detail", { key: 'ab5dc7952e555cae6f841ef4de2ab50d7039279b', items: this.categories, selectedItemId: this.selectedCategoryId, onItemSelect: this.handleCategorySelect }, this.renderCategoryContent()))));
|
|
30809
31237
|
}
|
|
30810
31238
|
static get watchers() { return {
|
|
30811
31239
|
"settings": [{
|
|
@@ -30938,9 +31366,9 @@ const KritzelShareDialog = class {
|
|
|
30938
31366
|
this.dialogClosed.emit();
|
|
30939
31367
|
};
|
|
30940
31368
|
render() {
|
|
30941
|
-
return (index.h(index.Host, { key: '
|
|
31369
|
+
return (index.h(index.Host, { key: '031cf5d1ab48f2791454d4c7348352295359d225' }, index.h("kritzel-dialog", { key: 'cdce63c86ca329a97d1f1787adcb2b92bbfa40f9', dialogTitle: this.terms['share.dialogTitle'] ?? 'Share Workspace', size: "small", isOpen: this.isDialogOpen, onDialogClose: this.closeDialog, contained: true }, index.h("div", { key: 'dbb62b3cb175358955b11f6c2d74b0b0eecf212e', class: "share-content" }, index.h("div", { key: '8dc0eaea9644b60ff33812dac20def226fa14232', class: "share-section" }, index.h("div", { key: 'd3cfbf05c28a01681b1223edb6f0b73998ccfd08', class: "share-row" }, index.h("div", { key: '2400f062f92dd918341391cf71086c2676f7fc66', class: "share-label-group" }, index.h("label", { key: 'ab01691b9f53f59f92116a2994b6e3551d347c7b', class: "share-label" }, this.terms['share.linkSharing.label'] ?? 'Link sharing'), index.h("p", { key: 'fd830ad21e32e4fc5d8ba97d5cea7ef8da15fba4', class: "share-description" }, this.internalIsPublic
|
|
30942
31370
|
? (this.terms['share.linkSharing.enabledDescription'] ?? 'Anyone with the link can access this workspace.')
|
|
30943
|
-
: (this.terms['share.linkSharing.disabledDescription'] ?? 'Link sharing is disabled. Only you can access this workspace.'))), index.h("kritzel-slide-toggle", { key: '
|
|
31371
|
+
: (this.terms['share.linkSharing.disabledDescription'] ?? 'Link sharing is disabled. Only you can access this workspace.'))), index.h("kritzel-slide-toggle", { key: '6f1a71ba524b34753ccd5437eab00bfcbeffdd79', checked: this.internalIsPublic, onCheckedChange: this.handleToggleChange, label: this.terms['share.linkSharing.toggleLabel'] ?? 'Enable link sharing' }))), this.internalIsPublic && (index.h("div", { key: '298680e1afdf0094c5393aa95c4983a0a8dd5e18', class: "share-section" }, index.h("div", { key: '546645a748cf9a42df0c8163f2478ef31445273a', class: "share-url-container" }, index.h("input", { key: '9d5b93d762d1cd899f3fc8041380bae603a4919c', type: "text", class: "share-url-input", value: this.getShareUrl(), readOnly: true, onClick: (e) => e.target.select() }), index.h("button", { key: '747a7ca4a25827de6934b7df30cabc2db4583e1b', class: { 'copy-button': true, 'copy-success': this.copySuccess }, onClick: this.handleCopyUrl, title: this.copySuccess ? (this.terms['share.copyLink.copied'] ?? 'Copied!') : (this.terms['share.copyLink.title'] ?? 'Copy link') }, index.h("kritzel-icon", { key: '096ca9a0527796462769dc9d42dd81d8f97f2865', name: this.copySuccess ? 'check' : 'copy', size: 18 })))))))));
|
|
30944
31372
|
}
|
|
30945
31373
|
static get watchers() { return {
|
|
30946
31374
|
"isPublic": [{
|
|
@@ -30978,7 +31406,7 @@ const KritzelSlideToggle = class {
|
|
|
30978
31406
|
}
|
|
30979
31407
|
};
|
|
30980
31408
|
render() {
|
|
30981
|
-
return (index.h(index.Host, { key: '
|
|
31409
|
+
return (index.h(index.Host, { key: '5850c758ccf3263b21c397219bf2301fa088087d', class: { checked: this.checked, disabled: this.disabled }, tabIndex: this.disabled ? -1 : 0, role: "switch", "aria-checked": this.checked ? 'true' : 'false', "aria-disabled": this.disabled ? 'true' : 'false', "aria-label": this.label, onClick: this.handleToggle, onKeyDown: this.handleKeyDown }, index.h("div", { key: 'df0adeca0447a13d5499219ac9d27b526252fdbe', class: "toggle-track" }, index.h("div", { key: '3938239bbdca29e62ed72229dfcf1904fcbaa983', class: "toggle-thumb" }))));
|
|
30982
31410
|
}
|
|
30983
31411
|
};
|
|
30984
31412
|
KritzelSlideToggle.style = kritzelSlideToggleCss();
|
|
@@ -31078,7 +31506,7 @@ const KritzelSplitButton = class {
|
|
|
31078
31506
|
this.menuScrollTop = event.target.scrollTop;
|
|
31079
31507
|
};
|
|
31080
31508
|
render() {
|
|
31081
|
-
return (index.h(index.Host, { key: '
|
|
31509
|
+
return (index.h(index.Host, { key: 'd6856a86b3be4d9a22c5e78df1bda19113cb988b', class: { mobile: this.isTouchDevice } }, index.h("button", { key: 'd26026af275a8bd5717254223d5829e3d7f02bcb', class: "split-main-button", tabIndex: 0, onClick: this.handleButtonClick, disabled: this.mainButtonDisabled, "aria-label": "Main action" }, this.buttonIcon && index.h("kritzel-icon", { key: '1b3e2f4c2f8245b281d0f85458fd6bcc0cc73c59', name: this.buttonIcon })), index.h("div", { key: 'b002b904e168d62075fa086c88df72e36cc8e8c2', class: "split-divider" }), index.h("button", { key: 'd39084da6775613f2c896f3fa1ae4e216505bacc', ref: el => (this.splitMenuButtonRef = el), class: "split-menu-button", tabIndex: 0, onClick: this.toggleMenu, disabled: this.menuButtonDisabled, "aria-label": "Open menu" }, index.h("kritzel-icon", { key: 'b1bc427b0d7cd26a283dbeb772dee0a6d2ca172c', name: this.dropdownIcon })), index.h("kritzel-portal", { key: 'e76300f48a23772a5923ea2cbd0824590302e7e7', anchor: this.anchorElement, offsetY: 4, onClose: this.closeMenu }, index.h("kritzel-menu", { key: 'f110b9315ec63dca9bb1b615136b2d3e284567ba', ref: el => (this.menuRef = el), items: this.items, onItemSelect: this.handleItemSelect, onItemSave: this.handleItemSave, onItemCancel: this.handleItemCancel, onItemToggleChildMenu: this.handleItemToggleChildMenu, onItemCloseChildMenu: this.handleItemCloseChildMenu, onClose: this.closeMenu, onScroll: this.handleScroll }))));
|
|
31082
31510
|
}
|
|
31083
31511
|
};
|
|
31084
31512
|
KritzelSplitButton.style = kritzelSplitButtonCss();
|
|
@@ -31099,7 +31527,7 @@ const KritzelStrokeSize = class {
|
|
|
31099
31527
|
}
|
|
31100
31528
|
render() {
|
|
31101
31529
|
const sizes = this.sizes ?? [];
|
|
31102
|
-
return (index.h(index.Host, { key: '
|
|
31530
|
+
return (index.h(index.Host, { key: 'bde2cc986aebbe869a3eea026654229dee0d3e0e' }, index.h("div", { key: 'f84c4b844b865080f4e0e245bbccc6d77ac3f049', class: "size-grid" }, sizes.map(size => (index.h("div", { tabIndex: 0, class: {
|
|
31103
31531
|
'size-container': true,
|
|
31104
31532
|
'selected': this.selectedSize === size,
|
|
31105
31533
|
}, onClick: () => this.handleSizeClick(size) }, index.h("kritzel-color", { value: 'var(--kritzel-global-text-primary)', size: size })))))));
|
|
@@ -31480,14 +31908,14 @@ const KritzelTooltip = class {
|
|
|
31480
31908
|
}
|
|
31481
31909
|
}
|
|
31482
31910
|
render() {
|
|
31483
|
-
return (index.h(index.Host, { key: '
|
|
31911
|
+
return (index.h(index.Host, { key: 'ba4d13171aa25acac6c615ee12f35eab96d0aad6', style: {
|
|
31484
31912
|
position: 'fixed',
|
|
31485
31913
|
zIndex: '9999',
|
|
31486
31914
|
transition: 'opacity 0.3s ease-in-out, transform 0.3s ease-in-out',
|
|
31487
31915
|
visibility: this.isVisible ? 'visible' : 'hidden',
|
|
31488
31916
|
left: `${this.positionX}px`,
|
|
31489
31917
|
bottom: `${this.positionY}px`,
|
|
31490
|
-
} }, index.h("div", { key: '
|
|
31918
|
+
} }, index.h("div", { key: '923168164a018b08eac4246d88c7f8648b71d078', class: "tooltip-content", onClick: event => event.stopPropagation(), onPointerDown: event => event.stopPropagation(), onMouseDown: event => event.stopPropagation() }, index.h("slot", { key: 'aafad8ab026d591ebb9e2aeffa15d07718eba261' }))));
|
|
31491
31919
|
}
|
|
31492
31920
|
static get watchers() { return {
|
|
31493
31921
|
"triggerElement": [{
|
|
@@ -31528,7 +31956,7 @@ const KritzelUtilityPanel = class {
|
|
|
31528
31956
|
this.redo.emit();
|
|
31529
31957
|
}
|
|
31530
31958
|
render() {
|
|
31531
|
-
return (index.h(index.Host, { key: '
|
|
31959
|
+
return (index.h(index.Host, { key: '22f3826d57b4d8f0e476951a860bde3dbc6c7200' }, index.h("button", { key: 'c3259c5e924b3cf74920dc4676ec8a682c3273e8', class: "utility-button", "data-testid": "utility-undo", disabled: !this.undoState?.canUndo, onClick: event => this.handleUndo(event), "aria-label": this.terms['utility.undo'] ?? 'Undo' }, index.h("kritzel-icon", { key: 'ab4e9da6b60d9fa470fd8f5002f2acd5a758a8ba', name: "undo" })), index.h("button", { key: 'd17e25e78831b5ee13596cc2639cfbb5bd75a1cb', class: "utility-button", "data-testid": "utility-redo", disabled: !this.undoState?.canRedo, onClick: event => this.handleRedo(event), "aria-label": this.terms['utility.redo'] ?? 'Redo' }, index.h("kritzel-icon", { key: '7ae8cec39ffab1303d76315ab85ac575b886b233', name: "redo" })), index.h("div", { key: 'f54e0262f133ad0eed0bbf853b67edd6c2f5e87f', class: "utility-separator" }), index.h("button", { key: '162d6e85965338b5700e661595dc6da6131ebccf', class: "utility-button", "data-testid": "utility-delete", onClick: () => this.delete.emit(), "aria-label": this.terms['utility.delete'] ?? 'Delete selected items' }, index.h("kritzel-icon", { key: 'dc00247ed45f09b86ad9314395f56e70d1122a4b', name: "delete" }))));
|
|
31532
31960
|
}
|
|
31533
31961
|
};
|
|
31534
31962
|
KritzelUtilityPanel.style = kritzelUtilityPanelCss();
|
|
@@ -31549,7 +31977,7 @@ const KritzelWatermark = class {
|
|
|
31549
31977
|
label;
|
|
31550
31978
|
render() {
|
|
31551
31979
|
const label = this.label ?? this.core.localizationManager.translate('watermark.poweredBy');
|
|
31552
|
-
return (index.h(index.Host, { key: '
|
|
31980
|
+
return (index.h(index.Host, { key: '975534180d82064e38fa0289a2955e97a4ca0a08' }, index.h("a", { key: 'c59723d1f5bf3089256c0b610d0574bfc385ef85', class: "watermark-link", href: KRITZEL_WEBSITE_URL, target: "_blank", rel: "noopener noreferrer", part: "watermark", onPointerDown: (ev) => ev.stopPropagation(), onPointerUp: (ev) => ev.stopPropagation() }, label)));
|
|
31553
31981
|
}
|
|
31554
31982
|
};
|
|
31555
31983
|
KritzelWatermark.style = kritzelWatermarkCss();
|
|
@@ -31737,7 +32165,7 @@ const KritzelZoomPanel = class {
|
|
|
31737
32165
|
return Number.isFinite(this.zoomPercent) ? Math.max(1, Math.round(this.zoomPercent)) : 100;
|
|
31738
32166
|
}
|
|
31739
32167
|
render() {
|
|
31740
|
-
return (index.h(index.Host, { key: '
|
|
32168
|
+
return (index.h(index.Host, { key: '00d5c674581d4efa40da3a2ad5cbdd8295406590' }, index.h("div", { key: 'c7a4158f57b8062f37ee69f7b198442ec357d746', class: { panel: true, visible: this.visible } }, index.h("button", { key: 'e20344f5e522d481185a9dab7afdb2668cf44408', class: "zoom-button", type: "button", "aria-label": this.terms['zoom.zoomOut'] ?? 'Zoom out', disabled: this.disabled, onClick: this.handleZoomOut }, index.h("kritzel-icon", { key: '4fc1eeb78669894b0939a96c5e6945cea5056ac1', name: "minus" })), index.h("span", { key: 'ed26096e2ca76fe91b50d73ea6c9481996d01590', class: "zoom-level", "aria-live": "polite" }, this.normalizedZoomPercent, "%"), index.h("button", { key: '42609c6e8558b7d9e9e348b864639ead6c4cc9bb', class: "zoom-button", type: "button", "aria-label": this.terms['zoom.zoomIn'] ?? 'Zoom in', disabled: this.disabled, onClick: this.handleZoomIn }, index.h("kritzel-icon", { key: '3a321afb57f532ef867bae73751314f3fd355214', name: "plus" })))));
|
|
31741
32169
|
}
|
|
31742
32170
|
};
|
|
31743
32171
|
KritzelZoomPanel.style = kritzelZoomPanelCss();
|
|
@@ -31770,6 +32198,7 @@ exports.kritzel_master_detail = KritzelMasterDetail;
|
|
|
31770
32198
|
exports.kritzel_menu = KritzelMenu;
|
|
31771
32199
|
exports.kritzel_menu_item = KritzelMenuItem;
|
|
31772
32200
|
exports.kritzel_more_menu = KritzelMoreMenu;
|
|
32201
|
+
exports.kritzel_notification_card = KritzelNotificationCard;
|
|
31773
32202
|
exports.kritzel_numeric_input = KritzelNumericInput;
|
|
31774
32203
|
exports.kritzel_opacity_slider = KritzelOpacitySlider;
|
|
31775
32204
|
exports.kritzel_pill_tabs = KritzelPillTabs;
|