kritzel-stencil 0.3.18 → 0.3.20
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-mz3pUWW4.js → p-Bm0aKWPw.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-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-D35cwCYd.js +1 -0
- package/dist/stencil/p-e8e69a16.entry.js +9 -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 +8 -2
- package/readme.md +7 -111
- 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-86348986.entry.js +0 -9
- package/dist/stencil/p-DchTXG3V.js +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { r as registerInstance, h, H as Host, c as createEvent, g as getElement } from './index-Dhio9uis.js';
|
|
2
|
-
import { c as KritzelPath, e as KritzelLine, P as KritzelColorHelper, Q as KritzelDevicesHelper, p as KritzelSelectionTool, m as KritzelTextTool, R as KritzelMouseButton, T as DEFAULT_STROKE_SIZES, U as DEFAULT_COLOR_PALETTE, S as ShapeType, D as DEFAULT_BRUSH_CONFIG, i as KritzelBrushTool, k as KritzelEraserTool, x as DEFAULT_LINE_TOOL_CONFIG, j as KritzelLineTool, n as KritzelShapeTool, w as DEFAULT_TEXT_CONFIG, l as KritzelImageTool, G as KritzelAlignment, y as DEFAULT_ASSET_STORAGE_CONFIG, V as ThemeHelper, B as darkTheme, z as lightTheme,
|
|
2
|
+
import { c as KritzelPath, e as KritzelLine, P as KritzelColorHelper, Q as KritzelDevicesHelper, p as KritzelSelectionTool, m as KritzelTextTool, R as KritzelMouseButton, T as DEFAULT_STROKE_SIZES, U as DEFAULT_COLOR_PALETTE, S as ShapeType, D as DEFAULT_BRUSH_CONFIG, i as KritzelBrushTool, k as KritzelEraserTool, x as DEFAULT_LINE_TOOL_CONFIG, j as KritzelLineTool, n as KritzelShapeTool, w as DEFAULT_TEXT_CONFIG, l as KritzelImageTool, G as KritzelAlignment, y as DEFAULT_ASSET_STORAGE_CONFIG, V as ObjectHelper, X as ThemeHelper, B as darkTheme, z as lightTheme, Y as KritzelSelectionGroup, Z as KritzelSelectionBox, _ as KritzelIconRegistry, $ as KritzelKeyboardHelper, a0 as KritzelBaseHandler, K as KritzelBaseObject, a1 as KritzelMathHelper, r as KritzelWorkspace, f as KritzelGroup, d as KritzelImage, g as KritzelShape, b as KritzelText, J as runMigrations, O as CURRENT_WORKSPACE_SCHEMA_VERSION, M as WORKSPACE_MIGRATIONS, N as CURRENT_APP_STATE_SCHEMA_VERSION, L as APP_STATE_MIGRATIONS, o as KritzelCursorHelper, a2 as KritzelClassHelper, a3 as imageCompression, s as KritzelAnchorManager, t as KritzelThemeManager, u as KritzelLocalizationManager, v as KritzelLicenseManager, q as KritzelAssetResolver, a4 as KritzelEventHelper, W as WORKSPACE_EXPORT_VERSION } from './schema.constants-D35cwCYd.js';
|
|
3
3
|
import * as Y from 'yjs';
|
|
4
4
|
import 'y-indexeddb';
|
|
5
5
|
import 'y-websocket';
|
|
@@ -132,16 +132,16 @@ const KritzelAvatar = class {
|
|
|
132
132
|
height: `${this.size}px`,
|
|
133
133
|
fontSize: `${Math.round(this.size * 0.4)}px`,
|
|
134
134
|
};
|
|
135
|
-
return (h(Host, { key: '
|
|
135
|
+
return (h(Host, { key: '4bdbe2c1d5d3a1708189166498ae4e36c19c46ff', style: containerStyles, class: {
|
|
136
136
|
'has-image': !!showImage,
|
|
137
137
|
'has-initials': !!showInitials,
|
|
138
138
|
'has-default': !!showDefaultIcon,
|
|
139
|
-
}, role: "img", "aria-label": this.getDisplayName() || 'User avatar' }, showImage && (h("img", { key: '
|
|
139
|
+
}, role: "img", "aria-label": this.getDisplayName() || 'User avatar' }, showImage && (h("img", { key: '55c3a13c9d514ea700c6b1a9339cd0dff1828b2b', src: imageUrl, alt: "", class: "avatar-image", ref: (el) => {
|
|
140
140
|
if (el) {
|
|
141
141
|
el.referrerPolicy = 'no-referrer';
|
|
142
142
|
el.crossOrigin = 'anonymous';
|
|
143
143
|
}
|
|
144
|
-
}, onError: this.handleImageError })), showInitials && (h("span", { key: '
|
|
144
|
+
}, onError: this.handleImageError })), showInitials && (h("span", { key: 'b60cbe2b94ea1d2cd2a09d10c928290fc1469a4a', class: "avatar-initials", style: { backgroundColor: this.getBackgroundColor() } }, initials)), showDefaultIcon && (h("span", { key: 'e8a0f49952b5b7e5e4a1fe3d67e68a56081d5e4c', class: "avatar-default" }, h("svg", { key: '1fdc256fd53aa5c866bb0e81fdd40393c8a7d69d', viewBox: "0 0 24 24", fill: "currentColor" }, 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" }))))));
|
|
145
145
|
}
|
|
146
146
|
static get watchers() { return {
|
|
147
147
|
"user": [{
|
|
@@ -451,7 +451,7 @@ const KritzelBackToContent = class {
|
|
|
451
451
|
this.backToContent.emit();
|
|
452
452
|
};
|
|
453
453
|
render() {
|
|
454
|
-
return (h(Host, { key: '
|
|
454
|
+
return (h(Host, { key: 'a7d52616642f45a0c0e7b76deb3cc5994184b968' }, h("button", { key: '9e7acae2b62f7f66ee0127545ee8ab115f9d340e', class: { 'back-to-content-button': true, visible: this.visible }, onClick: this.handleClick, "aria-label": this.text }, h("kritzel-icon", { key: '6c404376643554cdb86c33957c066dd4580f19f1', name: "chevrons-left" }))));
|
|
455
455
|
}
|
|
456
456
|
};
|
|
457
457
|
KritzelBackToContent.style = kritzelBackToContentCss();
|
|
@@ -478,11 +478,11 @@ const KritzelButton = class {
|
|
|
478
478
|
this.buttonClick.emit();
|
|
479
479
|
};
|
|
480
480
|
render() {
|
|
481
|
-
return (h(Host, { key: '
|
|
481
|
+
return (h(Host, { key: '0de2b5dcf75de9f5b7de0c6b876bd18733bf21b9' }, h("button", { key: '5ab9d80167c6b90add7779d4b1c3ebb80fafaed5', type: this.type, class: {
|
|
482
482
|
'kritzel-button': true,
|
|
483
483
|
[this.variant]: true,
|
|
484
484
|
'disabled': this.disabled,
|
|
485
|
-
}, disabled: this.disabled, onClick: this.handleClick }, h("slot", { key: '
|
|
485
|
+
}, disabled: this.disabled, onClick: this.handleClick }, h("slot", { key: 'dc105f7d1f87aa55c314d942a1cc6522b272526a' }))));
|
|
486
486
|
}
|
|
487
487
|
};
|
|
488
488
|
KritzelButton.style = kritzelButtonCss();
|
|
@@ -530,13 +530,13 @@ const KritzelColorComponent = class {
|
|
|
530
530
|
render() {
|
|
531
531
|
const resolvedColor = this.resolveColor();
|
|
532
532
|
const isColorVeryLight = this.isLightColor(resolvedColor);
|
|
533
|
-
return (h(Host, { key: '
|
|
533
|
+
return (h(Host, { key: '0d56c7ad01eddd523ebcf11a32e68367c96090bd' }, h("div", { key: '0bef4cb73804b98e6eea6b3cf006c19c8786bdb9', class: "checkerboard-bg", style: {
|
|
534
534
|
width: `${this.size}px`,
|
|
535
535
|
height: `${this.size}px`,
|
|
536
536
|
borderRadius: '50%',
|
|
537
537
|
display: 'inline-block',
|
|
538
538
|
position: 'relative',
|
|
539
|
-
} }, h("div", { key: '
|
|
539
|
+
} }, h("div", { key: '5be9714c3ddd56ae77c2870333ff97a59b58bd45', class: {
|
|
540
540
|
'color-circle': true,
|
|
541
541
|
'white': isColorVeryLight,
|
|
542
542
|
}, style: {
|
|
@@ -592,7 +592,7 @@ const KritzelColorPalette = class {
|
|
|
592
592
|
render() {
|
|
593
593
|
const displayedColors = this.isExpanded ? this.colors : this.colors.slice(0, 6);
|
|
594
594
|
const expandedHeight = this.isExpanded ? this.calculateHeight() : '32px';
|
|
595
|
-
return (h(Host, { key: '
|
|
595
|
+
return (h(Host, { key: '6d003ec5b92f586532782144c25ca5a733741f20' }, h("div", { key: '031838b45da4916aa91d87c066ac950cfe3a1ddc', class: {
|
|
596
596
|
'color-grid': true,
|
|
597
597
|
'expanded': this.isExpanded,
|
|
598
598
|
}, style: {
|
|
@@ -1160,13 +1160,13 @@ const KritzelControls = class {
|
|
|
1160
1160
|
// Separate tool controls from config control
|
|
1161
1161
|
const toolControls = this.internalControls.filter(c => c.type === 'tool' || c.type === 'separator');
|
|
1162
1162
|
const configControl = this.internalControls.find(c => c.type === 'config' && c.name === this.firstConfig?.name);
|
|
1163
|
-
return (h(Host, { key: '
|
|
1163
|
+
return (h(Host, { key: '266e38cdeffb8c22a7f778e865e5fab6b461f5b6', style: { display: this.visible ? '' : 'none' }, class: {
|
|
1164
1164
|
mobile: this.isTouchDevice,
|
|
1165
|
-
} }, this.isUtilityPanelVisible && (h("kritzel-utility-panel", { key: '
|
|
1165
|
+
} }, this.isUtilityPanelVisible && (h("kritzel-utility-panel", { key: '5e75ece000ac02675d3d226461b7f522dcf5ead9', style: {
|
|
1166
1166
|
position: 'absolute',
|
|
1167
1167
|
bottom: '56px',
|
|
1168
1168
|
left: '12px',
|
|
1169
|
-
}, undoState: this.undoState, terms: this.terms, onUndo: () => this.kritzelEngine?.undo(), onRedo: () => this.kritzelEngine?.redo(), onDelete: () => this.kritzelEngine?.delete() })), h("div", { key: '
|
|
1169
|
+
}, undoState: this.undoState, terms: this.terms, onUndo: () => this.kritzelEngine?.undo(), onRedo: () => this.kritzelEngine?.redo(), onDelete: () => this.kritzelEngine?.delete() })), h("div", { key: 'fc98b1675afe1abb6a8d391c4ace34c7f0e46677', class: "kritzel-controls" }, h("div", { key: 'b17bc9e9a65646735c56f78a326a281229fa9790', class: { 'scroll-indicator-left': true, 'visible': this.canScrollLeft } }), h("div", { key: '9ab9d5c44e515551d75f27c31875de72e9d3407c', class: "kritzel-tools-scroll", ref: el => (this.toolsScrollRef = el), onScroll: this.handleToolsScroll }, toolControls.map(control => {
|
|
1170
1170
|
// Check if this control has sub-options (split-button)
|
|
1171
1171
|
if (control.subOptions?.length) {
|
|
1172
1172
|
const selectedSubOption = this.getSelectedSubOption(control);
|
|
@@ -1196,10 +1196,10 @@ const KritzelControls = class {
|
|
|
1196
1196
|
'kritzel-control': true,
|
|
1197
1197
|
'selected': this.activeControl?.name === control?.name,
|
|
1198
1198
|
}, key: control.name, "data-testid": `tool-${control.name}`, onClick: _event => this.handleControlClick?.(control), "aria-label": control.name.charAt(0).toUpperCase() + control.name.slice(1) }, h("kritzel-icon", { name: control.icon })));
|
|
1199
|
-
})), h("div", { key: '
|
|
1199
|
+
})), h("div", { key: 'fad7512f5d1aa68905a56b8f22d498380f166f9f', class: { 'scroll-indicator-right': true, 'visible': this.canScrollRight && !(configControl && this.activeControl && hasConfigUI) } }), configControl && this.activeControl && (h("div", { class: {
|
|
1200
1200
|
'kritzel-config-container': true,
|
|
1201
1201
|
'visible': hasConfigUI,
|
|
1202
|
-
}, key: configControl.name }, h("div", { key: '
|
|
1202
|
+
}, key: configControl.name }, h("div", { key: '2ff7cb3ad18608102f3d8188b5936cf00b00451f', class: { 'config-gradient-left': true, 'visible': this.needsScrolling } }), h("kritzel-tooltip", { key: '10f15f717c8573cbad6ea53b412ad56254099ad1', anchorElement: this.host.shadowRoot?.querySelector('.kritzel-config-container'), triggerElement: this.configTriggerRef }, 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%' } })), h("div", { key: '7ac8214a3dbad5323a38cad3ff7324b57f9dbfb5', tabIndex: hasConfigUI ? 0 : -1, class: "kritzel-config", "data-testid": "tool-config", ref: el => {
|
|
1203
1203
|
if (el)
|
|
1204
1204
|
this.configTriggerRef = el;
|
|
1205
1205
|
}, onKeyDown: event => {
|
|
@@ -1208,7 +1208,7 @@ const KritzelControls = class {
|
|
|
1208
1208
|
}
|
|
1209
1209
|
}, style: {
|
|
1210
1210
|
cursor: 'pointer',
|
|
1211
|
-
} }, this.displayValues && (h("div", { key: '
|
|
1211
|
+
} }, this.displayValues && (h("div", { key: '7e64f79859f7f2b03d72bb7a93fb295e7d2b2ac0', class: "color-container" }, h("kritzel-color", { key: 'b87d9861949379d84954ef1ecb554e13317b3287', value: this.displayValues.color, theme: this.theme, size: 18, style: {
|
|
1212
1212
|
borderRadius: '50%',
|
|
1213
1213
|
border: 'none',
|
|
1214
1214
|
} })))))))));
|
|
@@ -1248,7 +1248,7 @@ const KritzelCurrentUser = class {
|
|
|
1248
1248
|
this.dialogRef?.open();
|
|
1249
1249
|
};
|
|
1250
1250
|
render() {
|
|
1251
|
-
return (h(Host, { key: '
|
|
1251
|
+
return (h(Host, { key: 'bdee6b71c08d6ea22aec40e88ba56077882b301d' }, h("kritzel-avatar", { key: '97bcaaa6b683c0d26d547ac5cbd9df7814f0cd80', user: this.user, size: this.avatarSize, onClick: this.handleAvatarClick }), h("kritzel-current-user-dialog", { key: 'c984ea1803bcf2b06569fd66d12e4e7054235225', ref: el => (this.dialogRef = el), user: this.user, terms: this.terms })));
|
|
1252
1252
|
}
|
|
1253
1253
|
};
|
|
1254
1254
|
KritzelCurrentUser.style = kritzelCurrentUserCss();
|
|
@@ -1282,7 +1282,7 @@ const KritzelCurrentUserDialog = class {
|
|
|
1282
1282
|
}
|
|
1283
1283
|
render() {
|
|
1284
1284
|
const displayName = this.getDisplayName();
|
|
1285
|
-
return (h(Host, { key: '
|
|
1285
|
+
return (h(Host, { key: '042455d68a432e0e218d5b8750fb1d22b0d202fc' }, h("kritzel-dialog", { key: '058abbc8e1c38c647cc02e85c272e89693cab22a', dialogTitle: this.terms['currentUser.dialogTitle'] ?? 'Account', isOpen: this.isDialogOpen, onDialogClose: this.closeDialog, size: "small", contained: true }, h("div", { key: 'ee141b2e91f093527e2d8f6649bade8e1a14f130', class: "user-info" }, h("kritzel-avatar", { key: '2734bb0d3c69df14d26c204eeaf726174afaabc0', user: this.user, size: 80 }), displayName && h("div", { key: '56cbad7a51264ebada0cb029e6455aabb9cb4ae9', class: "user-name" }, displayName), this.user?.email && h("div", { key: 'ef9075dfdeb52ce6f90bb41d1348fbdf7dbb93ee', class: "user-email" }, this.user.email)))));
|
|
1286
1286
|
}
|
|
1287
1287
|
};
|
|
1288
1288
|
KritzelCurrentUserDialog.style = kritzelCurrentUserDialogCss();
|
|
@@ -2171,7 +2171,7 @@ const DEFAULT_SYNC_CONFIG = {
|
|
|
2171
2171
|
providers: [],
|
|
2172
2172
|
};
|
|
2173
2173
|
|
|
2174
|
-
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}`;
|
|
2174
|
+
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}`;
|
|
2175
2175
|
|
|
2176
2176
|
const KritzelEditor = class {
|
|
2177
2177
|
constructor(hostRef) {
|
|
@@ -2269,13 +2269,11 @@ const KritzelEditor = class {
|
|
|
2269
2269
|
{
|
|
2270
2270
|
label: 'menu.paste',
|
|
2271
2271
|
icon: 'paste',
|
|
2272
|
-
disabled: async () => (await this.engineRef.getCopiedObjects()).length === 0,
|
|
2273
2272
|
action: menu => this.engineRef.paste(menu.x, menu.y),
|
|
2274
2273
|
},
|
|
2275
2274
|
{
|
|
2276
2275
|
label: 'menu.selectAll',
|
|
2277
2276
|
icon: 'select-all',
|
|
2278
|
-
disabled: async () => (await this.engineRef.getObjectsInViewport()).length === 0,
|
|
2279
2277
|
action: () => this.selectAllObjectsInViewport(),
|
|
2280
2278
|
},
|
|
2281
2279
|
];
|
|
@@ -2286,7 +2284,6 @@ const KritzelEditor = class {
|
|
|
2286
2284
|
label: 'menu.paste',
|
|
2287
2285
|
icon: 'paste',
|
|
2288
2286
|
group: 'clipboard',
|
|
2289
|
-
disabled: async () => (await this.engineRef.getCopiedObjects()).length === 0,
|
|
2290
2287
|
action: (menu, _) => this.engineRef.paste(menu.x, menu.y),
|
|
2291
2288
|
},
|
|
2292
2289
|
{
|
|
@@ -2304,7 +2301,6 @@ const KritzelEditor = class {
|
|
|
2304
2301
|
label: 'menu.align',
|
|
2305
2302
|
icon: 'align',
|
|
2306
2303
|
group: 'other',
|
|
2307
|
-
disabled: async () => (await this.engineRef.getSelectedObjects()).length < 2,
|
|
2308
2304
|
children: [
|
|
2309
2305
|
{ label: 'menu.alignLeft', icon: 'align-start-vertical', action: () => this.engineRef.alignObjects(KritzelAlignment.StartHorizontal) },
|
|
2310
2306
|
{ label: 'menu.alignCenterHorizontal', icon: 'align-center-horizontal', action: () => this.engineRef.alignObjects(KritzelAlignment.CenterHorizontal) },
|
|
@@ -2322,16 +2318,11 @@ const KritzelEditor = class {
|
|
|
2322
2318
|
{
|
|
2323
2319
|
label: 'menu.group',
|
|
2324
2320
|
icon: 'group',
|
|
2325
|
-
disabled: async () => (await this.engineRef.getSelectedObjects()).length < 2,
|
|
2326
2321
|
action: () => this.engineRef.group(),
|
|
2327
2322
|
},
|
|
2328
2323
|
{
|
|
2329
2324
|
label: 'menu.ungroup',
|
|
2330
2325
|
icon: 'ungroup',
|
|
2331
|
-
disabled: async () => {
|
|
2332
|
-
const selectedObjects = await this.engineRef.getSelectedObjects();
|
|
2333
|
-
return !selectedObjects.some(obj => obj.__class__ === 'KritzelGroup');
|
|
2334
|
-
},
|
|
2335
2326
|
action: () => this.engineRef.ungroup(),
|
|
2336
2327
|
},
|
|
2337
2328
|
],
|
|
@@ -2408,6 +2399,13 @@ const KritzelEditor = class {
|
|
|
2408
2399
|
shortcuts = [];
|
|
2409
2400
|
currentIsPublic = false;
|
|
2410
2401
|
isEditorVisible = false;
|
|
2402
|
+
activeNotification;
|
|
2403
|
+
isNotificationDismissing = false;
|
|
2404
|
+
notificationDismissTimeout;
|
|
2405
|
+
notificationDismissAnimationTimeout;
|
|
2406
|
+
notificationDisplayDurationMs = 5000;
|
|
2407
|
+
notificationDismissAnimationDurationMs = 180;
|
|
2408
|
+
isNotificationHovered = false;
|
|
2411
2409
|
onIsEngineReady(newValue) {
|
|
2412
2410
|
if (newValue && this.isControlsReady) {
|
|
2413
2411
|
this.checkIsReady();
|
|
@@ -2670,9 +2668,6 @@ const KritzelEditor = class {
|
|
|
2670
2668
|
async findObjects(predicate) {
|
|
2671
2669
|
return this.engineRef.findObjects(predicate);
|
|
2672
2670
|
}
|
|
2673
|
-
async getCopiedObjects() {
|
|
2674
|
-
return this.engineRef.getCopiedObjects();
|
|
2675
|
-
}
|
|
2676
2671
|
async getObjectsInViewport() {
|
|
2677
2672
|
return this.engineRef.getObjectsInViewport();
|
|
2678
2673
|
}
|
|
@@ -2688,6 +2683,22 @@ const KritzelEditor = class {
|
|
|
2688
2683
|
async getDisplayableShortcuts() {
|
|
2689
2684
|
return this.engineRef.getDisplayableShortcuts();
|
|
2690
2685
|
}
|
|
2686
|
+
/**
|
|
2687
|
+
* Triggers a UI notification programmatically.
|
|
2688
|
+
* @param notification - Notification payload. `id` and `timestamp` are optional.
|
|
2689
|
+
*/
|
|
2690
|
+
async triggerNotification(notification) {
|
|
2691
|
+
const normalizedNotification = {
|
|
2692
|
+
...notification,
|
|
2693
|
+
id: notification.id ?? ObjectHelper.generateUUID(),
|
|
2694
|
+
timestamp: notification.timestamp ?? new Date(),
|
|
2695
|
+
};
|
|
2696
|
+
this.clearNotificationDismissAnimationTimer();
|
|
2697
|
+
this.isNotificationDismissing = false;
|
|
2698
|
+
this.isNotificationHovered = false;
|
|
2699
|
+
this.activeNotification = normalizedNotification;
|
|
2700
|
+
this.scheduleNotificationDismiss();
|
|
2701
|
+
}
|
|
2691
2702
|
engineRef;
|
|
2692
2703
|
controlsRef;
|
|
2693
2704
|
settingsRef;
|
|
@@ -2712,6 +2723,10 @@ const KritzelEditor = class {
|
|
|
2712
2723
|
this.listenForMobileKeyboard();
|
|
2713
2724
|
this.setOsSpecificCssVariables();
|
|
2714
2725
|
}
|
|
2726
|
+
disconnectedCallback() {
|
|
2727
|
+
this.clearNotificationDismissTimer();
|
|
2728
|
+
this.clearNotificationDismissAnimationTimer();
|
|
2729
|
+
}
|
|
2715
2730
|
async checkIsReady() {
|
|
2716
2731
|
await customElements.whenDefined('kritzel-editor');
|
|
2717
2732
|
await customElements.whenDefined('kritzel-workspace-manager');
|
|
@@ -2811,6 +2826,57 @@ const KritzelEditor = class {
|
|
|
2811
2826
|
event.stopPropagation();
|
|
2812
2827
|
this.awarenessChange.emit(event.detail);
|
|
2813
2828
|
}
|
|
2829
|
+
handleNotificationsChange(event) {
|
|
2830
|
+
event.stopPropagation();
|
|
2831
|
+
this.clearNotificationDismissAnimationTimer();
|
|
2832
|
+
this.isNotificationDismissing = false;
|
|
2833
|
+
this.isNotificationHovered = false;
|
|
2834
|
+
this.activeNotification = event.detail;
|
|
2835
|
+
this.scheduleNotificationDismiss();
|
|
2836
|
+
}
|
|
2837
|
+
handleNotificationHoverChange(event) {
|
|
2838
|
+
event.stopPropagation();
|
|
2839
|
+
this.isNotificationHovered = event.detail;
|
|
2840
|
+
if (this.isNotificationHovered) {
|
|
2841
|
+
this.clearNotificationDismissTimer();
|
|
2842
|
+
return;
|
|
2843
|
+
}
|
|
2844
|
+
if (this.activeNotification && !this.isNotificationDismissing) {
|
|
2845
|
+
this.scheduleNotificationDismiss();
|
|
2846
|
+
}
|
|
2847
|
+
}
|
|
2848
|
+
scheduleNotificationDismiss() {
|
|
2849
|
+
this.clearNotificationDismissTimer();
|
|
2850
|
+
this.notificationDismissTimeout = setTimeout(() => {
|
|
2851
|
+
this.dismissNotification();
|
|
2852
|
+
}, this.notificationDisplayDurationMs);
|
|
2853
|
+
}
|
|
2854
|
+
clearNotificationDismissTimer() {
|
|
2855
|
+
if (this.notificationDismissTimeout) {
|
|
2856
|
+
clearTimeout(this.notificationDismissTimeout);
|
|
2857
|
+
this.notificationDismissTimeout = undefined;
|
|
2858
|
+
}
|
|
2859
|
+
}
|
|
2860
|
+
clearNotificationDismissAnimationTimer() {
|
|
2861
|
+
if (this.notificationDismissAnimationTimeout) {
|
|
2862
|
+
clearTimeout(this.notificationDismissAnimationTimeout);
|
|
2863
|
+
this.notificationDismissAnimationTimeout = undefined;
|
|
2864
|
+
}
|
|
2865
|
+
}
|
|
2866
|
+
dismissNotification = () => {
|
|
2867
|
+
this.clearNotificationDismissTimer();
|
|
2868
|
+
this.isNotificationHovered = false;
|
|
2869
|
+
if (!this.activeNotification || this.isNotificationDismissing) {
|
|
2870
|
+
return;
|
|
2871
|
+
}
|
|
2872
|
+
this.isNotificationDismissing = true;
|
|
2873
|
+
this.clearNotificationDismissAnimationTimer();
|
|
2874
|
+
this.notificationDismissAnimationTimeout = setTimeout(() => {
|
|
2875
|
+
this.activeNotification = undefined;
|
|
2876
|
+
this.isNotificationDismissing = false;
|
|
2877
|
+
this.notificationDismissAnimationTimeout = undefined;
|
|
2878
|
+
}, this.notificationDismissAnimationDurationMs);
|
|
2879
|
+
};
|
|
2814
2880
|
handleSettingsChange(event) {
|
|
2815
2881
|
this.scaleMin = event.detail.scaleMin;
|
|
2816
2882
|
this.scaleMax = event.detail.scaleMax;
|
|
@@ -3049,31 +3115,31 @@ const KritzelEditor = class {
|
|
|
3049
3115
|
const isLoggedIn = this.isLoggedIn;
|
|
3050
3116
|
const shouldShowCurrentUser = isLoggedIn;
|
|
3051
3117
|
const shouldShowLoginButton = this.isReady && !!this.loginConfig && !isLoggedIn;
|
|
3052
|
-
return (h(Host, { key: '
|
|
3118
|
+
return (h(Host, { key: '07fe246b722ca64cfbdd8cc3474e6288c39d1128', style: {
|
|
3053
3119
|
opacity: this.isEditorVisible ? '1' : '0',
|
|
3054
3120
|
visibility: this.isEditorVisible ? 'visible' : 'hidden',
|
|
3055
3121
|
transition: 'opacity 0.2s ease-in-out, visibility 0.2s ease-in-out',
|
|
3056
|
-
} }, h("div", { key: '
|
|
3122
|
+
} }, h("div", { key: '2d0db1e78161edb061779b5875114e901f8e79f8', class: "top-left-buttons" }, 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) }), h("kritzel-back-to-content", { key: 'f2a0305bf73bd14d7522974b7956a289a0a44258', visible: this.isBackToContentButtonVisible, text: this.resolvedTerms['backToContent.label'] ?? 'Back to content', onBackToContent: () => this.backToContent() })), this.activeNotification && (h("div", { key: '918fe80193999ec072042500cd1eaf3670f5ed3c', class: "top-center-notification-layer", role: "presentation" }, h("div", { key: '0a5609b2b32f9f04bac03618803c14d9a891742c', class: { 'top-center-notification-container': true, 'is-dismissing': this.isNotificationDismissing }, role: "presentation" }, h("kritzel-notification-card", { key: 'eb1ff7aeaee3a237baf3ba2d96a10ba03a8bf7fb', notification: this.activeNotification, locale: this.locale, onDismiss: this.dismissNotification, onHoverChange: event => this.handleNotificationHoverChange(event) })))), h("kritzel-engine", { key: '8783a87101f308029482ced926a8d2163aae1428', ref: el => {
|
|
3057
3123
|
if (el) {
|
|
3058
3124
|
this.engineRef = el;
|
|
3059
3125
|
}
|
|
3060
|
-
}, 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) }), h("kritzel-controls", { key: '
|
|
3126
|
+
}, 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) }), h("kritzel-controls", { key: '73a94f6baef4e0e26be4540ecd44d24588f5761b', visible: this.isControlsVisible, class: { 'keyboard-open': this.isVirtualKeyboardOpen }, ref: el => {
|
|
3061
3127
|
if (el) {
|
|
3062
3128
|
this.controlsRef = el;
|
|
3063
3129
|
}
|
|
3064
|
-
}, controls: this.controls, isUtilityPanelVisible: this.isUtilityPanelVisible, undoState: this.undoState ?? undefined, theme: this.theme, terms: this.resolvedTerms, onIsControlsReady: () => (this.isControlsReady = true) }), h("div", { key: '
|
|
3130
|
+
}, controls: this.controls, isUtilityPanelVisible: this.isUtilityPanelVisible, undoState: this.undoState ?? undefined, theme: this.theme, terms: this.resolvedTerms, onIsControlsReady: () => (this.isControlsReady = true) }), h("div", { key: 'b0653098e5e15b81f453a7f3c2b27f137eb38f2e', class: "bottom-left-buttons" }, h("kritzel-zoom-panel", { key: '33384aeb6bd32d17fb428bd9ed48e5d588ac60c0', visible: this.isZoomPanelVisible, disabled: !this.isZoomingEnabled, zoomPercent: this.currentZoomPercent, terms: this.resolvedTerms, onZoomIn: () => this.zoomIn(), onZoomOut: () => this.zoomOut() })), h("div", { key: '37bed04c062b63a99c930362fb8ce30b58ed8872', class: "top-right-buttons" }, h("kritzel-settings", { key: '4e339573e3d8d48bc9803b9dd40a549bd056d147', ref: el => {
|
|
3065
3131
|
if (el) {
|
|
3066
3132
|
this.settingsRef = el;
|
|
3067
3133
|
}
|
|
3068
|
-
}, 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) }), h("kritzel-export", { key: '
|
|
3134
|
+
}, 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) }), h("kritzel-export", { key: '2a726ea5b56cd36ecf92bbab17d69d04baf73009', ref: el => {
|
|
3069
3135
|
if (el) {
|
|
3070
3136
|
this.exportRef = el;
|
|
3071
3137
|
}
|
|
3072
|
-
}, workspaceName: this.activeWorkspace?.name || 'workspace', terms: this.resolvedTerms, onExportPng: () => this.engineRef.exportViewportAsPng(), onExportSvg: () => this.engineRef.exportViewportAsSvg(), onExportJson: event => this.engineRef.downloadAsJson(event.detail) }), h("kritzel-active-users", { key: '
|
|
3138
|
+
}, workspaceName: this.activeWorkspace?.name || 'workspace', terms: this.resolvedTerms, onExportPng: () => this.engineRef.exportViewportAsPng(), onExportSvg: () => this.engineRef.exportViewportAsSvg(), onExportJson: event => this.engineRef.downloadAsJson(event.detail) }), h("kritzel-active-users", { key: '26d9bbf922b1d4158a0875ba42e7b598011973d5', users: this.activeUsers }), shouldShowCurrentUser && h("kritzel-current-user", { key: '8179cc3e940c9fd8d97978af2bf52543f661a0fd', user: this.user, terms: this.resolvedTerms }), shouldShowLoginButton && (h("kritzel-button", { key: 'd4aa5bc108043eb103754d14f1b5df42ab73f8c4', onButtonClick: () => this.loginDialogRef?.open() }, this.resolvedTerms['login.dialogTitle'] ?? 'Sign in')), h("kritzel-more-menu", { key: '17ac617bde379d7484dbeed39ac7168349b634a1', items: this.moreMenuItems, visible: this.isMoreMenuVisible, terms: this.resolvedTerms }), h("kritzel-share-dialog", { key: '881729b36d34ef3ac3d87fc51ad828fc20fa36cd', ref: el => {
|
|
3073
3139
|
if (el) {
|
|
3074
3140
|
this.shareDialogRef = el;
|
|
3075
3141
|
}
|
|
3076
|
-
}, isPublic: this.currentIsPublic, workspaceId: this.activeWorkspace?.id, terms: this.resolvedTerms, onToggleIsPublic: this.handleToggleIsPublic }), this.loginConfig && (h("kritzel-login-dialog", { key: '
|
|
3142
|
+
}, isPublic: this.currentIsPublic, workspaceId: this.activeWorkspace?.id, terms: this.resolvedTerms, onToggleIsPublic: this.handleToggleIsPublic }), this.loginConfig && (h("kritzel-login-dialog", { key: '5e34b647ac4c3e18981042d765b4d443422c5db3', ref: el => {
|
|
3077
3143
|
if (el) {
|
|
3078
3144
|
this.loginDialogRef = el;
|
|
3079
3145
|
}
|
|
@@ -21152,7 +21218,7 @@ class KritzelViewport {
|
|
|
21152
21218
|
const NUDGE_AMOUNT = 10;
|
|
21153
21219
|
/**
|
|
21154
21220
|
* Handles keyboard events and manages keyboard shortcuts for the Kritzel canvas.
|
|
21155
|
-
* Provides functionality for tool switching,
|
|
21221
|
+
* Provides functionality for tool switching, object manipulation,
|
|
21156
21222
|
* undo/redo, and navigation via keyboard input.
|
|
21157
21223
|
*/
|
|
21158
21224
|
class KritzelKeyHandler extends KritzelBaseHandler {
|
|
@@ -21195,27 +21261,6 @@ class KritzelKeyHandler extends KritzelBaseHandler {
|
|
|
21195
21261
|
{ key: '7', ctrl: true, label: 'Tool 7', category: 'Tool Selection', action: () => this.switchToolByIndex(6) },
|
|
21196
21262
|
{ key: '8', ctrl: true, label: 'Tool 8', category: 'Tool Selection', action: () => this.switchToolByIndex(7) },
|
|
21197
21263
|
{ key: '9', ctrl: true, label: 'Tool 9', category: 'Tool Selection', action: () => this.switchToolByIndex(8) },
|
|
21198
|
-
// Clipboard
|
|
21199
|
-
{
|
|
21200
|
-
key: 'c',
|
|
21201
|
-
ctrl: true,
|
|
21202
|
-
label: 'Copy',
|
|
21203
|
-
category: 'Clipboard',
|
|
21204
|
-
condition: c => !!c.store.selectionGroup,
|
|
21205
|
-
action: c => {
|
|
21206
|
-
c.copy();
|
|
21207
|
-
c.rerender();
|
|
21208
|
-
},
|
|
21209
|
-
},
|
|
21210
|
-
{ key: 'x', ctrl: true, label: 'Cut', category: 'Clipboard', condition: c => !!c.store.selectionGroup, action: c => c.cut() },
|
|
21211
|
-
{
|
|
21212
|
-
key: 'v',
|
|
21213
|
-
ctrl: true,
|
|
21214
|
-
label: 'Paste',
|
|
21215
|
-
category: 'Clipboard',
|
|
21216
|
-
condition: c => !!c.store.state.copiedObjects && !c.store.activeText && !c.store.activeShape,
|
|
21217
|
-
action: c => c.paste(),
|
|
21218
|
-
},
|
|
21219
21264
|
// Object layering
|
|
21220
21265
|
{ key: '+', ctrl: true, label: 'Bring Forward', category: 'Object Layering', condition: c => !!c.store.selectionGroup, action: c => c.bringForward() },
|
|
21221
21266
|
{ key: '-', ctrl: true, label: 'Send Backward', category: 'Object Layering', condition: c => !!c.store.selectionGroup, action: c => c.sendBackward() },
|
|
@@ -21725,7 +21770,6 @@ class KritzelReviver {
|
|
|
21725
21770
|
const DEFAULT_ENGINE_CONFIG = {
|
|
21726
21771
|
activeWorkspace: undefined,
|
|
21727
21772
|
activeTool: null,
|
|
21728
|
-
copiedObjects: null,
|
|
21729
21773
|
objects: null,
|
|
21730
21774
|
snapCandidate: null,
|
|
21731
21775
|
resizeHandleType: null,
|
|
@@ -24068,6 +24112,467 @@ class KritzelCursorManager {
|
|
|
24068
24112
|
}
|
|
24069
24113
|
}
|
|
24070
24114
|
|
|
24115
|
+
/**
|
|
24116
|
+
* Manages browser permission checks and prompts for a core instance.
|
|
24117
|
+
*
|
|
24118
|
+
* Permission-specific prompt logic is routed through a handler registry so new
|
|
24119
|
+
* permissions can be added without changing the core control flow.
|
|
24120
|
+
*/
|
|
24121
|
+
class KritzelBrowserPermissionManager {
|
|
24122
|
+
_isFirefox = /firefox|fxios/i.test(navigator.userAgent);
|
|
24123
|
+
_isSafari = /safari/i.test(navigator.userAgent) && !/chrome|chromium|crios|android|edg/i.test(navigator.userAgent);
|
|
24124
|
+
_requestHandlers = new Map();
|
|
24125
|
+
/**
|
|
24126
|
+
* Creates a new KritzelBrowserPermissionManager instance.
|
|
24127
|
+
* @param core - The KritzelCore instance this manager belongs to
|
|
24128
|
+
*/
|
|
24129
|
+
constructor(_core) {
|
|
24130
|
+
this.registerRequestPermissionHandler('clipboard-read', async () => {
|
|
24131
|
+
// Firefox and Safari open native paste menus when readText() is called
|
|
24132
|
+
// proactively, so rely on the permission state instead of an eager read.
|
|
24133
|
+
if (this._isFirefox || this._isSafari) {
|
|
24134
|
+
return 'granted';
|
|
24135
|
+
}
|
|
24136
|
+
try {
|
|
24137
|
+
await navigator.clipboard.readText();
|
|
24138
|
+
return 'granted';
|
|
24139
|
+
}
|
|
24140
|
+
catch {
|
|
24141
|
+
return 'denied';
|
|
24142
|
+
}
|
|
24143
|
+
});
|
|
24144
|
+
}
|
|
24145
|
+
/**
|
|
24146
|
+
* Registers a custom request handler for a browser permission name.
|
|
24147
|
+
* Existing handlers are replaced, which makes the registry easy to extend.
|
|
24148
|
+
*
|
|
24149
|
+
* @param permissionName - The browser permission name to handle
|
|
24150
|
+
* @param handler - The request implementation for that permission
|
|
24151
|
+
*/
|
|
24152
|
+
registerRequestPermissionHandler(permissionName, handler) {
|
|
24153
|
+
this._requestHandlers.set(permissionName, handler);
|
|
24154
|
+
}
|
|
24155
|
+
/**
|
|
24156
|
+
* Checks the current state for a browser permission via the Permissions API.
|
|
24157
|
+
*
|
|
24158
|
+
* @param permissionName - The browser permission name to inspect
|
|
24159
|
+
*/
|
|
24160
|
+
async checkPermission(permissionName) {
|
|
24161
|
+
const status = await navigator.permissions.query({ name: permissionName });
|
|
24162
|
+
return status.state;
|
|
24163
|
+
}
|
|
24164
|
+
/**
|
|
24165
|
+
* Requests a browser permission using the registered handler for the given
|
|
24166
|
+
* permission name, then falls back to a permission check when no handler is
|
|
24167
|
+
* registered.
|
|
24168
|
+
*
|
|
24169
|
+
* @param permissionName - The browser permission name to request
|
|
24170
|
+
*/
|
|
24171
|
+
async requestPermission(permissionName) {
|
|
24172
|
+
const handler = this._requestHandlers.get(permissionName);
|
|
24173
|
+
if (handler) {
|
|
24174
|
+
return handler();
|
|
24175
|
+
}
|
|
24176
|
+
return this.checkPermission(permissionName);
|
|
24177
|
+
}
|
|
24178
|
+
}
|
|
24179
|
+
|
|
24180
|
+
const CLIPBOARD_PAYLOAD_PREFIX = 'kritzel-clipboard/v1:';
|
|
24181
|
+
/**
|
|
24182
|
+
* Manages clipboard operations (copy/cut/paste) for a core instance.
|
|
24183
|
+
*
|
|
24184
|
+
* The system clipboard is the single source of truth: copy serializes the current
|
|
24185
|
+
* selection into a Kritzel payload, paste reads + revives it. No copied objects are
|
|
24186
|
+
* cached on the engine state.
|
|
24187
|
+
*/
|
|
24188
|
+
class KritzelClipboardManager {
|
|
24189
|
+
_core;
|
|
24190
|
+
/**
|
|
24191
|
+
* In-memory cascade offset (world units) applied to successive pastes of the same
|
|
24192
|
+
* clipboard content so they don't stack exactly on top of each other. Reset on copy/cut.
|
|
24193
|
+
*/
|
|
24194
|
+
_pasteOffset = 0;
|
|
24195
|
+
constructor(core) {
|
|
24196
|
+
this._core = core;
|
|
24197
|
+
}
|
|
24198
|
+
/**
|
|
24199
|
+
* Serializes an object for the clipboard payload. Groups additionally embed their
|
|
24200
|
+
* (recursively serialized) children under `__children__` so the payload is self-contained.
|
|
24201
|
+
*/
|
|
24202
|
+
serializeForClipboard(object) {
|
|
24203
|
+
const serialized = (typeof object.serialize === 'function' ? object.serialize() : object);
|
|
24204
|
+
if (KritzelClassHelper.isInstanceOf(object, 'KritzelGroup')) {
|
|
24205
|
+
serialized.__children__ = object.children.map(child => this.serializeForClipboard(child));
|
|
24206
|
+
}
|
|
24207
|
+
return serialized;
|
|
24208
|
+
}
|
|
24209
|
+
serializeClipboardPayload(payload) {
|
|
24210
|
+
return `${CLIPBOARD_PAYLOAD_PREFIX}${JSON.stringify(payload)}`;
|
|
24211
|
+
}
|
|
24212
|
+
parseClipboardPayload(text) {
|
|
24213
|
+
if (!text || !text.startsWith(CLIPBOARD_PAYLOAD_PREFIX)) {
|
|
24214
|
+
return null;
|
|
24215
|
+
}
|
|
24216
|
+
try {
|
|
24217
|
+
const parsed = JSON.parse(text.slice(CLIPBOARD_PAYLOAD_PREFIX.length));
|
|
24218
|
+
if (parsed?.version !== 1 || !Array.isArray(parsed.objects)) {
|
|
24219
|
+
return null;
|
|
24220
|
+
}
|
|
24221
|
+
return parsed;
|
|
24222
|
+
}
|
|
24223
|
+
catch {
|
|
24224
|
+
return null;
|
|
24225
|
+
}
|
|
24226
|
+
}
|
|
24227
|
+
determineTextPasteIntent(text) {
|
|
24228
|
+
const payload = this.parseClipboardPayload(text);
|
|
24229
|
+
if (payload) {
|
|
24230
|
+
return { type: 'kritzel_objects', payload };
|
|
24231
|
+
}
|
|
24232
|
+
if (text && text.trim().length > 0) {
|
|
24233
|
+
return { type: 'plain_text', text };
|
|
24234
|
+
}
|
|
24235
|
+
return null;
|
|
24236
|
+
}
|
|
24237
|
+
async writeBrowserClipboardPayload(payload, event) {
|
|
24238
|
+
const serialized = this.serializeClipboardPayload(payload);
|
|
24239
|
+
if (event?.clipboardData) {
|
|
24240
|
+
event.clipboardData.setData('text/plain', serialized);
|
|
24241
|
+
return;
|
|
24242
|
+
}
|
|
24243
|
+
if (typeof navigator === 'undefined' || !navigator.clipboard?.writeText) {
|
|
24244
|
+
return;
|
|
24245
|
+
}
|
|
24246
|
+
try {
|
|
24247
|
+
await navigator.clipboard.writeText(serialized);
|
|
24248
|
+
}
|
|
24249
|
+
catch {
|
|
24250
|
+
// Ignore clipboard permission failures and keep the local clipboard working.
|
|
24251
|
+
}
|
|
24252
|
+
}
|
|
24253
|
+
/**
|
|
24254
|
+
* Revives a single serialized clipboard object (and its embedded group children).
|
|
24255
|
+
* IDs are NOT regenerated here; see regenerateIdsAndRemapAnchors.
|
|
24256
|
+
*/
|
|
24257
|
+
reviveClipboardObject(serialized) {
|
|
24258
|
+
const reviver = new KritzelReviver(this._core);
|
|
24259
|
+
const { __children__, ...objectData } = serialized;
|
|
24260
|
+
const revived = reviver.revive(objectData);
|
|
24261
|
+
if (!revived) {
|
|
24262
|
+
return null;
|
|
24263
|
+
}
|
|
24264
|
+
if (__children__ && KritzelClassHelper.isInstanceOf(revived, 'KritzelGroup')) {
|
|
24265
|
+
const children = __children__.map(child => this.reviveClipboardObject(child)).filter((child) => child != null);
|
|
24266
|
+
revived._pendingChildren = children;
|
|
24267
|
+
revived.childIds = children.map(child => child.id);
|
|
24268
|
+
}
|
|
24269
|
+
return revived;
|
|
24270
|
+
}
|
|
24271
|
+
/**
|
|
24272
|
+
* Assigns fresh unique IDs to every revived object (including nested group children),
|
|
24273
|
+
* keeping group.childIds in sync and remapping line anchors that reference copied
|
|
24274
|
+
* siblings to their new IDs. Anchors pointing at objects outside the pasted set are
|
|
24275
|
+
* left untouched so they stay connected to the existing object.
|
|
24276
|
+
*/
|
|
24277
|
+
regenerateIdsAndRemapAnchors(topLevel) {
|
|
24278
|
+
const all = [];
|
|
24279
|
+
const collect = (objects) => {
|
|
24280
|
+
for (const object of objects) {
|
|
24281
|
+
all.push(object);
|
|
24282
|
+
if (KritzelClassHelper.isInstanceOf(object, 'KritzelGroup')) {
|
|
24283
|
+
collect(object._pendingChildren);
|
|
24284
|
+
}
|
|
24285
|
+
}
|
|
24286
|
+
};
|
|
24287
|
+
collect(topLevel);
|
|
24288
|
+
const idMap = new Map();
|
|
24289
|
+
for (const object of all) {
|
|
24290
|
+
const newId = object.generateId();
|
|
24291
|
+
idMap.set(object.id, newId);
|
|
24292
|
+
object.id = newId;
|
|
24293
|
+
object.isMounted = false;
|
|
24294
|
+
}
|
|
24295
|
+
for (const object of all) {
|
|
24296
|
+
if (KritzelClassHelper.isInstanceOf(object, 'KritzelGroup')) {
|
|
24297
|
+
object.childIds = object.childIds.map(id => idMap.get(id) ?? id);
|
|
24298
|
+
}
|
|
24299
|
+
if (KritzelClassHelper.isInstanceOf(object, 'KritzelLine')) {
|
|
24300
|
+
if (object.startAnchor && idMap.has(object.startAnchor.objectId)) {
|
|
24301
|
+
object.startAnchor = { objectId: idMap.get(object.startAnchor.objectId) };
|
|
24302
|
+
}
|
|
24303
|
+
if (object.endAnchor && idMap.has(object.endAnchor.objectId)) {
|
|
24304
|
+
object.endAnchor = { objectId: idMap.get(object.endAnchor.objectId) };
|
|
24305
|
+
}
|
|
24306
|
+
}
|
|
24307
|
+
}
|
|
24308
|
+
}
|
|
24309
|
+
/**
|
|
24310
|
+
* Evaluates the clipboard event to determine exactly what the user is trying to paste.
|
|
24311
|
+
* Returns a PasteIntent covering the 3 main cases: Kritzel objects, Images, or Plain text.
|
|
24312
|
+
*/
|
|
24313
|
+
async determinePasteIntent(event) {
|
|
24314
|
+
if (event?.clipboardData) {
|
|
24315
|
+
const data = event.clipboardData;
|
|
24316
|
+
const imageFiles = Array.from(data.files ?? []).filter(file => file.type.startsWith('image/'));
|
|
24317
|
+
if (imageFiles.length > 0) {
|
|
24318
|
+
return { type: 'image_files', files: imageFiles };
|
|
24319
|
+
}
|
|
24320
|
+
if (data.types.includes('text/plain')) {
|
|
24321
|
+
const textIntent = this.determineTextPasteIntent(data.getData('text/plain'));
|
|
24322
|
+
if (textIntent)
|
|
24323
|
+
return textIntent;
|
|
24324
|
+
}
|
|
24325
|
+
return { type: 'unknown' };
|
|
24326
|
+
}
|
|
24327
|
+
if (typeof navigator === 'undefined' || !navigator.clipboard) {
|
|
24328
|
+
return { type: 'unknown' };
|
|
24329
|
+
}
|
|
24330
|
+
const { clipboard } = navigator;
|
|
24331
|
+
const permissionState = await this._core.permissionManager.checkPermission('clipboard-read');
|
|
24332
|
+
if (permissionState !== 'granted') {
|
|
24333
|
+
const requestedState = await this._core.permissionManager.requestPermission('clipboard-read');
|
|
24334
|
+
if (requestedState !== 'granted') {
|
|
24335
|
+
return { type: 'unknown' };
|
|
24336
|
+
}
|
|
24337
|
+
}
|
|
24338
|
+
if (clipboard.read) {
|
|
24339
|
+
try {
|
|
24340
|
+
const items = await clipboard.read();
|
|
24341
|
+
const { imageFiles, text } = await this.processClipboardItems(items);
|
|
24342
|
+
if (imageFiles.length > 0) {
|
|
24343
|
+
return { type: 'image_files', files: imageFiles };
|
|
24344
|
+
}
|
|
24345
|
+
if (text !== null) {
|
|
24346
|
+
const textIntent = this.determineTextPasteIntent(text);
|
|
24347
|
+
if (textIntent)
|
|
24348
|
+
return textIntent;
|
|
24349
|
+
}
|
|
24350
|
+
}
|
|
24351
|
+
catch {
|
|
24352
|
+
// Fall back to readText below when read() is denied or unavailable at runtime.
|
|
24353
|
+
}
|
|
24354
|
+
}
|
|
24355
|
+
if (clipboard.readText) {
|
|
24356
|
+
const textIntent = this.determineTextPasteIntent(await clipboard.readText());
|
|
24357
|
+
if (textIntent)
|
|
24358
|
+
return textIntent;
|
|
24359
|
+
}
|
|
24360
|
+
return { type: 'unknown' };
|
|
24361
|
+
}
|
|
24362
|
+
/**
|
|
24363
|
+
* Helper to parse clipboard items in parallel
|
|
24364
|
+
*/
|
|
24365
|
+
async processClipboardItems(items) {
|
|
24366
|
+
const imageFiles = [];
|
|
24367
|
+
let text = null;
|
|
24368
|
+
// Process items concurrently
|
|
24369
|
+
await Promise.all(items.map(async (item) => {
|
|
24370
|
+
const imageType = item.types.find(type => type.startsWith('image/'));
|
|
24371
|
+
if (imageType) {
|
|
24372
|
+
const blob = await item.getType(imageType);
|
|
24373
|
+
imageFiles.push(new File([blob], 'pasted-image', { type: imageType }));
|
|
24374
|
+
return;
|
|
24375
|
+
}
|
|
24376
|
+
if (text === null && item.types.includes('text/plain')) {
|
|
24377
|
+
const blob = await item.getType('text/plain');
|
|
24378
|
+
text = await blob.text();
|
|
24379
|
+
}
|
|
24380
|
+
}));
|
|
24381
|
+
return { imageFiles, text };
|
|
24382
|
+
}
|
|
24383
|
+
/**
|
|
24384
|
+
* Copies currently selected objects into internal clipboard state.
|
|
24385
|
+
*/
|
|
24386
|
+
copy(event) {
|
|
24387
|
+
const selectionGroup = this._core.store.selectionGroup;
|
|
24388
|
+
if (!selectionGroup) {
|
|
24389
|
+
return;
|
|
24390
|
+
}
|
|
24391
|
+
const payload = {
|
|
24392
|
+
version: 1,
|
|
24393
|
+
sourceWorkspaceId: this._core.store.state.activeWorkspace?.id,
|
|
24394
|
+
objects: selectionGroup.objects.sort((a, b) => a.zIndex - b.zIndex).map(obj => this.serializeForClipboard(obj)),
|
|
24395
|
+
};
|
|
24396
|
+
// A fresh copy resets the cascade so the first paste lands at the default offset.
|
|
24397
|
+
this._pasteOffset = 0;
|
|
24398
|
+
void this.writeBrowserClipboardPayload(payload, event);
|
|
24399
|
+
}
|
|
24400
|
+
/**
|
|
24401
|
+
* Cuts currently selected objects (copy then delete).
|
|
24402
|
+
*/
|
|
24403
|
+
cut(event) {
|
|
24404
|
+
const selectionGroup = this._core.store.selectionGroup;
|
|
24405
|
+
if (!selectionGroup) {
|
|
24406
|
+
return;
|
|
24407
|
+
}
|
|
24408
|
+
this.copy(event);
|
|
24409
|
+
this._core.delete();
|
|
24410
|
+
}
|
|
24411
|
+
materializeKritzelObjects(intent) {
|
|
24412
|
+
const objects = intent.payload.objects.map(object => this.reviveClipboardObject(object)).filter((object) => object != null);
|
|
24413
|
+
this.regenerateIdsAndRemapAnchors(objects);
|
|
24414
|
+
return objects;
|
|
24415
|
+
}
|
|
24416
|
+
async materializeImageFiles(intent) {
|
|
24417
|
+
try {
|
|
24418
|
+
const scale = this._core.store.state.scale;
|
|
24419
|
+
const offset = 25 / scale;
|
|
24420
|
+
const preparePromises = intent.files.map(async (file, index) => {
|
|
24421
|
+
// Use the default image compression size of 1200
|
|
24422
|
+
const compressed = await imageCompression(file, { maxWidthOrHeight: 1200 });
|
|
24423
|
+
return KritzelImage.fromBlob(this._core, compressed, {
|
|
24424
|
+
translateX: index * offset,
|
|
24425
|
+
translateY: index * offset,
|
|
24426
|
+
});
|
|
24427
|
+
});
|
|
24428
|
+
return await Promise.all(preparePromises);
|
|
24429
|
+
}
|
|
24430
|
+
catch (err) {
|
|
24431
|
+
console.error('Failed to import pasted image files:', err);
|
|
24432
|
+
return null;
|
|
24433
|
+
}
|
|
24434
|
+
}
|
|
24435
|
+
async materializePlainText(intent) {
|
|
24436
|
+
const textObject = KritzelText.create(this._core);
|
|
24437
|
+
const paragraphs = intent.text.split('\n').map(line => {
|
|
24438
|
+
if (line.length === 0) {
|
|
24439
|
+
return { type: 'paragraph' }; // Empty paragraph
|
|
24440
|
+
}
|
|
24441
|
+
return {
|
|
24442
|
+
type: 'paragraph',
|
|
24443
|
+
content: [{ type: 'text', text: line }],
|
|
24444
|
+
};
|
|
24445
|
+
});
|
|
24446
|
+
textObject.setContent({
|
|
24447
|
+
type: 'doc',
|
|
24448
|
+
content: paragraphs,
|
|
24449
|
+
});
|
|
24450
|
+
return [textObject];
|
|
24451
|
+
}
|
|
24452
|
+
/**
|
|
24453
|
+
* Pastes objects from clipboard with optional explicit world coordinates.
|
|
24454
|
+
*/
|
|
24455
|
+
async paste(x, y, event) {
|
|
24456
|
+
const pasteIntent = await this.determinePasteIntent(event);
|
|
24457
|
+
let objects = null;
|
|
24458
|
+
if (pasteIntent.type === 'kritzel_objects') {
|
|
24459
|
+
objects = this.materializeKritzelObjects(pasteIntent);
|
|
24460
|
+
}
|
|
24461
|
+
else if (pasteIntent.type === 'image_files') {
|
|
24462
|
+
objects = await this.materializeImageFiles(pasteIntent);
|
|
24463
|
+
}
|
|
24464
|
+
else if (pasteIntent.type === 'plain_text') {
|
|
24465
|
+
objects = await this.materializePlainText(pasteIntent);
|
|
24466
|
+
}
|
|
24467
|
+
if (!objects || objects.length === 0) {
|
|
24468
|
+
return;
|
|
24469
|
+
}
|
|
24470
|
+
await this.insertMaterializedObjects(objects, pasteIntent, x, y);
|
|
24471
|
+
}
|
|
24472
|
+
async insertMaterializedObjects(copiedObjects, pasteIntent, x, y) {
|
|
24473
|
+
const activeWorkspace = this._core.store.state.activeWorkspace;
|
|
24474
|
+
if (!activeWorkspace) {
|
|
24475
|
+
return;
|
|
24476
|
+
}
|
|
24477
|
+
// Determine if we should center the objects in the viewport.
|
|
24478
|
+
// This happens if the user specifically pasted from a different workspace,
|
|
24479
|
+
// OR if we're inserting brand new external items (like images or text).
|
|
24480
|
+
const isDifferentWorkspace = copiedObjects.some(obj => obj.workspaceId !== activeWorkspace.id);
|
|
24481
|
+
const isNewExternalContent = pasteIntent.type !== 'kritzel_objects';
|
|
24482
|
+
const shouldCenterInViewport = isDifferentWorkspace || isNewExternalContent;
|
|
24483
|
+
const hasExplicitPastePosition = x !== undefined && y !== undefined;
|
|
24484
|
+
const minX = Math.min(...copiedObjects.map(obj => obj.translateX));
|
|
24485
|
+
const minY = Math.min(...copiedObjects.map(obj => obj.translateY));
|
|
24486
|
+
let pasteX;
|
|
24487
|
+
let pasteY;
|
|
24488
|
+
const step = 25 / this._core.store.state.scale;
|
|
24489
|
+
if (x !== undefined && y !== undefined) {
|
|
24490
|
+
pasteX = x;
|
|
24491
|
+
pasteY = y;
|
|
24492
|
+
}
|
|
24493
|
+
else if (shouldCenterInViewport) {
|
|
24494
|
+
pasteX = minX;
|
|
24495
|
+
pasteY = minY;
|
|
24496
|
+
}
|
|
24497
|
+
else {
|
|
24498
|
+
pasteX = minX + step + this._pasteOffset;
|
|
24499
|
+
pasteY = minY + step + this._pasteOffset;
|
|
24500
|
+
// Advance the cascade so the next same-content paste is offset further.
|
|
24501
|
+
this._pasteOffset += step;
|
|
24502
|
+
}
|
|
24503
|
+
const offsetX = pasteX - minX;
|
|
24504
|
+
const offsetY = pasteY - minY;
|
|
24505
|
+
this._core.removeSelectionGroup();
|
|
24506
|
+
this._core.removeSelectionBox();
|
|
24507
|
+
const selectionGroup = KritzelSelectionGroup.create(this._core);
|
|
24508
|
+
const baseZIndex = this._core.store.currentZIndex;
|
|
24509
|
+
this._core.store.objects.transaction(() => {
|
|
24510
|
+
const flushPendingChildren = (group, parentZIndex) => {
|
|
24511
|
+
if (group._pendingChildren.length === 0) {
|
|
24512
|
+
return;
|
|
24513
|
+
}
|
|
24514
|
+
const pendingChildren = group._pendingChildren;
|
|
24515
|
+
group._pendingChildren = [];
|
|
24516
|
+
pendingChildren.forEach((child, childIndex) => {
|
|
24517
|
+
if (child.workspaceId !== activeWorkspace.id) {
|
|
24518
|
+
child.workspaceId = activeWorkspace.id;
|
|
24519
|
+
}
|
|
24520
|
+
child.updatePosition(child.translateX + offsetX, child.translateY + offsetY);
|
|
24521
|
+
child.zIndex = parentZIndex + childIndex + 1;
|
|
24522
|
+
if (KritzelClassHelper.isInstanceOf(child, 'KritzelGroup')) {
|
|
24523
|
+
flushPendingChildren(child, child.zIndex);
|
|
24524
|
+
}
|
|
24525
|
+
this._core.addObject(child);
|
|
24526
|
+
});
|
|
24527
|
+
group.finalize();
|
|
24528
|
+
};
|
|
24529
|
+
const newlyAddedObjects = [];
|
|
24530
|
+
copiedObjects.forEach((obj, i) => {
|
|
24531
|
+
if (obj.workspaceId !== activeWorkspace.id) {
|
|
24532
|
+
obj.workspaceId = activeWorkspace.id;
|
|
24533
|
+
}
|
|
24534
|
+
obj.updatePosition(obj.translateX + offsetX, obj.translateY + offsetY);
|
|
24535
|
+
obj.zIndex = baseZIndex + i;
|
|
24536
|
+
if (KritzelClassHelper.isInstanceOf(obj, 'KritzelGroup')) {
|
|
24537
|
+
flushPendingChildren(obj, obj.zIndex);
|
|
24538
|
+
}
|
|
24539
|
+
this._core.addObject(obj);
|
|
24540
|
+
newlyAddedObjects.push(obj);
|
|
24541
|
+
selectionGroup.addOrRemove(obj);
|
|
24542
|
+
});
|
|
24543
|
+
this._core.engine.emitObjectsAdded(newlyAddedObjects);
|
|
24544
|
+
});
|
|
24545
|
+
this._core.anchorManager.rebuildIndex();
|
|
24546
|
+
selectionGroup.isSelected = true;
|
|
24547
|
+
if (copiedObjects.length === 1) {
|
|
24548
|
+
selectionGroup.rotation = copiedObjects[0].rotation;
|
|
24549
|
+
}
|
|
24550
|
+
if (shouldCenterInViewport && !hasExplicitPastePosition) {
|
|
24551
|
+
selectionGroup.centerInViewport();
|
|
24552
|
+
}
|
|
24553
|
+
this._core.addSelectionGroup(selectionGroup);
|
|
24554
|
+
this._core.engine.viewport?.bringIntoViewIfNeeded(selectionGroup);
|
|
24555
|
+
this._core.store.state.isSelecting = false;
|
|
24556
|
+
// Use a double requestAnimationFrame to ensure the browser has fully rendered the DOM,
|
|
24557
|
+
// and objects like KritzelText have executed their own internal size-adjustment rAF calls.
|
|
24558
|
+
await new Promise(resolve => {
|
|
24559
|
+
requestAnimationFrame(() => requestAnimationFrame(() => resolve()));
|
|
24560
|
+
});
|
|
24561
|
+
// Re-evaluate bounding box dimensions now that any DOM nodes (like ProseMirror text editors)
|
|
24562
|
+
// have mounted and calculated their actual bounds.
|
|
24563
|
+
selectionGroup.refreshObjectDimensions();
|
|
24564
|
+
// We should update it if the centerInViewport or width adjustments changed it significantly
|
|
24565
|
+
if (shouldCenterInViewport && !hasExplicitPastePosition) {
|
|
24566
|
+
selectionGroup.centerInViewport();
|
|
24567
|
+
}
|
|
24568
|
+
this._core.engine.emitObjectsChange();
|
|
24569
|
+
this._core.rerender();
|
|
24570
|
+
this._core.store.setState('activeTool', this._core.toolRegistry.getTool('selection'));
|
|
24571
|
+
this._core.engine.emitObjectsChange();
|
|
24572
|
+
this._core.rerender();
|
|
24573
|
+
}
|
|
24574
|
+
}
|
|
24575
|
+
|
|
24071
24576
|
/**
|
|
24072
24577
|
* Central orchestrator class for the Kritzel canvas system.
|
|
24073
24578
|
* Manages workspaces, objects, selection, clipboard operations, and coordinates
|
|
@@ -24096,6 +24601,10 @@ class KritzelCore {
|
|
|
24096
24601
|
_localizationManager;
|
|
24097
24602
|
/** Manager for license validation and watermark gating */
|
|
24098
24603
|
_licenseManager;
|
|
24604
|
+
/** Manager for browser permission checks and permission prompts */
|
|
24605
|
+
_permissionManager;
|
|
24606
|
+
/** Manager for clipboard copy/cut/paste orchestration */
|
|
24607
|
+
_clipboardManager;
|
|
24099
24608
|
/** Per-core registry of drawing tools (one instance per editor). */
|
|
24100
24609
|
_toolRegistry;
|
|
24101
24610
|
/** Optional unique identifier for namespacing storage keys across multiple editor instances */
|
|
@@ -24158,6 +24667,13 @@ class KritzelCore {
|
|
|
24158
24667
|
get licenseManager() {
|
|
24159
24668
|
return this._licenseManager;
|
|
24160
24669
|
}
|
|
24670
|
+
/**
|
|
24671
|
+
* Gets the browser permission manager.
|
|
24672
|
+
* @returns The KritzelBrowserPermissionManager for browser permission checks and requests
|
|
24673
|
+
*/
|
|
24674
|
+
get permissionManager() {
|
|
24675
|
+
return this._permissionManager;
|
|
24676
|
+
}
|
|
24161
24677
|
/**
|
|
24162
24678
|
* Gets the tool registry scoped to this core instance.
|
|
24163
24679
|
* @returns The KritzelToolRegistry owned by this core
|
|
@@ -24165,6 +24681,13 @@ class KritzelCore {
|
|
|
24165
24681
|
get toolRegistry() {
|
|
24166
24682
|
return this._toolRegistry;
|
|
24167
24683
|
}
|
|
24684
|
+
/**
|
|
24685
|
+
* Gets the clipboard manager scoped to this core instance.
|
|
24686
|
+
* @returns The KritzelClipboardManager owned by this core
|
|
24687
|
+
*/
|
|
24688
|
+
get clipboardManager() {
|
|
24689
|
+
return this._clipboardManager;
|
|
24690
|
+
}
|
|
24168
24691
|
/**
|
|
24169
24692
|
* Gets the editor ID used for namespacing storage keys.
|
|
24170
24693
|
* @returns The editor ID or undefined if not set
|
|
@@ -24212,6 +24735,8 @@ class KritzelCore {
|
|
|
24212
24735
|
this._themeManager = new KritzelThemeManager(this);
|
|
24213
24736
|
this._localizationManager = new KritzelLocalizationManager(this);
|
|
24214
24737
|
this._licenseManager = new KritzelLicenseManager(this);
|
|
24738
|
+
this._permissionManager = new KritzelBrowserPermissionManager(this);
|
|
24739
|
+
this._clipboardManager = new KritzelClipboardManager(this);
|
|
24215
24740
|
this._toolRegistry = new KritzelToolRegistry(this);
|
|
24216
24741
|
this._assetResolver = new KritzelAssetResolver();
|
|
24217
24742
|
}
|
|
@@ -24709,216 +25234,6 @@ class KritzelCore {
|
|
|
24709
25234
|
this.rerender();
|
|
24710
25235
|
}
|
|
24711
25236
|
}
|
|
24712
|
-
/**
|
|
24713
|
-
* Copies the currently selected objects to the clipboard.
|
|
24714
|
-
* Creates deep copies of objects and tracks ID mappings for anchor remapping.
|
|
24715
|
-
*/
|
|
24716
|
-
copy() {
|
|
24717
|
-
const selectionGroup = this._store.selectionGroup;
|
|
24718
|
-
if (selectionGroup) {
|
|
24719
|
-
// Copy each object and store them in an array, also track the ID mapping
|
|
24720
|
-
const idMapping = new Map();
|
|
24721
|
-
const copiedObjects = selectionGroup.objects
|
|
24722
|
-
.sort((a, b) => a.zIndex - b.zIndex)
|
|
24723
|
-
.map(obj => {
|
|
24724
|
-
const copiedObj = obj.copy();
|
|
24725
|
-
// Map: newId -> originalId
|
|
24726
|
-
idMapping.set(copiedObj.id, obj.id);
|
|
24727
|
-
return copiedObj;
|
|
24728
|
-
});
|
|
24729
|
-
this._store.state.copiedObjects = copiedObjects;
|
|
24730
|
-
this._store.state.copiedObjectIdMapping = idMapping;
|
|
24731
|
-
}
|
|
24732
|
-
}
|
|
24733
|
-
/**
|
|
24734
|
-
* Cuts the currently selected objects (copy then delete).
|
|
24735
|
-
* Objects are copied to clipboard and then removed from the canvas.
|
|
24736
|
-
*/
|
|
24737
|
-
cut() {
|
|
24738
|
-
const selectionGroup = this._store.selectionGroup;
|
|
24739
|
-
if (!selectionGroup) {
|
|
24740
|
-
return;
|
|
24741
|
-
}
|
|
24742
|
-
// Copy first, then delete
|
|
24743
|
-
this.copy();
|
|
24744
|
-
this.delete();
|
|
24745
|
-
}
|
|
24746
|
-
/**
|
|
24747
|
-
* Pastes objects from the clipboard to the canvas.
|
|
24748
|
-
* Handles positioning (explicit, offset, or centered for cross-workspace paste),
|
|
24749
|
-
* workspace assignment, z-index ordering, group children, and anchor remapping.
|
|
24750
|
-
* Creates a selection group containing the pasted objects.
|
|
24751
|
-
* @param x - Optional explicit X position for paste
|
|
24752
|
-
* @param y - Optional explicit Y position for paste
|
|
24753
|
-
*/
|
|
24754
|
-
paste(x, y) {
|
|
24755
|
-
const copiedObjects = this._store.state.copiedObjects;
|
|
24756
|
-
if (!copiedObjects || copiedObjects.length === 0) {
|
|
24757
|
-
return;
|
|
24758
|
-
}
|
|
24759
|
-
const activeWorkspace = this._store.state.activeWorkspace;
|
|
24760
|
-
const originalIdMapping = this._store.state.copiedObjectIdMapping;
|
|
24761
|
-
// Check if we're pasting from a different workspace
|
|
24762
|
-
const isDifferentWorkspace = copiedObjects.some(obj => obj.workspaceId !== activeWorkspace.id);
|
|
24763
|
-
// Calculate the bounding box of all copied objects
|
|
24764
|
-
const minX = Math.min(...copiedObjects.map(obj => obj.translateX));
|
|
24765
|
-
const minY = Math.min(...copiedObjects.map(obj => obj.translateY));
|
|
24766
|
-
// Determine the paste position
|
|
24767
|
-
let pasteX;
|
|
24768
|
-
let pasteY;
|
|
24769
|
-
if (x !== undefined && y !== undefined) {
|
|
24770
|
-
// Explicit position provided (e.g., right-click paste)
|
|
24771
|
-
pasteX = x;
|
|
24772
|
-
pasteY = y;
|
|
24773
|
-
}
|
|
24774
|
-
else if (isDifferentWorkspace) {
|
|
24775
|
-
// Pasting to different workspace without explicit position
|
|
24776
|
-
// Keep original position; will be centered by centerInViewport() later
|
|
24777
|
-
pasteX = minX;
|
|
24778
|
-
pasteY = minY;
|
|
24779
|
-
}
|
|
24780
|
-
else {
|
|
24781
|
-
// Same workspace paste: offset by 25 pixels from original position
|
|
24782
|
-
pasteX = minX + 25 / this._store.state.scale;
|
|
24783
|
-
pasteY = minY + 25 / this._store.state.scale;
|
|
24784
|
-
}
|
|
24785
|
-
// Calculate the offset to apply to all objects
|
|
24786
|
-
const offsetX = pasteX - minX;
|
|
24787
|
-
const offsetY = pasteY - minY;
|
|
24788
|
-
this.removeSelectionGroup();
|
|
24789
|
-
this.removeSelectionBox();
|
|
24790
|
-
// Create a new selection group for the pasted objects
|
|
24791
|
-
const selectionGroup = KritzelSelectionGroup.create(this);
|
|
24792
|
-
// Build a reverse mapping: originalId -> newCopiedObjectId
|
|
24793
|
-
// This is used to remap anchor references from original IDs to the copied object IDs
|
|
24794
|
-
const originalToNewIdMap = new Map();
|
|
24795
|
-
if (originalIdMapping) {
|
|
24796
|
-
originalIdMapping.forEach((originalId, copiedId) => {
|
|
24797
|
-
originalToNewIdMap.set(originalId, copiedId);
|
|
24798
|
-
});
|
|
24799
|
-
}
|
|
24800
|
-
// Precompute zIndex once to avoid O(N * total_objects) repeated scans
|
|
24801
|
-
const baseZIndex = this._store.currentZIndex;
|
|
24802
|
-
// Batch all inserts and updates in a single Y.js transaction to avoid
|
|
24803
|
-
// N separate observer callbacks and N rerenders (fires only once at commit)
|
|
24804
|
-
this._store.objects.transaction(() => {
|
|
24805
|
-
// Recursively flush a group's pending children (and any nested groups'
|
|
24806
|
-
// pending children) into the store. Without recursion, nested groups
|
|
24807
|
-
// would have their grandchildren stranded in `_pendingChildren` and they
|
|
24808
|
-
// would never appear on the canvas, even though the parent group's
|
|
24809
|
-
// bounding box looks correct.
|
|
24810
|
-
const flushPendingChildren = (group, parentZIndex) => {
|
|
24811
|
-
if (group._pendingChildren.length === 0) {
|
|
24812
|
-
return;
|
|
24813
|
-
}
|
|
24814
|
-
const pendingChildren = group._pendingChildren;
|
|
24815
|
-
group._pendingChildren = [];
|
|
24816
|
-
pendingChildren.forEach((child, childIndex) => {
|
|
24817
|
-
if (child.workspaceId !== activeWorkspace.id) {
|
|
24818
|
-
child.workspaceId = activeWorkspace.id;
|
|
24819
|
-
}
|
|
24820
|
-
child.updatePosition(child.translateX + offsetX, child.translateY + offsetY);
|
|
24821
|
-
child.zIndex = parentZIndex + childIndex + 1;
|
|
24822
|
-
// Recurse before adding so grandchildren are inserted as well
|
|
24823
|
-
if (KritzelClassHelper.isInstanceOf(child, 'KritzelGroup')) {
|
|
24824
|
-
flushPendingChildren(child, child.zIndex);
|
|
24825
|
-
}
|
|
24826
|
-
this.addObject(child);
|
|
24827
|
-
});
|
|
24828
|
-
group.finalize();
|
|
24829
|
-
};
|
|
24830
|
-
const newlyAddedObjects = [];
|
|
24831
|
-
// First add all copied objects to the objectsMap with updated positions
|
|
24832
|
-
copiedObjects.forEach((obj, i) => {
|
|
24833
|
-
// Update workspace if pasting to a different workspace
|
|
24834
|
-
if (obj.workspaceId !== activeWorkspace.id) {
|
|
24835
|
-
obj.workspaceId = activeWorkspace.id;
|
|
24836
|
-
}
|
|
24837
|
-
// Update position
|
|
24838
|
-
obj.updatePosition(obj.translateX + offsetX, obj.translateY + offsetY);
|
|
24839
|
-
// Update z-index
|
|
24840
|
-
obj.zIndex = baseZIndex + i;
|
|
24841
|
-
// Handle KritzelGroup: also add pending children (and grandchildren) with offset
|
|
24842
|
-
if (KritzelClassHelper.isInstanceOf(obj, 'KritzelGroup')) {
|
|
24843
|
-
flushPendingChildren(obj, obj.zIndex);
|
|
24844
|
-
}
|
|
24845
|
-
// Add to objectsMap
|
|
24846
|
-
this.addObject(obj);
|
|
24847
|
-
newlyAddedObjects.push(obj);
|
|
24848
|
-
// Add to selection group
|
|
24849
|
-
selectionGroup.addOrRemove(obj);
|
|
24850
|
-
});
|
|
24851
|
-
this.engine.emitObjectsAdded(newlyAddedObjects);
|
|
24852
|
-
// Update line anchors to point to the newly pasted objects
|
|
24853
|
-
// Only remap if the anchor target was also part of the copied selection
|
|
24854
|
-
copiedObjects.forEach(obj => {
|
|
24855
|
-
if (KritzelClassHelper.isInstanceOf(obj, 'KritzelLine')) {
|
|
24856
|
-
let updated = false;
|
|
24857
|
-
if (obj.startAnchor && originalToNewIdMap.has(obj.startAnchor.objectId)) {
|
|
24858
|
-
obj.startAnchor = { objectId: originalToNewIdMap.get(obj.startAnchor.objectId) };
|
|
24859
|
-
updated = true;
|
|
24860
|
-
}
|
|
24861
|
-
if (obj.endAnchor && originalToNewIdMap.has(obj.endAnchor.objectId)) {
|
|
24862
|
-
obj.endAnchor = { objectId: originalToNewIdMap.get(obj.endAnchor.objectId) };
|
|
24863
|
-
updated = true;
|
|
24864
|
-
}
|
|
24865
|
-
// If anchors were updated, rebuild the anchor index and persist the change
|
|
24866
|
-
if (updated) {
|
|
24867
|
-
this._store.objects.update(obj);
|
|
24868
|
-
}
|
|
24869
|
-
}
|
|
24870
|
-
});
|
|
24871
|
-
});
|
|
24872
|
-
// Rebuild anchor index after all anchor updates
|
|
24873
|
-
this._anchorManager.rebuildIndex();
|
|
24874
|
-
// Mark selection group as selected
|
|
24875
|
-
selectionGroup.isSelected = true;
|
|
24876
|
-
// Set rotation for single object
|
|
24877
|
-
if (copiedObjects.length === 1) {
|
|
24878
|
-
selectionGroup.rotation = copiedObjects[0].rotation;
|
|
24879
|
-
}
|
|
24880
|
-
// For cross-workspace paste, set the selection group's position before inserting
|
|
24881
|
-
// it into the store. This mirrors the existing pattern where objects have
|
|
24882
|
-
// updatePosition called before addObject, so the correct position is captured
|
|
24883
|
-
// in the single initial insert with no separate Yjs update (and no extra undo step).
|
|
24884
|
-
if (isDifferentWorkspace) {
|
|
24885
|
-
if (x !== undefined && y !== undefined) {
|
|
24886
|
-
// Explicit cursor position provided (e.g. right-click paste)
|
|
24887
|
-
selectionGroup.updatePosition(x, y);
|
|
24888
|
-
}
|
|
24889
|
-
else {
|
|
24890
|
-
// Ctrl+V paste: center objects in the current viewport
|
|
24891
|
-
selectionGroup.centerInViewport();
|
|
24892
|
-
}
|
|
24893
|
-
}
|
|
24894
|
-
// Add the selection group (inserts with the already-adjusted position)
|
|
24895
|
-
this.addSelectionGroup(selectionGroup);
|
|
24896
|
-
// Bring pasted objects into view with a smooth animation if they are not
|
|
24897
|
-
// fully visible. These only mutate in-memory viewport state (scale, translateX/Y)
|
|
24898
|
-
// and do not produce any Yjs writes, so they have no impact on the undo history.
|
|
24899
|
-
this.engine.viewport.bringIntoViewIfNeeded(selectionGroup);
|
|
24900
|
-
this._store.state.isSelecting = false;
|
|
24901
|
-
// Defer creating copies for future pastes to next frame to avoid
|
|
24902
|
-
// doubling the object creation cost in the current paste frame
|
|
24903
|
-
requestAnimationFrame(() => {
|
|
24904
|
-
const newSelectionGroup = this._store.selectionGroup;
|
|
24905
|
-
if (newSelectionGroup) {
|
|
24906
|
-
const newIdMapping = new Map();
|
|
24907
|
-
const newCopiedObjects = newSelectionGroup.objects
|
|
24908
|
-
.sort((a, b) => a.zIndex - b.zIndex)
|
|
24909
|
-
.map(obj => {
|
|
24910
|
-
const copiedObj = obj.copy();
|
|
24911
|
-
newIdMapping.set(copiedObj.id, obj.id);
|
|
24912
|
-
return copiedObj;
|
|
24913
|
-
});
|
|
24914
|
-
this._store.state.copiedObjects = newCopiedObjects;
|
|
24915
|
-
this._store.state.copiedObjectIdMapping = newIdMapping;
|
|
24916
|
-
}
|
|
24917
|
-
});
|
|
24918
|
-
this._store.setState('activeTool', this._toolRegistry.getTool('selection'));
|
|
24919
|
-
this.engine.emitObjectsChange();
|
|
24920
|
-
this.rerender();
|
|
24921
|
-
}
|
|
24922
25237
|
/**
|
|
24923
25238
|
* Moves objects one step forward in the z-order stack.
|
|
24924
25239
|
* @param object - Optional specific object to move; defaults to all selected objects
|
|
@@ -27064,6 +27379,8 @@ const KritzelEngine = class {
|
|
|
27064
27379
|
viewportChange;
|
|
27065
27380
|
/** Emitted when the awareness state changes (remote user cursors, presence). */
|
|
27066
27381
|
awarenessChange;
|
|
27382
|
+
/** Emitted when notifications change. */
|
|
27383
|
+
notificationsChange;
|
|
27067
27384
|
forceUpdate = 0;
|
|
27068
27385
|
/** Manually triggers the `objectsSelectionChange` event. */
|
|
27069
27386
|
async triggerSelectionChange() {
|
|
@@ -27178,19 +27495,56 @@ const KritzelEngine = class {
|
|
|
27178
27495
|
this.viewport.handleResize();
|
|
27179
27496
|
}
|
|
27180
27497
|
handleKeyDown(ev) {
|
|
27181
|
-
if (this.core.store.isDisabled || !this.
|
|
27498
|
+
if (this.core.store.isDisabled || !this.shouldHandleGlobalShortcutEvent(ev)) {
|
|
27182
27499
|
return;
|
|
27183
27500
|
}
|
|
27184
27501
|
this.keyHandler.handleKeyDown(ev);
|
|
27185
27502
|
}
|
|
27186
27503
|
handleKeyUp(ev) {
|
|
27187
|
-
if (this.core.store.isDisabled || !this.
|
|
27504
|
+
if (this.core.store.isDisabled || !this.shouldHandleGlobalShortcutEvent(ev)) {
|
|
27188
27505
|
return;
|
|
27189
27506
|
}
|
|
27190
27507
|
this.keyHandler.handleKeyUp(ev);
|
|
27191
27508
|
}
|
|
27509
|
+
handleCopy(ev) {
|
|
27510
|
+
if (this.core.store.isDisabled || !this.shouldHandleGlobalShortcutEvent(ev)) {
|
|
27511
|
+
return;
|
|
27512
|
+
}
|
|
27513
|
+
if (!this.core.store.selectionGroup || this.core.store.activeText || this.core.store.activeShape) {
|
|
27514
|
+
return;
|
|
27515
|
+
}
|
|
27516
|
+
if (ev.cancelable) {
|
|
27517
|
+
ev.preventDefault();
|
|
27518
|
+
}
|
|
27519
|
+
this.core.clipboardManager.copy(ev);
|
|
27520
|
+
this.core.rerender();
|
|
27521
|
+
}
|
|
27522
|
+
handleCut(ev) {
|
|
27523
|
+
if (this.core.store.isDisabled || !this.shouldHandleGlobalShortcutEvent(ev)) {
|
|
27524
|
+
return;
|
|
27525
|
+
}
|
|
27526
|
+
if (!this.core.store.selectionGroup || this.core.store.activeText || this.core.store.activeShape) {
|
|
27527
|
+
return;
|
|
27528
|
+
}
|
|
27529
|
+
if (ev.cancelable) {
|
|
27530
|
+
ev.preventDefault();
|
|
27531
|
+
}
|
|
27532
|
+
this.core.clipboardManager.cut(ev);
|
|
27533
|
+
}
|
|
27534
|
+
handlePaste(ev) {
|
|
27535
|
+
if (this.core.store.isDisabled || !this.shouldHandleGlobalShortcutEvent(ev)) {
|
|
27536
|
+
return;
|
|
27537
|
+
}
|
|
27538
|
+
if (this.core.store.activeText || this.core.store.activeShape) {
|
|
27539
|
+
return;
|
|
27540
|
+
}
|
|
27541
|
+
if (ev.cancelable) {
|
|
27542
|
+
ev.preventDefault();
|
|
27543
|
+
}
|
|
27544
|
+
void this.core.clipboardManager.paste(undefined, undefined, ev);
|
|
27545
|
+
}
|
|
27192
27546
|
/**
|
|
27193
|
-
|
|
27547
|
+
* Determines if the engine should handle a keyboard/clipboard shortcut event.
|
|
27194
27548
|
* Returns true only if:
|
|
27195
27549
|
* - The event originates from within the engine component, OR
|
|
27196
27550
|
* - The event target is not an interactive element that needs keyboard input
|
|
@@ -27198,7 +27552,7 @@ const KritzelEngine = class {
|
|
|
27198
27552
|
* This prevents conflicts with inputs, textareas, dialogs, or other
|
|
27199
27553
|
* interactive elements that need their own keyboard handling.
|
|
27200
27554
|
*/
|
|
27201
|
-
|
|
27555
|
+
shouldHandleGlobalShortcutEvent(ev) {
|
|
27202
27556
|
const path = ev.composedPath();
|
|
27203
27557
|
// Check if event path includes our host - works reliably with Shadow DOM
|
|
27204
27558
|
if (path.includes(this.host)) {
|
|
@@ -27294,11 +27648,11 @@ const KritzelEngine = class {
|
|
|
27294
27648
|
}
|
|
27295
27649
|
/** Copies the currently selected objects to the internal clipboard. */
|
|
27296
27650
|
async copy() {
|
|
27297
|
-
this.core.copy();
|
|
27651
|
+
this.core.clipboardManager.copy();
|
|
27298
27652
|
}
|
|
27299
27653
|
/** Cuts the currently selected objects to the internal clipboard (deletes them from the canvas). */
|
|
27300
27654
|
async cut() {
|
|
27301
|
-
this.core.cut();
|
|
27655
|
+
this.core.clipboardManager.cut();
|
|
27302
27656
|
}
|
|
27303
27657
|
/**
|
|
27304
27658
|
* Pastes previously copied objects at the specified world coordinates.
|
|
@@ -27306,7 +27660,16 @@ const KritzelEngine = class {
|
|
|
27306
27660
|
* @param y - Y position in world coordinates.
|
|
27307
27661
|
*/
|
|
27308
27662
|
async paste(x, y) {
|
|
27309
|
-
this.core.
|
|
27663
|
+
const hasPermission = await this.core.permissionManager.requestPermission('clipboard-read');
|
|
27664
|
+
if (hasPermission !== 'granted') {
|
|
27665
|
+
this.notificationsChange.emit({
|
|
27666
|
+
type: 'error',
|
|
27667
|
+
message: 'Clipboard read permission is required to paste content. Please grant permission and try again.',
|
|
27668
|
+
id: ObjectHelper.generateUUID(),
|
|
27669
|
+
});
|
|
27670
|
+
return;
|
|
27671
|
+
}
|
|
27672
|
+
this.core.clipboardManager.paste(x, y);
|
|
27310
27673
|
}
|
|
27311
27674
|
/**
|
|
27312
27675
|
* Moves an object one layer forward in the z-order.
|
|
@@ -27797,10 +28160,6 @@ const KritzelEngine = class {
|
|
|
27797
28160
|
async worldToScreen(x, y) {
|
|
27798
28161
|
return this.viewport.worldToScreen(x, y);
|
|
27799
28162
|
}
|
|
27800
|
-
/** Returns the objects currently stored in the internal clipboard from a prior `copy()` call. */
|
|
27801
|
-
async getCopiedObjects() {
|
|
27802
|
-
return this.core.store.state.copiedObjects || [];
|
|
27803
|
-
}
|
|
27804
28163
|
/** Returns all objects currently visible within the viewport bounds. */
|
|
27805
28164
|
async getObjectsInViewport() {
|
|
27806
28165
|
return this.core.getObjectsInViewport();
|
|
@@ -28457,6 +28816,7 @@ const KritzelEngine = class {
|
|
|
28457
28816
|
this.objectsInViewportChange = createEvent(this, "objectsInViewportChange");
|
|
28458
28817
|
this.viewportChange = createEvent(this, "viewportChange");
|
|
28459
28818
|
this.awarenessChange = createEvent(this, "awarenessChange");
|
|
28819
|
+
this.notificationsChange = createEvent(this, "notificationsChange");
|
|
28460
28820
|
this.core = new KritzelCore(this);
|
|
28461
28821
|
}
|
|
28462
28822
|
disconnectedCallback() {
|
|
@@ -28735,7 +29095,6 @@ const KritzelEngine = class {
|
|
|
28735
29095
|
this.core.resetActiveShape();
|
|
28736
29096
|
}
|
|
28737
29097
|
this.core.store.state.skipContextMenu = false;
|
|
28738
|
-
this.core.store.state.copiedObjects = undefined;
|
|
28739
29098
|
if (activeTool) {
|
|
28740
29099
|
this.activeToolChange.emit(activeTool);
|
|
28741
29100
|
}
|
|
@@ -29387,7 +29746,7 @@ const KritzelExport = class {
|
|
|
29387
29746
|
return (h("div", { class: "export-tab-content" }, 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 })));
|
|
29388
29747
|
}
|
|
29389
29748
|
render() {
|
|
29390
|
-
return (h(Host, { key: '
|
|
29749
|
+
return (h(Host, { key: 'fd219fffd4d8bb528e6a90055c2b43a5f5a73060' }, h("kritzel-dialog", { key: '9f4ba5b05f5ad31084aab457386a86cbc6d4f2bc', isOpen: this.isDialogOpen, dialogTitle: this.terms['export.dialogTitle'] ?? 'Export', closable: true, contained: true, onDialogClose: this.closeDialog }, h("div", { key: '920bb8f20b42897680084bde47270b3812e2f3e4', class: "export-content" }, 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(), h("button", { key: 'ddf36c1e7cb81409c2cecfa6585e0f1dd7aca2c3', class: "export-primary-button", onClick: this.handleExport }, this.terms['export.exportButton'] ?? 'Export')))));
|
|
29391
29750
|
}
|
|
29392
29751
|
};
|
|
29393
29752
|
KritzelExport.style = kritzelExportCss();
|
|
@@ -29402,7 +29761,7 @@ const KritzelFont = class {
|
|
|
29402
29761
|
size = 24;
|
|
29403
29762
|
color = '#000000';
|
|
29404
29763
|
render() {
|
|
29405
|
-
return (h(Host, { key: '
|
|
29764
|
+
return (h(Host, { key: 'e37350dd092fb7c81a5624bfdc39c3b9af66b894' }, h("div", { key: 'a962ccc23a48f62b86d49ae41b1c9c27bdc9a5b9', class: "font-preview", style: {
|
|
29406
29765
|
fontFamily: this.fontFamily,
|
|
29407
29766
|
fontSize: `${this.size}px`,
|
|
29408
29767
|
color: this.color
|
|
@@ -29478,7 +29837,7 @@ const KritzelFontSize = class {
|
|
|
29478
29837
|
render() {
|
|
29479
29838
|
const color = 'var(--kritzel-global-text-primary)';
|
|
29480
29839
|
const sizes = this.sizes ?? [];
|
|
29481
|
-
return (h(Host, { key: '
|
|
29840
|
+
return (h(Host, { key: 'a314e990b56cb4e819c4d83a139016b1658606b8' }, sizes.map(size => (h("div", { tabIndex: 0, class: {
|
|
29482
29841
|
'size-container': true,
|
|
29483
29842
|
'selected': this.selectedSize === size,
|
|
29484
29843
|
}, onClick: () => this.handleSizeClick(size), onKeyDown: event => this.handleKeyDown(event, size) }, h("kritzel-font", { fontFamily: this.fontFamily, size: size, color: color }))))));
|
|
@@ -29545,7 +29904,7 @@ const KritzelInput = class {
|
|
|
29545
29904
|
this.valueChange.emit(input.value);
|
|
29546
29905
|
};
|
|
29547
29906
|
render() {
|
|
29548
|
-
return (h(Host, { key: '
|
|
29907
|
+
return (h(Host, { key: '7e16272802a5485207721f4f01ddf8e956b56dac' }, h("div", { key: 'ab60dacd08c6199db507d896c00cd0c788ecf7fa', class: "input-container" }, this.label && h("label", { key: 'e2e5769ca2954442da5a0f2a2abb07847986eac8', class: "input-label" }, this.label), h("div", { key: 'e7131f6d1a770cf71de9f7086e3a8a092296b80e', class: { 'input-wrapper': true, 'has-suffix': !!this.suffix } }, h("input", { key: '565cb30ed36818badc148475c596b468cdd2a65b', type: this.type, class: "text-input", value: this.inputValue, placeholder: this.placeholder, disabled: this.disabled, onInput: this.handleInput }), this.suffix && h("span", { key: 'ec4afb63443b6c89a829e515df7d33066f0f8def', class: "input-suffix" }, this.suffix)))));
|
|
29549
29908
|
}
|
|
29550
29909
|
static get watchers() { return {
|
|
29551
29910
|
"value": [{
|
|
@@ -29685,7 +30044,7 @@ const KritzelLoginDialog = class {
|
|
|
29685
30044
|
this.dialogClosed.emit();
|
|
29686
30045
|
};
|
|
29687
30046
|
render() {
|
|
29688
|
-
return (h(Host, { key: '
|
|
30047
|
+
return (h(Host, { key: '6ef65077c95d32fee8da4b70ad2e832ad1bb78f7' }, h("kritzel-dialog", { key: '04f3d3350393475c7267d8ca90c0b3f0fce10c38', dialogTitle: this.dialogTitle, isOpen: this.isDialogOpen, onDialogClose: this.closeDialog, size: "small", contained: true }, h("div", { key: 'c2ed4e339d86dcea23b4a0778b8966a6ae36107a', class: "login-content" }, this.subtitle && (h("p", { key: 'ae46baa70526d057b3427459903287489e645e08', class: "login-subtitle" }, this.subtitle)), h("div", { key: '1055d5861e5281be234094a3c5c86a6aaf58935f', class: "login-providers" }, this.providers.map(provider => (h("button", { key: provider.name, class: {
|
|
29689
30048
|
'provider-button': true,
|
|
29690
30049
|
'is-loading': this.loadingProvider === provider.name,
|
|
29691
30050
|
'is-disabled': this.loadingProvider !== null && this.loadingProvider !== provider.name,
|
|
@@ -29791,15 +30150,15 @@ const KritzelMasterDetail = class {
|
|
|
29791
30150
|
const selectedItem = this.items.find(item => item.id === this.selectedItemId);
|
|
29792
30151
|
const panelId = 'master-detail-panel';
|
|
29793
30152
|
const selectedTabId = selectedItem ? `tab-${selectedItem.id}` : undefined;
|
|
29794
|
-
return (h(Host, { key: '
|
|
30153
|
+
return (h(Host, { key: 'e094bc3df0e0d1598e84c9a17a033079b1db33f6' }, h("div", { key: '79509ba5d63703fe36650b07b5172f77bd6eafde', class: {
|
|
29795
30154
|
'master-detail-container': true,
|
|
29796
30155
|
'is-mobile-detail-visible': this.showMobileDetail,
|
|
29797
|
-
} }, h("nav", { key: '
|
|
30156
|
+
} }, h("nav", { key: '79d200d8c2e54789a33fc88b07c48f034de140ad', class: "master-menu", role: "tablist", "aria-orientation": "vertical", "aria-label": "Settings categories" }, this.items.map((item, index) => (h("button", { key: item.id, id: `tab-${item.id}`, ref: el => this.setTabRef(el, index), class: {
|
|
29798
30157
|
'menu-item': true,
|
|
29799
30158
|
'is-selected': item.id === this.selectedItemId,
|
|
29800
30159
|
'is-disabled': !!item.disabled,
|
|
29801
30160
|
'is-focused': index === this.focusedIndex,
|
|
29802
|
-
}, role: "tab", "aria-selected": item.id === this.selectedItemId ? 'true' : 'false', "aria-controls": panelId, "aria-disabled": item.disabled ? 'true' : undefined, tabIndex: this.getTabIndex(item, index), disabled: item.disabled, onClick: () => this.handleItemClick(item), onKeyDown: e => this.handleKeyDown(e, item, index), onFocus: () => this.handleFocus(index), onBlur: this.handleBlur }, item.icon && (h("kritzel-icon", { name: item.icon, size: 20, class: "menu-item-icon" })), h("span", { class: "menu-item-label" }, item.label), h("span", { class: "menu-item-chevron", "aria-hidden": "true" }, h("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "1.5", "stroke-linecap": "round", "stroke-linejoin": "round" }, h("path", { d: "m9 18 6-6-6-6" }))))))), h("div", { key: '
|
|
30161
|
+
}, role: "tab", "aria-selected": item.id === this.selectedItemId ? 'true' : 'false', "aria-controls": panelId, "aria-disabled": item.disabled ? 'true' : undefined, tabIndex: this.getTabIndex(item, index), disabled: item.disabled, onClick: () => this.handleItemClick(item), onKeyDown: e => this.handleKeyDown(e, item, index), onFocus: () => this.handleFocus(index), onBlur: this.handleBlur }, item.icon && (h("kritzel-icon", { name: item.icon, size: 20, class: "menu-item-icon" })), h("span", { class: "menu-item-label" }, item.label), h("span", { class: "menu-item-chevron", "aria-hidden": "true" }, h("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "1.5", "stroke-linecap": "round", "stroke-linejoin": "round" }, h("path", { d: "m9 18 6-6-6-6" }))))))), h("div", { key: '642b65781509d192330bb2602dd081585d16f76d', id: panelId, class: "detail-panel", role: "tabpanel", "aria-labelledby": selectedTabId }, h("button", { key: '18a922dbaad63f05bc3ca7de176de4996b5d7fcb', class: "mobile-back-button", onClick: this.handleBackClick, "aria-label": "Back to menu" }, h("kritzel-icon", { key: 'b31732cef2ffdb78e67be7ab793aaaf60e373763', name: "chevron-left", size: 20, class: "mobile-back-icon" }), "Back"), h("slot", { key: '48fe4ae631a8c0b2db9e4a232edb6300d603562c' })))));
|
|
29803
30162
|
}
|
|
29804
30163
|
static get watchers() { return {
|
|
29805
30164
|
"selectedItemId": [{
|
|
@@ -29872,7 +30231,7 @@ const KritzelMenu = class {
|
|
|
29872
30231
|
this.itemCloseChildMenu.emit(event.detail);
|
|
29873
30232
|
};
|
|
29874
30233
|
render() {
|
|
29875
|
-
return (h(Host, { key: '
|
|
30234
|
+
return (h(Host, { key: '6dfdc7928ae69aa191b2c64f9db79801e6978e92', tabIndex: 0, onClick: e => e.stopPropagation() }, this.openChildMenuItem && h("div", { key: 'ab8fa25f1b6ee0b7960cb0df84c40b1a7648c4e9', class: "has-open-child-overlay", onClick: this.onOverlayClick }), this.items.map(item => (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 })))));
|
|
29876
30235
|
}
|
|
29877
30236
|
};
|
|
29878
30237
|
KritzelMenu.style = kritzelMenuCss();
|
|
@@ -29977,12 +30336,12 @@ const KritzelMenuItem = class {
|
|
|
29977
30336
|
];
|
|
29978
30337
|
}
|
|
29979
30338
|
render() {
|
|
29980
|
-
return (h(Host, { key: '
|
|
30339
|
+
return (h(Host, { key: 'dbdcfcee7fd36fe0b9c405dd3d1641aa62465e53', tabIndex: this.item.isDisabled ? -1 : 0, class: {
|
|
29981
30340
|
'selected': this.item.isSelected,
|
|
29982
30341
|
'editing': this.item.isEditing,
|
|
29983
30342
|
'disabled': this.item.isDisabled,
|
|
29984
30343
|
'child-open': this.item.isChildMenuOpen,
|
|
29985
|
-
}, onClick: this.handleItemSelect }, h("div", { key: '
|
|
30344
|
+
}, onClick: this.handleItemSelect }, h("div", { key: 'ef97c7cf48190c1bbdde0dd9011cc1d5674b7c94', class: "menu-item-overlay" }), this.item.isEditing ? this.renderEditMode() : this.renderViewMode()));
|
|
29986
30345
|
}
|
|
29987
30346
|
static get watchers() { return {
|
|
29988
30347
|
"item": [{
|
|
@@ -30055,11 +30414,80 @@ const KritzelMoreMenu = class {
|
|
|
30055
30414
|
this.closeMenu();
|
|
30056
30415
|
};
|
|
30057
30416
|
render() {
|
|
30058
|
-
return (h(Host, { key: '
|
|
30417
|
+
return (h(Host, { key: '3e7179c87713cb0087d2d2053f97db8f603f7321', class: { mobile: this.isTouchDevice }, style: { display: this.visible ? '' : 'none' } }, h("div", { key: '23d6be1ec2c25cd0335c1134f18aad7d5be25c85', class: { 'more-menu-wrapper': true, visible: this.visible } }, h("button", { key: 'e3064ba3f7b4c20e8447e16327b73d0f47f3842b', class: "more-menu-button", "data-testid": "more-menu-button", onClick: this.toggleMenu, "aria-label": this.terms['moreMenu.ariaLabel'] ?? 'More options' }, h("kritzel-icon", { key: 'feed090efe4f80c62a29c8146c2d7d8041624381', name: this.icon, size: this.iconSize })), h("kritzel-portal", { key: '7b1a5db932c7bfb5ea8f4d666571c4f7fbbcd238', anchor: this.menuAnchor, offsetY: this.offsetY, onClose: this.closeMenu }, h("kritzel-menu", { key: '65b1225b15a494d49712ad1d2d108e90f09507e9', items: this.visibleItems, onItemSelect: this.handleMenuItemSelect })))));
|
|
30059
30418
|
}
|
|
30060
30419
|
};
|
|
30061
30420
|
KritzelMoreMenu.style = kritzelMoreMenuCss();
|
|
30062
30421
|
|
|
30422
|
+
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}`;
|
|
30423
|
+
|
|
30424
|
+
const KritzelNotificationCard = class {
|
|
30425
|
+
constructor(hostRef) {
|
|
30426
|
+
registerInstance(this, hostRef);
|
|
30427
|
+
this.dismiss = createEvent(this, "dismiss");
|
|
30428
|
+
this.hoverChange = createEvent(this, "hoverChange");
|
|
30429
|
+
}
|
|
30430
|
+
/** Notification data rendered by this card. */
|
|
30431
|
+
notification;
|
|
30432
|
+
/** Whether a formatted timestamp should be displayed when available. */
|
|
30433
|
+
showTimestamp = true;
|
|
30434
|
+
/** Locale used for formatting the timestamp. */
|
|
30435
|
+
locale;
|
|
30436
|
+
/** Emitted when the notification should be dismissed manually. */
|
|
30437
|
+
dismiss;
|
|
30438
|
+
/** Emitted when pointer hover state changes. */
|
|
30439
|
+
hoverChange;
|
|
30440
|
+
handleDismissClick = (event) => {
|
|
30441
|
+
event.stopPropagation();
|
|
30442
|
+
this.dismiss.emit();
|
|
30443
|
+
};
|
|
30444
|
+
handleMouseEnter = () => {
|
|
30445
|
+
this.hoverChange.emit(true);
|
|
30446
|
+
};
|
|
30447
|
+
handleMouseLeave = () => {
|
|
30448
|
+
this.hoverChange.emit(false);
|
|
30449
|
+
};
|
|
30450
|
+
get type() {
|
|
30451
|
+
return this.notification?.type ?? 'info';
|
|
30452
|
+
}
|
|
30453
|
+
get role() {
|
|
30454
|
+
return this.type === 'error' ? 'alert' : 'status';
|
|
30455
|
+
}
|
|
30456
|
+
getTypeLabel(type) {
|
|
30457
|
+
switch (type) {
|
|
30458
|
+
case 'warning':
|
|
30459
|
+
return 'Warning';
|
|
30460
|
+
case 'error':
|
|
30461
|
+
return 'Error';
|
|
30462
|
+
default:
|
|
30463
|
+
return 'Info';
|
|
30464
|
+
}
|
|
30465
|
+
}
|
|
30466
|
+
formatTimestamp(timestamp) {
|
|
30467
|
+
if (!timestamp || !this.showTimestamp) {
|
|
30468
|
+
return null;
|
|
30469
|
+
}
|
|
30470
|
+
const date = timestamp instanceof Date ? timestamp : new Date(timestamp);
|
|
30471
|
+
if (Number.isNaN(date.getTime())) {
|
|
30472
|
+
return null;
|
|
30473
|
+
}
|
|
30474
|
+
return new Intl.DateTimeFormat(this.locale, {
|
|
30475
|
+
dateStyle: 'medium',
|
|
30476
|
+
timeStyle: 'short',
|
|
30477
|
+
}).format(date);
|
|
30478
|
+
}
|
|
30479
|
+
render() {
|
|
30480
|
+
const notification = this.notification;
|
|
30481
|
+
if (!notification) {
|
|
30482
|
+
return h(Host, null);
|
|
30483
|
+
}
|
|
30484
|
+
const type = this.type;
|
|
30485
|
+
const timestamp = this.formatTimestamp(notification.timestamp);
|
|
30486
|
+
return (h(Host, null, h("article", { class: { card: true, [`type-${type}`]: true }, role: this.role, "aria-live": "polite", onMouseEnter: this.handleMouseEnter, onMouseLeave: this.handleMouseLeave }, h("header", { class: "card-header" }, h("span", { class: "type-pill" }, this.getTypeLabel(type)), h("div", { class: "header-right" }, timestamp && (h("time", { class: "timestamp", dateTime: notification.timestamp?.toISOString() }, timestamp)), h("button", { class: "dismiss-button", type: "button", "aria-label": "Dismiss notification", onClick: this.handleDismissClick }, h("kritzel-icon", { name: "x", size: 16 })))), h("p", { class: "message" }, notification.message))));
|
|
30487
|
+
}
|
|
30488
|
+
};
|
|
30489
|
+
KritzelNotificationCard.style = kritzelNotificationCardCss();
|
|
30490
|
+
|
|
30063
30491
|
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}`;
|
|
30064
30492
|
|
|
30065
30493
|
const KritzelNumericInput = class {
|
|
@@ -30153,7 +30581,7 @@ const KritzelNumericInput = class {
|
|
|
30153
30581
|
this.valueChange.emit(newValue);
|
|
30154
30582
|
};
|
|
30155
30583
|
render() {
|
|
30156
|
-
return (h(Host, { key: '
|
|
30584
|
+
return (h(Host, { key: '008f18fc5ab81adcd82364706ca7d4c39ea39d77' }, h("div", { key: '5d91b2ec6e0458d186d923c422e8f6461ac7c51a', class: "input-container" }, this.label && h("label", { key: '45c911f1e11ff8289ab876192511f506eb65c940', class: "input-label" }, this.label), h("div", { key: 'f5e0bd1610a4085a291cc1d32787b68066757c69', class: "input-wrapper" }, 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 }), h("div", { key: '1acab70c82ff7431f916685084a6e5dd827cdca3', class: "spinner-buttons" }, h("button", { key: 'd93c4bec338d49ead87897baf61d2e036999a035', type: "button", class: "spinner-button spinner-up", onClick: this.handleIncrement, tabIndex: -1, "aria-label": "Increase value" }, h("svg", { key: '1e52d43c1eb1e9a43025302a7cd1f3d74c038c36', viewBox: "0 0 10 6", class: "spinner-icon" }, h("path", { key: '2a96516390bd9caf5b6a3617d07f7b10e2b42451', d: "M1 5L5 1L9 5", stroke: "currentColor", "stroke-width": "1.5", fill: "none", "stroke-linecap": "round", "stroke-linejoin": "round" }))), h("button", { key: '038cf61f4b8982a17bf5c279d78556872a03efea', type: "button", class: "spinner-button spinner-down", onClick: this.handleDecrement, tabIndex: -1, "aria-label": "Decrease value" }, h("svg", { key: '30110c2ad975b51049a902953c52be66c1b7b0af', viewBox: "0 0 10 6", class: "spinner-icon" }, h("path", { key: '5abe735234debfa80a983d2fb60eeeaedb1dbf9b', d: "M1 1L5 5L9 1", stroke: "currentColor", "stroke-width": "1.5", fill: "none", "stroke-linecap": "round", "stroke-linejoin": "round" }))))))));
|
|
30157
30585
|
}
|
|
30158
30586
|
static get watchers() { return {
|
|
30159
30587
|
"value": [{
|
|
@@ -30192,7 +30620,7 @@ const KritzelOpacitySlider = class {
|
|
|
30192
30620
|
}
|
|
30193
30621
|
render() {
|
|
30194
30622
|
const percentage = this.getPercentage();
|
|
30195
|
-
return (h(Host, { key: '
|
|
30623
|
+
return (h(Host, { key: 'e3a18981e5193ecd1ffaae5c807bdf6fa67e9695' }, h("div", { key: 'ee5ff0bb1355ca4f7e5d727ab8861933259c1a82', class: "opacity-container" }, h("div", { key: '6362fb3dba6910c55f5fe3b2a4245bcbb33dcdbb', class: "slider-wrapper" }, 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: {
|
|
30196
30624
|
'--slider-progress': `${percentage}%`,
|
|
30197
30625
|
'--kritzel-opacity-slider-thumb-border-color': this.previewColor,
|
|
30198
30626
|
} })))));
|
|
@@ -30545,7 +30973,7 @@ const KritzelPortal = class {
|
|
|
30545
30973
|
this.portal.style.visibility = 'visible';
|
|
30546
30974
|
}
|
|
30547
30975
|
render() {
|
|
30548
|
-
return (h(Host, { key: '
|
|
30976
|
+
return (h(Host, { key: '95fbfde070f33a7f1b59026de7c687a2f6d0119c', style: { display: this.anchor ? 'block' : 'none' } }, h("slot", { key: '14af59a35c5caf71079f7afb5ea6f4c5f13b05f8' })));
|
|
30549
30977
|
}
|
|
30550
30978
|
static get watchers() { return {
|
|
30551
30979
|
"anchor": [{
|
|
@@ -30559,7 +30987,7 @@ const KritzelPortal = class {
|
|
|
30559
30987
|
* This file is auto-generated by the version bump scripts.
|
|
30560
30988
|
* Do not modify manually.
|
|
30561
30989
|
*/
|
|
30562
|
-
const KRITZEL_VERSION = '0.3.
|
|
30990
|
+
const KRITZEL_VERSION = '0.3.20';
|
|
30563
30991
|
|
|
30564
30992
|
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)}`;
|
|
30565
30993
|
|
|
@@ -30783,7 +31211,7 @@ const KritzelSettings = class {
|
|
|
30783
31211
|
}
|
|
30784
31212
|
}
|
|
30785
31213
|
render() {
|
|
30786
|
-
return (h(Host, { key: '
|
|
31214
|
+
return (h(Host, { key: '6f26bd23bf7bb51653f09b96bafef221c51c2bfa' }, h("kritzel-dialog", { key: '49ffda0a422ae1c2c9c8e6e608bce532e7d4099e', isOpen: this.isDialogOpen, dialogTitle: this.t('settings.dialogTitle', 'Settings'), size: "large", contained: true, onDialogClose: this.closeDialog }, h("kritzel-master-detail", { key: 'ab5dc7952e555cae6f841ef4de2ab50d7039279b', items: this.categories, selectedItemId: this.selectedCategoryId, onItemSelect: this.handleCategorySelect }, this.renderCategoryContent()))));
|
|
30787
31215
|
}
|
|
30788
31216
|
static get watchers() { return {
|
|
30789
31217
|
"settings": [{
|
|
@@ -30916,9 +31344,9 @@ const KritzelShareDialog = class {
|
|
|
30916
31344
|
this.dialogClosed.emit();
|
|
30917
31345
|
};
|
|
30918
31346
|
render() {
|
|
30919
|
-
return (h(Host, { key: '
|
|
31347
|
+
return (h(Host, { key: '031cf5d1ab48f2791454d4c7348352295359d225' }, h("kritzel-dialog", { key: 'cdce63c86ca329a97d1f1787adcb2b92bbfa40f9', dialogTitle: this.terms['share.dialogTitle'] ?? 'Share Workspace', size: "small", isOpen: this.isDialogOpen, onDialogClose: this.closeDialog, contained: true }, h("div", { key: 'dbb62b3cb175358955b11f6c2d74b0b0eecf212e', class: "share-content" }, h("div", { key: '8dc0eaea9644b60ff33812dac20def226fa14232', class: "share-section" }, h("div", { key: 'd3cfbf05c28a01681b1223edb6f0b73998ccfd08', class: "share-row" }, h("div", { key: '2400f062f92dd918341391cf71086c2676f7fc66', class: "share-label-group" }, h("label", { key: 'ab01691b9f53f59f92116a2994b6e3551d347c7b', class: "share-label" }, this.terms['share.linkSharing.label'] ?? 'Link sharing'), h("p", { key: 'fd830ad21e32e4fc5d8ba97d5cea7ef8da15fba4', class: "share-description" }, this.internalIsPublic
|
|
30920
31348
|
? (this.terms['share.linkSharing.enabledDescription'] ?? 'Anyone with the link can access this workspace.')
|
|
30921
|
-
: (this.terms['share.linkSharing.disabledDescription'] ?? 'Link sharing is disabled. Only you can access this workspace.'))), h("kritzel-slide-toggle", { key: '
|
|
31349
|
+
: (this.terms['share.linkSharing.disabledDescription'] ?? 'Link sharing is disabled. Only you can access this workspace.'))), h("kritzel-slide-toggle", { key: '6f1a71ba524b34753ccd5437eab00bfcbeffdd79', checked: this.internalIsPublic, onCheckedChange: this.handleToggleChange, label: this.terms['share.linkSharing.toggleLabel'] ?? 'Enable link sharing' }))), this.internalIsPublic && (h("div", { key: '298680e1afdf0094c5393aa95c4983a0a8dd5e18', class: "share-section" }, h("div", { key: '546645a748cf9a42df0c8163f2478ef31445273a', class: "share-url-container" }, h("input", { key: '9d5b93d762d1cd899f3fc8041380bae603a4919c', type: "text", class: "share-url-input", value: this.getShareUrl(), readOnly: true, onClick: (e) => e.target.select() }), 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') }, h("kritzel-icon", { key: '096ca9a0527796462769dc9d42dd81d8f97f2865', name: this.copySuccess ? 'check' : 'copy', size: 18 })))))))));
|
|
30922
31350
|
}
|
|
30923
31351
|
static get watchers() { return {
|
|
30924
31352
|
"isPublic": [{
|
|
@@ -30956,7 +31384,7 @@ const KritzelSlideToggle = class {
|
|
|
30956
31384
|
}
|
|
30957
31385
|
};
|
|
30958
31386
|
render() {
|
|
30959
|
-
return (h(Host, { key: '
|
|
31387
|
+
return (h(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 }, h("div", { key: 'df0adeca0447a13d5499219ac9d27b526252fdbe', class: "toggle-track" }, h("div", { key: '3938239bbdca29e62ed72229dfcf1904fcbaa983', class: "toggle-thumb" }))));
|
|
30960
31388
|
}
|
|
30961
31389
|
};
|
|
30962
31390
|
KritzelSlideToggle.style = kritzelSlideToggleCss();
|
|
@@ -31056,7 +31484,7 @@ const KritzelSplitButton = class {
|
|
|
31056
31484
|
this.menuScrollTop = event.target.scrollTop;
|
|
31057
31485
|
};
|
|
31058
31486
|
render() {
|
|
31059
|
-
return (h(Host, { key: '
|
|
31487
|
+
return (h(Host, { key: 'd6856a86b3be4d9a22c5e78df1bda19113cb988b', class: { mobile: this.isTouchDevice } }, h("button", { key: 'd26026af275a8bd5717254223d5829e3d7f02bcb', class: "split-main-button", tabIndex: 0, onClick: this.handleButtonClick, disabled: this.mainButtonDisabled, "aria-label": "Main action" }, this.buttonIcon && h("kritzel-icon", { key: '1b3e2f4c2f8245b281d0f85458fd6bcc0cc73c59', name: this.buttonIcon })), h("div", { key: 'b002b904e168d62075fa086c88df72e36cc8e8c2', class: "split-divider" }), 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" }, h("kritzel-icon", { key: 'b1bc427b0d7cd26a283dbeb772dee0a6d2ca172c', name: this.dropdownIcon })), h("kritzel-portal", { key: 'e76300f48a23772a5923ea2cbd0824590302e7e7', anchor: this.anchorElement, offsetY: 4, onClose: this.closeMenu }, 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 }))));
|
|
31060
31488
|
}
|
|
31061
31489
|
};
|
|
31062
31490
|
KritzelSplitButton.style = kritzelSplitButtonCss();
|
|
@@ -31077,7 +31505,7 @@ const KritzelStrokeSize = class {
|
|
|
31077
31505
|
}
|
|
31078
31506
|
render() {
|
|
31079
31507
|
const sizes = this.sizes ?? [];
|
|
31080
|
-
return (h(Host, { key: '
|
|
31508
|
+
return (h(Host, { key: 'bde2cc986aebbe869a3eea026654229dee0d3e0e' }, h("div", { key: 'f84c4b844b865080f4e0e245bbccc6d77ac3f049', class: "size-grid" }, sizes.map(size => (h("div", { tabIndex: 0, class: {
|
|
31081
31509
|
'size-container': true,
|
|
31082
31510
|
'selected': this.selectedSize === size,
|
|
31083
31511
|
}, onClick: () => this.handleSizeClick(size) }, h("kritzel-color", { value: 'var(--kritzel-global-text-primary)', size: size })))))));
|
|
@@ -31458,14 +31886,14 @@ const KritzelTooltip = class {
|
|
|
31458
31886
|
}
|
|
31459
31887
|
}
|
|
31460
31888
|
render() {
|
|
31461
|
-
return (h(Host, { key: '
|
|
31889
|
+
return (h(Host, { key: 'ba4d13171aa25acac6c615ee12f35eab96d0aad6', style: {
|
|
31462
31890
|
position: 'fixed',
|
|
31463
31891
|
zIndex: '9999',
|
|
31464
31892
|
transition: 'opacity 0.3s ease-in-out, transform 0.3s ease-in-out',
|
|
31465
31893
|
visibility: this.isVisible ? 'visible' : 'hidden',
|
|
31466
31894
|
left: `${this.positionX}px`,
|
|
31467
31895
|
bottom: `${this.positionY}px`,
|
|
31468
|
-
} }, h("div", { key: '
|
|
31896
|
+
} }, h("div", { key: '923168164a018b08eac4246d88c7f8648b71d078', class: "tooltip-content", onClick: event => event.stopPropagation(), onPointerDown: event => event.stopPropagation(), onMouseDown: event => event.stopPropagation() }, h("slot", { key: 'aafad8ab026d591ebb9e2aeffa15d07718eba261' }))));
|
|
31469
31897
|
}
|
|
31470
31898
|
static get watchers() { return {
|
|
31471
31899
|
"triggerElement": [{
|
|
@@ -31506,7 +31934,7 @@ const KritzelUtilityPanel = class {
|
|
|
31506
31934
|
this.redo.emit();
|
|
31507
31935
|
}
|
|
31508
31936
|
render() {
|
|
31509
|
-
return (h(Host, { key: '
|
|
31937
|
+
return (h(Host, { key: '22f3826d57b4d8f0e476951a860bde3dbc6c7200' }, 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' }, h("kritzel-icon", { key: 'ab4e9da6b60d9fa470fd8f5002f2acd5a758a8ba', name: "undo" })), 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' }, h("kritzel-icon", { key: '7ae8cec39ffab1303d76315ab85ac575b886b233', name: "redo" })), h("div", { key: 'f54e0262f133ad0eed0bbf853b67edd6c2f5e87f', class: "utility-separator" }), h("button", { key: '162d6e85965338b5700e661595dc6da6131ebccf', class: "utility-button", "data-testid": "utility-delete", onClick: () => this.delete.emit(), "aria-label": this.terms['utility.delete'] ?? 'Delete selected items' }, h("kritzel-icon", { key: 'dc00247ed45f09b86ad9314395f56e70d1122a4b', name: "delete" }))));
|
|
31510
31938
|
}
|
|
31511
31939
|
};
|
|
31512
31940
|
KritzelUtilityPanel.style = kritzelUtilityPanelCss();
|
|
@@ -31527,7 +31955,7 @@ const KritzelWatermark = class {
|
|
|
31527
31955
|
label;
|
|
31528
31956
|
render() {
|
|
31529
31957
|
const label = this.label ?? this.core.localizationManager.translate('watermark.poweredBy');
|
|
31530
|
-
return (h(Host, { key: '
|
|
31958
|
+
return (h(Host, { key: '975534180d82064e38fa0289a2955e97a4ca0a08' }, 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)));
|
|
31531
31959
|
}
|
|
31532
31960
|
};
|
|
31533
31961
|
KritzelWatermark.style = kritzelWatermarkCss();
|
|
@@ -31715,9 +32143,9 @@ const KritzelZoomPanel = class {
|
|
|
31715
32143
|
return Number.isFinite(this.zoomPercent) ? Math.max(1, Math.round(this.zoomPercent)) : 100;
|
|
31716
32144
|
}
|
|
31717
32145
|
render() {
|
|
31718
|
-
return (h(Host, { key: '
|
|
32146
|
+
return (h(Host, { key: '00d5c674581d4efa40da3a2ad5cbdd8295406590' }, h("div", { key: 'c7a4158f57b8062f37ee69f7b198442ec357d746', class: { panel: true, visible: this.visible } }, h("button", { key: 'e20344f5e522d481185a9dab7afdb2668cf44408', class: "zoom-button", type: "button", "aria-label": this.terms['zoom.zoomOut'] ?? 'Zoom out', disabled: this.disabled, onClick: this.handleZoomOut }, h("kritzel-icon", { key: '4fc1eeb78669894b0939a96c5e6945cea5056ac1', name: "minus" })), h("span", { key: 'ed26096e2ca76fe91b50d73ea6c9481996d01590', class: "zoom-level", "aria-live": "polite" }, this.normalizedZoomPercent, "%"), h("button", { key: '42609c6e8558b7d9e9e348b864639ead6c4cc9bb', class: "zoom-button", type: "button", "aria-label": this.terms['zoom.zoomIn'] ?? 'Zoom in', disabled: this.disabled, onClick: this.handleZoomIn }, h("kritzel-icon", { key: '3a321afb57f532ef867bae73751314f3fd355214', name: "plus" })))));
|
|
31719
32147
|
}
|
|
31720
32148
|
};
|
|
31721
32149
|
KritzelZoomPanel.style = kritzelZoomPanelCss();
|
|
31722
32150
|
|
|
31723
|
-
export { KritzelActiveUsers as kritzel_active_users, KritzelAvatar as kritzel_avatar, KritzelAwarenessCursors as kritzel_awareness_cursors, KritzelBackToContent as kritzel_back_to_content, KritzelButton as kritzel_button, KritzelColorComponent as kritzel_color, KritzelColorPalette as kritzel_color_palette, KritzelContextMenu as kritzel_context_menu, KritzelControls as kritzel_controls, KritzelCurrentUser as kritzel_current_user, KritzelCurrentUserDialog as kritzel_current_user_dialog, KritzelCursorTrail as kritzel_cursor_trail, KritzelDialog as kritzel_dialog, KritzelDropdown as kritzel_dropdown, KritzelEditor as kritzel_editor, KritzelEngine as kritzel_engine, KritzelExport as kritzel_export, KritzelFont as kritzel_font, KritzelFontFamily as kritzel_font_family, KritzelFontSize as kritzel_font_size, KritzelIcon as kritzel_icon, KritzelInput as kritzel_input, KritzelLineEndings as kritzel_line_endings, KritzelLoginDialog as kritzel_login_dialog, KritzelMasterDetail as kritzel_master_detail, KritzelMenu as kritzel_menu, KritzelMenuItem as kritzel_menu_item, KritzelMoreMenu as kritzel_more_menu, KritzelNumericInput as kritzel_numeric_input, KritzelOpacitySlider as kritzel_opacity_slider, KritzelPillTabs as kritzel_pill_tabs, KritzelPortal as kritzel_portal, KritzelSettings as kritzel_settings, KritzelShapeFill as kritzel_shape_fill, KritzelShareDialog as kritzel_share_dialog, KritzelSlideToggle as kritzel_slide_toggle, KritzelSplitButton as kritzel_split_button, KritzelStrokeSize as kritzel_stroke_size, KritzelToolConfig as kritzel_tool_config, KritzelTooltip as kritzel_tooltip, KritzelUtilityPanel as kritzel_utility_panel, KritzelWatermark as kritzel_watermark, KritzelWorkspaceManager as kritzel_workspace_manager, KritzelZoomPanel as kritzel_zoom_panel };
|
|
32151
|
+
export { KritzelActiveUsers as kritzel_active_users, KritzelAvatar as kritzel_avatar, KritzelAwarenessCursors as kritzel_awareness_cursors, KritzelBackToContent as kritzel_back_to_content, KritzelButton as kritzel_button, KritzelColorComponent as kritzel_color, KritzelColorPalette as kritzel_color_palette, KritzelContextMenu as kritzel_context_menu, KritzelControls as kritzel_controls, KritzelCurrentUser as kritzel_current_user, KritzelCurrentUserDialog as kritzel_current_user_dialog, KritzelCursorTrail as kritzel_cursor_trail, KritzelDialog as kritzel_dialog, KritzelDropdown as kritzel_dropdown, KritzelEditor as kritzel_editor, KritzelEngine as kritzel_engine, KritzelExport as kritzel_export, KritzelFont as kritzel_font, KritzelFontFamily as kritzel_font_family, KritzelFontSize as kritzel_font_size, KritzelIcon as kritzel_icon, KritzelInput as kritzel_input, KritzelLineEndings as kritzel_line_endings, KritzelLoginDialog as kritzel_login_dialog, KritzelMasterDetail as kritzel_master_detail, KritzelMenu as kritzel_menu, KritzelMenuItem as kritzel_menu_item, KritzelMoreMenu as kritzel_more_menu, KritzelNotificationCard as kritzel_notification_card, KritzelNumericInput as kritzel_numeric_input, KritzelOpacitySlider as kritzel_opacity_slider, KritzelPillTabs as kritzel_pill_tabs, KritzelPortal as kritzel_portal, KritzelSettings as kritzel_settings, KritzelShapeFill as kritzel_shape_fill, KritzelShareDialog as kritzel_share_dialog, KritzelSlideToggle as kritzel_slide_toggle, KritzelSplitButton as kritzel_split_button, KritzelStrokeSize as kritzel_stroke_size, KritzelToolConfig as kritzel_tool_config, KritzelTooltip as kritzel_tooltip, KritzelUtilityPanel as kritzel_utility_panel, KritzelWatermark as kritzel_watermark, KritzelWorkspaceManager as kritzel_workspace_manager, KritzelZoomPanel as kritzel_zoom_panel };
|