cyclecad 3.10.1 → 3.10.2

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/app/index.html CHANGED
@@ -130,6 +130,9 @@
130
130
  .menu-item:hover .menu-dropdown {
131
131
  display: flex;
132
132
  }
133
+ .menu-item.open .menu-dropdown { display: flex !important; }
134
+ .menu-dropdown { padding-top: 2px; margin-top: -2px; }
135
+ .menu-item.open { background: var(--bg-tertiary); }
133
136
 
134
137
  .menu-item-link {
135
138
  padding: 8px 16px;
@@ -1534,7 +1537,8 @@ window._dismissSplash = function(action) {
1534
1537
  <script type="module" src="/app/js/marketplace.js"></script>
1535
1538
 
1536
1539
  <!-- Killer Feature Modules -->
1537
- <script src="/app/js/modules/ai-copilot.js"></script>
1540
+ <script src="/app/js/agent-api.js?v=a41b98a5"></script>
1541
+ <script src="/app/js/modules/ai-copilot.js?v=407987b9"></script>
1538
1542
  <script src="/app/js/modules/text-to-cad.js"></script>
1539
1543
  <script src="/app/js/modules/photo-to-cad.js"></script>
1540
1544
  <script src="/app/js/modules/manufacturability.js"></script>
@@ -2871,5 +2875,75 @@ window._dismissSplash = function(action) {
2871
2875
  initializeUI();
2872
2876
  </script>
2873
2877
 
2878
+ <script>
2879
+ (function(){
2880
+ function initMenuPin(){
2881
+ const items = document.querySelectorAll('.menu-item');
2882
+ if (!items.length) { setTimeout(initMenuPin, 300); return; }
2883
+ items.forEach(item => {
2884
+ const drop = item.querySelector('.menu-dropdown');
2885
+ if (!drop) return;
2886
+ // Click on menu-item itself (NOT children) toggles open
2887
+ item.addEventListener('click', (e) => {
2888
+ if (e.target.closest('.menu-dropdown')) return; // clicks inside dropdown bubble to their own handler
2889
+ e.stopPropagation();
2890
+ const wasOpen = item.classList.contains('open');
2891
+ document.querySelectorAll('.menu-item.open').forEach(x => x.classList.remove('open'));
2892
+ if (!wasOpen) item.classList.add('open');
2893
+ });
2894
+ // Clicks on menu-item-link close the menu after action
2895
+ drop.addEventListener('click', (e) => {
2896
+ if (e.target.classList.contains('menu-item-link')) {
2897
+ setTimeout(() => item.classList.remove('open'), 50);
2898
+ }
2899
+ });
2900
+ });
2901
+ // Click outside closes any open menu
2902
+ document.addEventListener('click', (e) => {
2903
+ if (!e.target.closest('.menu-item')) {
2904
+ document.querySelectorAll('.menu-item.open').forEach(x => x.classList.remove('open'));
2905
+ }
2906
+ });
2907
+ console.log('[menu-pin] wired', items.length, 'menu items');
2908
+ }
2909
+ if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', initMenuPin);
2910
+ else initMenuPin();
2911
+ })();
2912
+ </script>
2913
+ <script>
2914
+ (function(){
2915
+ function initDialogDrag(){
2916
+ const dlg = document.getElementById('dialog-overlay');
2917
+ const title = document.getElementById('dialog-title');
2918
+ if (!dlg || !title) { setTimeout(initDialogDrag, 300); return; }
2919
+ let dragging = false, ox = 0, oy = 0, sx = 0, sy = 0;
2920
+ const inner = dlg.querySelector('.dialog-container, .dialog-content, [class*="dialog-"]:not([id])') || dlg.firstElementChild;
2921
+ if (!inner) return;
2922
+ inner.setAttribute('data-dialog-drag', 'wired');
2923
+ title.style.cursor = 'move';
2924
+ title.style.userSelect = 'none';
2925
+ title.addEventListener('pointerdown', (e) => {
2926
+ dragging = true; sx = e.clientX; sy = e.clientY;
2927
+ const rect = inner.getBoundingClientRect();
2928
+ ox = rect.left; oy = rect.top;
2929
+ inner.style.position = 'fixed';
2930
+ inner.style.margin = '0';
2931
+ inner.style.left = ox + 'px';
2932
+ inner.style.top = oy + 'px';
2933
+ inner.style.transform = 'none';
2934
+ title.setPointerCapture(e.pointerId);
2935
+ });
2936
+ title.addEventListener('pointermove', (e) => {
2937
+ if (!dragging) return;
2938
+ inner.style.left = (ox + e.clientX - sx) + 'px';
2939
+ inner.style.top = (oy + e.clientY - sy) + 'px';
2940
+ });
2941
+ title.addEventListener('pointerup', (e) => { dragging = false; try { title.releasePointerCapture(e.pointerId); } catch(_){} });
2942
+ console.log('[dialog-drag] wired');
2943
+ }
2944
+ if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', initDialogDrag);
2945
+ else initDialogDrag();
2946
+ })();
2947
+ </script>
2874
2948
  </body>
2875
2949
  </html>
@@ -57,11 +57,11 @@ export const KillerFeatures = {
57
57
  registerKeyboardShortcuts() {
58
58
  document.addEventListener('keydown', (e) => {
59
59
  if (e.ctrlKey || e.metaKey) {
60
- if (e.key === 'k') { e.preventDefault(); this.features.aiCopilot?.show(); }
61
- if (e.key === 'p') { e.preventDefault(); this.features.physics?.toggle(); }
62
- if (e.key === 'g') { e.preventDefault(); this.features.generative?.show(); }
63
- if (e.key === 'c') { e.preventDefault(); this.features.costEstimator?.show(); }
64
- if (e.key === 't') { e.preventDefault(); this.features.parameterTable?.show(); }
60
+ if (e.key === 'k' && e.shiftKey) { e.preventDefault(); this.features.aiCopilot?.show(); }
61
+ if (e.key === 'p' && e.shiftKey) { e.preventDefault(); this.features.physics?.toggle(); }
62
+ if (e.key === 'g' && e.shiftKey) { e.preventDefault(); this.features.generative?.show(); }
63
+ if (e.key === 'c' && e.shiftKey) { e.preventDefault(); this.features.costEstimator?.toggle(); }
64
+ if (e.key === 't' && e.shiftKey) { e.preventDefault(); this.features.parameterTable?.show(); }
65
65
  }
66
66
  });
67
67
  },
@@ -609,6 +609,17 @@ export const KillerFeatures = {
609
609
  const estimator = {
610
610
  show() {
611
611
  this.createPanel();
612
+ const p = document.getElementById('kf-cost-panel');
613
+ if (p) p.style.display = 'block';
614
+ },
615
+ hide() {
616
+ const p = document.getElementById('kf-cost-panel');
617
+ if (p) p.style.display = 'none';
618
+ },
619
+ toggle() {
620
+ const p = document.getElementById('kf-cost-panel');
621
+ if (p && p.style.display !== 'none') this.hide();
622
+ else this.show();
612
623
  },
613
624
 
614
625
  createPanel() {
@@ -624,7 +635,7 @@ export const KillerFeatures = {
624
635
  `;
625
636
 
626
637
  panel.innerHTML = `
627
- <h3 style="margin: 0 0 16px 0; font-size: 16px;">Manufacturing Cost</h3>
638
+ <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:16px"><h3 style="margin: 0; font-size: 16px;">Manufacturing Cost</h3><button id="kf-cost-close" style="background:rgba(0,0,0,0.2);border:0;color:#fff;width:28px;height:28px;border-radius:50%;cursor:pointer;font-size:18px;line-height:1">x</button></div>
628
639
 
629
640
  <div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 12px;">
630
641
  <div style="background: rgba(0,0,0,0.15); padding: 12px; border-radius: 8px; text-align: center;">
@@ -658,6 +669,7 @@ export const KillerFeatures = {
658
669
  `;
659
670
 
660
671
  document.body.appendChild(panel);
672
+ document.getElementById('kf-cost-close')?.addEventListener('click', () => estimator.hide());
661
673
  this.updateCosts();
662
674
 
663
675
  // Listen to scene changes