kritzel-stencil 0.4.4 → 0.4.6

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 (128) hide show
  1. package/dist/cjs/kritzel-active-users_47.cjs.entry.js +79 -13
  2. package/dist/cjs/loader.cjs.js +1 -1
  3. package/dist/cjs/stencil.cjs.js +1 -1
  4. package/dist/collection/classes/core/viewport.class.js +14 -1
  5. package/dist/collection/components/core/kritzel-editor/kritzel-editor.js +48 -8
  6. package/dist/collection/components/core/kritzel-engine/kritzel-engine.js +84 -3
  7. package/dist/collection/constants/version.js +1 -1
  8. package/dist/components/index.js +1226 -1
  9. package/dist/components/kritzel-active-users.js +6 -1
  10. package/dist/components/kritzel-avatar.js +6 -1
  11. package/dist/components/kritzel-awareness-cursors.js +6 -1
  12. package/dist/components/kritzel-back-to-content.js +6 -1
  13. package/dist/components/kritzel-brush-style.js +64 -1
  14. package/dist/components/kritzel-button.js +6 -1
  15. package/dist/components/kritzel-color-palette.js +6 -1
  16. package/dist/components/kritzel-color.js +6 -1
  17. package/dist/components/kritzel-context-menu.js +6 -1
  18. package/dist/components/kritzel-controls.js +6 -1
  19. package/dist/components/kritzel-current-user-dialog.js +6 -1
  20. package/dist/components/kritzel-current-user.js +6 -1
  21. package/dist/components/kritzel-cursor-trail.js +6 -1
  22. package/dist/components/kritzel-dialog.js +6 -1
  23. package/dist/components/kritzel-dropdown.js +6 -1
  24. package/dist/components/kritzel-editor.js +4404 -1
  25. package/dist/components/kritzel-engine.js +6 -1
  26. package/dist/components/kritzel-export.js +6 -1
  27. package/dist/components/kritzel-font-family.js +6 -1
  28. package/dist/components/kritzel-font-size.js +6 -1
  29. package/dist/components/kritzel-font.js +6 -1
  30. package/dist/components/kritzel-icon.js +6 -1
  31. package/dist/components/kritzel-input.js +6 -1
  32. package/dist/components/kritzel-line-endings.js +6 -1
  33. package/dist/components/kritzel-loading-overlay.js +6 -1
  34. package/dist/components/kritzel-login-dialog.js +6 -1
  35. package/dist/components/kritzel-master-detail.js +6 -1
  36. package/dist/components/kritzel-menu-item.js +6 -1
  37. package/dist/components/kritzel-menu.js +6 -1
  38. package/dist/components/kritzel-more-menu.js +6 -1
  39. package/dist/components/kritzel-notification-card.js +6 -1
  40. package/dist/components/kritzel-numeric-input.js +6 -1
  41. package/dist/components/kritzel-opacity-slider.js +6 -1
  42. package/dist/components/kritzel-pill-tabs.js +6 -1
  43. package/dist/components/kritzel-portal.js +6 -1
  44. package/dist/components/kritzel-settings.js +6 -1
  45. package/dist/components/kritzel-shape-fill.js +6 -1
  46. package/dist/components/kritzel-share-dialog.js +6 -1
  47. package/dist/components/kritzel-slide-toggle.js +6 -1
  48. package/dist/components/kritzel-split-button.js +6 -1
  49. package/dist/components/kritzel-stroke-size.js +6 -1
  50. package/dist/components/kritzel-sync-indicator.js +6 -1
  51. package/dist/components/kritzel-tool-config.js +6 -1
  52. package/dist/components/kritzel-tooltip.js +6 -1
  53. package/dist/components/kritzel-utility-panel.js +6 -1
  54. package/dist/components/kritzel-watermark.js +6 -1
  55. package/dist/components/kritzel-workspace-manager.js +6 -1
  56. package/dist/components/kritzel-zoom-panel.js +6 -1
  57. package/dist/components/p-894OnDQV.js +39 -1
  58. package/dist/components/p-B43upypT.js +1500 -1
  59. package/dist/components/p-B5oHmPJb.js +97 -1
  60. package/dist/components/p-B6t5q-V4.js +63 -1
  61. package/dist/components/p-B8Xi4Clg.js +43 -1
  62. package/dist/components/p-BBmP8lVY.js +51726 -0
  63. package/dist/components/p-BDzlx2hB.js +135 -1
  64. package/dist/components/p-BFTU3MAI.js +7 -1
  65. package/dist/components/p-BFYtCsZu.js +56 -1
  66. package/dist/components/p-BI2ng9I_.js +62 -1
  67. package/dist/components/p-BTzlrIxe.js +194 -1
  68. package/dist/components/p-BmyTdQGy.js +1090 -1
  69. package/dist/components/p-BsANVili.js +150 -1
  70. package/dist/components/p-BxpKq94F.js +290 -1
  71. package/dist/components/p-C38P-Vd0.js +446 -1
  72. package/dist/components/p-C4NrrUfN.js +77 -1
  73. package/dist/components/p-CW-VyJgK.js +6 -1
  74. package/dist/components/p-CWRSGYOE.js +57 -1
  75. package/dist/components/p-CXpv9Rxe.js +106 -1
  76. package/dist/components/p-Ca-igU1f.js +320 -1
  77. package/dist/components/p-CdR76C4L.js +165 -1
  78. package/dist/components/p-Ch42cOeY.js +320 -0
  79. package/dist/components/p-ClFprFvz.js +209 -1
  80. package/dist/components/p-Cm33td2O.js +122 -1
  81. package/dist/components/p-CqLgB8JK.js +91 -1
  82. package/dist/components/p-Cr682JI_.js +156 -1
  83. package/dist/components/p-CsvMgk_f.js +62 -1
  84. package/dist/components/p-CwJwsRR3.js +277 -1
  85. package/dist/components/p-Cymum41a.js +88 -1
  86. package/dist/components/p-D09kgc5Q.js +94 -1
  87. package/dist/components/p-D30zs0kA.js +121 -1
  88. package/dist/components/p-D3y_Hauo.js +85 -1
  89. package/dist/components/p-D5jf8wAu.js +142 -1
  90. package/dist/components/p-D82VaHce.js +53 -1
  91. package/dist/components/p-DAwPPDMS.js +101 -1
  92. package/dist/components/p-DEBwmRTC.js +55 -1
  93. package/dist/components/p-DIazmg6w.js +52 -1
  94. package/dist/components/p-DJ88BrIW.js +70 -1
  95. package/dist/components/p-DJkKlUyZ.js +182 -1
  96. package/dist/components/p-DUYmwrWV.js +3267 -1
  97. package/dist/components/p-DX2nriaq.js +486 -1
  98. package/dist/components/p-Dd-pMvlr.js +20 -1
  99. package/dist/components/p-Df3BwVGy.js +299 -1
  100. package/dist/components/p-DgJ0ufzr.js +43 -1
  101. package/dist/components/p-DkUb2czk.js +70 -1
  102. package/dist/components/p-Dlp84thc.js +57 -1
  103. package/dist/components/p-JYj3Facr.js +431 -1
  104. package/dist/components/p-Ka7OWbnk.js +2304 -1
  105. package/dist/components/p-PSFAfAyd.js +49 -1
  106. package/dist/components/p-WUdQqYnu.js +118 -1
  107. package/dist/components/p-djJSnjAX.js +84 -1
  108. package/dist/components/p-e6Zpc9Vp.js +143 -1
  109. package/dist/components/p-jGOpkGDl.js +30 -1
  110. package/dist/components/p-pagW8YF7.js +99 -1
  111. package/dist/esm/kritzel-active-users_47.entry.js +79 -13
  112. package/dist/esm/loader.js +1 -1
  113. package/dist/esm/stencil.js +1 -1
  114. package/dist/stencil/index.esm.js +1172 -1
  115. package/dist/stencil/p-5b969a42.entry.js +36109 -0
  116. package/dist/stencil/p-DQuL1Twl.js +3 -1
  117. package/dist/stencil/p-Dhio9uis.js +1717 -2
  118. package/dist/stencil/p-fb32cd8f.entry.js +29 -1
  119. package/dist/stencil/p-uC7_X6yr.js +30737 -1
  120. package/dist/stencil/stencil.esm.js +21 -1
  121. package/dist/types/components/core/kritzel-editor/kritzel-editor.d.ts +2 -0
  122. package/dist/types/components/core/kritzel-engine/kritzel-engine.d.ts +7 -0
  123. package/dist/types/components.d.ts +10 -0
  124. package/dist/types/constants/version.d.ts +1 -1
  125. package/package.json +1 -1
  126. package/dist/components/p--Oazz-BP.js +0 -9
  127. package/dist/components/p-Xsiz1D5Q.js +0 -1
  128. package/dist/stencil/p-9abc21b9.entry.js +0 -9
@@ -1 +1,150 @@
1
- import{p as e,H as t,c as i,h as a,d as r,t as l}from"./p-B43upypT.js";import{d as o}from"./p-CdR76C4L.js";const s=e(class extends t{constructor(e){super(),!1!==e&&this.__registerHost(),this.__attachShadow(),this.itemSelect=i(this,"itemSelect")}get host(){return this}items=[];selectedItemId;itemSelect;focusedIndex=-1;showMobileDetail=!1;tabRefs=[];watchSelectedItemId(e,t){e!==t&&(this.showMobileDetail=!0)}componentWillRender(){this.tabRefs=[]}handleItemClick=e=>{e.disabled||(this.itemSelect.emit({item:e}),this.showMobileDetail=!0)};handleBackClick=()=>{this.showMobileDetail=!1};handleKeyDown=(e,t,i)=>{const a=this.items.map(((e,t)=>e.disabled?-1:t)).filter((e=>-1!==e)),r=a.indexOf(i);switch(e.key){case"ArrowDown":e.preventDefault(),this.focusTab(a[(r+1)%a.length]);break;case"ArrowUp":e.preventDefault(),this.focusTab(a[(r-1+a.length)%a.length]);break;case"Home":e.preventDefault(),this.focusTab(a[0]);break;case"End":e.preventDefault(),this.focusTab(a[a.length-1]);break;case"Enter":case" ":e.preventDefault(),this.handleItemClick(t)}};focusTab(e){this.focusedIndex=e;const t=this.tabRefs[e];t&&t.focus()}handleFocus=e=>{this.focusedIndex=e};handleBlur=()=>{this.focusedIndex=-1};setTabRef=(e,t)=>{e&&(this.tabRefs[t]=e)};getTabIndex(e,t){return e.disabled?-1:0}render(){const e=this.items.find((e=>e.id===this.selectedItemId)),t="master-detail-panel",i=e?`tab-${e.id}`:void 0;return a(r,{key:"e363142a5175b1f711cebfc98cfeedf07cd2c6c3"},a("div",{key:"eebf863ecdb4a53289cb56e14c02977375781167",class:{"master-detail-container":!0,"is-mobile-detail-visible":this.showMobileDetail}},a("nav",{key:"06660d3cd7de29ba46e3437169f99cb00eef1cc6",class:"master-menu",role:"tablist","aria-orientation":"vertical","aria-label":"Settings categories"},this.items.map(((e,i)=>a("button",{key:e.id,id:`tab-${e.id}`,ref:e=>this.setTabRef(e,i),class:{"menu-item":!0,"is-selected":e.id===this.selectedItemId,"is-disabled":!!e.disabled,"is-focused":i===this.focusedIndex},role:"tab","aria-selected":e.id===this.selectedItemId?"true":"false","aria-controls":t,"aria-disabled":e.disabled?"true":void 0,tabIndex:this.getTabIndex(e,i),disabled:e.disabled,onClick:()=>this.handleItemClick(e),onKeyDown:t=>this.handleKeyDown(t,e,i),onFocus:()=>this.handleFocus(i),onBlur:this.handleBlur},e.icon&&a("kritzel-icon",{name:e.icon,size:20,class:"menu-item-icon"}),a("span",{class:"menu-item-label"},e.label),a("span",{class:"menu-item-chevron","aria-hidden":"true"},a("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"1.5","stroke-linecap":"round","stroke-linejoin":"round"},a("path",{d:"m9 18 6-6-6-6"}))))))),a("div",{key:"0d6b6722ecbf64b28d27754161f861edafa3882c",id:t,class:"detail-panel",role:"tabpanel","aria-labelledby":i},a("button",{key:"3d8ac88c0f8a7a840b5560c4917d74ff910a99c8",class:"mobile-back-button",onClick:this.handleBackClick,"aria-label":"Back to menu"},a("kritzel-icon",{key:"03cf6ca5ea2b9d16ff21b1b38fd0b6148d35ff1f",name:"chevron-left",size:20,class:"mobile-back-icon"}),"Back"),a("slot",{key:"3323357889024c0d2126c30d976c3ece7ddd706a"}))))}static get watchers(){return{selectedItemId:[{watchSelectedItemId:0}]}}static get style(){return":host{display:block;width:100%;height:100%}.master-detail-container{display:flex;width:100%;height:100%;min-height:var(--kritzel-master-detail-min-height, 300px);gap:var(--kritzel-master-detail-gap, 0);background-color:var(--kritzel-master-detail-background-color, transparent)}.master-menu{display:flex;flex-direction:column;width:var(--kritzel-master-detail-menu-width, 200px);min-width:var(--kritzel-master-detail-menu-min-width, 160px);padding:var(--kritzel-master-detail-menu-padding, 8px);background-color:var(--kritzel-master-detail-menu-background-color, #ffffff);border-right:var(--kritzel-master-detail-menu-border-right, 1px solid #ebebeb);gap:var(--kritzel-master-detail-menu-gap, 4px);overflow-y:auto}.menu-item{display:flex;align-items:center;gap:var(--kritzel-master-detail-menu-item-gap, 10px);padding:var(--kritzel-master-detail-menu-item-padding, 10px 12px);border:none;border-radius:var(--kritzel-master-detail-menu-item-border-radius, 6px);background-color:var(--kritzel-master-detail-menu-item-background-color, transparent);color:var(--kritzel-master-detail-menu-item-color, #333333);font-family:inherit;font-size:var(--kritzel-master-detail-menu-item-font-size, 14px);font-weight:var(--kritzel-master-detail-menu-item-font-weight, 400);text-align:left;cursor:var(--kritzel-global-pointer-cursor, pointer);transition:background-color 150ms ease, color 150ms ease;-webkit-tap-highlight-color:transparent}.menu-item:hover:not(.is-disabled){background-color:var(--kritzel-master-detail-menu-item-hover-background-color, #ebebeb)}.menu-item:active:not(.is-disabled){background-color:var(--kritzel-master-detail-menu-item-active-background-color, #e0e0e0)}.menu-item.is-selected{background-color:var(--kritzel-master-detail-menu-item-selected-background-color, #0066cc);color:var(--kritzel-master-detail-menu-item-selected-color, #ffffff);font-weight:var(--kritzel-master-detail-menu-item-selected-font-weight, 500)}.menu-item.is-selected:hover{background-color:var(--kritzel-master-detail-menu-item-selected-hover-background-color, #0052a3)}.menu-item.is-disabled{color:var(--kritzel-master-detail-menu-item-disabled-color, #999999);cursor:not-allowed;opacity:0.6}.menu-item:focus-visible{outline:var(--kritzel-master-detail-menu-item-focus-outline, revert);outline-offset:var(--kritzel-master-detail-menu-item-focus-outline-offset, revert)}.menu-item-icon{flex-shrink:0;display:flex;align-items:center;justify-content:center}.menu-item-label{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.detail-panel{flex:1;min-height:0;padding:var(--kritzel-master-detail-detail-padding, 16px);background-color:var(--kritzel-master-detail-detail-background-color, #ffffff);overflow-y:auto;-webkit-overflow-scrolling:touch;scrollbar-color:var(--kritzel-global-scrollbar-thumb-color, #ebebeb) transparent;scrollbar-width:thin}.detail-panel:focus{outline:none}.detail-panel:focus-visible{outline:var(--kritzel-master-detail-detail-focus-outline, revert);outline-offset:var(--kritzel-master-detail-detail-focus-outline-offset, revert)}.mobile-back-button{display:none;align-items:center;gap:8px;background:none;border:none;padding:0 0 16px 0;cursor:pointer;-webkit-tap-highlight-color:transparent;color:var(--kritzel-master-detail-back-button-color, #333333);font-weight:500;font-size:14px;font-family:inherit}.mobile-back-icon{display:flex;align-items:center;flex-shrink:0}.menu-item-chevron{display:none;flex-shrink:0;margin-left:auto;color:var(--kritzel-master-detail-menu-item-chevron-color, #999999)}.menu-item-chevron svg{width:16px;height:16px;stroke:currentColor}@media (max-width: 768px){.master-menu{width:100%;border-right:none}.detail-panel{display:none;width:100%}.master-detail-container.is-mobile-detail-visible .master-menu{display:none}.master-detail-container.is-mobile-detail-visible .detail-panel{display:block}.mobile-back-button{display:flex}.menu-item.is-selected{background-color:transparent;color:var(--kritzel-master-detail-menu-item-color, #333333);font-weight:var(--kritzel-master-detail-menu-item-font-weight, 400)}.menu-item.is-selected:hover{background-color:var(--kritzel-master-detail-menu-item-hover-background-color, #ebebeb)}.menu-item-chevron{display:flex;align-items:center}}"}},[769,"kritzel-master-detail",{items:[16],selectedItemId:[1,"selected-item-id"],focusedIndex:[32],showMobileDetail:[32]},void 0,{selectedItemId:[{watchSelectedItemId:0}]}]);function n(){"undefined"!=typeof customElements&&["kritzel-master-detail","kritzel-icon"].forEach((e=>{switch(e){case"kritzel-master-detail":customElements.get(l(e))||customElements.define(l(e),s);break;case"kritzel-icon":customElements.get(l(e))||o()}}))}export{s as K,n as d}
1
+ import { p as proxyCustomElement, H, c as createEvent, h, d as Host, t as transformTag } from './p-B43upypT.js';
2
+ import { d as defineCustomElement$1 } from './p-CdR76C4L.js';
3
+
4
+ const kritzelMasterDetailCss = () => `:host{display:block;width:100%;height:100%}.master-detail-container{display:flex;width:100%;height:100%;min-height:var(--kritzel-master-detail-min-height, 300px);gap:var(--kritzel-master-detail-gap, 0);background-color:var(--kritzel-master-detail-background-color, transparent)}.master-menu{display:flex;flex-direction:column;width:var(--kritzel-master-detail-menu-width, 200px);min-width:var(--kritzel-master-detail-menu-min-width, 160px);padding:var(--kritzel-master-detail-menu-padding, 8px);background-color:var(--kritzel-master-detail-menu-background-color, #ffffff);border-right:var(--kritzel-master-detail-menu-border-right, 1px solid #ebebeb);gap:var(--kritzel-master-detail-menu-gap, 4px);overflow-y:auto}.menu-item{display:flex;align-items:center;gap:var(--kritzel-master-detail-menu-item-gap, 10px);padding:var(--kritzel-master-detail-menu-item-padding, 10px 12px);border:none;border-radius:var(--kritzel-master-detail-menu-item-border-radius, 6px);background-color:var(--kritzel-master-detail-menu-item-background-color, transparent);color:var(--kritzel-master-detail-menu-item-color, #333333);font-family:inherit;font-size:var(--kritzel-master-detail-menu-item-font-size, 14px);font-weight:var(--kritzel-master-detail-menu-item-font-weight, 400);text-align:left;cursor:var(--kritzel-global-pointer-cursor, pointer);transition:background-color 150ms ease, color 150ms ease;-webkit-tap-highlight-color:transparent}.menu-item:hover:not(.is-disabled){background-color:var(--kritzel-master-detail-menu-item-hover-background-color, #ebebeb)}.menu-item:active:not(.is-disabled){background-color:var(--kritzel-master-detail-menu-item-active-background-color, #e0e0e0)}.menu-item.is-selected{background-color:var(--kritzel-master-detail-menu-item-selected-background-color, #0066cc);color:var(--kritzel-master-detail-menu-item-selected-color, #ffffff);font-weight:var(--kritzel-master-detail-menu-item-selected-font-weight, 500)}.menu-item.is-selected:hover{background-color:var(--kritzel-master-detail-menu-item-selected-hover-background-color, #0052a3)}.menu-item.is-disabled{color:var(--kritzel-master-detail-menu-item-disabled-color, #999999);cursor:not-allowed;opacity:0.6}.menu-item:focus-visible{outline:var(--kritzel-master-detail-menu-item-focus-outline, revert);outline-offset:var(--kritzel-master-detail-menu-item-focus-outline-offset, revert)}.menu-item-icon{flex-shrink:0;display:flex;align-items:center;justify-content:center}.menu-item-label{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.detail-panel{flex:1;min-height:0;padding:var(--kritzel-master-detail-detail-padding, 16px);background-color:var(--kritzel-master-detail-detail-background-color, #ffffff);overflow-y:auto;-webkit-overflow-scrolling:touch;scrollbar-color:var(--kritzel-global-scrollbar-thumb-color, #ebebeb) transparent;scrollbar-width:thin}.detail-panel:focus{outline:none}.detail-panel:focus-visible{outline:var(--kritzel-master-detail-detail-focus-outline, revert);outline-offset:var(--kritzel-master-detail-detail-focus-outline-offset, revert)}.mobile-back-button{display:none;align-items:center;gap:8px;background:none;border:none;padding:0 0 16px 0;cursor:pointer;-webkit-tap-highlight-color:transparent;color:var(--kritzel-master-detail-back-button-color, #333333);font-weight:500;font-size:14px;font-family:inherit}.mobile-back-icon{display:flex;align-items:center;flex-shrink:0}.menu-item-chevron{display:none;flex-shrink:0;margin-left:auto;color:var(--kritzel-master-detail-menu-item-chevron-color, #999999)}.menu-item-chevron svg{width:16px;height:16px;stroke:currentColor}@media (max-width: 768px){.master-menu{width:100%;border-right:none}.detail-panel{display:none;width:100%}.master-detail-container.is-mobile-detail-visible .master-menu{display:none}.master-detail-container.is-mobile-detail-visible .detail-panel{display:block}.mobile-back-button{display:flex}.menu-item.is-selected{background-color:transparent;color:var(--kritzel-master-detail-menu-item-color, #333333);font-weight:var(--kritzel-master-detail-menu-item-font-weight, 400)}.menu-item.is-selected:hover{background-color:var(--kritzel-master-detail-menu-item-hover-background-color, #ebebeb)}.menu-item-chevron{display:flex;align-items:center}}`;
5
+
6
+ const KritzelMasterDetail = /*@__PURE__*/ proxyCustomElement(class KritzelMasterDetail extends H {
7
+ constructor(registerHost) {
8
+ super();
9
+ if (registerHost !== false) {
10
+ this.__registerHost();
11
+ }
12
+ this.__attachShadow();
13
+ this.itemSelect = createEvent(this, "itemSelect");
14
+ }
15
+ get host() { return this; }
16
+ /** Array of menu items to display in the master (left) panel */
17
+ items = [];
18
+ /** ID of the currently selected item */
19
+ selectedItemId;
20
+ /** Emitted when an item is selected */
21
+ itemSelect;
22
+ focusedIndex = -1;
23
+ showMobileDetail = false;
24
+ tabRefs = [];
25
+ watchSelectedItemId(newValue, oldValue) {
26
+ if (newValue !== oldValue) {
27
+ this.showMobileDetail = true;
28
+ }
29
+ }
30
+ componentWillRender() {
31
+ this.tabRefs = [];
32
+ }
33
+ handleItemClick = (item) => {
34
+ if (item.disabled)
35
+ return;
36
+ this.itemSelect.emit({ item });
37
+ this.showMobileDetail = true;
38
+ };
39
+ handleBackClick = () => {
40
+ this.showMobileDetail = false;
41
+ };
42
+ handleKeyDown = (event, item, index) => {
43
+ const enabledIndices = this.items
44
+ .map((it, idx) => (!it.disabled ? idx : -1))
45
+ .filter(idx => idx !== -1);
46
+ const currentEnabledIndex = enabledIndices.indexOf(index);
47
+ switch (event.key) {
48
+ case 'ArrowDown': {
49
+ event.preventDefault();
50
+ const nextIndex = enabledIndices[(currentEnabledIndex + 1) % enabledIndices.length];
51
+ this.focusTab(nextIndex);
52
+ break;
53
+ }
54
+ case 'ArrowUp': {
55
+ event.preventDefault();
56
+ const prevIndex = enabledIndices[(currentEnabledIndex - 1 + enabledIndices.length) % enabledIndices.length];
57
+ this.focusTab(prevIndex);
58
+ break;
59
+ }
60
+ case 'Home': {
61
+ event.preventDefault();
62
+ this.focusTab(enabledIndices[0]);
63
+ break;
64
+ }
65
+ case 'End': {
66
+ event.preventDefault();
67
+ this.focusTab(enabledIndices[enabledIndices.length - 1]);
68
+ break;
69
+ }
70
+ case 'Enter':
71
+ case ' ': {
72
+ event.preventDefault();
73
+ this.handleItemClick(item);
74
+ break;
75
+ }
76
+ }
77
+ };
78
+ focusTab(index) {
79
+ this.focusedIndex = index;
80
+ const tab = this.tabRefs[index];
81
+ if (tab) {
82
+ tab.focus();
83
+ }
84
+ }
85
+ handleFocus = (index) => {
86
+ this.focusedIndex = index;
87
+ };
88
+ handleBlur = () => {
89
+ this.focusedIndex = -1;
90
+ };
91
+ setTabRef = (el, index) => {
92
+ if (el) {
93
+ this.tabRefs[index] = el;
94
+ }
95
+ };
96
+ getTabIndex(item, _index) {
97
+ if (item.disabled)
98
+ return -1;
99
+ return 0;
100
+ }
101
+ render() {
102
+ const selectedItem = this.items.find(item => item.id === this.selectedItemId);
103
+ const panelId = 'master-detail-panel';
104
+ const selectedTabId = selectedItem ? `tab-${selectedItem.id}` : undefined;
105
+ return (h(Host, { key: 'e363142a5175b1f711cebfc98cfeedf07cd2c6c3' }, h("div", { key: 'eebf863ecdb4a53289cb56e14c02977375781167', class: {
106
+ 'master-detail-container': true,
107
+ 'is-mobile-detail-visible': this.showMobileDetail,
108
+ } }, h("nav", { key: '06660d3cd7de29ba46e3437169f99cb00eef1cc6', class: "master-menu", role: "tablist", "aria-orientation": "vertical", "aria-label": "Settings categories" }, this.items.map((item, index) => (h("button", { key: item.id, id: `tab-${item.id}`, ref: el => this.setTabRef(el, index), class: {
109
+ 'menu-item': true,
110
+ 'is-selected': item.id === this.selectedItemId,
111
+ 'is-disabled': !!item.disabled,
112
+ 'is-focused': index === this.focusedIndex,
113
+ }, role: "tab", "aria-selected": item.id === this.selectedItemId ? 'true' : 'false', "aria-controls": panelId, "aria-disabled": item.disabled ? 'true' : undefined, tabIndex: this.getTabIndex(item, index), disabled: item.disabled, onClick: () => this.handleItemClick(item), onKeyDown: e => this.handleKeyDown(e, item, index), onFocus: () => this.handleFocus(index), onBlur: this.handleBlur }, item.icon && (h("kritzel-icon", { name: item.icon, size: 20, class: "menu-item-icon" })), h("span", { class: "menu-item-label" }, item.label), h("span", { class: "menu-item-chevron", "aria-hidden": "true" }, h("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "1.5", "stroke-linecap": "round", "stroke-linejoin": "round" }, h("path", { d: "m9 18 6-6-6-6" }))))))), h("div", { key: '0d6b6722ecbf64b28d27754161f861edafa3882c', id: panelId, class: "detail-panel", role: "tabpanel", "aria-labelledby": selectedTabId }, h("button", { key: '3d8ac88c0f8a7a840b5560c4917d74ff910a99c8', class: "mobile-back-button", onClick: this.handleBackClick, "aria-label": "Back to menu" }, h("kritzel-icon", { key: '03cf6ca5ea2b9d16ff21b1b38fd0b6148d35ff1f', name: "chevron-left", size: 20, class: "mobile-back-icon" }), "Back"), h("slot", { key: '3323357889024c0d2126c30d976c3ece7ddd706a' })))));
114
+ }
115
+ static get watchers() { return {
116
+ "selectedItemId": [{
117
+ "watchSelectedItemId": 0
118
+ }]
119
+ }; }
120
+ static get style() { return kritzelMasterDetailCss(); }
121
+ }, [769, "kritzel-master-detail", {
122
+ "items": [16],
123
+ "selectedItemId": [1, "selected-item-id"],
124
+ "focusedIndex": [32],
125
+ "showMobileDetail": [32]
126
+ }, undefined, {
127
+ "selectedItemId": [{
128
+ "watchSelectedItemId": 0
129
+ }]
130
+ }]);
131
+ function defineCustomElement() {
132
+ if (typeof customElements === "undefined") {
133
+ return;
134
+ }
135
+ const components = ["kritzel-master-detail", "kritzel-icon"];
136
+ components.forEach(tagName => { switch (tagName) {
137
+ case "kritzel-master-detail":
138
+ if (!customElements.get(transformTag(tagName))) {
139
+ customElements.define(transformTag(tagName), KritzelMasterDetail);
140
+ }
141
+ break;
142
+ case "kritzel-icon":
143
+ if (!customElements.get(transformTag(tagName))) {
144
+ defineCustomElement$1();
145
+ }
146
+ break;
147
+ } });
148
+ }
149
+
150
+ export { KritzelMasterDetail as K, defineCustomElement as d };
@@ -1 +1,290 @@
1
- import{p as e,H as t,c as i,h as n,d as s,t as o}from"./p-B43upypT.js";import{d as r}from"./p-CdR76C4L.js";const a=e(class extends t{constructor(e){super(),!1!==e&&this.__registerHost(),this.__attachShadow(),this.actionSelected=i(this,"actionSelected"),this.close=i(this,"close")}get host(){return this}items;onItemsChanged(){this.updateMenuItems()}objects;actionSelected;close;processedItems=[];openSubmenuPath="";submenuPositions={};submenuTimer=null;submenuRefs=new Map;menuItemWrapperRefs=new Map;handleOutsideClick(e){e.composedPath().includes(this.host)||this.close.emit()}componentWillLoad(){this.updateMenuItems()}componentDidLoad(){this.adjustPositionToViewport()}componentDidUpdate(){this.adjustPositionToViewport(),this.adjustSubmenuPositions(),this.pruneStaleRefs()}disconnectedCallback(){this.submenuTimer&&clearTimeout(this.submenuTimer)}adjustPositionToViewport(){const e=this.host.getBoundingClientRect(),t=window.innerWidth,i=window.innerHeight,n=parseFloat(this.host.style.left)||0,s=parseFloat(this.host.style.top)||0;let o=n,r=s;e.right>t-8&&(o=t-e.width-8),e.bottom>i-8&&(r=i-e.height-8),o<8&&(o=8),r<8&&(r=8),o===n&&r===s||(this.host.style.left=`${o}px`,this.host.style.top=`${r}px`)}adjustSubmenuPositions(){if(!this.openSubmenuPath)return;const e=window.innerHeight;for(const t of this.getOpenSubmenuPaths()){const i=this.submenuRefs.get(t),n=this.menuItemWrapperRefs.get(t);if(!i||!n)continue;const s=n.getBoundingClientRect(),o=s.top+i.offsetHeight;if(o>e-8){let t=o-(e-8);s.top-t<8&&(t=s.top-8),i.style.top=-t+"px"}else i.style.top="0px"}}getOpenSubmenuPaths(){if(!this.openSubmenuPath)return[];const e=this.openSubmenuPath.split("."),t=[];for(let i=1;i<=e.length;i++)t.push(e.slice(0,i).join("."));return t}isSubmenuOpen(e){return this.openSubmenuPath===e||this.openSubmenuPath.startsWith(e+".")}getParentPath(e){const t=e.lastIndexOf(".");return-1===t?"":e.substring(0,t)}getMenuDepth(e){return e?e.split(".").length:0}pruneStaleRefs(){const e=new Set(this.getOpenSubmenuPaths());for(const t of Array.from(this.submenuRefs.keys()))e.has(t)||this.submenuRefs.delete(t);for(const t of Array.from(this.menuItemWrapperRefs.keys())){const i=this.getParentPath(t);""===i||e.has(i)||this.menuItemWrapperRefs.delete(t)}}handleItemClick(e,t,i){t||i||e.action&&this.actionSelected.emit(e)}handleItemMouseEnter(e,t){this.submenuTimer&&(clearTimeout(this.submenuTimer),this.submenuTimer=null);const i=this.getParentPath(e);this.submenuTimer=t?setTimeout((()=>{const t=this.menuItemWrapperRefs.get(e);let i="right";if(t){const e=t.getBoundingClientRect(),n=window.innerWidth;i=e.right+160>n-8?"left":"right"}this.submenuPositions={...this.submenuPositions,[e]:i},this.openSubmenuPath=e}),150):setTimeout((()=>{this.openSubmenuPath=i}),150)}handleSubmenuMouseEnter(){this.submenuTimer&&(clearTimeout(this.submenuTimer),this.submenuTimer=null)}handleSubmenuMouseLeave(e){const t=this.getParentPath(e);this.submenuTimer=setTimeout((()=>{this.openSubmenuPath=t}),150)}async updateMenuItems(){this.processedItems=await this.processItems(this.items)}async processItems(e){const t=[];for(const i of e)if(await this.evaluateProperty(i.visible,!0)){const e=await this.evaluateProperty(i.disabled,!1);let n;i.children&&i.children.length>0&&(n=await this.processItems(i.children)),t.push({item:i,isDisabled:e,processedChildren:n})}return t}async evaluateProperty(e,t){return"boolean"==typeof e?e:"function"==typeof e?await Promise.resolve(e(null,this.objects)):t}renderItems(e,t){return e.map((({item:i,isDisabled:s,processedChildren:o},r)=>{const a=""===t?String(r):`${t}.${r}`,l=r>0?e[r-1].item:null,u=l&&l.group!==i.group,c=!!o&&o.length>0,d=c&&this.isSubmenuOpen(a);return[u&&n("div",{class:"menu-divider",key:`divider-${a}`}),n("div",{class:"menu-item-wrapper",key:`wrapper-${a}`,ref:e=>e&&this.menuItemWrapperRefs.set(a,e),onMouseEnter:()=>this.handleItemMouseEnter(a,c)},n("button",{key:`${i.label}-${a}`,class:{"menu-item":!0,disabled:s,"has-children":c,"submenu-open":d},onClick:()=>this.handleItemClick(i,s,c),disabled:s&&!c},i.icon&&n("kritzel-icon",{name:i.icon,size:16}),n("span",{class:"label"},i.label),c&&n("kritzel-icon",{name:"chevron-right",size:12,class:"submenu-arrow"})),c&&d&&this.renderSubmenu(o,a))]}))}renderSubmenu(e,t){const i="left"===this.submenuPositions[t]?"left":"right",s=this.getMenuDepth(t)+1;return n("div",{class:{"submenu-container":!0,"position-left":"left"===i},key:`submenu-${t}`,style:{zIndex:String(s)},ref:e=>e&&this.submenuRefs.set(t,e),onMouseEnter:()=>this.handleSubmenuMouseEnter(),onMouseLeave:()=>this.handleSubmenuMouseLeave(t)},this.renderItems(e,t))}render(){return this.processedItems&&0!==this.processedItems.length?n(s,null,n("div",{class:"menu-container"},this.renderItems(this.processedItems,""))):null}static get watchers(){return{items:[{onItemsChanged:0}]}}static get style(){return":host{display:block}.menu-container{position:relative;z-index:1;display:flex;flex-direction:column;gap:var(--kritzel-context-menu-item-spacing, 2px);background-color:var(--kritzel-context-menu-background-color, #ffffff);border-radius:var(--kritzel-context-menu-border-radius, 12px);box-shadow:var(--kritzel-context-menu-box-shadow, 0 1px 6px rgba(0, 0, 0, 0.12));border:var(--kritzel-context-menu-border, 1px solid #ebebeb);padding:var(--kritzel-context-menu-padding, 4px);min-width:var(--kritzel-context-menu-min-width, 140px)}.menu-item-wrapper{position:relative}.menu-item{display:flex;align-items:center;gap:var(--kritzel-context-menu-item-gap, 8px);background:none;border:none;text-align:left;padding:var(--kritzel-context-menu-item-padding, 8px);border-radius:var(--kritzel-context-menu-item-border-radius, 12px);cursor:var(--kritzel-global-pointer-cursor, pointer);font-size:var(--kritzel-context-menu-item-font-size, 14px);color:var(--kritzel-context-menu-item-color, #333333);white-space:nowrap;-webkit-tap-highlight-color:transparent;width:100%;min-width:0}.menu-item:not(.disabled):hover,.menu-item.submenu-open{background-color:var(--kritzel-context-menu-item-hover-background-color, hsl(0, 0%, 0%, 4.3%))}.menu-item:not(.disabled):active{background-color:var(--kritzel-context-menu-item-active-background-color, hsl(0, 0%, 0%, 8.6%))}.menu-item.disabled{color:var(--kritzel-context-menu-item-disabled-color, #aaaaaa)}.menu-item.has-children.disabled{cursor:var(--kritzel-global-pointer-cursor, pointer);color:var(--kritzel-context-menu-item-color, #333333)}.menu-item kritzel-icon{opacity:0.8;flex-shrink:0}.menu-item.disabled kritzel-icon{opacity:0.4}.menu-item.has-children.disabled kritzel-icon{opacity:0.8}.label{flex-grow:1;min-width:0;overflow:hidden;text-overflow:ellipsis}.submenu-arrow{margin-left:auto;opacity:0.5}.menu-divider{height:1px;background-color:var(--kritzel-context-menu-divider-color, rgba(0, 0, 0, 0.1));margin:var(--kritzel-context-menu-divider-margin, 4px 8px)}.submenu-container{position:absolute;top:0;left:100%;z-index:2;margin-left:4px;display:flex;flex-direction:column;gap:var(--kritzel-context-menu-item-spacing, 2px);background-color:var(--kritzel-context-menu-background-color, #ffffff);border-radius:var(--kritzel-context-menu-border-radius, 12px);box-shadow:var(--kritzel-context-menu-box-shadow, 0 1px 6px rgba(0, 0, 0, 0.12));border:var(--kritzel-context-menu-border, 1px solid #ebebeb);padding:var(--kritzel-context-menu-padding, 4px);min-width:120px}.submenu-container.position-left{left:auto;right:100%;margin-left:0;margin-right:4px}"}},[513,"kritzel-context-menu",{items:[16],objects:[16],processedItems:[32],openSubmenuPath:[32],submenuPositions:[32]},[[9,"pointerdown","handleOutsideClick"]],{items:[{onItemsChanged:0}]}]);function l(){"undefined"!=typeof customElements&&["kritzel-context-menu","kritzel-icon"].forEach((e=>{switch(e){case"kritzel-context-menu":customElements.get(o(e))||customElements.define(o(e),a);break;case"kritzel-icon":customElements.get(o(e))||r()}}))}export{a as K,l as d}
1
+ import { p as proxyCustomElement, H, c as createEvent, h, d as Host, t as transformTag } from './p-B43upypT.js';
2
+ import { d as defineCustomElement$1 } from './p-CdR76C4L.js';
3
+
4
+ const kritzelContextMenuCss = () => `:host{display:block}.menu-container{position:relative;z-index:1;display:flex;flex-direction:column;gap:var(--kritzel-context-menu-item-spacing, 2px);background-color:var(--kritzel-context-menu-background-color, #ffffff);border-radius:var(--kritzel-context-menu-border-radius, 12px);box-shadow:var(--kritzel-context-menu-box-shadow, 0 1px 6px rgba(0, 0, 0, 0.12));border:var(--kritzel-context-menu-border, 1px solid #ebebeb);padding:var(--kritzel-context-menu-padding, 4px);min-width:var(--kritzel-context-menu-min-width, 140px)}.menu-item-wrapper{position:relative}.menu-item{display:flex;align-items:center;gap:var(--kritzel-context-menu-item-gap, 8px);background:none;border:none;text-align:left;padding:var(--kritzel-context-menu-item-padding, 8px);border-radius:var(--kritzel-context-menu-item-border-radius, 12px);cursor:var(--kritzel-global-pointer-cursor, pointer);font-size:var(--kritzel-context-menu-item-font-size, 14px);color:var(--kritzel-context-menu-item-color, #333333);white-space:nowrap;-webkit-tap-highlight-color:transparent;width:100%;min-width:0}.menu-item:not(.disabled):hover,.menu-item.submenu-open{background-color:var(--kritzel-context-menu-item-hover-background-color, hsl(0, 0%, 0%, 4.3%))}.menu-item:not(.disabled):active{background-color:var(--kritzel-context-menu-item-active-background-color, hsl(0, 0%, 0%, 8.6%))}.menu-item.disabled{color:var(--kritzel-context-menu-item-disabled-color, #aaaaaa)}.menu-item.has-children.disabled{cursor:var(--kritzel-global-pointer-cursor, pointer);color:var(--kritzel-context-menu-item-color, #333333)}.menu-item kritzel-icon{opacity:0.8;flex-shrink:0}.menu-item.disabled kritzel-icon{opacity:0.4}.menu-item.has-children.disabled kritzel-icon{opacity:0.8}.label{flex-grow:1;min-width:0;overflow:hidden;text-overflow:ellipsis}.submenu-arrow{margin-left:auto;opacity:0.5}.menu-divider{height:1px;background-color:var(--kritzel-context-menu-divider-color, rgba(0, 0, 0, 0.1));margin:var(--kritzel-context-menu-divider-margin, 4px 8px)}.submenu-container{position:absolute;top:0;left:100%;z-index:2;margin-left:4px;display:flex;flex-direction:column;gap:var(--kritzel-context-menu-item-spacing, 2px);background-color:var(--kritzel-context-menu-background-color, #ffffff);border-radius:var(--kritzel-context-menu-border-radius, 12px);box-shadow:var(--kritzel-context-menu-box-shadow, 0 1px 6px rgba(0, 0, 0, 0.12));border:var(--kritzel-context-menu-border, 1px solid #ebebeb);padding:var(--kritzel-context-menu-padding, 4px);min-width:120px}.submenu-container.position-left{left:auto;right:100%;margin-left:0;margin-right:4px}`;
5
+
6
+ const VIEWPORT_PADDING = 8;
7
+ const SUBMENU_DELAY = 150;
8
+ const ESTIMATED_SUBMENU_WIDTH = 160; // Estimated width for pre-calculation
9
+ const KritzelContextMenu = /*@__PURE__*/ proxyCustomElement(class KritzelContextMenu extends H {
10
+ constructor(registerHost) {
11
+ super();
12
+ if (registerHost !== false) {
13
+ this.__registerHost();
14
+ }
15
+ this.__attachShadow();
16
+ this.actionSelected = createEvent(this, "actionSelected");
17
+ this.close = createEvent(this, "close");
18
+ }
19
+ get host() { return this; }
20
+ items;
21
+ onItemsChanged() {
22
+ this.updateMenuItems();
23
+ }
24
+ objects;
25
+ actionSelected;
26
+ close;
27
+ processedItems = [];
28
+ /** Current open submenu path (e.g. '0.2.1'). Empty if none. */
29
+ openSubmenuPath = '';
30
+ submenuPositions = {};
31
+ submenuTimer = null;
32
+ submenuRefs = new Map();
33
+ menuItemWrapperRefs = new Map();
34
+ handleOutsideClick(event) {
35
+ const path = event.composedPath();
36
+ if (!path.includes(this.host)) {
37
+ this.close.emit();
38
+ }
39
+ }
40
+ componentWillLoad() {
41
+ this.updateMenuItems();
42
+ }
43
+ componentDidLoad() {
44
+ this.adjustPositionToViewport();
45
+ }
46
+ componentDidUpdate() {
47
+ this.adjustPositionToViewport();
48
+ this.adjustSubmenuPositions();
49
+ this.pruneStaleRefs();
50
+ }
51
+ disconnectedCallback() {
52
+ if (this.submenuTimer) {
53
+ clearTimeout(this.submenuTimer);
54
+ }
55
+ }
56
+ adjustPositionToViewport() {
57
+ const rect = this.host.getBoundingClientRect();
58
+ const viewportWidth = window.innerWidth;
59
+ const viewportHeight = window.innerHeight;
60
+ const currentLeft = parseFloat(this.host.style.left) || 0;
61
+ const currentTop = parseFloat(this.host.style.top) || 0;
62
+ let newLeft = currentLeft;
63
+ let newTop = currentTop;
64
+ // Check if menu extends beyond right edge
65
+ if (rect.right > viewportWidth - VIEWPORT_PADDING) {
66
+ newLeft = viewportWidth - rect.width - VIEWPORT_PADDING;
67
+ }
68
+ // Check if menu extends beyond bottom edge
69
+ if (rect.bottom > viewportHeight - VIEWPORT_PADDING) {
70
+ newTop = viewportHeight - rect.height - VIEWPORT_PADDING;
71
+ }
72
+ // Ensure menu doesn't go beyond left edge
73
+ if (newLeft < VIEWPORT_PADDING) {
74
+ newLeft = VIEWPORT_PADDING;
75
+ }
76
+ // Ensure menu doesn't go beyond top edge
77
+ if (newTop < VIEWPORT_PADDING) {
78
+ newTop = VIEWPORT_PADDING;
79
+ }
80
+ // Only update if position changed to avoid infinite loops
81
+ if (newLeft !== currentLeft || newTop !== currentTop) {
82
+ this.host.style.left = `${newLeft}px`;
83
+ this.host.style.top = `${newTop}px`;
84
+ }
85
+ }
86
+ adjustSubmenuPositions() {
87
+ if (!this.openSubmenuPath)
88
+ return;
89
+ const viewportHeight = window.innerHeight;
90
+ // Adjust every open submenu in the chain (every prefix of openSubmenuPath).
91
+ for (const path of this.getOpenSubmenuPaths()) {
92
+ const submenuEl = this.submenuRefs.get(path);
93
+ const wrapperEl = this.menuItemWrapperRefs.get(path);
94
+ if (!submenuEl || !wrapperEl)
95
+ continue;
96
+ const wrapperRect = wrapperEl.getBoundingClientRect();
97
+ const submenuHeight = submenuEl.offsetHeight; // Constant regardless of current top shift
98
+ const naturalBottom = wrapperRect.top + submenuHeight;
99
+ if (naturalBottom > viewportHeight - VIEWPORT_PADDING) {
100
+ let overflow = naturalBottom - (viewportHeight - VIEWPORT_PADDING);
101
+ // Don't shift up so far that the top goes above the viewport
102
+ if (wrapperRect.top - overflow < VIEWPORT_PADDING) {
103
+ overflow = wrapperRect.top - VIEWPORT_PADDING;
104
+ }
105
+ submenuEl.style.top = `${-overflow}px`;
106
+ }
107
+ else {
108
+ submenuEl.style.top = '0px';
109
+ }
110
+ }
111
+ }
112
+ getOpenSubmenuPaths() {
113
+ if (!this.openSubmenuPath)
114
+ return [];
115
+ const parts = this.openSubmenuPath.split('.');
116
+ const paths = [];
117
+ for (let i = 1; i <= parts.length; i++) {
118
+ paths.push(parts.slice(0, i).join('.'));
119
+ }
120
+ return paths;
121
+ }
122
+ isSubmenuOpen(path) {
123
+ return this.openSubmenuPath === path || this.openSubmenuPath.startsWith(path + '.');
124
+ }
125
+ getParentPath(path) {
126
+ const idx = path.lastIndexOf('.');
127
+ return idx === -1 ? '' : path.substring(0, idx);
128
+ }
129
+ getMenuDepth(path) {
130
+ if (!path)
131
+ return 0;
132
+ return path.split('.').length;
133
+ }
134
+ pruneStaleRefs() {
135
+ const openPaths = new Set(this.getOpenSubmenuPaths());
136
+ for (const key of Array.from(this.submenuRefs.keys())) {
137
+ if (!openPaths.has(key)) {
138
+ this.submenuRefs.delete(key);
139
+ }
140
+ }
141
+ // Keep root-level wrapper refs (single-segment paths) always rendered; prune deeper
142
+ // wrappers whose parent submenu is no longer open.
143
+ for (const key of Array.from(this.menuItemWrapperRefs.keys())) {
144
+ const parent = this.getParentPath(key);
145
+ if (parent !== '' && !openPaths.has(parent)) {
146
+ this.menuItemWrapperRefs.delete(key);
147
+ }
148
+ }
149
+ }
150
+ handleItemClick(item, isDisabled, hasChildren) {
151
+ if (isDisabled)
152
+ return;
153
+ if (hasChildren) {
154
+ // Hover handles open/close; click on a parent is a no-op.
155
+ return;
156
+ }
157
+ if (item.action) {
158
+ this.actionSelected.emit(item);
159
+ }
160
+ }
161
+ handleItemMouseEnter(path, hasChildren) {
162
+ if (this.submenuTimer) {
163
+ clearTimeout(this.submenuTimer);
164
+ this.submenuTimer = null;
165
+ }
166
+ const parentPath = this.getParentPath(path);
167
+ if (hasChildren) {
168
+ this.submenuTimer = setTimeout(() => {
169
+ // Pre-calculate horizontal position before opening to avoid flicker.
170
+ const wrapperEl = this.menuItemWrapperRefs.get(path);
171
+ let position = 'right';
172
+ if (wrapperEl) {
173
+ const rect = wrapperEl.getBoundingClientRect();
174
+ const viewportWidth = window.innerWidth;
175
+ const wouldOverflowRight = rect.right + ESTIMATED_SUBMENU_WIDTH > viewportWidth - VIEWPORT_PADDING;
176
+ position = wouldOverflowRight ? 'left' : 'right';
177
+ }
178
+ this.submenuPositions = { ...this.submenuPositions, [path]: position };
179
+ this.openSubmenuPath = path;
180
+ }, SUBMENU_DELAY);
181
+ }
182
+ else {
183
+ // Hovering a sibling without children: collapse to the parent chain so any
184
+ // sibling-rooted submenu closes, but the ancestor chain stays open.
185
+ this.submenuTimer = setTimeout(() => {
186
+ this.openSubmenuPath = parentPath;
187
+ }, SUBMENU_DELAY);
188
+ }
189
+ }
190
+ handleSubmenuMouseEnter() {
191
+ if (this.submenuTimer) {
192
+ clearTimeout(this.submenuTimer);
193
+ this.submenuTimer = null;
194
+ }
195
+ }
196
+ handleSubmenuMouseLeave(path) {
197
+ // Close this submenu (and any deeper levels) but keep the ancestor chain open.
198
+ const parentPath = this.getParentPath(path);
199
+ this.submenuTimer = setTimeout(() => {
200
+ this.openSubmenuPath = parentPath;
201
+ }, SUBMENU_DELAY);
202
+ }
203
+ async updateMenuItems() {
204
+ this.processedItems = await this.processItems(this.items);
205
+ }
206
+ async processItems(items) {
207
+ const processed = [];
208
+ for (const item of items) {
209
+ const isVisible = await this.evaluateProperty(item.visible, true);
210
+ if (isVisible) {
211
+ const isDisabled = await this.evaluateProperty(item.disabled, false);
212
+ let processedChildren;
213
+ if (item.children && item.children.length > 0) {
214
+ processedChildren = await this.processItems(item.children);
215
+ }
216
+ processed.push({ item, isDisabled, processedChildren });
217
+ }
218
+ }
219
+ return processed;
220
+ }
221
+ async evaluateProperty(value, defaultValue) {
222
+ if (typeof value === 'boolean') {
223
+ return value;
224
+ }
225
+ if (typeof value === 'function') {
226
+ return await Promise.resolve(value(null, this.objects));
227
+ }
228
+ return defaultValue;
229
+ }
230
+ renderItems(items, parentPath) {
231
+ return items.map(({ item, isDisabled, processedChildren }, index) => {
232
+ const path = parentPath === '' ? String(index) : `${parentPath}.${index}`;
233
+ const prevItem = index > 0 ? items[index - 1].item : null;
234
+ const showDivider = prevItem && prevItem.group !== item.group;
235
+ const hasChildren = !!processedChildren && processedChildren.length > 0;
236
+ const submenuOpen = hasChildren && this.isSubmenuOpen(path);
237
+ return [
238
+ showDivider && h("div", { class: "menu-divider", key: `divider-${path}` }),
239
+ h("div", { class: "menu-item-wrapper", key: `wrapper-${path}`, ref: el => el && this.menuItemWrapperRefs.set(path, el), onMouseEnter: () => this.handleItemMouseEnter(path, hasChildren) }, h("button", { key: `${item.label}-${path}`, class: { 'menu-item': true, 'disabled': isDisabled, 'has-children': hasChildren, 'submenu-open': submenuOpen }, onClick: () => this.handleItemClick(item, isDisabled, hasChildren), disabled: isDisabled && !hasChildren }, item.icon && h("kritzel-icon", { name: item.icon, size: 16 }), h("span", { class: "label" }, item.label), hasChildren && h("kritzel-icon", { name: "chevron-right", size: 12, class: "submenu-arrow" })), hasChildren && submenuOpen && this.renderSubmenu(processedChildren, path)),
240
+ ];
241
+ });
242
+ }
243
+ renderSubmenu(processedChildren, path) {
244
+ const position = this.submenuPositions[path] === 'left' ? 'left' : 'right';
245
+ const zIndex = this.getMenuDepth(path) + 1;
246
+ return (h("div", { class: { 'submenu-container': true, 'position-left': position === 'left' }, key: `submenu-${path}`, style: { zIndex: String(zIndex) }, ref: el => el && this.submenuRefs.set(path, el), onMouseEnter: () => this.handleSubmenuMouseEnter(), onMouseLeave: () => this.handleSubmenuMouseLeave(path) }, this.renderItems(processedChildren, path)));
247
+ }
248
+ render() {
249
+ if (!this.processedItems || this.processedItems.length === 0) {
250
+ return null;
251
+ }
252
+ return (h(Host, null, h("div", { class: "menu-container" }, this.renderItems(this.processedItems, ''))));
253
+ }
254
+ static get watchers() { return {
255
+ "items": [{
256
+ "onItemsChanged": 0
257
+ }]
258
+ }; }
259
+ static get style() { return kritzelContextMenuCss(); }
260
+ }, [513, "kritzel-context-menu", {
261
+ "items": [16],
262
+ "objects": [16],
263
+ "processedItems": [32],
264
+ "openSubmenuPath": [32],
265
+ "submenuPositions": [32]
266
+ }, [[9, "pointerdown", "handleOutsideClick"]], {
267
+ "items": [{
268
+ "onItemsChanged": 0
269
+ }]
270
+ }]);
271
+ function defineCustomElement() {
272
+ if (typeof customElements === "undefined") {
273
+ return;
274
+ }
275
+ const components = ["kritzel-context-menu", "kritzel-icon"];
276
+ components.forEach(tagName => { switch (tagName) {
277
+ case "kritzel-context-menu":
278
+ if (!customElements.get(transformTag(tagName))) {
279
+ customElements.define(transformTag(tagName), KritzelContextMenu);
280
+ }
281
+ break;
282
+ case "kritzel-icon":
283
+ if (!customElements.get(transformTag(tagName))) {
284
+ defineCustomElement$1();
285
+ }
286
+ break;
287
+ } });
288
+ }
289
+
290
+ export { KritzelContextMenu as K, defineCustomElement as d };