kritzel-stencil 0.4.4 → 0.4.5

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.
Files changed (117) hide show
  1. package/dist/cjs/kritzel-active-users_47.cjs.entry.js +1 -1
  2. package/dist/collection/constants/version.js +1 -1
  3. package/dist/components/index.js +1226 -1
  4. package/dist/components/kritzel-active-users.js +6 -1
  5. package/dist/components/kritzel-avatar.js +6 -1
  6. package/dist/components/kritzel-awareness-cursors.js +6 -1
  7. package/dist/components/kritzel-back-to-content.js +6 -1
  8. package/dist/components/kritzel-brush-style.js +64 -1
  9. package/dist/components/kritzel-button.js +6 -1
  10. package/dist/components/kritzel-color-palette.js +6 -1
  11. package/dist/components/kritzel-color.js +6 -1
  12. package/dist/components/kritzel-context-menu.js +6 -1
  13. package/dist/components/kritzel-controls.js +6 -1
  14. package/dist/components/kritzel-current-user-dialog.js +6 -1
  15. package/dist/components/kritzel-current-user.js +6 -1
  16. package/dist/components/kritzel-cursor-trail.js +6 -1
  17. package/dist/components/kritzel-dialog.js +6 -1
  18. package/dist/components/kritzel-dropdown.js +6 -1
  19. package/dist/components/kritzel-editor.js +4396 -1
  20. package/dist/components/kritzel-engine.js +6 -1
  21. package/dist/components/kritzel-export.js +6 -1
  22. package/dist/components/kritzel-font-family.js +6 -1
  23. package/dist/components/kritzel-font-size.js +6 -1
  24. package/dist/components/kritzel-font.js +6 -1
  25. package/dist/components/kritzel-icon.js +6 -1
  26. package/dist/components/kritzel-input.js +6 -1
  27. package/dist/components/kritzel-line-endings.js +6 -1
  28. package/dist/components/kritzel-loading-overlay.js +6 -1
  29. package/dist/components/kritzel-login-dialog.js +6 -1
  30. package/dist/components/kritzel-master-detail.js +6 -1
  31. package/dist/components/kritzel-menu-item.js +6 -1
  32. package/dist/components/kritzel-menu.js +6 -1
  33. package/dist/components/kritzel-more-menu.js +6 -1
  34. package/dist/components/kritzel-notification-card.js +6 -1
  35. package/dist/components/kritzel-numeric-input.js +6 -1
  36. package/dist/components/kritzel-opacity-slider.js +6 -1
  37. package/dist/components/kritzel-pill-tabs.js +6 -1
  38. package/dist/components/kritzel-portal.js +6 -1
  39. package/dist/components/kritzel-settings.js +6 -1
  40. package/dist/components/kritzel-shape-fill.js +6 -1
  41. package/dist/components/kritzel-share-dialog.js +6 -1
  42. package/dist/components/kritzel-slide-toggle.js +6 -1
  43. package/dist/components/kritzel-split-button.js +6 -1
  44. package/dist/components/kritzel-stroke-size.js +6 -1
  45. package/dist/components/kritzel-sync-indicator.js +6 -1
  46. package/dist/components/kritzel-tool-config.js +6 -1
  47. package/dist/components/kritzel-tooltip.js +6 -1
  48. package/dist/components/kritzel-utility-panel.js +6 -1
  49. package/dist/components/kritzel-watermark.js +6 -1
  50. package/dist/components/kritzel-workspace-manager.js +6 -1
  51. package/dist/components/kritzel-zoom-panel.js +6 -1
  52. package/dist/components/p--Oazz-BP.js +51657 -2
  53. package/dist/components/p-894OnDQV.js +39 -1
  54. package/dist/components/p-B43upypT.js +1500 -1
  55. package/dist/components/p-B5oHmPJb.js +97 -1
  56. package/dist/components/p-B6t5q-V4.js +63 -1
  57. package/dist/components/p-B8Xi4Clg.js +43 -1
  58. package/dist/components/p-BDzlx2hB.js +135 -1
  59. package/dist/components/p-BFTU3MAI.js +7 -1
  60. package/dist/components/p-BFYtCsZu.js +56 -1
  61. package/dist/components/p-BI2ng9I_.js +62 -1
  62. package/dist/components/p-BTzlrIxe.js +194 -1
  63. package/dist/components/p-BmyTdQGy.js +1090 -1
  64. package/dist/components/p-BsANVili.js +150 -1
  65. package/dist/components/p-BxpKq94F.js +290 -1
  66. package/dist/components/p-C38P-Vd0.js +446 -1
  67. package/dist/components/p-C4NrrUfN.js +77 -1
  68. package/dist/components/p-CW-VyJgK.js +6 -1
  69. package/dist/components/p-CWRSGYOE.js +57 -1
  70. package/dist/components/p-CXpv9Rxe.js +106 -1
  71. package/dist/components/p-Ca-igU1f.js +320 -1
  72. package/dist/components/p-CdR76C4L.js +165 -1
  73. package/dist/components/p-ClFprFvz.js +209 -1
  74. package/dist/components/p-Cm33td2O.js +122 -1
  75. package/dist/components/p-CqLgB8JK.js +91 -1
  76. package/dist/components/p-Cr682JI_.js +156 -1
  77. package/dist/components/p-CsvMgk_f.js +62 -1
  78. package/dist/components/p-CwJwsRR3.js +277 -1
  79. package/dist/components/p-Cymum41a.js +88 -1
  80. package/dist/components/p-D09kgc5Q.js +94 -1
  81. package/dist/components/p-D30zs0kA.js +121 -1
  82. package/dist/components/p-D3y_Hauo.js +85 -1
  83. package/dist/components/p-D5jf8wAu.js +142 -1
  84. package/dist/components/p-D82VaHce.js +53 -1
  85. package/dist/components/p-DAwPPDMS.js +101 -1
  86. package/dist/components/p-DEBwmRTC.js +55 -1
  87. package/dist/components/p-DIazmg6w.js +52 -1
  88. package/dist/components/p-DJ88BrIW.js +70 -1
  89. package/dist/components/p-DJkKlUyZ.js +182 -1
  90. package/dist/components/p-DUYmwrWV.js +3267 -1
  91. package/dist/components/p-DX2nriaq.js +486 -1
  92. package/dist/components/p-Dd-pMvlr.js +20 -1
  93. package/dist/components/p-Df3BwVGy.js +299 -1
  94. package/dist/components/p-DgJ0ufzr.js +43 -1
  95. package/dist/components/p-DkUb2czk.js +70 -1
  96. package/dist/components/p-Dlp84thc.js +57 -1
  97. package/dist/components/p-JYj3Facr.js +431 -1
  98. package/dist/components/p-Ka7OWbnk.js +2304 -1
  99. package/dist/components/p-PSFAfAyd.js +49 -1
  100. package/dist/components/p-U6uE85Qx.js +320 -0
  101. package/dist/components/p-WUdQqYnu.js +118 -1
  102. package/dist/components/p-djJSnjAX.js +84 -1
  103. package/dist/components/p-e6Zpc9Vp.js +143 -1
  104. package/dist/components/p-jGOpkGDl.js +30 -1
  105. package/dist/components/p-pagW8YF7.js +99 -1
  106. package/dist/esm/kritzel-active-users_47.entry.js +1 -1
  107. package/dist/stencil/index.esm.js +1172 -1
  108. package/dist/stencil/p-4463dade.entry.js +36043 -0
  109. package/dist/stencil/p-DQuL1Twl.js +3 -1
  110. package/dist/stencil/p-Dhio9uis.js +1717 -2
  111. package/dist/stencil/p-fb32cd8f.entry.js +29 -1
  112. package/dist/stencil/p-uC7_X6yr.js +30737 -1
  113. package/dist/stencil/stencil.esm.js +21 -1
  114. package/dist/types/constants/version.d.ts +1 -1
  115. package/package.json +1 -1
  116. package/dist/components/p-Xsiz1D5Q.js +0 -1
  117. package/dist/stencil/p-9abc21b9.entry.js +0 -9
@@ -1 +1,486 @@
1
- import{p as t,H as e,c as i,h as o,d as l,t as n}from"./p-B43upypT.js";import{K as s}from"./p-WUdQqYnu.js";const a=t(class extends e{constructor(t){super(),!1!==t&&this.__registerHost(),this.__attachShadow(),this.dialogOpen=i(this,"dialogOpen"),this.dialogClose=i(this,"dialogClose")}get host(){return this}isOpen=!1;dialogTitle;closable=!0;closeOnBackdrop=!0;closeOnEscape=!0;autoFocus=!0;trapFocus=!0;size="medium";fullscreenOnMobile=!0;contained=!1;isAnimating=!1;mobileLockedHeight=null;containerRect=null;containerBorderRadius=null;dialogOpen;dialogClose;previousOverflow="";previousActiveElement=null;visualViewportListenersAttached=!1;containerElement=null;containerResizeObserver=null;containerTrackingFrame=null;handleIsOpenChange(t){t?this.openDialog():this.closeDialog()}handleKeyDown(t){this.isOpen&&("Escape"===t.key&&this.closeOnEscape&&(t.preventDefault(),t.stopPropagation(),this.emitClose("escape")),"Tab"===t.key&&this.trapFocus&&this.handleTabKey(t))}handleWindowResize(){this.isOpen&&this.lockMobileViewportHeight()}handleOrientationChange(){this.isOpen&&requestAnimationFrame((()=>this.lockMobileViewportHeight()))}async open(){this.isOpen||(this.isOpen=!0)}async close(t="programmatic"){this.emitClose(t)}async focusFirstElement(){this.focusFirst()}componentDidLoad(){this.isOpen&&this.openDialog()}disconnectedCallback(){this.removeVisualViewportListeners(),this.stopContainerTracking(),this.restoreBodyScroll()}openDialog(){this.isAnimating=!0,this.previousActiveElement=document.activeElement,this.contained?this.startContainerTracking():(this.lockBodyScroll(),this.addVisualViewportListeners()),this.lockMobileViewportHeight(),this.dialogOpen.emit(),this.autoFocus&&requestAnimationFrame((()=>{this.focusFirst()})),requestAnimationFrame((()=>{this.isAnimating=!1}))}closeDialog(){this.restoreBodyScroll(),this.removeVisualViewportListeners(),this.stopContainerTracking(),this.mobileLockedHeight=null,this.returnFocusToPreviousElement()}findContainerElement(){let t=this.host;for(;t;){if(t instanceof e&&(t.hasAttribute("data-kritzel-dialog-container")||"KRITZEL-EDITOR"===t.tagName))return t;t=t.parentNode||(t instanceof ShadowRoot?t.host:null)}return null}startContainerTracking(){this.containerElement=this.findContainerElement(),this.containerElement?(this.updateContainerRect(),"undefined"!=typeof ResizeObserver&&(this.containerResizeObserver=new ResizeObserver((()=>this.updateContainerRect())),this.containerResizeObserver.observe(this.containerElement)),window.addEventListener("resize",this.handleContainerTrackingEvent,{passive:!0}),window.addEventListener("scroll",this.handleContainerTrackingEvent,{capture:!0,passive:!0})):this.containerRect=null}stopContainerTracking(){this.containerResizeObserver&&(this.containerResizeObserver.disconnect(),this.containerResizeObserver=null),window.removeEventListener("resize",this.handleContainerTrackingEvent),window.removeEventListener("scroll",this.handleContainerTrackingEvent,{capture:!0}),null!==this.containerTrackingFrame&&(cancelAnimationFrame(this.containerTrackingFrame),this.containerTrackingFrame=null),this.containerElement=null,this.containerRect=null,this.containerBorderRadius=null}handleContainerTrackingEvent=()=>{null===this.containerTrackingFrame&&(this.containerTrackingFrame=requestAnimationFrame((()=>{this.containerTrackingFrame=null,this.updateContainerRect()})))};updateContainerRect(){if(!this.containerElement)return;const t=this.containerElement.getBoundingClientRect(),e={top:t.top,left:t.left,width:t.width,height:t.height},i=this.containerRect;i&&i.top===e.top&&i.left===e.left&&i.width===e.width&&i.height===e.height||(this.containerRect=e);const o=this.findVisualBorderRadius(this.containerElement);this.containerBorderRadius!==o&&(this.containerBorderRadius=o)}findVisualBorderRadius(t){let e=t;for(;e&&e!==document.body&&e!==document.documentElement;){const t=window.getComputedStyle(e),i=t.borderTopLeftRadius,o=t.borderTopRightRadius,l=t.borderBottomRightRadius,n=t.borderBottomLeftRadius,s=t=>!t||"0px"===t||"0%"===t;if(!(s(i)&&s(o)&&s(l)&&s(n)))return`${i} ${o} ${l} ${n}`;e=e.parentElement}return null}emitClose(t){this.dialogClose.emit({reason:t})}lockBodyScroll(){this.previousOverflow=document.body.style.overflow,document.body.style.overflow="hidden"}lockMobileViewportHeight(){if(this.contained)return void(this.mobileLockedHeight=null);const t=this.getViewportWidth(),e=this.getViewportHeight();this.mobileLockedHeight=!this.fullscreenOnMobile||Math.min(t,e)>576?null:`${e}px`}getViewportWidth(){return Math.round(window.visualViewport?.width??window.innerWidth)}getViewportHeight(){return Math.round(window.visualViewport?.height??window.innerHeight)}addVisualViewportListeners(){const t=window.visualViewport;t&&!this.visualViewportListenersAttached&&(t.addEventListener("resize",this.handleVisualViewportChange),t.addEventListener("scroll",this.handleVisualViewportChange),this.visualViewportListenersAttached=!0)}removeVisualViewportListeners(){const t=window.visualViewport;t&&this.visualViewportListenersAttached&&(t.removeEventListener("resize",this.handleVisualViewportChange),t.removeEventListener("scroll",this.handleVisualViewportChange),this.visualViewportListenersAttached=!1)}handleVisualViewportChange=()=>{this.isOpen&&this.lockMobileViewportHeight()};restoreBodyScroll(){document.body.style.overflow=this.previousOverflow}returnFocusToPreviousElement(){this.previousActiveElement?.focus&&this.previousActiveElement.focus()}focusFirst(){const t=this.host.shadowRoot?.querySelector(".dialog-content");if(!t)return;const e=[...s.getFocusableElements(t),...this.getSlottedFocusableElements()];e.length>0?e[0].focus():t.focus()}getSlottedFocusableElements(){const t=this.host.shadowRoot?.querySelectorAll("slot")??[],e=[];return t.forEach((t=>{t.assignedElements({flatten:!0}).forEach((t=>{const i=s.getFocusableElements(t);e.push(...i)}))})),e}handleTabKey(t){const e=this.getSlottedFocusableElements(),i=this.host.shadowRoot?.querySelector(".close-button");if(i&&this.closable&&e.unshift(i),0===e.length)return;const o=e[0],l=e[e.length-1],n=this.getDeepActiveElement();t.shiftKey?n===o&&(t.preventDefault(),l.focus()):n===l&&(t.preventDefault(),o.focus())}getDeepActiveElement(){let t=document.activeElement;for(;t?.shadowRoot?.activeElement;)t=t.shadowRoot.activeElement;return t}handleBackdropClick=t=>{t.stopPropagation(),this.closeOnBackdrop&&this.emitClose("backdrop")};handleCloseButtonClick=t=>{t.stopPropagation(),this.emitClose("close-button")};handleContentClick=t=>{t.stopPropagation()};renderCloseButton(){return this.closable?o("button",{class:"close-button",type:"button","aria-label":"Close dialog",onClick:this.handleCloseButtonClick},o("svg",{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},o("line",{x1:"18",y1:"6",x2:"6",y2:"18"}),o("line",{x1:"6",y1:"6",x2:"18",y2:"18"}))):null}renderHeader(){const t=null!==this.host.querySelector('[slot="header"]'),e=!!this.dialogTitle;return t||e||this.closable?o("div",{class:"dialog-header"},t?o("slot",{name:"header"}):e?o("h2",{class:"dialog-title"},this.dialogTitle):null,this.renderCloseButton()):null}renderFooter(){return null!==this.host.querySelector('[slot="footer"]')?o("div",{class:"dialog-footer"},o("slot",{name:"footer"})):null}getBackdropStyle(){if(!this.contained||!this.containerRect)return;const{top:t,left:e,width:i,height:o}=this.containerRect,l={top:`${t}px`,left:`${e}px`,right:"auto",bottom:"auto",width:`${i}px`,height:`${o}px`};return this.containerBorderRadius&&(l.borderRadius=this.containerBorderRadius,l.overflow="hidden"),l}getDialogContentStyle(){const t={};if(this.contained&&this.containerRect){const{width:e,height:i}=this.containerRect;if(this.isContainerMobile())t.width=`${e}px`,t.height=`${i}px`,t.maxWidth=`${e}px`,t.maxHeight=`${i}px`,t.borderRadius="0";else{const o=Math.max(0,e-32),l=Math.max(0,i-32);t.maxWidth=`${o}px`,t.maxHeight=`${l}px`}}return this.mobileLockedHeight&&(t.height=this.mobileLockedHeight,t.maxHeight=this.mobileLockedHeight),Object.keys(t).length>0?t:void 0}isContainerMobile(){return!(!this.fullscreenOnMobile||!this.containerRect)&&Math.min(this.containerRect.width,this.containerRect.height)<=576}render(){if(!this.isOpen)return null;const t=this.contained&&this.isContainerMobile();return o(l,null,o("div",{class:{backdrop:!0,"is-animating":this.isAnimating,"contained-fullscreen":t},style:this.getBackdropStyle(),onClick:this.handleBackdropClick},o("div",{class:{"dialog-content":!0,"is-animating":this.isAnimating,[`size-${this.size}`]:!0,"fullscreen-on-mobile":this.fullscreenOnMobile,"contained-fullscreen":t},style:this.getDialogContentStyle(),role:"dialog","aria-modal":"true","aria-labelledby":this.dialogTitle?"dialog-title":void 0,tabIndex:-1,onClick:this.handleContentClick},this.renderHeader(),o("div",{class:"dialog-body"},o("slot",null)),this.renderFooter())))}static get watchers(){return{isOpen:[{handleIsOpenChange:0}]}}static get style(){return":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}"}},[769,"kritzel-dialog",{isOpen:[516,"is-open"],dialogTitle:[1,"dialog-title"],closable:[4],closeOnBackdrop:[4,"close-on-backdrop"],closeOnEscape:[4,"close-on-escape"],autoFocus:[4,"auto-focus"],trapFocus:[4,"trap-focus"],size:[1],fullscreenOnMobile:[4,"fullscreen-on-mobile"],contained:[516],isAnimating:[32],mobileLockedHeight:[32],containerRect:[32],containerBorderRadius:[32],open:[64],close:[64],focusFirstElement:[64]},[[8,"keydown","handleKeyDown"],[9,"resize","handleWindowResize"],[8,"orientationchange","handleOrientationChange"]],{isOpen:[{handleIsOpenChange:0}]}]);function r(){"undefined"!=typeof customElements&&["kritzel-dialog"].forEach((t=>{"kritzel-dialog"===t&&(customElements.get(n(t))||customElements.define(n(t),a))}))}export{a as K,r as d}
1
+ import { p as proxyCustomElement, H, c as createEvent, h, d as Host, t as transformTag } from './p-B43upypT.js';
2
+ import { K as KritzelHTMLHelper } from './p-WUdQqYnu.js';
3
+
4
+ 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}`;
5
+
6
+ const KritzelDialog = /*@__PURE__*/ proxyCustomElement(class KritzelDialog extends H {
7
+ constructor(registerHost) {
8
+ super();
9
+ if (registerHost !== false) {
10
+ this.__registerHost();
11
+ }
12
+ this.__attachShadow();
13
+ this.dialogOpen = createEvent(this, "dialogOpen");
14
+ this.dialogClose = createEvent(this, "dialogClose");
15
+ }
16
+ get host() { return this; }
17
+ /** Whether the dialog is open */
18
+ isOpen = false;
19
+ /** Optional title displayed in the header */
20
+ dialogTitle;
21
+ /** Whether to show the close button in the header */
22
+ closable = true;
23
+ /** Whether clicking the backdrop closes the dialog */
24
+ closeOnBackdrop = true;
25
+ /** Whether pressing Escape closes the dialog */
26
+ closeOnEscape = true;
27
+ /** Whether to auto-focus the first focusable element when opened */
28
+ autoFocus = true;
29
+ /** Whether to trap focus within the dialog */
30
+ trapFocus = true;
31
+ /** Size of the dialog */
32
+ size = 'medium';
33
+ /** Whether to automatically go fullscreen on mobile viewports */
34
+ fullscreenOnMobile = true;
35
+ /** Constrain the dialog to its nearest editor/container ancestor instead of the viewport. */
36
+ contained = false;
37
+ isAnimating = false;
38
+ mobileLockedHeight = null;
39
+ containerRect = null;
40
+ containerBorderRadius = null;
41
+ /** Emitted when the dialog opens */
42
+ dialogOpen;
43
+ /** Emitted when the dialog closes */
44
+ dialogClose;
45
+ previousOverflow = '';
46
+ previousActiveElement = null;
47
+ visualViewportListenersAttached = false;
48
+ containerElement = null;
49
+ containerResizeObserver = null;
50
+ containerTrackingFrame = null;
51
+ handleIsOpenChange(newValue) {
52
+ if (newValue) {
53
+ this.openDialog();
54
+ }
55
+ else {
56
+ this.closeDialog();
57
+ }
58
+ }
59
+ handleKeyDown(event) {
60
+ if (!this.isOpen)
61
+ return;
62
+ if (event.key === 'Escape' && this.closeOnEscape) {
63
+ event.preventDefault();
64
+ event.stopPropagation();
65
+ this.emitClose('escape');
66
+ }
67
+ if (event.key === 'Tab' && this.trapFocus) {
68
+ this.handleTabKey(event);
69
+ }
70
+ }
71
+ handleWindowResize() {
72
+ if (!this.isOpen)
73
+ return;
74
+ this.lockMobileViewportHeight();
75
+ }
76
+ handleOrientationChange() {
77
+ if (!this.isOpen)
78
+ return;
79
+ // Let viewport metrics settle before recalculating after orientation flips.
80
+ requestAnimationFrame(() => this.lockMobileViewportHeight());
81
+ }
82
+ async open() {
83
+ if (!this.isOpen) {
84
+ this.isOpen = true;
85
+ }
86
+ }
87
+ async close(reason = 'programmatic') {
88
+ this.emitClose(reason);
89
+ }
90
+ async focusFirstElement() {
91
+ this.focusFirst();
92
+ }
93
+ componentDidLoad() {
94
+ if (this.isOpen) {
95
+ this.openDialog();
96
+ }
97
+ }
98
+ disconnectedCallback() {
99
+ this.removeVisualViewportListeners();
100
+ this.stopContainerTracking();
101
+ this.restoreBodyScroll();
102
+ }
103
+ openDialog() {
104
+ this.isAnimating = true;
105
+ this.previousActiveElement = document.activeElement;
106
+ if (this.contained) {
107
+ this.startContainerTracking();
108
+ }
109
+ else {
110
+ this.lockBodyScroll();
111
+ this.addVisualViewportListeners();
112
+ }
113
+ this.lockMobileViewportHeight();
114
+ this.dialogOpen.emit();
115
+ if (this.autoFocus) {
116
+ requestAnimationFrame(() => {
117
+ this.focusFirst();
118
+ });
119
+ }
120
+ requestAnimationFrame(() => {
121
+ this.isAnimating = false;
122
+ });
123
+ }
124
+ closeDialog() {
125
+ this.restoreBodyScroll();
126
+ this.removeVisualViewportListeners();
127
+ this.stopContainerTracking();
128
+ this.mobileLockedHeight = null;
129
+ this.returnFocusToPreviousElement();
130
+ }
131
+ findContainerElement() {
132
+ // Walk up the composed DOM (crossing shadow roots) and return the first
133
+ // ancestor that opts into containing dialogs. We accept either an explicit
134
+ // [data-kritzel-dialog-container] marker or the kritzel-editor host so any
135
+ // consumer can opt in without modifying the editor itself.
136
+ let node = this.host;
137
+ while (node) {
138
+ if (node instanceof H) {
139
+ if (node.hasAttribute('data-kritzel-dialog-container') || node.tagName === 'KRITZEL-EDITOR') {
140
+ return node;
141
+ }
142
+ }
143
+ const parent = node.parentNode;
144
+ if (parent) {
145
+ node = parent;
146
+ }
147
+ else if (node instanceof ShadowRoot) {
148
+ node = node.host;
149
+ }
150
+ else {
151
+ node = null;
152
+ }
153
+ }
154
+ return null;
155
+ }
156
+ startContainerTracking() {
157
+ this.containerElement = this.findContainerElement();
158
+ if (!this.containerElement) {
159
+ // No container found — fall back to viewport behavior.
160
+ this.containerRect = null;
161
+ return;
162
+ }
163
+ this.updateContainerRect();
164
+ if (typeof ResizeObserver !== 'undefined') {
165
+ this.containerResizeObserver = new ResizeObserver(() => this.updateContainerRect());
166
+ this.containerResizeObserver.observe(this.containerElement);
167
+ }
168
+ window.addEventListener('resize', this.handleContainerTrackingEvent, { passive: true });
169
+ window.addEventListener('scroll', this.handleContainerTrackingEvent, { capture: true, passive: true });
170
+ }
171
+ stopContainerTracking() {
172
+ if (this.containerResizeObserver) {
173
+ this.containerResizeObserver.disconnect();
174
+ this.containerResizeObserver = null;
175
+ }
176
+ window.removeEventListener('resize', this.handleContainerTrackingEvent);
177
+ window.removeEventListener('scroll', this.handleContainerTrackingEvent, { capture: true });
178
+ if (this.containerTrackingFrame !== null) {
179
+ cancelAnimationFrame(this.containerTrackingFrame);
180
+ this.containerTrackingFrame = null;
181
+ }
182
+ this.containerElement = null;
183
+ this.containerRect = null;
184
+ this.containerBorderRadius = null;
185
+ }
186
+ handleContainerTrackingEvent = () => {
187
+ if (this.containerTrackingFrame !== null)
188
+ return;
189
+ this.containerTrackingFrame = requestAnimationFrame(() => {
190
+ this.containerTrackingFrame = null;
191
+ this.updateContainerRect();
192
+ });
193
+ };
194
+ updateContainerRect() {
195
+ if (!this.containerElement)
196
+ return;
197
+ const rect = this.containerElement.getBoundingClientRect();
198
+ const next = { top: rect.top, left: rect.left, width: rect.width, height: rect.height };
199
+ const prev = this.containerRect;
200
+ if (!prev || prev.top !== next.top || prev.left !== next.left || prev.width !== next.width || prev.height !== next.height) {
201
+ this.containerRect = next;
202
+ }
203
+ // Look for the nearest visually-rounded ancestor (the container itself or
204
+ // any ancestor up to the document) so the backdrop matches wrappers that
205
+ // round their corners around the editor.
206
+ const radius = this.findVisualBorderRadius(this.containerElement);
207
+ if (this.containerBorderRadius !== radius) {
208
+ this.containerBorderRadius = radius;
209
+ }
210
+ }
211
+ findVisualBorderRadius(start) {
212
+ let node = start;
213
+ while (node && node !== document.body && node !== document.documentElement) {
214
+ const computed = window.getComputedStyle(node);
215
+ const tl = computed.borderTopLeftRadius;
216
+ const tr = computed.borderTopRightRadius;
217
+ const br = computed.borderBottomRightRadius;
218
+ const bl = computed.borderBottomLeftRadius;
219
+ const isZero = (v) => !v || v === '0px' || v === '0%';
220
+ if (!(isZero(tl) && isZero(tr) && isZero(br) && isZero(bl))) {
221
+ return `${tl} ${tr} ${br} ${bl}`;
222
+ }
223
+ node = node.parentElement;
224
+ }
225
+ return null;
226
+ }
227
+ emitClose(reason) {
228
+ this.dialogClose.emit({ reason });
229
+ }
230
+ lockBodyScroll() {
231
+ this.previousOverflow = document.body.style.overflow;
232
+ document.body.style.overflow = 'hidden';
233
+ }
234
+ lockMobileViewportHeight() {
235
+ // Skip mobile viewport height locking when contained — the dialog is sized
236
+ // by its wrapper, not the viewport.
237
+ if (this.contained) {
238
+ this.mobileLockedHeight = null;
239
+ return;
240
+ }
241
+ // Only lock height on mobile when fullscreenOnMobile is enabled.
242
+ // Use the smaller dimension so landscape phones (wide but short) are also detected.
243
+ const viewportWidth = this.getViewportWidth();
244
+ const viewportHeight = this.getViewportHeight();
245
+ if (!this.fullscreenOnMobile || Math.min(viewportWidth, viewportHeight) > 576) {
246
+ this.mobileLockedHeight = null;
247
+ return;
248
+ }
249
+ this.mobileLockedHeight = `${viewportHeight}px`;
250
+ }
251
+ getViewportWidth() {
252
+ return Math.round(window.visualViewport?.width ?? window.innerWidth);
253
+ }
254
+ getViewportHeight() {
255
+ return Math.round(window.visualViewport?.height ?? window.innerHeight);
256
+ }
257
+ addVisualViewportListeners() {
258
+ const viewport = window.visualViewport;
259
+ if (!viewport || this.visualViewportListenersAttached)
260
+ return;
261
+ viewport.addEventListener('resize', this.handleVisualViewportChange);
262
+ viewport.addEventListener('scroll', this.handleVisualViewportChange);
263
+ this.visualViewportListenersAttached = true;
264
+ }
265
+ removeVisualViewportListeners() {
266
+ const viewport = window.visualViewport;
267
+ if (!viewport || !this.visualViewportListenersAttached)
268
+ return;
269
+ viewport.removeEventListener('resize', this.handleVisualViewportChange);
270
+ viewport.removeEventListener('scroll', this.handleVisualViewportChange);
271
+ this.visualViewportListenersAttached = false;
272
+ }
273
+ handleVisualViewportChange = () => {
274
+ if (!this.isOpen)
275
+ return;
276
+ this.lockMobileViewportHeight();
277
+ };
278
+ restoreBodyScroll() {
279
+ document.body.style.overflow = this.previousOverflow;
280
+ }
281
+ returnFocusToPreviousElement() {
282
+ if (this.previousActiveElement?.focus) {
283
+ this.previousActiveElement.focus();
284
+ }
285
+ }
286
+ focusFirst() {
287
+ const dialogContent = this.host.shadowRoot?.querySelector('.dialog-content');
288
+ if (!dialogContent)
289
+ return;
290
+ const focusableElements = KritzelHTMLHelper.getFocusableElements(dialogContent);
291
+ const slotElements = this.getSlottedFocusableElements();
292
+ const allFocusable = [...focusableElements, ...slotElements];
293
+ if (allFocusable.length > 0) {
294
+ allFocusable[0].focus();
295
+ }
296
+ else {
297
+ dialogContent.focus();
298
+ }
299
+ }
300
+ getSlottedFocusableElements() {
301
+ const slots = this.host.shadowRoot?.querySelectorAll('slot') ?? [];
302
+ const focusable = [];
303
+ slots.forEach(slot => {
304
+ const assigned = slot.assignedElements({ flatten: true });
305
+ assigned.forEach(el => {
306
+ // Use KritzelHTMLHelper to find focusable elements including those in nested shadow DOMs
307
+ const elements = KritzelHTMLHelper.getFocusableElements(el);
308
+ focusable.push(...elements);
309
+ });
310
+ });
311
+ return focusable;
312
+ }
313
+ handleTabKey(event) {
314
+ const focusableElements = this.getSlottedFocusableElements();
315
+ const closeButton = this.host.shadowRoot?.querySelector('.close-button');
316
+ if (closeButton && this.closable) {
317
+ focusableElements.unshift(closeButton);
318
+ }
319
+ if (focusableElements.length === 0)
320
+ return;
321
+ const firstFocusable = focusableElements[0];
322
+ const lastFocusable = focusableElements[focusableElements.length - 1];
323
+ const activeElement = this.getDeepActiveElement();
324
+ if (event.shiftKey) {
325
+ if (activeElement === firstFocusable) {
326
+ event.preventDefault();
327
+ lastFocusable.focus();
328
+ }
329
+ }
330
+ else {
331
+ if (activeElement === lastFocusable) {
332
+ event.preventDefault();
333
+ firstFocusable.focus();
334
+ }
335
+ }
336
+ }
337
+ getDeepActiveElement() {
338
+ let activeEl = document.activeElement;
339
+ while (activeEl?.shadowRoot?.activeElement) {
340
+ activeEl = activeEl.shadowRoot.activeElement;
341
+ }
342
+ return activeEl;
343
+ }
344
+ handleBackdropClick = (event) => {
345
+ event.stopPropagation();
346
+ if (this.closeOnBackdrop) {
347
+ this.emitClose('backdrop');
348
+ }
349
+ };
350
+ handleCloseButtonClick = (event) => {
351
+ event.stopPropagation();
352
+ this.emitClose('close-button');
353
+ };
354
+ handleContentClick = (event) => {
355
+ event.stopPropagation();
356
+ };
357
+ renderCloseButton() {
358
+ if (!this.closable)
359
+ return null;
360
+ return (h("button", { class: "close-button", type: "button", "aria-label": "Close dialog", onClick: this.handleCloseButtonClick }, h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }, h("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), h("line", { x1: "6", y1: "6", x2: "18", y2: "18" }))));
361
+ }
362
+ renderHeader() {
363
+ const hasHeaderSlot = this.host.querySelector('[slot="header"]') !== null;
364
+ const hasTitle = !!this.dialogTitle;
365
+ if (!hasHeaderSlot && !hasTitle && !this.closable)
366
+ return null;
367
+ return (h("div", { class: "dialog-header" }, hasHeaderSlot ? (h("slot", { name: "header" })) : hasTitle ? (h("h2", { class: "dialog-title" }, this.dialogTitle)) : null, this.renderCloseButton()));
368
+ }
369
+ renderFooter() {
370
+ const hasFooterSlot = this.host.querySelector('[slot="footer"]') !== null;
371
+ if (!hasFooterSlot)
372
+ return null;
373
+ return (h("div", { class: "dialog-footer" }, h("slot", { name: "footer" })));
374
+ }
375
+ getBackdropStyle() {
376
+ if (!this.contained || !this.containerRect)
377
+ return undefined;
378
+ const { top, left, width, height } = this.containerRect;
379
+ const style = {
380
+ top: `${top}px`,
381
+ left: `${left}px`,
382
+ right: 'auto',
383
+ bottom: 'auto',
384
+ width: `${width}px`,
385
+ height: `${height}px`,
386
+ };
387
+ if (this.containerBorderRadius) {
388
+ style.borderRadius = this.containerBorderRadius;
389
+ // Ensure rounded corners actually clip the inner dialog content.
390
+ style.overflow = 'hidden';
391
+ }
392
+ return style;
393
+ }
394
+ getDialogContentStyle() {
395
+ const style = {};
396
+ // In contained mode, cap the dialog dimensions to the container so the
397
+ // declared widths/heights of size variants cannot overflow the wrapper.
398
+ if (this.contained && this.containerRect) {
399
+ const { width, height } = this.containerRect;
400
+ if (this.isContainerMobile()) {
401
+ // Mobile-sized container: behave like fullscreen-on-mobile but scoped
402
+ // to the container instead of the viewport (works in any orientation).
403
+ style.width = `${width}px`;
404
+ style.height = `${height}px`;
405
+ style.maxWidth = `${width}px`;
406
+ style.maxHeight = `${height}px`;
407
+ style.borderRadius = '0';
408
+ }
409
+ else {
410
+ // Leave a small margin so the dialog visibly sits within the container.
411
+ const maxWidth = Math.max(0, width - 32);
412
+ const maxHeight = Math.max(0, height - 32);
413
+ style.maxWidth = `${maxWidth}px`;
414
+ style.maxHeight = `${maxHeight}px`;
415
+ }
416
+ }
417
+ if (this.mobileLockedHeight) {
418
+ style.height = this.mobileLockedHeight;
419
+ style.maxHeight = this.mobileLockedHeight;
420
+ }
421
+ return Object.keys(style).length > 0 ? style : undefined;
422
+ }
423
+ isContainerMobile() {
424
+ if (!this.fullscreenOnMobile || !this.containerRect)
425
+ return false;
426
+ // Match the existing viewport media-query threshold: container is "mobile"
427
+ // when its smaller dimension is <= 576px. This handles both portrait and
428
+ // landscape wrappers symmetrically.
429
+ return Math.min(this.containerRect.width, this.containerRect.height) <= 576;
430
+ }
431
+ render() {
432
+ if (!this.isOpen)
433
+ return null;
434
+ const containerFullscreen = this.contained && this.isContainerMobile();
435
+ return (h(Host, null, h("div", { class: { backdrop: true, 'is-animating': this.isAnimating, 'contained-fullscreen': containerFullscreen }, style: this.getBackdropStyle(), onClick: this.handleBackdropClick }, h("div", { class: {
436
+ 'dialog-content': true,
437
+ 'is-animating': this.isAnimating,
438
+ [`size-${this.size}`]: true,
439
+ 'fullscreen-on-mobile': this.fullscreenOnMobile,
440
+ 'contained-fullscreen': containerFullscreen,
441
+ }, style: this.getDialogContentStyle(), role: "dialog", "aria-modal": "true", "aria-labelledby": this.dialogTitle ? 'dialog-title' : undefined, tabIndex: -1, onClick: this.handleContentClick }, this.renderHeader(), h("div", { class: "dialog-body" }, h("slot", null)), this.renderFooter()))));
442
+ }
443
+ static get watchers() { return {
444
+ "isOpen": [{
445
+ "handleIsOpenChange": 0
446
+ }]
447
+ }; }
448
+ static get style() { return kritzelDialogCss(); }
449
+ }, [769, "kritzel-dialog", {
450
+ "isOpen": [516, "is-open"],
451
+ "dialogTitle": [1, "dialog-title"],
452
+ "closable": [4],
453
+ "closeOnBackdrop": [4, "close-on-backdrop"],
454
+ "closeOnEscape": [4, "close-on-escape"],
455
+ "autoFocus": [4, "auto-focus"],
456
+ "trapFocus": [4, "trap-focus"],
457
+ "size": [1],
458
+ "fullscreenOnMobile": [4, "fullscreen-on-mobile"],
459
+ "contained": [516],
460
+ "isAnimating": [32],
461
+ "mobileLockedHeight": [32],
462
+ "containerRect": [32],
463
+ "containerBorderRadius": [32],
464
+ "open": [64],
465
+ "close": [64],
466
+ "focusFirstElement": [64]
467
+ }, [[8, "keydown", "handleKeyDown"], [9, "resize", "handleWindowResize"], [8, "orientationchange", "handleOrientationChange"]], {
468
+ "isOpen": [{
469
+ "handleIsOpenChange": 0
470
+ }]
471
+ }]);
472
+ function defineCustomElement() {
473
+ if (typeof customElements === "undefined") {
474
+ return;
475
+ }
476
+ const components = ["kritzel-dialog"];
477
+ components.forEach(tagName => { switch (tagName) {
478
+ case "kritzel-dialog":
479
+ if (!customElements.get(transformTag(tagName))) {
480
+ customElements.define(transformTag(tagName), KritzelDialog);
481
+ }
482
+ break;
483
+ } });
484
+ }
485
+
486
+ export { KritzelDialog as K, defineCustomElement as d };
@@ -1 +1,20 @@
1
- class t{static generateUUID(t=16){const r=crypto.getRandomValues(new Uint8Array(t));return Array.from(r).map((t=>"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"[t%62])).join("")}static isEmpty(t){return null==t||0===Object?.keys(t).length&&t?.constructor===Object}static isClass(t,r){return!!t&&t.__class__===r}}export{t as O}
1
+ class ObjectHelper {
2
+ static generateUUID(length = 16) {
3
+ const alphabet = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
4
+ const bytes = crypto.getRandomValues(new Uint8Array(length));
5
+ return Array.from(bytes)
6
+ .map(byte => alphabet[byte % alphabet.length])
7
+ .join('');
8
+ }
9
+ static isEmpty(obj) {
10
+ if (obj === null || obj === undefined) {
11
+ return true;
12
+ }
13
+ return Object?.keys(obj).length === 0 && obj?.constructor === Object;
14
+ }
15
+ static isClass(object, className) {
16
+ return !!object && object.__class__ === className;
17
+ }
18
+ }
19
+
20
+ export { ObjectHelper as O };