kritzel-stencil 0.2.10 → 0.2.12
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/kritzel-active-users_42.cjs.entry.js +280 -33
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/stencil.cjs.js +1 -1
- package/dist/collection/classes/core/core.class.js +12 -7
- package/dist/collection/classes/core/viewport.class.js +65 -0
- package/dist/collection/classes/handlers/context-menu.handler.js +7 -6
- package/dist/collection/components/core/kritzel-editor/kritzel-editor.css +8 -1
- package/dist/collection/components/core/kritzel-engine/kritzel-engine.js +4 -4
- package/dist/collection/components/shared/kritzel-dialog/kritzel-dialog.css +29 -0
- package/dist/collection/components/shared/kritzel-dialog/kritzel-dialog.js +201 -5
- package/dist/collection/components/shared/kritzel-menu/kritzel-menu.js +1 -1
- package/dist/collection/components/ui/kritzel-controls/kritzel-controls.css +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-settings/kritzel-settings.js +1 -1
- package/dist/collection/components/ui/kritzel-share-dialog/kritzel-share-dialog.js +2 -2
- package/dist/collection/configs/default-engine-config.js +2 -0
- package/dist/collection/constants/version.js +1 -1
- package/dist/components/index.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-dialog.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-login-dialog.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-settings.js +1 -1
- package/dist/components/kritzel-share-dialog.js +1 -1
- package/dist/components/kritzel-split-button.js +1 -1
- package/dist/components/kritzel-workspace-manager.js +1 -1
- package/dist/components/p-BTSOqHMI.js +1 -0
- package/dist/components/{p-B_fA1LTU.js → p-BWB2UGxj.js} +1 -1
- package/dist/components/{p-BpRNLd4z.js → p-Bw1PPSFV.js} +1 -1
- package/dist/components/p-C51_twnc.js +1 -0
- package/dist/components/{p-DykzXVCs.js → p-CS3JA3yn.js} +1 -1
- package/dist/components/p-CrSLn46K.js +1 -0
- package/dist/components/p-CrmWVXea.js +1 -0
- package/dist/components/{p-DQ1fRE9J.js → p-CvCTQQcJ.js} +1 -1
- package/dist/components/{p-CRsnBR8O.js → p-D9BJCr8V.js} +1 -1
- package/dist/components/p-DMfU0hHe.js +1 -0
- package/dist/components/p-DsxW_miC.js +1 -0
- package/dist/components/p-DzxPDPED.js +1 -0
- package/dist/components/{p-nW05C2cx.js → p-Z9_amVdR.js} +1 -1
- package/dist/esm/kritzel-active-users_42.entry.js +280 -33
- package/dist/esm/loader.js +1 -1
- package/dist/esm/stencil.js +1 -1
- package/dist/stencil/p-ddd603ac.entry.js +9 -0
- package/dist/stencil/stencil.esm.js +1 -1
- package/dist/types/classes/core/viewport.class.d.ts +22 -0
- package/dist/types/components/shared/kritzel-dialog/kritzel-dialog.d.ts +21 -0
- package/dist/types/components.d.ts +11 -0
- package/dist/types/constants/version.d.ts +1 -1
- package/dist/types/interfaces/engine-state.interface.d.ts +2 -0
- package/package.json +1 -1
- package/dist/components/p-B1V6yEGY.js +0 -1
- package/dist/components/p-BuSOJ7Xd.js +0 -1
- package/dist/components/p-CzYgMB2N.js +0 -1
- package/dist/components/p-DBIK7z89.js +0 -1
- package/dist/components/p-DPxSr1wV.js +0 -1
- package/dist/components/p-Dpr_JQam.js +0 -1
- package/dist/components/p-xHh03blG.js +0 -1
- package/dist/stencil/p-bfff1c18.entry.js +0 -9
|
@@ -892,7 +892,7 @@ class KritzelToolConfigHelper {
|
|
|
892
892
|
}
|
|
893
893
|
}
|
|
894
894
|
|
|
895
|
-
const kritzelControlsCss = () => `:host{display:flex;flex-direction:column;user-select:none;max-width:
|
|
895
|
+
const kritzelControlsCss = () => `:host{display:flex;flex-direction:column;user-select:none;max-width:100%}:host(.mobile){--kritzel-controls-control-hover-background-color:transparent;--kritzel-controls-control-active-background-color:transparent}.kritzel-controls{display:flex;flex-direction:row;align-items:center;justify-content:flex-start;gap:var(--kritzel-controls-gap, 8px);height:100%;padding:var(--kritzel-controls-padding, 8px);background-color:var(--kritzel-controls-background-color, #ffffff);border-radius:var(--kritzel-controls-border-radius, 16px);box-shadow:var(--kritzel-controls-box-shadow, 0 0 3px rgba(0, 0, 0, 0.08));border:var(--kritzel-controls-border, 1px solid #ebebeb);z-index:10000;position:relative;max-width:100%;overflow:hidden}.kritzel-tools-scroll{display:flex;flex-direction:row;align-items:center;gap:var(--kritzel-controls-gap, 8px);overflow-x:auto;overflow-y:hidden;flex:1 1 auto;min-width:0;padding:4px;margin:-4px;scrollbar-width:none;-ms-overflow-style:none}.kritzel-tools-scroll::-webkit-scrollbar{display:none}.scroll-indicator-left,.scroll-indicator-right{position:absolute;top:0;bottom:0;width:32px;pointer-events:none;opacity:0;transition:opacity 0.2s ease-out;z-index:1}.scroll-indicator-left{left:0;background:linear-gradient(to right, var(--kritzel-controls-background-color, #ffffff), transparent);border-radius:var(--kritzel-controls-border-radius, 16px) 0 0 var(--kritzel-controls-border-radius, 16px)}.scroll-indicator-right{right:0;background:linear-gradient(to left, var(--kritzel-controls-background-color, #ffffff), transparent);border-radius:0 var(--kritzel-controls-border-radius, 16px) var(--kritzel-controls-border-radius, 16px) 0}.scroll-indicator-left.visible,.scroll-indicator-right.visible{opacity:1}.kritzel-control{display:flex;justify-content:center;align-items:center;color:var(--kritzel-controls-control-color, #000000);border-radius:var(--kritzel-controls-control-border-radius, 12px);padding:var(--kritzel-controls-control-padding, 8px);border:none;background:none;cursor:var(--kritzel-global-pointer-cursor, pointer);-webkit-tap-highlight-color:transparent;font-weight:bold}.kritzel-control:focus,.kritzel-control:hover{background-color:var(--kritzel-controls-control-hover-background-color, hsl(0, 0%, 0%, 4.3%))}.kritzel-control:active{background-color:var(--kritzel-controls-control-active-background-color, hsl(0, 0%, 0%, 8.6%))}.kritzel-control.selected,.kritzel-control.selected:hover,.kritzel-control.selected:active{background-color:var(--kritzel-controls-control-selected-background-color, #007AFF) !important;color:var(--kritzel-controls-control-selected-color, #ffffff) !important}.kritzel-control.selected:focus{background-color:var(--kritzel-controls-control-selected-background-color, #007bffe3) !important}.kritzel-control-separator{width:1px;height:24px;background-color:var(--kritzel-controls-border, #ebebeb);margin:0 4px}.kritzel-control-split{position:relative;display:flex;align-items:center;border-radius:var(--kritzel-controls-control-border-radius, 12px);color:var(--kritzel-controls-control-color, #000000)}.kritzel-control-split .kritzel-control-main{display:flex;justify-content:center;align-items:center;padding:var(--kritzel-controls-control-padding, 8px);border:none;background:none;cursor:var(--kritzel-global-pointer-cursor, pointer);-webkit-tap-highlight-color:transparent;border-radius:var(--kritzel-controls-control-border-radius, 12px);color:inherit}.kritzel-control-split.selected .kritzel-control-main{border-radius:var(--kritzel-controls-control-border-radius, 12px) 0 0 var(--kritzel-controls-control-border-radius, 12px)}.kritzel-control-split .kritzel-control-dropdown{display:flex;justify-content:center;align-items:center;align-self:stretch;border:none;background:none;cursor:var(--kritzel-global-pointer-cursor, pointer);-webkit-tap-highlight-color:transparent;border-radius:0 var(--kritzel-controls-control-border-radius, 12px) var(--kritzel-controls-control-border-radius, 12px) 0;color:inherit;width:0;padding:0;opacity:0;overflow:hidden;pointer-events:none;transition:width 0.15s ease-out, padding 0.15s ease-out, opacity 0.15s ease-out}.kritzel-control-split .kritzel-control-dropdown.visible{width:auto;padding:0 6px;opacity:1;pointer-events:auto}.kritzel-control-split .kritzel-control-main:focus,.kritzel-control-split .kritzel-control-main:hover,.kritzel-control-split .kritzel-control-dropdown:focus,.kritzel-control-split .kritzel-control-dropdown:hover{background-color:var(--kritzel-controls-control-hover-background-color, hsl(0, 0%, 0%, 4.3%))}.kritzel-control-split .kritzel-control-main:active,.kritzel-control-split .kritzel-control-dropdown:active{background-color:var(--kritzel-controls-control-active-background-color, hsl(0, 0%, 0%, 8.6%))}.kritzel-control-split.selected{background-color:var(--kritzel-controls-control-selected-background-color, #007AFF) !important;color:var(--kritzel-controls-control-selected-color, #ffffff) !important}.kritzel-control-split.selected .kritzel-control-main:hover,.kritzel-control-split.selected .kritzel-control-dropdown:hover{background-color:rgba(255, 255, 255, 0.15)}.kritzel-submenu-content{display:flex;flex-direction:column;gap:var(--kritzel-submenu-gap, 4px);min-width:140px}.kritzel-submenu-item{display:flex;align-items:center;gap:10px;padding:10px 12px;border:none;background:none;cursor:var(--kritzel-global-pointer-cursor, pointer);border-radius:8px;color:var(--kritzel-controls-control-color, #000000);font-size:14px;text-align:left;white-space:nowrap;-webkit-tap-highlight-color:transparent}.kritzel-submenu-item:hover{background-color:var(--kritzel-controls-control-hover-background-color, hsl(0, 0%, 0%, 4.3%))}.kritzel-submenu-item.active{background-color:var(--kritzel-controls-control-selected-background-color, #007AFF);color:var(--kritzel-controls-control-selected-color, #ffffff)}.kritzel-submenu-item.active:hover{background-color:var(--kritzel-controls-control-selected-background-color, #007AFF)}.kritzel-config-container{position:relative;display:flex;justify-content:center;align-items:center;height:40px;box-sizing:border-box;-webkit-tap-highlight-color:transparent;flex-shrink:0;width:0;opacity:0;overflow:hidden;pointer-events:none;margin-left:calc(-1 * var(--kritzel-controls-gap, 8px));transition:width 0.2s ease-out, opacity 0.2s ease-out, margin-left 0.2s ease-out}.kritzel-config-container.visible{width:40px;opacity:1;pointer-events:auto;margin-left:0;overflow:visible}.config-gradient-left{position:absolute;top:0;bottom:0;left:-32px;width:32px;background:linear-gradient(to right, transparent, var(--kritzel-controls-background-color, #ffffff));pointer-events:none;z-index:1;opacity:0;transition:opacity 0.2s ease-out}.config-gradient-left.visible{opacity:1}.kritzel-config{display:flex;justify-content:center;align-items:center;cursor:var(--kritzel-global-pointer-cursor, pointer);border-radius:50%}.color-container{display:flex;justify-content:center;align-items:center;width:32px;height:32px;border-radius:50%;cursor:var(--kritzel-global-pointer-cursor, pointer);border:2px solid transparent;box-sizing:border-box;background-color:var(--kritzel-color-palette-hover-background-color, #ebebeb)}.font-container{display:flex;justify-content:center;align-items:center;width:32px;height:32px;border-radius:50%;cursor:var(--kritzel-global-pointer-cursor, pointer);border:2px solid transparent;box-sizing:border-box;background-color:var(--kritzel-color-palette-hover-background-color, #ebebeb)}.no-config{height:24px;width:24px;border-radius:50%;border:1px dashed gray}kritzel-tooltip{z-index:10001}`;
|
|
896
896
|
|
|
897
897
|
const KritzelControls = class {
|
|
898
898
|
constructor(hostRef) {
|
|
@@ -1204,7 +1204,7 @@ const KritzelCurrentUserDialog = class {
|
|
|
1204
1204
|
}
|
|
1205
1205
|
render() {
|
|
1206
1206
|
const displayName = this.getDisplayName();
|
|
1207
|
-
return (index.h(index.Host, { key: 'e1dd44cdfdbaebfe886fed0d9feba2ef232b6615' }, index.h("kritzel-dialog", { key: '
|
|
1207
|
+
return (index.h(index.Host, { key: 'e1dd44cdfdbaebfe886fed0d9feba2ef232b6615' }, index.h("kritzel-dialog", { key: 'cd3daa7abd53c10852d63a2fe53d919414cd8904', dialogTitle: "Account", isOpen: this.isDialogOpen, onDialogClose: this.closeDialog, size: "small", contained: true }, index.h("div", { key: '94d0a691ede73135e6cf4ef144c13e52e410ffbe', class: "user-info" }, index.h("kritzel-avatar", { key: 'e57592d2f3663b593534055be5aae1b224fa8906', user: this.user, size: 80 }), displayName && index.h("div", { key: '237db2d0608ee49ea70e5282b61a59077f0f4595', class: "user-name" }, displayName), this.user?.email && index.h("div", { key: 'd821e8171530b92ce6f1781c1145b611d3c533d0', class: "user-email" }, this.user.email)))));
|
|
1208
1208
|
}
|
|
1209
1209
|
};
|
|
1210
1210
|
KritzelCurrentUserDialog.style = kritzelCurrentUserDialogCss();
|
|
@@ -1365,7 +1365,7 @@ class KritzelHTMLHelper {
|
|
|
1365
1365
|
}
|
|
1366
1366
|
}
|
|
1367
1367
|
|
|
1368
|
-
const kritzelDialogCss = () => `:host{display:contents}.backdrop{position:fixed;top:0;left:0;right:0;bottom:0;z-index:10002;display:flex;align-items:center;justify-content:center;background-color:var(--kritzel-dialog-backdrop-color, rgba(0, 0, 0, 0.5));opacity:1;transition:opacity 150ms ease-out}.backdrop.is-animating{opacity:0}.dialog-content{position:relative;display:flex;flex-direction:column;background-color:var(--kritzel-dialog-background-color, #ffffff);border-radius:var(--kritzel-dialog-border-radius, 12px);box-shadow:var(--kritzel-dialog-box-shadow, 0 4px 20px rgba(0, 0, 0, 0.15));border:var(--kritzel-dialog-border, 1px solid #ebebeb);max-height:var(--kritzel-dialog-max-height, 90vh);max-width:var(--kritzel-dialog-max-width, 90vw);overflow:hidden;transform:scale(1);opacity:1;transition:transform 200ms ease-out, opacity 200ms ease-out;font-family:var(--kritzel-dialog-font-family, sans-serif)}.dialog-content.is-animating{transform:scale(0.95);opacity:0}.dialog-content.size-small{width:var(--kritzel-dialog-width-small, 320px);height:var(--kritzel-dialog-height-small, auto)}.dialog-content.size-medium{width:var(--kritzel-dialog-width-medium, 480px);height:var(--kritzel-dialog-height-medium, auto)}.dialog-content.size-large{width:var(--kritzel-dialog-width-large, 640px);height:var(--kritzel-dialog-height-large, auto)}.dialog-content.size-fullscreen{width:100vw;height:100vh;height:100dvh;max-width:100vw;max-height:100vh;max-height:100dvh;border-radius:0}@media (max-width: 576px), (max-height: 576px) and (orientation: landscape){.backdrop:has(.fullscreen-on-mobile){background-color:transparent}.dialog-content.fullscreen-on-mobile{width:100vw;height:100vh;height:100dvh;max-width:100vw;max-height:100vh;max-height:100dvh;border-radius:0}.dialog-content.fullscreen-on-mobile .dialog-body{display:flex;flex-direction:column}.dialog-content.fullscreen-on-mobile .dialog-body ::slotted(*){flex:1;min-height:0}}.dialog-header{display:flex;align-items:center;justify-content:space-between;padding:var(--kritzel-dialog-header-padding, 16px 20px);border-bottom:var(--kritzel-dialog-header-border, 1px solid #ebebeb);gap:12px}.dialog-title{margin:0;font-size:var(--kritzel-dialog-title-font-size, 18px);font-weight:var(--kritzel-dialog-title-font-weight, 600);color:var(--kritzel-dialog-title-color, #1a1a1a);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.close-button{display:flex;align-items:center;justify-content:center;width:32px;height:32px;padding:0;border:none;border-radius:var(--kritzel-dialog-close-button-border-radius, 6px);background-color:var(--kritzel-dialog-close-button-background, transparent);color:var(--kritzel-dialog-close-button-color, #666666);cursor:var(--kritzel-global-pointer-cursor, pointer);transition:background-color 150ms ease, color 150ms ease;flex-shrink:0;-webkit-tap-highlight-color:transparent}.close-button:hover{background-color:var(--kritzel-dialog-close-button-hover-background, #f5f5f5);color:var(--kritzel-dialog-close-button-hover-color, #1a1a1a)}.close-button:active{background-color:var(--kritzel-dialog-close-button-active-background, #ebebeb)}.close-button:focus-visible{outline:revert;outline-offset:revert}.dialog-body{padding:var(--kritzel-dialog-body-padding, 20px);overflow-y:auto;flex:1;min-height:0;scrollbar-color:var(--kritzel-global-scrollbar-thumb-color, #ebebeb) transparent;scrollbar-width:thin}.dialog-footer{display:flex;align-items:center;justify-content:flex-end;gap:var(--kritzel-dialog-footer-gap, 8px);padding:var(--kritzel-dialog-footer-padding, 16px 20px);border-top:var(--kritzel-dialog-footer-border, 1px solid #ebebeb)}::slotted([slot='header']){flex:1}::slotted([slot='footer']){display:contents}`;
|
|
1368
|
+
const kritzelDialogCss = () => `:host{display:contents}.dialog-content{text-align:start;line-height:normal}.backdrop{position:fixed;top:0;left:0;right:0;bottom:0;z-index:10002;display:flex;align-items:center;justify-content:center;background-color:var(--kritzel-dialog-backdrop-color, rgba(0, 0, 0, 0.5));opacity:1;transition:opacity 150ms ease-out}.backdrop.is-animating{opacity:0}.dialog-content{position:relative;display:flex;flex-direction:column;background-color:var(--kritzel-dialog-background-color, #ffffff);border-radius:var(--kritzel-dialog-border-radius, 12px);box-shadow:var(--kritzel-dialog-box-shadow, 0 4px 20px rgba(0, 0, 0, 0.15));border:var(--kritzel-dialog-border, 1px solid #ebebeb);max-height:var(--kritzel-dialog-max-height, 90vh);max-width:var(--kritzel-dialog-max-width, 90vw);overflow:hidden;transform:scale(1);opacity:1;transition:transform 200ms ease-out, opacity 200ms ease-out;font-family:var(--kritzel-dialog-font-family, sans-serif)}.dialog-content.is-animating{transform:scale(0.95);opacity:0}.dialog-content.size-small{width:var(--kritzel-dialog-width-small, 320px);height:var(--kritzel-dialog-height-small, auto)}.dialog-content.size-medium{width:var(--kritzel-dialog-width-medium, 480px);height:var(--kritzel-dialog-height-medium, auto)}.dialog-content.size-large{width:var(--kritzel-dialog-width-large, 640px);height:var(--kritzel-dialog-height-large, auto)}.dialog-content.size-fullscreen{width:100vw;height:100vh;height:100dvh;max-width:100vw;max-height:100vh;max-height:100dvh;border-radius:0}.backdrop.contained-fullscreen{background-color:transparent}.dialog-content.contained-fullscreen{border-radius:0}.dialog-content.contained-fullscreen .dialog-body{display:flex;flex-direction:column}.dialog-content.contained-fullscreen .dialog-body ::slotted(*){flex:1;min-height:0}@media (max-width: 576px), (max-height: 576px) and (orientation: landscape){.backdrop:has(.fullscreen-on-mobile){background-color:transparent}.dialog-content.fullscreen-on-mobile{width:100vw;height:100vh;height:100dvh;max-width:100vw;max-height:100vh;max-height:100dvh;border-radius:0}.dialog-content.fullscreen-on-mobile .dialog-body{display:flex;flex-direction:column}.dialog-content.fullscreen-on-mobile .dialog-body ::slotted(*){flex:1;min-height:0}}.dialog-header{display:flex;align-items:center;justify-content:space-between;padding:var(--kritzel-dialog-header-padding, 16px 20px);border-bottom:var(--kritzel-dialog-header-border, 1px solid #ebebeb);gap:12px}.dialog-title{margin:0;font-size:var(--kritzel-dialog-title-font-size, 18px);font-weight:var(--kritzel-dialog-title-font-weight, 600);color:var(--kritzel-dialog-title-color, #1a1a1a);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.close-button{display:flex;align-items:center;justify-content:center;width:32px;height:32px;padding:0;border:none;border-radius:var(--kritzel-dialog-close-button-border-radius, 6px);background-color:var(--kritzel-dialog-close-button-background, transparent);color:var(--kritzel-dialog-close-button-color, #666666);cursor:var(--kritzel-global-pointer-cursor, pointer);transition:background-color 150ms ease, color 150ms ease;flex-shrink:0;-webkit-tap-highlight-color:transparent}.close-button:hover{background-color:var(--kritzel-dialog-close-button-hover-background, #f5f5f5);color:var(--kritzel-dialog-close-button-hover-color, #1a1a1a)}.close-button:active{background-color:var(--kritzel-dialog-close-button-active-background, #ebebeb)}.close-button:focus-visible{outline:revert;outline-offset:revert}.dialog-body{padding:var(--kritzel-dialog-body-padding, 20px);overflow-y:auto;flex:1;min-height:0;scrollbar-color:var(--kritzel-global-scrollbar-thumb-color, #ebebeb) transparent;scrollbar-width:thin}.dialog-footer{display:flex;align-items:center;justify-content:flex-end;gap:var(--kritzel-dialog-footer-gap, 8px);padding:var(--kritzel-dialog-footer-padding, 16px 20px);border-top:var(--kritzel-dialog-footer-border, 1px solid #ebebeb)}::slotted([slot='header']){flex:1}::slotted([slot='footer']){display:contents}`;
|
|
1369
1369
|
|
|
1370
1370
|
const KritzelDialog = class {
|
|
1371
1371
|
constructor(hostRef) {
|
|
@@ -1392,8 +1392,12 @@ const KritzelDialog = class {
|
|
|
1392
1392
|
size = 'medium';
|
|
1393
1393
|
/** Whether to automatically go fullscreen on mobile viewports */
|
|
1394
1394
|
fullscreenOnMobile = true;
|
|
1395
|
+
/** Constrain the dialog to its nearest editor/container ancestor instead of the viewport. */
|
|
1396
|
+
contained = false;
|
|
1395
1397
|
isAnimating = false;
|
|
1396
1398
|
mobileLockedHeight = null;
|
|
1399
|
+
containerRect = null;
|
|
1400
|
+
containerBorderRadius = null;
|
|
1397
1401
|
/** Emitted when the dialog opens */
|
|
1398
1402
|
dialogOpen;
|
|
1399
1403
|
/** Emitted when the dialog closes */
|
|
@@ -1401,6 +1405,9 @@ const KritzelDialog = class {
|
|
|
1401
1405
|
previousOverflow = '';
|
|
1402
1406
|
previousActiveElement = null;
|
|
1403
1407
|
visualViewportListenersAttached = false;
|
|
1408
|
+
containerElement = null;
|
|
1409
|
+
containerResizeObserver = null;
|
|
1410
|
+
containerTrackingFrame = null;
|
|
1404
1411
|
handleIsOpenChange(newValue) {
|
|
1405
1412
|
if (newValue) {
|
|
1406
1413
|
this.openDialog();
|
|
@@ -1450,13 +1457,19 @@ const KritzelDialog = class {
|
|
|
1450
1457
|
}
|
|
1451
1458
|
disconnectedCallback() {
|
|
1452
1459
|
this.removeVisualViewportListeners();
|
|
1460
|
+
this.stopContainerTracking();
|
|
1453
1461
|
this.restoreBodyScroll();
|
|
1454
1462
|
}
|
|
1455
1463
|
openDialog() {
|
|
1456
1464
|
this.isAnimating = true;
|
|
1457
1465
|
this.previousActiveElement = document.activeElement;
|
|
1458
|
-
this.
|
|
1459
|
-
|
|
1466
|
+
if (this.contained) {
|
|
1467
|
+
this.startContainerTracking();
|
|
1468
|
+
}
|
|
1469
|
+
else {
|
|
1470
|
+
this.lockBodyScroll();
|
|
1471
|
+
this.addVisualViewportListeners();
|
|
1472
|
+
}
|
|
1460
1473
|
this.lockMobileViewportHeight();
|
|
1461
1474
|
this.dialogOpen.emit();
|
|
1462
1475
|
if (this.autoFocus) {
|
|
@@ -1471,9 +1484,106 @@ const KritzelDialog = class {
|
|
|
1471
1484
|
closeDialog() {
|
|
1472
1485
|
this.restoreBodyScroll();
|
|
1473
1486
|
this.removeVisualViewportListeners();
|
|
1487
|
+
this.stopContainerTracking();
|
|
1474
1488
|
this.mobileLockedHeight = null;
|
|
1475
1489
|
this.returnFocusToPreviousElement();
|
|
1476
1490
|
}
|
|
1491
|
+
findContainerElement() {
|
|
1492
|
+
// Walk up the composed DOM (crossing shadow roots) and return the first
|
|
1493
|
+
// ancestor that opts into containing dialogs. We accept either an explicit
|
|
1494
|
+
// [data-kritzel-dialog-container] marker or the kritzel-editor host so any
|
|
1495
|
+
// consumer can opt in without modifying the editor itself.
|
|
1496
|
+
let node = this.host;
|
|
1497
|
+
while (node) {
|
|
1498
|
+
if (node instanceof HTMLElement) {
|
|
1499
|
+
if (node.hasAttribute('data-kritzel-dialog-container') || node.tagName === 'KRITZEL-EDITOR') {
|
|
1500
|
+
return node;
|
|
1501
|
+
}
|
|
1502
|
+
}
|
|
1503
|
+
const parent = node.parentNode;
|
|
1504
|
+
if (parent) {
|
|
1505
|
+
node = parent;
|
|
1506
|
+
}
|
|
1507
|
+
else if (node instanceof ShadowRoot) {
|
|
1508
|
+
node = node.host;
|
|
1509
|
+
}
|
|
1510
|
+
else {
|
|
1511
|
+
node = null;
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1514
|
+
return null;
|
|
1515
|
+
}
|
|
1516
|
+
startContainerTracking() {
|
|
1517
|
+
this.containerElement = this.findContainerElement();
|
|
1518
|
+
if (!this.containerElement) {
|
|
1519
|
+
// No container found — fall back to viewport behavior.
|
|
1520
|
+
this.containerRect = null;
|
|
1521
|
+
return;
|
|
1522
|
+
}
|
|
1523
|
+
this.updateContainerRect();
|
|
1524
|
+
if (typeof ResizeObserver !== 'undefined') {
|
|
1525
|
+
this.containerResizeObserver = new ResizeObserver(() => this.updateContainerRect());
|
|
1526
|
+
this.containerResizeObserver.observe(this.containerElement);
|
|
1527
|
+
}
|
|
1528
|
+
window.addEventListener('resize', this.handleContainerTrackingEvent, { passive: true });
|
|
1529
|
+
window.addEventListener('scroll', this.handleContainerTrackingEvent, { capture: true, passive: true });
|
|
1530
|
+
}
|
|
1531
|
+
stopContainerTracking() {
|
|
1532
|
+
if (this.containerResizeObserver) {
|
|
1533
|
+
this.containerResizeObserver.disconnect();
|
|
1534
|
+
this.containerResizeObserver = null;
|
|
1535
|
+
}
|
|
1536
|
+
window.removeEventListener('resize', this.handleContainerTrackingEvent);
|
|
1537
|
+
window.removeEventListener('scroll', this.handleContainerTrackingEvent, { capture: true });
|
|
1538
|
+
if (this.containerTrackingFrame !== null) {
|
|
1539
|
+
cancelAnimationFrame(this.containerTrackingFrame);
|
|
1540
|
+
this.containerTrackingFrame = null;
|
|
1541
|
+
}
|
|
1542
|
+
this.containerElement = null;
|
|
1543
|
+
this.containerRect = null;
|
|
1544
|
+
this.containerBorderRadius = null;
|
|
1545
|
+
}
|
|
1546
|
+
handleContainerTrackingEvent = () => {
|
|
1547
|
+
if (this.containerTrackingFrame !== null)
|
|
1548
|
+
return;
|
|
1549
|
+
this.containerTrackingFrame = requestAnimationFrame(() => {
|
|
1550
|
+
this.containerTrackingFrame = null;
|
|
1551
|
+
this.updateContainerRect();
|
|
1552
|
+
});
|
|
1553
|
+
};
|
|
1554
|
+
updateContainerRect() {
|
|
1555
|
+
if (!this.containerElement)
|
|
1556
|
+
return;
|
|
1557
|
+
const rect = this.containerElement.getBoundingClientRect();
|
|
1558
|
+
const next = { top: rect.top, left: rect.left, width: rect.width, height: rect.height };
|
|
1559
|
+
const prev = this.containerRect;
|
|
1560
|
+
if (!prev || prev.top !== next.top || prev.left !== next.left || prev.width !== next.width || prev.height !== next.height) {
|
|
1561
|
+
this.containerRect = next;
|
|
1562
|
+
}
|
|
1563
|
+
// Look for the nearest visually-rounded ancestor (the container itself or
|
|
1564
|
+
// any ancestor up to the document) so the backdrop matches wrappers that
|
|
1565
|
+
// round their corners around the editor.
|
|
1566
|
+
const radius = this.findVisualBorderRadius(this.containerElement);
|
|
1567
|
+
if (this.containerBorderRadius !== radius) {
|
|
1568
|
+
this.containerBorderRadius = radius;
|
|
1569
|
+
}
|
|
1570
|
+
}
|
|
1571
|
+
findVisualBorderRadius(start) {
|
|
1572
|
+
let node = start;
|
|
1573
|
+
while (node && node !== document.body && node !== document.documentElement) {
|
|
1574
|
+
const computed = window.getComputedStyle(node);
|
|
1575
|
+
const tl = computed.borderTopLeftRadius;
|
|
1576
|
+
const tr = computed.borderTopRightRadius;
|
|
1577
|
+
const br = computed.borderBottomRightRadius;
|
|
1578
|
+
const bl = computed.borderBottomLeftRadius;
|
|
1579
|
+
const isZero = (v) => !v || v === '0px' || v === '0%';
|
|
1580
|
+
if (!(isZero(tl) && isZero(tr) && isZero(br) && isZero(bl))) {
|
|
1581
|
+
return `${tl} ${tr} ${br} ${bl}`;
|
|
1582
|
+
}
|
|
1583
|
+
node = node.parentElement;
|
|
1584
|
+
}
|
|
1585
|
+
return null;
|
|
1586
|
+
}
|
|
1477
1587
|
emitClose(reason) {
|
|
1478
1588
|
this.dialogClose.emit({ reason });
|
|
1479
1589
|
}
|
|
@@ -1482,6 +1592,12 @@ const KritzelDialog = class {
|
|
|
1482
1592
|
document.body.style.overflow = 'hidden';
|
|
1483
1593
|
}
|
|
1484
1594
|
lockMobileViewportHeight() {
|
|
1595
|
+
// Skip mobile viewport height locking when contained — the dialog is sized
|
|
1596
|
+
// by its wrapper, not the viewport.
|
|
1597
|
+
if (this.contained) {
|
|
1598
|
+
this.mobileLockedHeight = null;
|
|
1599
|
+
return;
|
|
1600
|
+
}
|
|
1485
1601
|
// Only lock height on mobile when fullscreenOnMobile is enabled.
|
|
1486
1602
|
// Use the smaller dimension so landscape phones (wide but short) are also detected.
|
|
1487
1603
|
const viewportWidth = this.getViewportWidth();
|
|
@@ -1616,15 +1732,73 @@ const KritzelDialog = class {
|
|
|
1616
1732
|
return null;
|
|
1617
1733
|
return (index.h("div", { class: "dialog-footer" }, index.h("slot", { name: "footer" })));
|
|
1618
1734
|
}
|
|
1735
|
+
getBackdropStyle() {
|
|
1736
|
+
if (!this.contained || !this.containerRect)
|
|
1737
|
+
return undefined;
|
|
1738
|
+
const { top, left, width, height } = this.containerRect;
|
|
1739
|
+
const style = {
|
|
1740
|
+
top: `${top}px`,
|
|
1741
|
+
left: `${left}px`,
|
|
1742
|
+
right: 'auto',
|
|
1743
|
+
bottom: 'auto',
|
|
1744
|
+
width: `${width}px`,
|
|
1745
|
+
height: `${height}px`,
|
|
1746
|
+
};
|
|
1747
|
+
if (this.containerBorderRadius) {
|
|
1748
|
+
style.borderRadius = this.containerBorderRadius;
|
|
1749
|
+
// Ensure rounded corners actually clip the inner dialog content.
|
|
1750
|
+
style.overflow = 'hidden';
|
|
1751
|
+
}
|
|
1752
|
+
return style;
|
|
1753
|
+
}
|
|
1754
|
+
getDialogContentStyle() {
|
|
1755
|
+
const style = {};
|
|
1756
|
+
// In contained mode, cap the dialog dimensions to the container so the
|
|
1757
|
+
// declared widths/heights of size variants cannot overflow the wrapper.
|
|
1758
|
+
if (this.contained && this.containerRect) {
|
|
1759
|
+
const { width, height } = this.containerRect;
|
|
1760
|
+
if (this.isContainerMobile()) {
|
|
1761
|
+
// Mobile-sized container: behave like fullscreen-on-mobile but scoped
|
|
1762
|
+
// to the container instead of the viewport (works in any orientation).
|
|
1763
|
+
style.width = `${width}px`;
|
|
1764
|
+
style.height = `${height}px`;
|
|
1765
|
+
style.maxWidth = `${width}px`;
|
|
1766
|
+
style.maxHeight = `${height}px`;
|
|
1767
|
+
style.borderRadius = '0';
|
|
1768
|
+
}
|
|
1769
|
+
else {
|
|
1770
|
+
// Leave a small margin so the dialog visibly sits within the container.
|
|
1771
|
+
const maxWidth = Math.max(0, width - 32);
|
|
1772
|
+
const maxHeight = Math.max(0, height - 32);
|
|
1773
|
+
style.maxWidth = `${maxWidth}px`;
|
|
1774
|
+
style.maxHeight = `${maxHeight}px`;
|
|
1775
|
+
}
|
|
1776
|
+
}
|
|
1777
|
+
if (this.mobileLockedHeight) {
|
|
1778
|
+
style.height = this.mobileLockedHeight;
|
|
1779
|
+
style.maxHeight = this.mobileLockedHeight;
|
|
1780
|
+
}
|
|
1781
|
+
return Object.keys(style).length > 0 ? style : undefined;
|
|
1782
|
+
}
|
|
1783
|
+
isContainerMobile() {
|
|
1784
|
+
if (!this.fullscreenOnMobile || !this.containerRect)
|
|
1785
|
+
return false;
|
|
1786
|
+
// Match the existing viewport media-query threshold: container is "mobile"
|
|
1787
|
+
// when its smaller dimension is <= 576px. This handles both portrait and
|
|
1788
|
+
// landscape wrappers symmetrically.
|
|
1789
|
+
return Math.min(this.containerRect.width, this.containerRect.height) <= 576;
|
|
1790
|
+
}
|
|
1619
1791
|
render() {
|
|
1620
1792
|
if (!this.isOpen)
|
|
1621
1793
|
return null;
|
|
1622
|
-
|
|
1794
|
+
const containerFullscreen = this.contained && this.isContainerMobile();
|
|
1795
|
+
return (index.h(index.Host, null, index.h("div", { class: { backdrop: true, 'is-animating': this.isAnimating, 'contained-fullscreen': containerFullscreen }, style: this.getBackdropStyle(), onClick: this.handleBackdropClick }, index.h("div", { class: {
|
|
1623
1796
|
'dialog-content': true,
|
|
1624
1797
|
'is-animating': this.isAnimating,
|
|
1625
1798
|
[`size-${this.size}`]: true,
|
|
1626
1799
|
'fullscreen-on-mobile': this.fullscreenOnMobile,
|
|
1627
|
-
|
|
1800
|
+
'contained-fullscreen': containerFullscreen,
|
|
1801
|
+
}, style: this.getDialogContentStyle(), role: "dialog", "aria-modal": "true", "aria-labelledby": this.dialogTitle ? 'dialog-title' : undefined, tabIndex: -1, onClick: this.handleContentClick }, this.renderHeader(), index.h("div", { class: "dialog-body" }, index.h("slot", null)), this.renderFooter()))));
|
|
1628
1802
|
}
|
|
1629
1803
|
static get watchers() { return {
|
|
1630
1804
|
"isOpen": [{
|
|
@@ -1917,7 +2091,7 @@ const DEFAULT_SYNC_CONFIG = {
|
|
|
1917
2091
|
],
|
|
1918
2092
|
};
|
|
1919
2093
|
|
|
1920
|
-
const kritzelEditorCss = () => `kritzel-editor{display:flex;margin:0;position:relative;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}kritzel-controls{position:absolute;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;z-index:10000}.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;z-index:10000}.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}`;
|
|
2094
|
+
const kritzelEditorCss = () => `kritzel-editor{display:flex;margin:0;position:relative;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;z-index:10000}.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;z-index:10000}.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}`;
|
|
1921
2095
|
|
|
1922
2096
|
const KritzelEditor = class {
|
|
1923
2097
|
constructor(hostRef) {
|
|
@@ -20395,6 +20569,71 @@ class KritzelViewport {
|
|
|
20395
20569
|
this._core.store.state.scale = clampedScale;
|
|
20396
20570
|
this.centerInViewport(object);
|
|
20397
20571
|
}
|
|
20572
|
+
/**
|
|
20573
|
+
* Centers the viewport on a given object and zooms out only if the object
|
|
20574
|
+
* does not fit at the current scale. Never zooms in — if the object already
|
|
20575
|
+
* fits, the scale is left unchanged.
|
|
20576
|
+
* @param object - The object to fit in the viewport
|
|
20577
|
+
*/
|
|
20578
|
+
centerFitInViewportIfNeeded(object) {
|
|
20579
|
+
const scaleX = this._core.store.state.viewportWidth / (object.rotatedBoundingBox.width * 1.1);
|
|
20580
|
+
const scaleY = this._core.store.state.viewportHeight / (object.rotatedBoundingBox.height * 1.1);
|
|
20581
|
+
const newScale = Math.min(scaleX, scaleY, this._core.store.state.scaleMax);
|
|
20582
|
+
const clampedScale = Math.max(newScale, this.getEffectiveMinScale());
|
|
20583
|
+
if (clampedScale < this._core.store.state.scale) {
|
|
20584
|
+
this._core.store.state.scale = clampedScale;
|
|
20585
|
+
}
|
|
20586
|
+
this.centerInViewport(object);
|
|
20587
|
+
}
|
|
20588
|
+
/**
|
|
20589
|
+
* Zooms out and centers the viewport on a given object only if the object
|
|
20590
|
+
* does not fit at the current scale. If the object already fits, the
|
|
20591
|
+
* viewport is left completely unchanged.
|
|
20592
|
+
* @param object - The object to check and fit in the viewport
|
|
20593
|
+
*/
|
|
20594
|
+
fitInViewportIfNeeded(object) {
|
|
20595
|
+
const scaleX = this._core.store.state.viewportWidth / (object.rotatedBoundingBox.width * 1.1);
|
|
20596
|
+
const scaleY = this._core.store.state.viewportHeight / (object.rotatedBoundingBox.height * 1.1);
|
|
20597
|
+
const newScale = Math.min(scaleX, scaleY, this._core.store.state.scaleMax);
|
|
20598
|
+
const clampedScale = Math.max(newScale, this.getEffectiveMinScale());
|
|
20599
|
+
if (clampedScale < this._core.store.state.scale) {
|
|
20600
|
+
this._core.store.state.scale = clampedScale;
|
|
20601
|
+
this.centerInViewport(object);
|
|
20602
|
+
}
|
|
20603
|
+
}
|
|
20604
|
+
/**
|
|
20605
|
+
* Smoothly brings a given object into view if it is not fully visible within
|
|
20606
|
+
* the current viewport. Zooms out only if the object is too large to fit at
|
|
20607
|
+
* the current scale; never zooms in. If the object is already fully visible,
|
|
20608
|
+
* the viewport is left unchanged.
|
|
20609
|
+
* @param object - The object to bring into view
|
|
20610
|
+
*/
|
|
20611
|
+
bringIntoViewIfNeeded(object) {
|
|
20612
|
+
const { scale, translateX, translateY, viewportWidth, viewportHeight } = this._core.store.state;
|
|
20613
|
+
const bounds = object.rotatedBoundingBox;
|
|
20614
|
+
// Compute the object's bounding box in screen-space coordinates
|
|
20615
|
+
const screenLeft = bounds.x * scale + translateX;
|
|
20616
|
+
const screenTop = bounds.y * scale + translateY;
|
|
20617
|
+
const screenRight = (bounds.x + bounds.width) * scale + translateX;
|
|
20618
|
+
const screenBottom = (bounds.y + bounds.height) * scale + translateY;
|
|
20619
|
+
// If fully visible, no adjustment needed
|
|
20620
|
+
if (screenLeft >= 0 && screenTop >= 0 && screenRight <= viewportWidth && screenBottom <= viewportHeight) {
|
|
20621
|
+
return;
|
|
20622
|
+
}
|
|
20623
|
+
// Calculate the scale needed to fit the object with padding; never zoom in
|
|
20624
|
+
const scaleX = viewportWidth / (bounds.width * 1.1);
|
|
20625
|
+
const scaleY = viewportHeight / (bounds.height * 1.1);
|
|
20626
|
+
const fitScale = Math.min(scaleX, scaleY, this._core.store.state.scaleMax);
|
|
20627
|
+
const clampedFitScale = Math.max(fitScale, this.getEffectiveMinScale());
|
|
20628
|
+
const targetScale = Math.min(clampedFitScale, scale);
|
|
20629
|
+
// Animate to center the object at the target scale
|
|
20630
|
+
const objectCenterX = bounds.x + bounds.width / 2;
|
|
20631
|
+
const objectCenterY = bounds.y + bounds.height / 2;
|
|
20632
|
+
const targetTranslateX = viewportWidth / 2 - objectCenterX * targetScale;
|
|
20633
|
+
const targetTranslateY = viewportHeight / 2 - objectCenterY * targetScale;
|
|
20634
|
+
const clamped = this.clampTranslate(targetTranslateX, targetTranslateY);
|
|
20635
|
+
this.animateViewportTo(clamped.translateX, clamped.translateY, targetScale);
|
|
20636
|
+
}
|
|
20398
20637
|
/**
|
|
20399
20638
|
* Handles zoom operations triggered by wheel events with Ctrl key.
|
|
20400
20639
|
* Zooms around the cursor position, respecting scale limits.
|
|
@@ -20845,17 +21084,18 @@ class KritzelContextMenuHandler extends workspace_migrations.KritzelBaseHandler
|
|
|
20845
21084
|
this._core.rerender();
|
|
20846
21085
|
}
|
|
20847
21086
|
this._core.store.state.contextMenuItems = this._core.store.selectionGroup ? this.objectContextMenuItems : this.globalContextMenuItems;
|
|
20848
|
-
|
|
20849
|
-
|
|
21087
|
+
const clickX = event.clientX - this._core.store.offsetX;
|
|
21088
|
+
const clickY = event.clientY - this._core.store.offsetY;
|
|
21089
|
+
const { translateX, translateY, scale } = this._core.store.state;
|
|
21090
|
+
this._core.store.state.contextMenuWorldX = (clickX - translateX) / scale;
|
|
21091
|
+
this._core.store.state.contextMenuWorldY = (clickY - translateY) / scale;
|
|
21092
|
+
let x = clickX;
|
|
21093
|
+
let y = clickY;
|
|
20850
21094
|
const menuWidthEstimate = 150;
|
|
20851
|
-
const menuHeightEstimate = 200;
|
|
20852
21095
|
const margin = 10;
|
|
20853
21096
|
if (x + menuWidthEstimate > window.innerWidth - margin) {
|
|
20854
21097
|
x = window.innerWidth - menuWidthEstimate - margin;
|
|
20855
21098
|
}
|
|
20856
|
-
if (y + menuHeightEstimate > window.innerHeight - margin) {
|
|
20857
|
-
y = window.innerHeight - menuHeightEstimate - margin;
|
|
20858
|
-
}
|
|
20859
21099
|
x = Math.max(margin, x);
|
|
20860
21100
|
y = Math.max(margin, y);
|
|
20861
21101
|
this._core.store.state.contextMenuX = x;
|
|
@@ -21121,6 +21361,8 @@ const DEFAULT_ENGINE_CONFIG = {
|
|
|
21121
21361
|
contextMenuItems: [],
|
|
21122
21362
|
contextMenuX: 0,
|
|
21123
21363
|
contextMenuY: 0,
|
|
21364
|
+
contextMenuWorldX: 0,
|
|
21365
|
+
contextMenuWorldY: 0,
|
|
21124
21366
|
skipContextMenu: false,
|
|
21125
21367
|
debugInfo: {
|
|
21126
21368
|
showObjectInfo: false,
|
|
@@ -24128,21 +24370,26 @@ class KritzelCore {
|
|
|
24128
24370
|
if (copiedObjects.length === 1) {
|
|
24129
24371
|
selectionGroup.rotation = copiedObjects[0].rotation;
|
|
24130
24372
|
}
|
|
24131
|
-
//
|
|
24132
|
-
|
|
24133
|
-
//
|
|
24373
|
+
// For cross-workspace paste, set the selection group's position before inserting
|
|
24374
|
+
// it into the store. This mirrors the existing pattern where objects have
|
|
24375
|
+
// updatePosition called before addObject, so the correct position is captured
|
|
24376
|
+
// in the single initial insert with no separate Yjs update (and no extra undo step).
|
|
24134
24377
|
if (isDifferentWorkspace) {
|
|
24135
24378
|
if (x !== undefined && y !== undefined) {
|
|
24136
|
-
//
|
|
24379
|
+
// Explicit cursor position provided (e.g. right-click paste)
|
|
24137
24380
|
selectionGroup.updatePosition(x, y);
|
|
24138
24381
|
}
|
|
24139
24382
|
else {
|
|
24140
|
-
//
|
|
24383
|
+
// Ctrl+V paste: center objects in the current viewport
|
|
24141
24384
|
selectionGroup.centerInViewport();
|
|
24142
24385
|
}
|
|
24143
|
-
// Fit the viewport to show the pasted objects
|
|
24144
|
-
this.engine.viewport.centerFitInViewport(selectionGroup);
|
|
24145
24386
|
}
|
|
24387
|
+
// Add the selection group (inserts with the already-adjusted position)
|
|
24388
|
+
this.addSelectionGroup(selectionGroup);
|
|
24389
|
+
// Bring pasted objects into view with a smooth animation if they are not
|
|
24390
|
+
// fully visible. These only mutate in-memory viewport state (scale, translateX/Y)
|
|
24391
|
+
// and do not produce any Yjs writes, so they have no impact on the undo history.
|
|
24392
|
+
this.engine.viewport.bringIntoViewIfNeeded(selectionGroup);
|
|
24146
24393
|
this._store.state.isSelecting = false;
|
|
24147
24394
|
// Defer creating copies for future pastes to next frame to avoid
|
|
24148
24395
|
// doubling the object creation cost in the current paste frame
|
|
@@ -26207,9 +26454,9 @@ const KritzelEngine = class {
|
|
|
26207
26454
|
if (isInsideDialog) {
|
|
26208
26455
|
return false;
|
|
26209
26456
|
}
|
|
26210
|
-
const target =
|
|
26457
|
+
const target = path[0];
|
|
26211
26458
|
// Don't handle if target is an interactive element that needs keyboard input
|
|
26212
|
-
if (target.matches?.('input, textarea, select, [contenteditable="true"], [contenteditable=""]')) {
|
|
26459
|
+
if (target instanceof HTMLElement && target.matches?.('input, textarea, select, [contenteditable="true"], [contenteditable=""]')) {
|
|
26213
26460
|
return false;
|
|
26214
26461
|
}
|
|
26215
26462
|
// Handle global shortcuts when no interactive element has focus
|
|
@@ -27887,8 +28134,8 @@ const KritzelEngine = class {
|
|
|
27887
28134
|
}, onActionSelected: event => {
|
|
27888
28135
|
if (event.detail.action) {
|
|
27889
28136
|
event.detail.action({
|
|
27890
|
-
x:
|
|
27891
|
-
y:
|
|
28137
|
+
x: this.core.store.state.contextMenuWorldX,
|
|
28138
|
+
y: this.core.store.state.contextMenuWorldY,
|
|
27892
28139
|
}, this.core.store.selectionGroup?.objects || []);
|
|
27893
28140
|
}
|
|
27894
28141
|
this.hideContextMenu();
|
|
@@ -28021,7 +28268,7 @@ const KritzelExport = class {
|
|
|
28021
28268
|
return (index.h("div", { class: "export-tab-content" }, index.h("kritzel-input", { label: "Filename", value: this.exportFilename, placeholder: "Enter filename", suffix: ".json", onValueChange: this.handleFilenameChange })));
|
|
28022
28269
|
}
|
|
28023
28270
|
render() {
|
|
28024
|
-
return (index.h(index.Host, { key: '5178e66f75b94697c771e2dc6fe7ce317e21cd1a' }, index.h("kritzel-dialog", { key: '
|
|
28271
|
+
return (index.h(index.Host, { key: '5178e66f75b94697c771e2dc6fe7ce317e21cd1a' }, index.h("kritzel-dialog", { key: 'f80cbe3fa709ed7e046303034b7345ca1f94bc48', isOpen: this.isDialogOpen, dialogTitle: "Export", closable: true, contained: true, onDialogClose: this.closeDialog }, index.h("div", { key: 'e7968807c2b67ebfc800cb1694b4e34af245ffba', class: "export-content" }, index.h("kritzel-pill-tabs", { key: 'eac62225c4c42431296f330791a1fb2212f579f5', tabs: this.tabs, value: this.activeTab, onValueChange: this.handleTabChange }), this.activeTab === 'viewport' && this.renderViewportExport(), this.activeTab === 'workspace' && this.renderWorkspaceExport(), index.h("button", { key: '3489affca39a901c2ef05a0698cdf51c0a7f6d1a', class: "export-primary-button", onClick: this.handleExport }, "Export")))));
|
|
28025
28272
|
}
|
|
28026
28273
|
};
|
|
28027
28274
|
KritzelExport.style = kritzelExportCss();
|
|
@@ -28318,7 +28565,7 @@ const KritzelLoginDialog = class {
|
|
|
28318
28565
|
this.dialogClosed.emit();
|
|
28319
28566
|
};
|
|
28320
28567
|
render() {
|
|
28321
|
-
return (index.h(index.Host, { key: '1a664868b840030a773f61c2a0f4388dfb014675' }, index.h("kritzel-dialog", { key: '
|
|
28568
|
+
return (index.h(index.Host, { key: '1a664868b840030a773f61c2a0f4388dfb014675' }, index.h("kritzel-dialog", { key: '54844ffa772a211515c1ef3e6834ec45f7f3d035', dialogTitle: this.dialogTitle, isOpen: this.isDialogOpen, onDialogClose: this.closeDialog, size: "small", contained: true }, index.h("div", { key: 'd9b981b6904c58bc39173ae37ee5c4c0ee329005', class: "login-content" }, this.subtitle && (index.h("p", { key: 'd4d200060507d2b8b755796d8313acdfc7e2f587', class: "login-subtitle" }, this.subtitle)), index.h("div", { key: '3dc1e3c070e62d026eb16ceb48eb63c94bc2bed0', class: "login-providers" }, this.providers.map(provider => (index.h("button", { key: provider.name, class: {
|
|
28322
28569
|
'provider-button': true,
|
|
28323
28570
|
'is-loading': this.loadingProvider === provider.name,
|
|
28324
28571
|
'is-disabled': this.loadingProvider !== null && this.loadingProvider !== provider.name,
|
|
@@ -28505,7 +28752,7 @@ const KritzelMenu = class {
|
|
|
28505
28752
|
this.itemCloseChildMenu.emit(event.detail);
|
|
28506
28753
|
};
|
|
28507
28754
|
render() {
|
|
28508
|
-
return (index.h(index.Host, { key: 'a81ea8a1fe2dc6cb8d9f395cafbcadec3eb4aa45', tabIndex: 0, onClick: e => e.stopPropagation() }, this.openChildMenuItem && index.h("div", { key: 'bb27d7a923431d79567e79283e505ea4ae02ef36', class: "has-open-child-overlay", onClick: this.onOverlayClick }), this.items.map(item => (index.h("kritzel-menu-item", { key: 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 })))));
|
|
28755
|
+
return (index.h(index.Host, { key: 'a81ea8a1fe2dc6cb8d9f395cafbcadec3eb4aa45', tabIndex: 0, onClick: e => e.stopPropagation() }, this.openChildMenuItem && index.h("div", { key: 'bb27d7a923431d79567e79283e505ea4ae02ef36', class: "has-open-child-overlay", onClick: this.onOverlayClick }), this.items.map(item => (index.h("kritzel-menu-item", { key: item.id, "data-testid": `menu-item-${item.id}`, item: item, parent: this.parent, style: { pointerEvents: this.editingMenuItem && !item.isEditing ? 'none' : 'auto' }, onItemSelect: this.handleItemSelect, onItemSave: this.handleSave, onItemCancel: this.handleCancel, onItemToggleChildMenu: this.handleToggleChildMenu, onItemCloseChildMenu: this.handleCloseChildMenu })))));
|
|
28509
28756
|
}
|
|
28510
28757
|
};
|
|
28511
28758
|
KritzelMenu.style = kritzelMenuCss();
|
|
@@ -28686,7 +28933,7 @@ const KritzelMoreMenu = class {
|
|
|
28686
28933
|
this.closeMenu();
|
|
28687
28934
|
};
|
|
28688
28935
|
render() {
|
|
28689
|
-
return (index.h(index.Host, { key: '0e12ffc8c72566ec92080e6a19bd1d929795bef9', class: { mobile: this.isTouchDevice } }, index.h("div", { key: 'cc73b51c5aa39522a7ab7ec23d5c0a2732ed7acc', class: { 'more-menu-wrapper': true, visible: this.visible } }, index.h("button", { key: '
|
|
28936
|
+
return (index.h(index.Host, { key: '0e12ffc8c72566ec92080e6a19bd1d929795bef9', class: { mobile: this.isTouchDevice } }, index.h("div", { key: 'cc73b51c5aa39522a7ab7ec23d5c0a2732ed7acc', class: { 'more-menu-wrapper': true, visible: this.visible } }, index.h("button", { key: '6b4bda0bcfec9ef9a5506f844c835d8e270b636e', class: "more-menu-button", "data-testid": "more-menu-button", onClick: this.toggleMenu }, index.h("kritzel-icon", { key: '0de3f4404db14c92b8d81d41514c62eac3b3e0f0', name: this.icon, size: this.iconSize })), index.h("kritzel-portal", { key: '6aad3b6ac4161c195a15a49b67005e9605253dbc', anchor: this.menuAnchor, offsetY: this.offsetY, onClose: this.closeMenu }, index.h("kritzel-menu", { key: 'aee02f7da9cbd2b49ee430fedc1a0404991982ba', items: this.visibleItems, onItemSelect: this.handleMenuItemSelect })))));
|
|
28690
28937
|
}
|
|
28691
28938
|
};
|
|
28692
28939
|
KritzelMoreMenu.style = kritzelMoreMenuCss();
|
|
@@ -29189,7 +29436,7 @@ const KritzelPortal = class {
|
|
|
29189
29436
|
* This file is auto-generated by the version bump scripts.
|
|
29190
29437
|
* Do not modify manually.
|
|
29191
29438
|
*/
|
|
29192
|
-
const KRITZEL_VERSION = '0.2.
|
|
29439
|
+
const KRITZEL_VERSION = '0.2.12';
|
|
29193
29440
|
|
|
29194
29441
|
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)}`;
|
|
29195
29442
|
|
|
@@ -29377,7 +29624,7 @@ const KritzelSettings = class {
|
|
|
29377
29624
|
}
|
|
29378
29625
|
}
|
|
29379
29626
|
render() {
|
|
29380
|
-
return (index.h(index.Host, { key: 'e86192a8ca49f8618d58ede4d04d321ea238d7d4' }, index.h("kritzel-dialog", { key: '
|
|
29627
|
+
return (index.h(index.Host, { key: 'e86192a8ca49f8618d58ede4d04d321ea238d7d4' }, index.h("kritzel-dialog", { key: '23a47a8cd9281794bfd2aec7edd6a4ef4b931550', isOpen: this.isDialogOpen, dialogTitle: "Settings", size: "large", contained: true, onDialogClose: this.closeDialog }, index.h("kritzel-master-detail", { key: '007c8a1c04bd0d692b55d88988b0f8874f9242a4', items: SETTINGS_CATEGORIES, selectedItemId: this.selectedCategoryId, onItemSelect: this.handleCategorySelect }, this.renderCategoryContent()))));
|
|
29381
29628
|
}
|
|
29382
29629
|
static get watchers() { return {
|
|
29383
29630
|
"settings": [{
|
|
@@ -29508,9 +29755,9 @@ const KritzelShareDialog = class {
|
|
|
29508
29755
|
this.dialogClosed.emit();
|
|
29509
29756
|
};
|
|
29510
29757
|
render() {
|
|
29511
|
-
return (index.h(index.Host, { key: 'bd58f146337b3eca96ca34408a3d30621f01765a' }, index.h("kritzel-dialog", { key: '
|
|
29758
|
+
return (index.h(index.Host, { key: 'bd58f146337b3eca96ca34408a3d30621f01765a' }, index.h("kritzel-dialog", { key: '0575ac82e19d07cf909556cae2ec433e0057fd5b', dialogTitle: "Share Workspace", size: "small", isOpen: this.isDialogOpen, onDialogClose: this.closeDialog, contained: true }, index.h("div", { key: 'c51d207e31255f45724103bfecbe858f13a721e6', class: "share-content" }, index.h("div", { key: 'ca6cb7721b9ba834c133b2cb953b208475e34fb5', class: "share-section" }, index.h("div", { key: '2c76845c903cc1c18cc26b9111d608e732ed12a5', class: "share-row" }, index.h("div", { key: '7700533f54372bc81d8d795414318a6bf0e93c47', class: "share-label-group" }, index.h("label", { key: 'a1d80009cb09cfe35bce35ce1151bf0754b052c1', class: "share-label" }, "Link sharing"), index.h("p", { key: '10c1963e95e658c7fb86174f1dba7565ce40d5a6', class: "share-description" }, this.internalIsPublic
|
|
29512
29759
|
? 'Anyone with the link can access this workspace.'
|
|
29513
|
-
: 'Link sharing is disabled. Only you can access this workspace.')), index.h("kritzel-slide-toggle", { key: '
|
|
29760
|
+
: 'Link sharing is disabled. Only you can access this workspace.')), index.h("kritzel-slide-toggle", { key: 'ec62a5ece12be0cea18a16c5d41db0a992309174', checked: this.internalIsPublic, onCheckedChange: this.handleToggleChange, label: "Enable link sharing" }))), this.internalIsPublic && (index.h("div", { key: '5e826d4c8c37792ba3a74a0189ad313a8ab482e2', class: "share-section" }, index.h("div", { key: 'f8e35cda32cb34ab21f56335aa27503fd6fe98c4', class: "share-url-container" }, index.h("input", { key: '47feb20a1843e1d3d8f7d146d71574b187002e8d', type: "text", class: "share-url-input", value: this.getShareUrl(), readOnly: true, onClick: (e) => e.target.select() }), index.h("button", { key: '052f56f35d057430cbc8fd03da5bef574b173791', class: { 'copy-button': true, 'copy-success': this.copySuccess }, onClick: this.handleCopyUrl, title: this.copySuccess ? 'Copied!' : 'Copy link' }, index.h("kritzel-icon", { key: '4e1de478f837a352185be2a06e15796dc1fb2f5e', name: this.copySuccess ? 'check' : 'copy', size: 18 })))))))));
|
|
29514
29761
|
}
|
|
29515
29762
|
static get watchers() { return {
|
|
29516
29763
|
"isPublic": [{
|