pptx-vanilla-viewer 0.6.0 → 0.8.0

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.
@@ -0,0 +1 @@
1
+ 'use strict';var three=require('three'),OrbitControls_js=require('three/examples/jsm/controls/OrbitControls.js');var M=4,P=.86;function Q(o,i,e){let t=i.split(/\s+/u).filter(Boolean);if(t.length===0)return [];let a=[],s=t[0];for(let r=1;r<t.length;r++){let c=`${s} ${t[r]}`;o.measureText(c).width<=e?s=c:(a.push(s),s=t[r]);}return a.push(s),a}function _(o,i,e,t,a){if(typeof document>"u"||!o.trim()||t<=0||a<=0)return null;let s=t*P,r=a*P,c=document.createElement("canvas");c.width=Math.max(8,Math.round(s*M)),c.height=Math.max(8,Math.round(r*M));let n=c.getContext("2d");if(!n)return null;let d="system-ui, -apple-system, Segoe UI, Roboto, sans-serif",p=c.width*.94,u=Math.max(6,e)*M,f=[];for(let l=0;l<12;l++){n.font=`600 ${u}px ${d}`,f=Q(n,o,p);let g=u*1.2;if(f.length*g<=c.height*.96||u<=6*M)break;u*=.88;}n.clearRect(0,0,c.width,c.height),n.fillStyle=i,n.textAlign="center",n.textBaseline="middle",n.font=`600 ${u}px ${d}`;let x=u*1.2,w=f.length*x,y=c.height/2-w/2+x/2;for(let l=0;l<f.length;l++)n.fillText(f[l],c.width/2,y+l*x);let h=new three.CanvasTexture(c);return h.colorSpace=three.SRGBColorSpace,h.minFilter=three.LinearFilter,h.magFilter=three.LinearFilter,h.flipY=false,h.premultiplyAlpha=false,h.wrapT=three.RepeatWrapping,h.repeat.set(1,-1),h.offset.set(0,1),h.needsUpdate=true,{texture:h,worldWidth:s,worldHeight:r}}function ee(o){let i=new three.Shape;o.outline.forEach((t,a)=>{a===0?i.moveTo(t.x,t.y):i.lineTo(t.x,t.y);}),i.closePath();let e=o.bevel>0;return new three.ExtrudeGeometry(i,{depth:o.depth,bevelEnabled:e,bevelThickness:o.bevel,bevelSize:o.bevel,bevelSegments:2,curveSegments:o.rounded?24:1,steps:1})}function te(o,i,e){let t=ee(e),a=new three.MeshStandardMaterial({color:new three.Color(e.fill),metalness:.12,roughness:.52,transparent:e.opacity<1,opacity:e.opacity}),s=new three.Mesh(t,a);if(s.position.set(e.position.x,e.position.y,e.position.z),s.rotation.set(e.rotation.x,e.rotation.y,e.rotation.z),o.add(s),i.push(t,a),e.strokeWidth>0){let r=new three.EdgesGeometry(t,30),c=new three.LineBasicMaterial({color:new three.Color(e.stroke)}),n=new three.LineSegments(r,c);n.position.copy(s.position),n.rotation.copy(s.rotation),o.add(n),i.push(r,c);}return t}function ne(o,i,e){if(!e.text)return;let t=_(e.text,e.textColor,e.fontSize,e.halfWidth*2,e.halfHeight*2);if(!t)return;let a=new three.PlaneGeometry(t.worldWidth,t.worldHeight),s=new three.MeshBasicMaterial({map:t.texture,transparent:true,depthWrite:false}),r=new three.Mesh(a,s),c=new three.Euler(e.rotation.x,e.rotation.y,e.rotation.z),n=new three.Vector3(0,0,e.depth+e.bevel+.4).applyEuler(c);r.position.set(e.position.x+n.x,e.position.y+n.y,e.position.z+n.z),r.rotation.copy(c),o.add(r),i.push(a,s,t.texture);}function oe(o,i,e){for(let t of e.connectors){if(t.points.length<2)continue;let a=new three.BufferGeometry().setFromPoints(t.points.map(r=>new three.Vector3(r.x,r.y,r.z))),s=new three.LineBasicMaterial({color:new three.Color(t.color),transparent:true,opacity:.7});o.add(new three.Line(a,s)),i.push(a,s);}}function ie(o){let i=new three.Group,e=[];for(let t of o.meshes)te(i,e,t),ne(i,e,t);return oe(i,e,o),{group:i,dispose(){for(let t of e)t.dispose();}}}var T=42;function ae(o){let i=1/0,e=1/0,t=1/0,a=-1/0,s=-1/0,r=-1/0,c=(n,d,p,u)=>{i=Math.min(i,n-u),e=Math.min(e,d-u),t=Math.min(t,p-u),a=Math.max(a,n+u),s=Math.max(s,d+u),r=Math.max(r,p+u);};for(let n of o.meshes){let d=Math.max(n.halfWidth,n.halfHeight)+n.depth+n.bevel;c(n.position.x,n.position.y,n.position.z,d);}for(let n of o.connectors)for(let d of n.points)c(d.x,d.y,d.z,1);return Number.isFinite(i)?{cx:(i+a)/2,cy:(e+s)/2,cz:(t+r)/2,radius:.5*Math.hypot(a-i,s-e,r-t)||1}:{cx:0,cy:0,cz:0,radius:Math.max(o.bounds.width,o.bounds.height)/2||1}}function se(o,i){let e=T*Math.PI/180,t=2*Math.atan(Math.tan(e/2)*i),a=Math.min(e,t);return o/Math.sin(a/2)*1.1}function le(o,i,e,t,a={}){let s=new three.WebGLRenderer({canvas:o,antialias:true,alpha:!a.background});s.setPixelRatio(Math.min(typeof window>"u"?1:window.devicePixelRatio||1,a.maxPixelRatio??2)),s.setSize(e,t,false);let r=new three.Scene;a.background&&(r.background=new three.Color(a.background));let{cx:c,cy:n,cz:d,radius:p}=ae(i),u=e/Math.max(1,t),f=se(p,u),x=new three.PerspectiveCamera(T,u,.1,f*8+p*4);x.position.set(c+p*.25,n+p*.3,d+f),x.lookAt(c,n,d),r.add(new three.AmbientLight(16777215,.62));let w=new three.DirectionalLight(16777215,.95);w.position.set(c+p,n+p*1.4,d+f),r.add(w);let y=new three.DirectionalLight(16777215,.3);y.position.set(c-p,n-p*.6,d+f*.6),r.add(y);let h=ie(i);r.add(h.group);let l=null,g=m=>{m&&!l?(l=new OrbitControls_js.OrbitControls(x,o),l.enablePan=false,l.target.set(c,n,d),l.minDistance=f*.4,l.maxDistance=f*3,l.update()):!m&&l&&(l.dispose(),l=null),l&&(l.autoRotate=!!a.autoRotate,l.autoRotateSpeed=1.2);};g(!!a.interactive);let v=0,S=false,k=()=>{S||(v=requestAnimationFrame(k),l?.update(),s.render(r,x));};return v=requestAnimationFrame(k),{resize(m,z){x.aspect=m/Math.max(1,z),x.updateProjectionMatrix(),s.setSize(m,z,false);},setInteractive(m){g(m);},dispose(){S=true,cancelAnimationFrame(v),l?.dispose(),h.dispose(),s.dispose();}}}exports.mountSmartArt3D=le;
@@ -0,0 +1 @@
1
+ import {WebGLRenderer,Scene,Color,PerspectiveCamera,AmbientLight,DirectionalLight,Group,MeshStandardMaterial,Mesh,EdgesGeometry,LineBasicMaterial,LineSegments,PlaneGeometry,MeshBasicMaterial,Euler,Vector3,BufferGeometry,Line,Shape,ExtrudeGeometry,CanvasTexture,SRGBColorSpace,LinearFilter,RepeatWrapping}from'three';import {OrbitControls}from'three/examples/jsm/controls/OrbitControls.js';var M=4,P=.86;function Q(o,i,e){let t=i.split(/\s+/u).filter(Boolean);if(t.length===0)return [];let a=[],s=t[0];for(let r=1;r<t.length;r++){let c=`${s} ${t[r]}`;o.measureText(c).width<=e?s=c:(a.push(s),s=t[r]);}return a.push(s),a}function _(o,i,e,t,a){if(typeof document>"u"||!o.trim()||t<=0||a<=0)return null;let s=t*P,r=a*P,c=document.createElement("canvas");c.width=Math.max(8,Math.round(s*M)),c.height=Math.max(8,Math.round(r*M));let n=c.getContext("2d");if(!n)return null;let d="system-ui, -apple-system, Segoe UI, Roboto, sans-serif",p=c.width*.94,u=Math.max(6,e)*M,f=[];for(let l=0;l<12;l++){n.font=`600 ${u}px ${d}`,f=Q(n,o,p);let g=u*1.2;if(f.length*g<=c.height*.96||u<=6*M)break;u*=.88;}n.clearRect(0,0,c.width,c.height),n.fillStyle=i,n.textAlign="center",n.textBaseline="middle",n.font=`600 ${u}px ${d}`;let x=u*1.2,w=f.length*x,y=c.height/2-w/2+x/2;for(let l=0;l<f.length;l++)n.fillText(f[l],c.width/2,y+l*x);let h=new CanvasTexture(c);return h.colorSpace=SRGBColorSpace,h.minFilter=LinearFilter,h.magFilter=LinearFilter,h.flipY=false,h.premultiplyAlpha=false,h.wrapT=RepeatWrapping,h.repeat.set(1,-1),h.offset.set(0,1),h.needsUpdate=true,{texture:h,worldWidth:s,worldHeight:r}}function ee(o){let i=new Shape;o.outline.forEach((t,a)=>{a===0?i.moveTo(t.x,t.y):i.lineTo(t.x,t.y);}),i.closePath();let e=o.bevel>0;return new ExtrudeGeometry(i,{depth:o.depth,bevelEnabled:e,bevelThickness:o.bevel,bevelSize:o.bevel,bevelSegments:2,curveSegments:o.rounded?24:1,steps:1})}function te(o,i,e){let t=ee(e),a=new MeshStandardMaterial({color:new Color(e.fill),metalness:.12,roughness:.52,transparent:e.opacity<1,opacity:e.opacity}),s=new Mesh(t,a);if(s.position.set(e.position.x,e.position.y,e.position.z),s.rotation.set(e.rotation.x,e.rotation.y,e.rotation.z),o.add(s),i.push(t,a),e.strokeWidth>0){let r=new EdgesGeometry(t,30),c=new LineBasicMaterial({color:new Color(e.stroke)}),n=new LineSegments(r,c);n.position.copy(s.position),n.rotation.copy(s.rotation),o.add(n),i.push(r,c);}return t}function ne(o,i,e){if(!e.text)return;let t=_(e.text,e.textColor,e.fontSize,e.halfWidth*2,e.halfHeight*2);if(!t)return;let a=new PlaneGeometry(t.worldWidth,t.worldHeight),s=new MeshBasicMaterial({map:t.texture,transparent:true,depthWrite:false}),r=new Mesh(a,s),c=new Euler(e.rotation.x,e.rotation.y,e.rotation.z),n=new Vector3(0,0,e.depth+e.bevel+.4).applyEuler(c);r.position.set(e.position.x+n.x,e.position.y+n.y,e.position.z+n.z),r.rotation.copy(c),o.add(r),i.push(a,s,t.texture);}function oe(o,i,e){for(let t of e.connectors){if(t.points.length<2)continue;let a=new BufferGeometry().setFromPoints(t.points.map(r=>new Vector3(r.x,r.y,r.z))),s=new LineBasicMaterial({color:new Color(t.color),transparent:true,opacity:.7});o.add(new Line(a,s)),i.push(a,s);}}function ie(o){let i=new Group,e=[];for(let t of o.meshes)te(i,e,t),ne(i,e,t);return oe(i,e,o),{group:i,dispose(){for(let t of e)t.dispose();}}}var T=42;function ae(o){let i=1/0,e=1/0,t=1/0,a=-1/0,s=-1/0,r=-1/0,c=(n,d,p,u)=>{i=Math.min(i,n-u),e=Math.min(e,d-u),t=Math.min(t,p-u),a=Math.max(a,n+u),s=Math.max(s,d+u),r=Math.max(r,p+u);};for(let n of o.meshes){let d=Math.max(n.halfWidth,n.halfHeight)+n.depth+n.bevel;c(n.position.x,n.position.y,n.position.z,d);}for(let n of o.connectors)for(let d of n.points)c(d.x,d.y,d.z,1);return Number.isFinite(i)?{cx:(i+a)/2,cy:(e+s)/2,cz:(t+r)/2,radius:.5*Math.hypot(a-i,s-e,r-t)||1}:{cx:0,cy:0,cz:0,radius:Math.max(o.bounds.width,o.bounds.height)/2||1}}function se(o,i){let e=T*Math.PI/180,t=2*Math.atan(Math.tan(e/2)*i),a=Math.min(e,t);return o/Math.sin(a/2)*1.1}function le(o,i,e,t,a={}){let s=new WebGLRenderer({canvas:o,antialias:true,alpha:!a.background});s.setPixelRatio(Math.min(typeof window>"u"?1:window.devicePixelRatio||1,a.maxPixelRatio??2)),s.setSize(e,t,false);let r=new Scene;a.background&&(r.background=new Color(a.background));let{cx:c,cy:n,cz:d,radius:p}=ae(i),u=e/Math.max(1,t),f=se(p,u),x=new PerspectiveCamera(T,u,.1,f*8+p*4);x.position.set(c+p*.25,n+p*.3,d+f),x.lookAt(c,n,d),r.add(new AmbientLight(16777215,.62));let w=new DirectionalLight(16777215,.95);w.position.set(c+p,n+p*1.4,d+f),r.add(w);let y=new DirectionalLight(16777215,.3);y.position.set(c-p,n-p*.6,d+f*.6),r.add(y);let h=ie(i);r.add(h.group);let l=null,g=m=>{m&&!l?(l=new OrbitControls(x,o),l.enablePan=false,l.target.set(c,n,d),l.minDistance=f*.4,l.maxDistance=f*3,l.update()):!m&&l&&(l.dispose(),l=null),l&&(l.autoRotate=!!a.autoRotate,l.autoRotateSpeed=1.2);};g(!!a.interactive);let v=0,S=false,k=()=>{S||(v=requestAnimationFrame(k),l?.update(),s.render(r,x));};return v=requestAnimationFrame(k),{resize(m,z){x.aspect=m/Math.max(1,z),x.updateProjectionMatrix(),s.setSize(m,z,false);},setInteractive(m){g(m);},dispose(){S=true,cancelAnimationFrame(v),l?.dispose(),h.dispose(),s.dispose();}}}export{le as mountSmartArt3D};
package/dist/styles.css CHANGED
@@ -37,6 +37,14 @@
37
37
  .pptxv *, .pptxv *::before, .pptxv *::after { box-sizing: border-box; }
38
38
  .pptxv:focus { outline: none; }
39
39
  .pptxv:focus-visible { outline: 2px solid var(--pptx-ring); outline-offset: -2px; }
40
+ .pptxv :is(button, a, input, select, textarea, [tabindex]):focus-visible { outline: 2px solid var(--pptx-ring) !important; outline-offset: 2px; }
41
+ .pptxv :is(button, [role='button']) { min-width: 24px; min-height: 24px; touch-action: manipulation; }
42
+ @media (prefers-reduced-motion: reduce) {
43
+ .pptxv *, .pptxv *::before, .pptxv *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; scroll-behavior: auto !important; }
44
+ }
45
+ @media (forced-colors: active) {
46
+ .pptxv :is(button, a, input, select, textarea, [tabindex]):focus-visible { outline-color: Highlight; }
47
+ }
40
48
 
41
49
  /* Ribbon shell layout (primary row + nav row + tab bar + groups) lives in
42
50
  * ribbon-css.ts; .pptxv-btn below is the shared icon-button primitive used by
@@ -133,7 +141,7 @@
133
141
  .pptxv-cmdsearch-item { cursor: pointer; }
134
142
  .pptxv-cmdsearch-item:hover { background: var(--pptx-accent); color: var(--pptx-accent-foreground); }
135
143
  .pptxv-cmdsearch-empty { color: var(--pptx-muted-foreground); }
136
- @media (max-width: 767px) { .pptxv-titlebar { display: none; } }
144
+ @media (max-width: 767px), (max-width: 1023px) and (max-height: 520px) { .pptxv-titlebar { display: none; } }
137
145
 
138
146
  /* ── Body: thumbnail rail + viewport ─────────────────────────────────── */
139
147
  .pptxv-body { display: flex; flex: 1; min-height: 0; }
@@ -373,41 +381,13 @@
373
381
  .pptxv-statusbar-zoom:hover { background: var(--pptx-accent); color: var(--pptx-accent-foreground); }
374
382
  .pptxv.pptxv-presenting .pptxv-statusbar { display: none; }
375
383
 
376
- /* ── Compact mobile navigation ───────────────────────────────────────── */
377
- .pptxv-mobile-nav { display: none; }
378
- @media (max-width: 767px) {
384
+ @media (max-width: 767px), (max-width: 1023px) and (max-height: 520px) {
379
385
  .pptxv-ribbon,
380
386
  .pptxv-thumbs,
381
387
  .pptxv-inspector,
382
388
  .pptxv-statusbar { display: none; }
383
389
  .pptxv-viewport { padding: 10px; }
384
- .pptxv-mobile-nav {
385
- display: grid;
386
- grid-template-columns: auto minmax(48px, 1fr) auto auto auto minmax(42px, auto) auto auto;
387
- align-items: center;
388
- gap: 2px;
389
- min-height: 52px;
390
- padding: 6px max(10px, env(safe-area-inset-left)) max(6px, env(safe-area-inset-bottom));
391
- border-top: 1px solid var(--pptx-border);
392
- background: var(--pptx-card);
393
- color: var(--pptx-card-foreground);
394
- }
395
- .pptxv-mobile-nav-btn {
396
- width: 36px;
397
- height: 36px;
398
- border-radius: 8px;
399
- }
400
- .pptxv-mobile-nav-btn svg { width: 18px; height: 18px; }
401
- .pptxv-mobile-nav-counter,
402
- .pptxv-mobile-nav-zoom {
403
- justify-self: center;
404
- font-size: 11px;
405
- font-variant-numeric: tabular-nums;
406
- white-space: nowrap;
407
- }
408
- .pptxv-mobile-nav-counter { color: var(--pptx-muted-foreground); }
409
- }
410
- .pptxv.pptxv-presenting .pptxv-mobile-nav { display: none; }
390
+ }
411
391
 
412
392
  /* ── Placeholder (element types without a renderer yet) ──────────────── */
413
393
  .pptxv-placeholder {
@@ -499,7 +479,7 @@
499
479
  /* ── Property inspector ──────────────────────────────────────────────── */
500
480
  .pptxv-inspector {
501
481
  flex: none;
502
- width: 232px;
482
+ width: 288px;
503
483
  overflow-y: auto;
504
484
  border-left: 1px solid var(--pptx-border);
505
485
  background: var(--pptx-card);
@@ -551,6 +531,30 @@
551
531
  }
552
532
  .pptxv-inspector-row-label { color: var(--pptx-muted-foreground); }
553
533
 
534
+ /* Compact SmartArt layout switcher and editable text pane. */
535
+ .pptxv-smartart-label { display: block; margin-bottom: 6px; color: var(--pptx-muted-foreground); }
536
+ .pptxv-smartart-layout-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 5px; margin-bottom: 10px; }
537
+ .pptxv-smartart-layout-button {
538
+ min-width: 0;
539
+ padding: 6px 3px;
540
+ border: 1px solid var(--pptx-border);
541
+ border-radius: var(--pptx-radius);
542
+ background: transparent;
543
+ color: var(--pptx-muted-foreground);
544
+ font: inherit;
545
+ font-size: 10px;
546
+ cursor: pointer;
547
+ overflow: hidden;
548
+ text-overflow: ellipsis;
549
+ }
550
+ .pptxv-smartart-layout-button:hover { background: var(--pptx-accent); color: var(--pptx-accent-foreground); }
551
+ .pptxv-smartart-layout-button.is-active { border-color: var(--pptx-primary); background: color-mix(in srgb, var(--pptx-primary) 16%, transparent); color: var(--pptx-primary); }
552
+ .pptxv-smartart-nodes { display: flex; max-height: 208px; flex-direction: column; gap: 5px; overflow-y: auto; }
553
+ .pptxv-smartart-node { display: grid; grid-template-columns: 20px minmax(0, 1fr); align-items: center; gap: 5px; }
554
+ .pptxv-smartart-node-index { color: var(--pptx-muted-foreground); text-align: center; }
555
+ .pptxv-smartart-node-input { min-width: 0; height: 26px; box-sizing: border-box; padding: 2px 6px; border: 1px solid var(--pptx-border); border-radius: var(--pptx-radius); background: var(--pptx-background); color: var(--pptx-foreground); font: inherit; }
556
+ .pptxv-smartart-node-input:focus-visible { outline: 2px solid var(--pptx-ring); outline-offset: -1px; }
557
+
554
558
  /* Select / checkbox / range fields (text/image/table inspector sections). */
555
559
  .pptxv-field-select,
556
560
  .pptxv-field-checkbox,
@@ -648,6 +652,7 @@
648
652
  padding: 4px 8px;
649
653
  border-bottom: 1px solid var(--pptx-border);
650
654
  }
655
+ .pptxv-ribbon-primary:empty { display: none; }
651
656
  .pptxv-ribbon-primary[hidden] { display: none; }
652
657
  /* ── Tab bar ─────────────────────────────────────────────────────────── */
653
658
  .pptxv-ribbon-tabs {
@@ -689,6 +694,13 @@
689
694
  padding: 6px 8px;
690
695
  }
691
696
  .pptxv-ribbon-tab-content[hidden] { display: none; }
697
+ .pptxv-record-dot { width: 12px; height: 12px; margin: 7px; border-radius: 50%; background: #ef4444; }
698
+ .pptxv-shortcut-help { align-self: center; padding: 5px 8px; color: var(--pptx-muted-foreground); font-size: 11px; }
699
+ .pptxv-ribbon-insert-content {
700
+ flex-wrap: nowrap;
701
+ overflow-x: auto;
702
+ overflow-y: hidden;
703
+ }
692
704
  .pptxv-rgroup {
693
705
  display: flex;
694
706
  flex-direction: column;
@@ -850,6 +862,146 @@
850
862
  .pptxv-findreplace-status { font-size: 11px; color: var(--pptx-muted-foreground); }
851
863
 
852
864
 
865
+ .pptxv-smartart-dialog-layer {
866
+ position: fixed;
867
+ inset: 0;
868
+ z-index: 1200;
869
+ display: flex;
870
+ align-items: center;
871
+ justify-content: center;
872
+ }
873
+ .pptxv-smartart-dialog-layer[hidden] { display: none; }
874
+ .pptxv-smartart-dialog-backdrop {
875
+ position: absolute;
876
+ inset: 0;
877
+ width: 100%;
878
+ height: 100%;
879
+ padding: 0;
880
+ border: 0;
881
+ background: rgb(0 0 0 / 0.5);
882
+ cursor: default;
883
+ }
884
+ .pptxv-smartart-dialog {
885
+ position: relative;
886
+ z-index: 1;
887
+ display: flex;
888
+ flex-direction: column;
889
+ width: min(600px, 90vw);
890
+ max-height: 80vh;
891
+ overflow: hidden;
892
+ border: 1px solid var(--pptx-border);
893
+ border-radius: 8px;
894
+ background: var(--pptx-background);
895
+ color: var(--pptx-foreground);
896
+ box-shadow: 0 20px 50px rgb(0 0 0 / 0.35);
897
+ }
898
+ .pptxv-smartart-dialog:focus { outline: none; }
899
+ .pptxv-smartart-dialog-header,
900
+ .pptxv-smartart-dialog-footer {
901
+ display: flex;
902
+ align-items: center;
903
+ padding: 12px 16px;
904
+ }
905
+ .pptxv-smartart-dialog-header {
906
+ justify-content: space-between;
907
+ border-bottom: 1px solid var(--pptx-border);
908
+ }
909
+ .pptxv-smartart-dialog-header h2 { margin: 0; font-size: 14px; font-weight: 500; }
910
+ .pptxv-smartart-dialog-close {
911
+ display: grid;
912
+ width: 28px;
913
+ height: 28px;
914
+ padding: 0;
915
+ place-items: center;
916
+ border: 0;
917
+ border-radius: var(--pptx-radius);
918
+ background: transparent;
919
+ color: inherit;
920
+ font: inherit;
921
+ font-size: 20px;
922
+ line-height: 1;
923
+ cursor: pointer;
924
+ }
925
+ .pptxv-smartart-dialog-close:hover { background: var(--pptx-muted); }
926
+ .pptxv-smartart-dialog-body { display: flex; flex: 1; min-height: 0; overflow: hidden; }
927
+ .pptxv-smartart-categories {
928
+ flex: 0 0 160px;
929
+ padding: 8px 0;
930
+ border-right: 1px solid var(--pptx-border);
931
+ }
932
+ .pptxv-smartart-category {
933
+ display: block;
934
+ width: 100%;
935
+ padding: 6px 12px;
936
+ border: 0;
937
+ background: transparent;
938
+ color: inherit;
939
+ font: inherit;
940
+ font-size: 12px;
941
+ text-align: left;
942
+ cursor: pointer;
943
+ }
944
+ .pptxv-smartart-category:hover { background: var(--pptx-muted); }
945
+ .pptxv-smartart-category.is-active { background: var(--pptx-primary); color: #fff; }
946
+ .pptxv-smartart-gallery { flex: 1; min-width: 0; overflow-y: auto; padding: 12px; }
947
+ .pptxv-smartart-options { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
948
+ .pptxv-smartart-option {
949
+ display: flex;
950
+ min-width: 0;
951
+ padding: 8px;
952
+ align-items: center;
953
+ flex-direction: column;
954
+ gap: 4px;
955
+ border: 1px solid var(--pptx-border);
956
+ border-radius: var(--pptx-radius);
957
+ background: transparent;
958
+ color: inherit;
959
+ font: inherit;
960
+ cursor: pointer;
961
+ }
962
+ .pptxv-smartart-option:hover { background: color-mix(in srgb, var(--pptx-muted) 50%, transparent); }
963
+ .pptxv-smartart-option.is-selected {
964
+ border-color: var(--pptx-primary);
965
+ background: color-mix(in srgb, var(--pptx-primary) 20%, transparent);
966
+ }
967
+ .pptxv-smartart-option-preview {
968
+ display: grid;
969
+ width: 64px;
970
+ height: 48px;
971
+ place-items: center;
972
+ border-radius: var(--pptx-radius);
973
+ background: var(--pptx-muted);
974
+ color: var(--pptx-primary);
975
+ }
976
+ .pptxv-smartart-option-preview svg { width: 30px; height: 30px; }
977
+ .pptxv-smartart-option-label { font-size: 10px; line-height: 1.25; text-align: center; }
978
+ .pptxv-smartart-dialog-footer {
979
+ justify-content: flex-end;
980
+ gap: 8px;
981
+ border-top: 1px solid var(--pptx-border);
982
+ }
983
+ .pptxv-smartart-dialog-cancel,
984
+ .pptxv-smartart-dialog-insert {
985
+ padding: 6px 12px;
986
+ border: 0;
987
+ border-radius: var(--pptx-radius);
988
+ font: inherit;
989
+ font-size: 12px;
990
+ cursor: pointer;
991
+ }
992
+ .pptxv-smartart-dialog-cancel { background: var(--pptx-muted); color: inherit; }
993
+ .pptxv-smartart-dialog-insert { background: var(--pptx-primary); color: #fff; }
994
+ .pptxv-smartart-dialog-insert:disabled { background: var(--pptx-muted); color: var(--pptx-muted-foreground); cursor: not-allowed; }
995
+ .pptxv-smartart-dialog button:focus-visible { outline: 2px solid var(--pptx-ring); outline-offset: 1px; }
996
+
997
+ @media (max-width: 767px) {
998
+ .pptxv-smartart-dialog-layer { align-items: flex-end; }
999
+ .pptxv-smartart-dialog { width: 100%; max-height: 88dvh; border-radius: 16px 16px 0 0; }
1000
+ .pptxv-smartart-categories { flex-basis: 120px; }
1001
+ .pptxv-smartart-options { grid-template-columns: repeat(2, minmax(0, 1fr)); }
1002
+ }
1003
+
1004
+
853
1005
  /* ── Modal dialog (Share / Broadcast) ────────────────────────────────── */
854
1006
  .pptxv-modal-backdrop {
855
1007
  position: fixed;
@@ -873,6 +1025,7 @@
873
1025
  background: var(--pptx-card);
874
1026
  color: var(--pptx-card-foreground);
875
1027
  box-shadow: 0 12px 36px rgb(0 0 0 / 0.35);
1028
+ overscroll-behavior: contain;
876
1029
  }
877
1030
  .pptxv-modal-panel:focus { outline: none; }
878
1031
  .pptxv-modal-header {
@@ -909,6 +1062,9 @@
909
1062
  }
910
1063
  .pptxv-modal-section { display: flex; flex-direction: column; gap: 12px; }
911
1064
  .pptxv-modal-section[hidden] { display: none; }
1065
+ .pptxv-share-tabs { display: grid; grid-template-columns: 1fr 1fr; gap: 4px; padding: 4px; border-radius: 8px; background: var(--pptx-muted); }
1066
+ .pptxv-share-tabs button { border: 0; border-radius: 6px; background: transparent; color: var(--pptx-muted-foreground); padding: 6px 10px; font: 500 12px/1.2 inherit; cursor: pointer; }
1067
+ .pptxv-share-tabs button[aria-selected='true'] { background: var(--pptx-background); color: var(--pptx-foreground); box-shadow: 0 1px 2px rgb(0 0 0 / 0.18); }
912
1068
  .pptxv-modal-desc { margin: 0; font-size: 13px; line-height: 1.5; color: var(--pptx-muted-foreground); }
913
1069
  .pptxv-modal-hint { margin: 4px 0 0; font-size: 11px; color: var(--pptx-muted-foreground); }
914
1070
  .pptxv-modal-hint[hidden] { display: none; }
@@ -1112,12 +1268,23 @@
1112
1268
  }
1113
1269
 
1114
1270
 
1115
- .pptxv-mobile-actions { display: none; }
1116
- @media (max-width: 720px) {
1271
+ .pptxv-mobile-toolbar, .pptxv-mobile-actions { display: none; }
1272
+ @media (max-width: 767px), (max-width: 1023px) and (max-height: 520px) {
1117
1273
  .pptxv-ribbon { display: none; }
1274
+ .pptxv-mobile-toolbar { position: relative; z-index: 20; display: flex; flex: none; align-items: center; gap: 4px; min-height: 52px; padding: max(env(safe-area-inset-top), 0px) 8px 4px; border-bottom: 1px solid var(--pptx-border); background: color-mix(in srgb, var(--pptx-muted) 55%, var(--pptx-card)); }
1275
+ .pptxv-mobile-toolbar-btn { display: inline-flex; align-items: center; justify-content: center; min-width: 44px; min-height: 44px; padding: 0; border: 0; border-radius: 6px; background: transparent; color: var(--pptx-foreground); touch-action: manipulation; }
1276
+ .pptxv-mobile-toolbar-btn:hover:not(:disabled) { background: var(--pptx-accent); }
1277
+ .pptxv-mobile-toolbar-btn:disabled { opacity: .4; }
1278
+ .pptxv-mobile-toolbar-btn svg { width: 20px; height: 20px; }
1279
+ .pptxv-mobile-toolbar-spacer { flex: 1; }
1280
+ .pptxv-mobile-present { color: var(--pptx-primary); }
1281
+ .pptxv-mobile-toolbar-collaboration { display: flex; }
1282
+ .pptxv-mobile-toolbar-collaboration[hidden], .pptxv-mobile-toolbar-collaboration:empty { display: none; }
1283
+ .pptxv-mobile-share { min-width: 44px; background: var(--pptx-primary); color: var(--pptx-primary-foreground); }
1118
1284
  .pptxv-mobile-actions { display: contents; }
1119
- .pptxv-mobile-actions > nav { position: absolute; z-index: 50; right: 0; bottom: 0; left: 0; display: flex; min-height: 64px; padding-bottom: env(safe-area-inset-bottom); border-top: 1px solid var(--pptx-border); background: var(--pptx-card); }
1120
- .pptxv-mobile-actions > nav button { flex: 1; min-width: 44px; border: 0; background: transparent; color: var(--pptx-muted-foreground); font-size: 10px; touch-action: manipulation; }
1285
+ .pptxv-mobile-actions > nav { position: relative; z-index: 50; display: flex; flex: none; min-height: 64px; padding-bottom: env(safe-area-inset-bottom); border-top: 1px solid var(--pptx-border); background: var(--pptx-card); }
1286
+ .pptxv-mobile-actions > nav button { position: relative; display: flex; flex: 1; flex-direction: column; align-items: center; justify-content: center; gap: 2px; min-width: 44px; border: 0; background: transparent; color: var(--pptx-muted-foreground); font-size: 10px; touch-action: manipulation; }
1287
+ .pptxv-mobile-actions > nav button svg { width: 20px; height: 20px; }
1121
1288
  .pptxv-mobile-actions > nav button[aria-pressed='true'] { color: var(--pptx-primary); }
1122
1289
  .pptxv-mobile-sheet-host { position: absolute; z-index: 48; inset: 0 0 64px; display: flex; align-items: end; }
1123
1290
  .pptxv-mobile-sheet-host[hidden] { display: none; }
@@ -1136,6 +1303,58 @@
1136
1303
  .pptxv-mobile-slide-list button { min-height: 44px; border: 1px solid var(--pptx-border); border-radius: 8px; background: var(--pptx-muted); color: inherit; }
1137
1304
  .pptxv-mobile-slide-list button.is-active { border-color: var(--pptx-primary); color: var(--pptx-primary); }
1138
1305
  .pptxv-mobile-sheet .pptxv-inspector { display: flex; width: 100%; max-height: 55dvh; border: 0; }
1139
- .pptxv-mobile-nav { bottom: calc(72px + env(safe-area-inset-bottom)); }
1306
+ .pptxv.pptxv-presenting .pptxv-mobile-toolbar,
1307
+ .pptxv.pptxv-presenting .pptxv-mobile-actions > nav,
1308
+ .pptxv.pptxv-presenting .pptxv-mobile-sheet-host { display: none; }
1140
1309
  }
1141
1310
 
1311
+
1312
+ .pptxv-master-sidebar {
1313
+ display: flex;
1314
+ flex: none;
1315
+ flex-direction: column;
1316
+ width: 224px;
1317
+ min-height: 0;
1318
+ border-right: 1px solid var(--pptx-border);
1319
+ background: color-mix(in srgb, var(--pptx-card) 92%, transparent);
1320
+ }
1321
+ .pptxv-master-sidebar[hidden] { display: none; }
1322
+ .pptxv-master-header { display: flex; align-items: center; justify-content: space-between; padding: 8px 12px; }
1323
+ .pptxv-master-title { color: var(--pptx-muted-foreground); font-size: 10px; letter-spacing: 0.07em; text-transform: uppercase; }
1324
+ .pptxv-master-collapse { width: 24px; height: 24px; border: 0; border-radius: 4px; background: transparent; color: var(--pptx-muted-foreground); cursor: pointer; font-size: 20px; line-height: 1; }
1325
+ .pptxv-master-collapse:hover { background: var(--pptx-accent); color: var(--pptx-accent-foreground); }
1326
+ .pptxv-master-collapse:focus-visible, .pptxv-master-tab:focus-visible, .pptxv-master-count:focus-visible, .pptxv-master-thumb:focus-visible { outline: 2px solid var(--pptx-ring); outline-offset: -2px; }
1327
+ .pptxv-master-tabs { display: flex; padding: 0 4px; border-bottom: 1px solid var(--pptx-border); }
1328
+ .pptxv-master-tab { flex: 1; padding: 6px 2px; border: 0; border-bottom: 2px solid transparent; background: transparent; color: var(--pptx-muted-foreground); cursor: pointer; font: inherit; font-size: 10px; }
1329
+ .pptxv-master-tab.is-active { border-bottom-color: #f59e0b; color: #f59e0b; font-weight: 600; }
1330
+ .pptxv-master-body { display: flex; flex: 1; flex-direction: column; gap: 8px; min-height: 0; overflow-y: auto; padding: 6px; }
1331
+ .pptxv-master-thumb { display: flex; flex-direction: column; gap: 4px; padding: 5px; border: 1px solid transparent; border-radius: 5px; background: transparent; color: var(--pptx-foreground); cursor: pointer; text-align: left; }
1332
+ .pptxv-master-thumb.is-layout { margin-left: 14px; }
1333
+ .pptxv-master-thumb:hover { background: var(--pptx-accent); }
1334
+ .pptxv-master-thumb.is-active { border-color: var(--pptx-primary); background: color-mix(in srgb, var(--pptx-primary) 10%, transparent); }
1335
+ .pptxv-master-thumb-name { overflow: hidden; font-size: 10px; text-overflow: ellipsis; white-space: nowrap; }
1336
+ .pptxv-master-thumb-frame { position: relative; display: block; overflow: hidden; border: 1px solid var(--pptx-border); border-radius: 3px; background: #fff; }
1337
+ .pptxv-master-card { padding: 8px; border: 1px solid var(--pptx-border); border-radius: 6px; background: color-mix(in srgb, var(--pptx-muted) 55%, transparent); }
1338
+ .pptxv-master-card-label { margin-bottom: 6px; color: var(--pptx-muted-foreground); font-size: 10px; }
1339
+ .pptxv-master-background { width: 100%; height: 32px; border: 1px solid var(--pptx-border); border-radius: 4px; }
1340
+ .pptxv-master-placeholder { display: flex; align-items: center; gap: 7px; margin-top: 4px; padding: 5px 6px; border-radius: 4px; background: color-mix(in srgb, var(--pptx-background) 65%, transparent); font-size: 10px; }
1341
+ .pptxv-master-dot { width: 8px; height: 8px; flex: none; border-radius: 50%; background: rgb(34 197 94 / 0.65); }
1342
+ .pptxv-master-dot.is-handout { background: rgb(168 85 247 / 0.65); }
1343
+ .pptxv-master-empty { padding: 16px 8px; color: var(--pptx-muted-foreground); font-size: 11px; text-align: center; }
1344
+ .pptxv-master-counts { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; }
1345
+ .pptxv-master-count { padding: 6px; border: 0; border-radius: 4px; background: var(--pptx-accent); color: var(--pptx-muted-foreground); cursor: pointer; font: inherit; font-size: 11px; }
1346
+ .pptxv-master-count.is-active { background: var(--pptx-primary); color: var(--pptx-primary-foreground); }
1347
+ .pptxv-master-page { position: relative; overflow: hidden; border: 1px solid #d1d5db; border-radius: 4px; background: #fff; box-shadow: 0 8px 24px rgb(0 0 0 / 0.18); }
1348
+ .pptxv-master-canvas-empty { display: grid; width: 100%; height: 100%; place-items: center; color: var(--pptx-muted-foreground); }
1349
+ .pptxv-notes-region { position: absolute; display: flex; overflow: hidden; align-items: center; justify-content: center; border: 1px dashed rgb(156 163 175 / 0.45); color: rgb(107 114 128 / 0.8); font-size: 10px; text-align: center; }
1350
+ .pptxv-notes-region.is-sldImg { border-color: rgb(59 130 246 / 0.55); background: rgb(59 130 246 / 0.05); color: rgb(59 130 246 / 0.75); }
1351
+ .pptxv-notes-region.is-body { border-color: rgb(34 197 94 / 0.55); background: rgb(34 197 94 / 0.05); color: rgb(34 197 94 / 0.75); }
1352
+ .pptxv-handout-slot { position: absolute; display: flex; overflow: hidden; align-items: center; justify-content: center; border: 1px dashed rgb(96 165 250 / 0.55); background: rgb(239 246 255 / 0.35); color: rgb(96 165 250 / 0.7); font-size: 10px; font-weight: 500; }
1353
+ .pptxv-handout-corner { position: absolute; padding: 1px 4px; border-color: rgb(209 213 219 / 0.5); border-style: dashed; color: rgb(107 114 128 / 0.55); font-size: 8px; }
1354
+ .pptxv-handout-corner.is-top-left { top: 0; left: 0; border-right-width: 1px; border-bottom-width: 1px; }
1355
+ .pptxv-handout-corner.is-top-right { top: 0; right: 0; border-bottom-width: 1px; border-left-width: 1px; }
1356
+ .pptxv-handout-corner.is-bottom-left { bottom: 0; left: 0; border-top-width: 1px; border-right-width: 1px; }
1357
+ .pptxv-handout-corner.is-bottom-right { right: 0; bottom: 0; border-top-width: 1px; border-left-width: 1px; }
1358
+ @media (max-width: 767px), (max-width: 1023px) and (max-height: 520px) { .pptxv-master-sidebar { display: none; } }
1359
+ .pptxv.pptxv-presenting .pptxv-master-sidebar { display: none; }
1360
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pptx-vanilla-viewer",
3
- "version": "0.6.0",
3
+ "version": "0.8.0",
4
4
  "description": "Zero-framework PowerPoint viewer: render PPTX slides in the browser with plain DOM, no React/Vue/Angular required.",
5
5
  "keywords": [
6
6
  "javascript",