pptx-react-viewer 1.1.5 → 1.1.7

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 (33) hide show
  1. package/dist/{PowerPointViewer-CX0a7wz_.d.mts → PowerPointViewer-C5jGuKGB.d.mts} +3 -1
  2. package/dist/{PowerPointViewer-CX0a7wz_.d.ts → PowerPointViewer-C5jGuKGB.d.ts} +3 -1
  3. package/dist/index.d.mts +3 -2
  4. package/dist/index.d.ts +3 -2
  5. package/dist/index.js +1575 -515
  6. package/dist/index.mjs +1577 -517
  7. package/dist/pptx-viewer.css +1 -1
  8. package/dist/viewer/index.d.mts +6 -25
  9. package/dist/viewer/index.d.ts +6 -25
  10. package/dist/viewer/index.js +1575 -515
  11. package/dist/viewer/index.mjs +1577 -517
  12. package/node_modules/emf-converter/package.json +1 -1
  13. package/node_modules/mtx-decompressor/package.json +1 -1
  14. package/node_modules/pptx-viewer-core/dist/{SvgExporter-0TxiiorD.d.ts → SvgExporter-BtZczTlB.d.ts} +1 -1
  15. package/node_modules/pptx-viewer-core/dist/{SvgExporter-BQ4KbRO9.d.mts → SvgExporter-D4mBWJHE.d.mts} +1 -1
  16. package/node_modules/pptx-viewer-core/dist/cli/index.d.mts +2 -2
  17. package/node_modules/pptx-viewer-core/dist/cli/index.d.ts +2 -2
  18. package/node_modules/pptx-viewer-core/dist/cli/index.js +0 -0
  19. package/node_modules/pptx-viewer-core/dist/cli/index.mjs +0 -0
  20. package/node_modules/pptx-viewer-core/dist/converter/index.d.mts +3 -3
  21. package/node_modules/pptx-viewer-core/dist/converter/index.d.ts +3 -3
  22. package/node_modules/pptx-viewer-core/dist/converter/index.js +0 -0
  23. package/node_modules/pptx-viewer-core/dist/converter/index.mjs +0 -0
  24. package/node_modules/pptx-viewer-core/dist/index.d.mts +967 -60
  25. package/node_modules/pptx-viewer-core/dist/index.d.ts +967 -60
  26. package/node_modules/pptx-viewer-core/dist/index.js +29613 -16737
  27. package/node_modules/pptx-viewer-core/dist/index.mjs +29588 -16737
  28. package/node_modules/pptx-viewer-core/dist/{presentation-ArhfImJ5.d.mts → presentation-nZxgWvXq.d.mts} +875 -27
  29. package/node_modules/pptx-viewer-core/dist/{presentation-ArhfImJ5.d.ts → presentation-nZxgWvXq.d.ts} +875 -27
  30. package/node_modules/pptx-viewer-core/dist/{text-operations-CLj-sJyk.d.mts → text-operations-DCTGMltY.d.mts} +1 -1
  31. package/node_modules/pptx-viewer-core/dist/{text-operations-rhJV-A_W.d.ts → text-operations-DYmhoi7U.d.ts} +1 -1
  32. package/node_modules/pptx-viewer-core/package.json +1 -1
  33. package/package.json +4 -4
@@ -198,7 +198,7 @@ function generateUUID() {
198
198
  const uuid = _lut[d0 & 255] + _lut[d0 >> 8 & 255] + _lut[d0 >> 16 & 255] + _lut[d0 >> 24 & 255] + "-" + _lut[d1 & 255] + _lut[d1 >> 8 & 255] + "-" + _lut[d1 >> 16 & 15 | 64] + _lut[d1 >> 24 & 255] + "-" + _lut[d2 & 63 | 128] + _lut[d2 >> 8 & 255] + "-" + _lut[d2 >> 16 & 255] + _lut[d2 >> 24 & 255] + _lut[d3 & 255] + _lut[d3 >> 8 & 255] + _lut[d3 >> 16 & 255] + _lut[d3 >> 24 & 255];
199
199
  return uuid.toLowerCase();
200
200
  }
201
- function clamp(value, min2, max2) {
201
+ function clamp2(value, min2, max2) {
202
202
  return Math.max(min2, Math.min(max2, value));
203
203
  }
204
204
  function euclideanModulo(n, m2) {
@@ -573,7 +573,7 @@ function _generateTables() {
573
573
  }
574
574
  function toHalfFloat(val2) {
575
575
  if (Math.abs(val2) > 65504) warn("DataUtils.toHalfFloat(): Value out of range.");
576
- val2 = clamp(val2, -65504, 65504);
576
+ val2 = clamp2(val2, -65504, 65504);
577
577
  _tables.floatView[0] = val2;
578
578
  const f = _tables.uint32View[0];
579
579
  const e2 = f >> 23 & 511;
@@ -2062,7 +2062,7 @@ var init_three_core = __esm({
2062
2062
  * @param {number} max - The max value.
2063
2063
  * @return {number} The clamped value.
2064
2064
  */
2065
- clamp,
2065
+ clamp: clamp2,
2066
2066
  /**
2067
2067
  * Computes the Euclidean modulo of the given parameters that
2068
2068
  * is `( ( n % m ) + m ) % m`.
@@ -2589,8 +2589,8 @@ var init_three_core = __esm({
2589
2589
  * @return {Vector2} A reference to this vector.
2590
2590
  */
2591
2591
  clamp(min2, max2) {
2592
- this.x = clamp(this.x, min2.x, max2.x);
2593
- this.y = clamp(this.y, min2.y, max2.y);
2592
+ this.x = clamp2(this.x, min2.x, max2.x);
2593
+ this.y = clamp2(this.y, min2.y, max2.y);
2594
2594
  return this;
2595
2595
  }
2596
2596
  /**
@@ -2604,8 +2604,8 @@ var init_three_core = __esm({
2604
2604
  * @return {Vector2} A reference to this vector.
2605
2605
  */
2606
2606
  clampScalar(minVal, maxVal) {
2607
- this.x = clamp(this.x, minVal, maxVal);
2608
- this.y = clamp(this.y, minVal, maxVal);
2607
+ this.x = clamp2(this.x, minVal, maxVal);
2608
+ this.y = clamp2(this.y, minVal, maxVal);
2609
2609
  return this;
2610
2610
  }
2611
2611
  /**
@@ -2620,7 +2620,7 @@ var init_three_core = __esm({
2620
2620
  */
2621
2621
  clampLength(min2, max2) {
2622
2622
  const length2 = this.length();
2623
- return this.divideScalar(length2 || 1).multiplyScalar(clamp(length2, min2, max2));
2623
+ return this.divideScalar(length2 || 1).multiplyScalar(clamp2(length2, min2, max2));
2624
2624
  }
2625
2625
  /**
2626
2626
  * The components of this vector are rounded down to the nearest integer value.
@@ -2745,7 +2745,7 @@ var init_three_core = __esm({
2745
2745
  const denominator = Math.sqrt(this.lengthSq() * v.lengthSq());
2746
2746
  if (denominator === 0) return Math.PI / 2;
2747
2747
  const theta = this.dot(v) / denominator;
2748
- return Math.acos(clamp(theta, -1, 1));
2748
+ return Math.acos(clamp2(theta, -1, 1));
2749
2749
  }
2750
2750
  /**
2751
2751
  * Computes the distance from the given vector to this instance.
@@ -3232,7 +3232,7 @@ var init_three_core = __esm({
3232
3232
  * @return {number} The angle in radians.
3233
3233
  */
3234
3234
  angleTo(q) {
3235
- return 2 * Math.acos(Math.abs(clamp(this.dot(q), -1, 1)));
3235
+ return 2 * Math.acos(Math.abs(clamp2(this.dot(q), -1, 1)));
3236
3236
  }
3237
3237
  /**
3238
3238
  * Rotates this quaternion by a given angular step to the given quaternion.
@@ -3938,9 +3938,9 @@ var init_three_core = __esm({
3938
3938
  * @return {Vector3} A reference to this vector.
3939
3939
  */
3940
3940
  clamp(min2, max2) {
3941
- this.x = clamp(this.x, min2.x, max2.x);
3942
- this.y = clamp(this.y, min2.y, max2.y);
3943
- this.z = clamp(this.z, min2.z, max2.z);
3941
+ this.x = clamp2(this.x, min2.x, max2.x);
3942
+ this.y = clamp2(this.y, min2.y, max2.y);
3943
+ this.z = clamp2(this.z, min2.z, max2.z);
3944
3944
  return this;
3945
3945
  }
3946
3946
  /**
@@ -3954,9 +3954,9 @@ var init_three_core = __esm({
3954
3954
  * @return {Vector3} A reference to this vector.
3955
3955
  */
3956
3956
  clampScalar(minVal, maxVal) {
3957
- this.x = clamp(this.x, minVal, maxVal);
3958
- this.y = clamp(this.y, minVal, maxVal);
3959
- this.z = clamp(this.z, minVal, maxVal);
3957
+ this.x = clamp2(this.x, minVal, maxVal);
3958
+ this.y = clamp2(this.y, minVal, maxVal);
3959
+ this.z = clamp2(this.z, minVal, maxVal);
3960
3960
  return this;
3961
3961
  }
3962
3962
  /**
@@ -3971,7 +3971,7 @@ var init_three_core = __esm({
3971
3971
  */
3972
3972
  clampLength(min2, max2) {
3973
3973
  const length2 = this.length();
3974
- return this.divideScalar(length2 || 1).multiplyScalar(clamp(length2, min2, max2));
3974
+ return this.divideScalar(length2 || 1).multiplyScalar(clamp2(length2, min2, max2));
3975
3975
  }
3976
3976
  /**
3977
3977
  * The components of this vector are rounded down to the nearest integer value.
@@ -4181,7 +4181,7 @@ var init_three_core = __esm({
4181
4181
  const denominator = Math.sqrt(this.lengthSq() * v.lengthSq());
4182
4182
  if (denominator === 0) return Math.PI / 2;
4183
4183
  const theta = this.dot(v) / denominator;
4184
- return Math.acos(clamp(theta, -1, 1));
4184
+ return Math.acos(clamp2(theta, -1, 1));
4185
4185
  }
4186
4186
  /**
4187
4187
  * Computes the distance from the given vector to this instance.
@@ -5870,10 +5870,10 @@ var init_three_core = __esm({
5870
5870
  * @return {Vector4} A reference to this vector.
5871
5871
  */
5872
5872
  clamp(min2, max2) {
5873
- this.x = clamp(this.x, min2.x, max2.x);
5874
- this.y = clamp(this.y, min2.y, max2.y);
5875
- this.z = clamp(this.z, min2.z, max2.z);
5876
- this.w = clamp(this.w, min2.w, max2.w);
5873
+ this.x = clamp2(this.x, min2.x, max2.x);
5874
+ this.y = clamp2(this.y, min2.y, max2.y);
5875
+ this.z = clamp2(this.z, min2.z, max2.z);
5876
+ this.w = clamp2(this.w, min2.w, max2.w);
5877
5877
  return this;
5878
5878
  }
5879
5879
  /**
@@ -5887,10 +5887,10 @@ var init_three_core = __esm({
5887
5887
  * @return {Vector4} A reference to this vector.
5888
5888
  */
5889
5889
  clampScalar(minVal, maxVal) {
5890
- this.x = clamp(this.x, minVal, maxVal);
5891
- this.y = clamp(this.y, minVal, maxVal);
5892
- this.z = clamp(this.z, minVal, maxVal);
5893
- this.w = clamp(this.w, minVal, maxVal);
5890
+ this.x = clamp2(this.x, minVal, maxVal);
5891
+ this.y = clamp2(this.y, minVal, maxVal);
5892
+ this.z = clamp2(this.z, minVal, maxVal);
5893
+ this.w = clamp2(this.w, minVal, maxVal);
5894
5894
  return this;
5895
5895
  }
5896
5896
  /**
@@ -5905,7 +5905,7 @@ var init_three_core = __esm({
5905
5905
  */
5906
5906
  clampLength(min2, max2) {
5907
5907
  const length2 = this.length();
5908
- return this.divideScalar(length2 || 1).multiplyScalar(clamp(length2, min2, max2));
5908
+ return this.divideScalar(length2 || 1).multiplyScalar(clamp2(length2, min2, max2));
5909
5909
  }
5910
5910
  /**
5911
5911
  * The components of this vector are rounded down to the nearest integer value.
@@ -7688,7 +7688,7 @@ var init_three_core = __esm({
7688
7688
  const m31 = te[2], m32 = te[6], m33 = te[10];
7689
7689
  switch (order) {
7690
7690
  case "XYZ":
7691
- this._y = Math.asin(clamp(m13, -1, 1));
7691
+ this._y = Math.asin(clamp2(m13, -1, 1));
7692
7692
  if (Math.abs(m13) < 0.9999999) {
7693
7693
  this._x = Math.atan2(-m23, m33);
7694
7694
  this._z = Math.atan2(-m12, m11);
@@ -7698,7 +7698,7 @@ var init_three_core = __esm({
7698
7698
  }
7699
7699
  break;
7700
7700
  case "YXZ":
7701
- this._x = Math.asin(-clamp(m23, -1, 1));
7701
+ this._x = Math.asin(-clamp2(m23, -1, 1));
7702
7702
  if (Math.abs(m23) < 0.9999999) {
7703
7703
  this._y = Math.atan2(m13, m33);
7704
7704
  this._z = Math.atan2(m21, m22);
@@ -7708,7 +7708,7 @@ var init_three_core = __esm({
7708
7708
  }
7709
7709
  break;
7710
7710
  case "ZXY":
7711
- this._x = Math.asin(clamp(m32, -1, 1));
7711
+ this._x = Math.asin(clamp2(m32, -1, 1));
7712
7712
  if (Math.abs(m32) < 0.9999999) {
7713
7713
  this._y = Math.atan2(-m31, m33);
7714
7714
  this._z = Math.atan2(-m12, m22);
@@ -7718,7 +7718,7 @@ var init_three_core = __esm({
7718
7718
  }
7719
7719
  break;
7720
7720
  case "ZYX":
7721
- this._y = Math.asin(-clamp(m31, -1, 1));
7721
+ this._y = Math.asin(-clamp2(m31, -1, 1));
7722
7722
  if (Math.abs(m31) < 0.9999999) {
7723
7723
  this._x = Math.atan2(m32, m33);
7724
7724
  this._z = Math.atan2(m21, m11);
@@ -7728,7 +7728,7 @@ var init_three_core = __esm({
7728
7728
  }
7729
7729
  break;
7730
7730
  case "YZX":
7731
- this._z = Math.asin(clamp(m21, -1, 1));
7731
+ this._z = Math.asin(clamp2(m21, -1, 1));
7732
7732
  if (Math.abs(m21) < 0.9999999) {
7733
7733
  this._x = Math.atan2(-m23, m22);
7734
7734
  this._y = Math.atan2(-m31, m11);
@@ -7738,7 +7738,7 @@ var init_three_core = __esm({
7738
7738
  }
7739
7739
  break;
7740
7740
  case "XZY":
7741
- this._z = Math.asin(-clamp(m12, -1, 1));
7741
+ this._z = Math.asin(-clamp2(m12, -1, 1));
7742
7742
  if (Math.abs(m12) < 0.9999999) {
7743
7743
  this._x = Math.atan2(m32, m22);
7744
7744
  this._y = Math.atan2(m13, m11);
@@ -9362,8 +9362,8 @@ var init_three_core = __esm({
9362
9362
  */
9363
9363
  setHSL(h2, s, l2, colorSpace = ColorManagement.workingColorSpace) {
9364
9364
  h2 = euclideanModulo(h2, 1);
9365
- s = clamp(s, 0, 1);
9366
- l2 = clamp(l2, 0, 1);
9365
+ s = clamp2(s, 0, 1);
9366
+ l2 = clamp2(l2, 0, 1);
9367
9367
  if (s === 0) {
9368
9368
  this.r = this.g = this.b = l2;
9369
9369
  } else {
@@ -9549,7 +9549,7 @@ var init_three_core = __esm({
9549
9549
  */
9550
9550
  getHex(colorSpace = SRGBColorSpace) {
9551
9551
  ColorManagement.workingToColorSpace(_color.copy(this), colorSpace);
9552
- return Math.round(clamp(_color.r * 255, 0, 255)) * 65536 + Math.round(clamp(_color.g * 255, 0, 255)) * 256 + Math.round(clamp(_color.b * 255, 0, 255));
9552
+ return Math.round(clamp2(_color.r * 255, 0, 255)) * 65536 + Math.round(clamp2(_color.g * 255, 0, 255)) * 256 + Math.round(clamp2(_color.b * 255, 0, 255));
9553
9553
  }
9554
9554
  /**
9555
9555
  * Returns the hexadecimal value of this color as a string (for example, 'FFFFFF').
@@ -18480,13 +18480,13 @@ var init_three_core = __esm({
18480
18480
  vec.crossVectors(tangents[i3 - 1], tangents[i3]);
18481
18481
  if (vec.length() > Number.EPSILON) {
18482
18482
  vec.normalize();
18483
- const theta = Math.acos(clamp(tangents[i3 - 1].dot(tangents[i3]), -1, 1));
18483
+ const theta = Math.acos(clamp2(tangents[i3 - 1].dot(tangents[i3]), -1, 1));
18484
18484
  normals[i3].applyMatrix4(mat.makeRotationAxis(vec, theta));
18485
18485
  }
18486
18486
  binormals[i3].crossVectors(tangents[i3], normals[i3]);
18487
18487
  }
18488
18488
  if (closed === true) {
18489
- let theta = Math.acos(clamp(normals[0].dot(normals[segments]), -1, 1));
18489
+ let theta = Math.acos(clamp2(normals[0].dot(normals[segments]), -1, 1));
18490
18490
  theta /= segments;
18491
18491
  if (tangents[0].dot(vec.crossVectors(normals[0], normals[segments])) > 0) {
18492
18492
  theta = -theta;
@@ -20275,7 +20275,7 @@ var init_three_core = __esm({
20275
20275
  phiLength
20276
20276
  };
20277
20277
  segments = Math.floor(segments);
20278
- phiLength = clamp(phiLength, 0, Math.PI * 2);
20278
+ phiLength = clamp2(phiLength, 0, Math.PI * 2);
20279
20279
  const indices = [];
20280
20280
  const vertices = [];
20281
20281
  const uvs = [];
@@ -21491,7 +21491,7 @@ var init_three_core = __esm({
21491
21491
  this.ior = 1.5;
21492
21492
  Object.defineProperty(this, "reflectivity", {
21493
21493
  get: function() {
21494
- return clamp(2.5 * (this.ior - 1) / (this.ior + 1), 0, 1);
21494
+ return clamp2(2.5 * (this.ior - 1) / (this.ior + 1), 0, 1);
21495
21495
  },
21496
21496
  set: function(reflectivity) {
21497
21497
  this.ior = (1 + 0.4 * reflectivity) / (1 - 0.4 * reflectivity);
@@ -29759,7 +29759,7 @@ var init_three_core = __esm({
29759
29759
  */
29760
29760
  makeSafe() {
29761
29761
  const EPS = 1e-6;
29762
- this.phi = clamp(this.phi, EPS, Math.PI - EPS);
29762
+ this.phi = clamp2(this.phi, EPS, Math.PI - EPS);
29763
29763
  return this;
29764
29764
  }
29765
29765
  /**
@@ -29787,7 +29787,7 @@ var init_three_core = __esm({
29787
29787
  this.phi = 0;
29788
29788
  } else {
29789
29789
  this.theta = Math.atan2(x2, z);
29790
- this.phi = Math.acos(clamp(y / this.radius, -1, 1));
29790
+ this.phi = Math.acos(clamp2(y / this.radius, -1, 1));
29791
29791
  }
29792
29792
  return this;
29793
29793
  }
@@ -30302,7 +30302,7 @@ var init_three_core = __esm({
30302
30302
  const startEnd_startP = _startEnd.dot(_startP);
30303
30303
  let t2 = startEnd_startP / startEnd2;
30304
30304
  if (clampToLine) {
30305
- t2 = clamp(t2, 0, 1);
30305
+ t2 = clamp2(t2, 0, 1);
30306
30306
  }
30307
30307
  return t2;
30308
30308
  }
@@ -30348,27 +30348,27 @@ var init_three_core = __esm({
30348
30348
  if (a2 <= EPSILON) {
30349
30349
  s = 0;
30350
30350
  t2 = f / e2;
30351
- t2 = clamp(t2, 0, 1);
30351
+ t2 = clamp2(t2, 0, 1);
30352
30352
  } else {
30353
30353
  const c3 = _d1.dot(_r);
30354
30354
  if (e2 <= EPSILON) {
30355
30355
  t2 = 0;
30356
- s = clamp(-c3 / a2, 0, 1);
30356
+ s = clamp2(-c3 / a2, 0, 1);
30357
30357
  } else {
30358
30358
  const b2 = _d1.dot(_d2);
30359
30359
  const denom = a2 * e2 - b2 * b2;
30360
30360
  if (denom !== 0) {
30361
- s = clamp((b2 * f - c3 * e2) / denom, 0, 1);
30361
+ s = clamp2((b2 * f - c3 * e2) / denom, 0, 1);
30362
30362
  } else {
30363
30363
  s = 0;
30364
30364
  }
30365
30365
  t2 = (b2 * s + f) / e2;
30366
30366
  if (t2 < 0) {
30367
30367
  t2 = 0;
30368
- s = clamp(-c3 / a2, 0, 1);
30368
+ s = clamp2(-c3 / a2, 0, 1);
30369
30369
  } else if (t2 > 1) {
30370
30370
  t2 = 1;
30371
- s = clamp((b2 - c3) / a2, 0, 1);
30371
+ s = clamp2((b2 - c3) / a2, 0, 1);
30372
30372
  }
30373
30373
  }
30374
30374
  }
@@ -43598,7 +43598,7 @@ var require_use_sync_external_store_shim_development = __commonJS({
43598
43598
  return x2 === y && (0 !== x2 || 1 / x2 === 1 / y) || x2 !== x2 && y !== y;
43599
43599
  }
43600
43600
  function useSyncExternalStore$2(subscribe3, getSnapshot2) {
43601
- didWarnOld18Alpha || void 0 === React100.startTransition || (didWarnOld18Alpha = true, console.error(
43601
+ didWarnOld18Alpha || void 0 === React103.startTransition || (didWarnOld18Alpha = true, console.error(
43602
43602
  "You are using an outdated, pre-release alpha of React 18 that does not support useSyncExternalStore. The use-sync-external-store shim will not work correctly. Upgrade to a newer pre-release."
43603
43603
  ));
43604
43604
  var value = getSnapshot2();
@@ -43608,7 +43608,7 @@ var require_use_sync_external_store_shim_development = __commonJS({
43608
43608
  "The result of getSnapshot should be cached to avoid an infinite loop"
43609
43609
  ), didWarnUncachedGetSnapshot = true);
43610
43610
  }
43611
- cachedValue = useState86({
43611
+ cachedValue = useState89({
43612
43612
  inst: { value, getSnapshot: getSnapshot2 }
43613
43613
  });
43614
43614
  var inst = cachedValue[0].inst, forceUpdate = cachedValue[1];
@@ -43620,7 +43620,7 @@ var require_use_sync_external_store_shim_development = __commonJS({
43620
43620
  },
43621
43621
  [subscribe3, value, getSnapshot2]
43622
43622
  );
43623
- useEffect72(
43623
+ useEffect73(
43624
43624
  function() {
43625
43625
  checkIfSnapshotChanged(inst) && forceUpdate({ inst });
43626
43626
  return subscribe3(function() {
@@ -43646,8 +43646,8 @@ var require_use_sync_external_store_shim_development = __commonJS({
43646
43646
  return getSnapshot2();
43647
43647
  }
43648
43648
  "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(Error());
43649
- var React100 = __require("react"), objectIs = "function" === typeof Object.is ? Object.is : is2, useState86 = React100.useState, useEffect72 = React100.useEffect, useLayoutEffect7 = React100.useLayoutEffect, useDebugValue = React100.useDebugValue, didWarnOld18Alpha = false, didWarnUncachedGetSnapshot = false, shim = "undefined" === typeof window || "undefined" === typeof window.document || "undefined" === typeof window.document.createElement ? useSyncExternalStore$1 : useSyncExternalStore$2;
43650
- exports$1.useSyncExternalStore = void 0 !== React100.useSyncExternalStore ? React100.useSyncExternalStore : shim;
43649
+ var React103 = __require("react"), objectIs = "function" === typeof Object.is ? Object.is : is2, useState89 = React103.useState, useEffect73 = React103.useEffect, useLayoutEffect7 = React103.useLayoutEffect, useDebugValue = React103.useDebugValue, didWarnOld18Alpha = false, didWarnUncachedGetSnapshot = false, shim = "undefined" === typeof window || "undefined" === typeof window.document || "undefined" === typeof window.document.createElement ? useSyncExternalStore$1 : useSyncExternalStore$2;
43650
+ exports$1.useSyncExternalStore = void 0 !== React103.useSyncExternalStore ? React103.useSyncExternalStore : shim;
43651
43651
  "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error());
43652
43652
  })();
43653
43653
  }
@@ -43670,9 +43670,9 @@ var require_with_selector_development = __commonJS({
43670
43670
  return x2 === y && (0 !== x2 || 1 / x2 === 1 / y) || x2 !== x2 && y !== y;
43671
43671
  }
43672
43672
  "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(Error());
43673
- var React100 = __require("react"), shim = require_shim(), objectIs = "function" === typeof Object.is ? Object.is : is2, useSyncExternalStore3 = shim.useSyncExternalStore, useRef73 = React100.useRef, useEffect72 = React100.useEffect, useMemo42 = React100.useMemo, useDebugValue = React100.useDebugValue;
43673
+ var React103 = __require("react"), shim = require_shim(), objectIs = "function" === typeof Object.is ? Object.is : is2, useSyncExternalStore3 = shim.useSyncExternalStore, useRef74 = React103.useRef, useEffect73 = React103.useEffect, useMemo42 = React103.useMemo, useDebugValue = React103.useDebugValue;
43674
43674
  exports$1.useSyncExternalStoreWithSelector = function(subscribe3, getSnapshot2, getServerSnapshot2, selector, isEqual) {
43675
- var instRef = useRef73(null);
43675
+ var instRef = useRef74(null);
43676
43676
  if (null === instRef.current) {
43677
43677
  var inst = { hasValue: false, value: null };
43678
43678
  instRef.current = inst;
@@ -43713,7 +43713,7 @@ var require_with_selector_development = __commonJS({
43713
43713
  [getSnapshot2, getServerSnapshot2, selector, isEqual]
43714
43714
  );
43715
43715
  var value = useSyncExternalStore3(subscribe3, instRef[0], instRef[1]);
43716
- useEffect72(
43716
+ useEffect73(
43717
43717
  function() {
43718
43718
  inst.hasValue = true;
43719
43719
  inst.value = value;
@@ -70307,6 +70307,55 @@ var ACTION_BUTTON_PRESETS = [
70307
70307
  label: "Return",
70308
70308
  defaultAction: "prevSlide",
70309
70309
  iconPath: "M18 8 L18 14 L6 14 M6 14 L10 10 M6 14 L10 18"
70310
+ },
70311
+ {
70312
+ shapeType: "actionButtonHome",
70313
+ label: "Home",
70314
+ defaultAction: "firstSlide",
70315
+ // House: roof + body
70316
+ iconPath: "M12 4 L20 11 L20 20 L14 20 L14 14 L10 14 L10 20 L4 20 L4 11 Z"
70317
+ },
70318
+ {
70319
+ shapeType: "actionButtonHelp",
70320
+ label: "Help",
70321
+ defaultAction: "none",
70322
+ // Question mark
70323
+ iconPath: "M9 9 a3 3 0 1 1 4 2.8 c-1 0.4 -1 1.2 -1 2 M12 17 v0.5"
70324
+ },
70325
+ {
70326
+ shapeType: "actionButtonInformation",
70327
+ label: "Information",
70328
+ defaultAction: "none",
70329
+ // Lower-case "i": dot + body
70330
+ iconPath: "M12 6 v0.01 M12 10 v8"
70331
+ },
70332
+ {
70333
+ shapeType: "actionButtonDocument",
70334
+ label: "Document",
70335
+ defaultAction: "none",
70336
+ // Document with folded corner
70337
+ iconPath: "M6 4 L14 4 L18 8 L18 20 L6 20 Z M14 4 L14 8 L18 8"
70338
+ },
70339
+ {
70340
+ shapeType: "actionButtonSound",
70341
+ label: "Sound",
70342
+ defaultAction: "none",
70343
+ // Speaker cone + sound waves
70344
+ iconPath: "M4 10 L4 14 L8 14 L12 18 L12 6 L8 10 Z M16 9 a4 4 0 0 1 0 6 M18 7 a7 7 0 0 1 0 10"
70345
+ },
70346
+ {
70347
+ shapeType: "actionButtonMovie",
70348
+ label: "Movie",
70349
+ defaultAction: "none",
70350
+ // Film strip with play triangle
70351
+ iconPath: "M4 6 L20 6 L20 18 L4 18 Z M10 9 L15 12 L10 15 Z"
70352
+ },
70353
+ {
70354
+ shapeType: "actionButtonBlank",
70355
+ label: "Custom",
70356
+ defaultAction: "none",
70357
+ // No glyph — empty path. The button still renders as a rounded rect via clip-path.
70358
+ iconPath: ""
70310
70359
  }
70311
70360
  ];
70312
70361
  Object.fromEntries(ACTION_BUTTON_PRESETS.map((p3) => [p3.shapeType, p3.defaultAction]));
@@ -72586,8 +72635,8 @@ function hexToRgb2(hex) {
72586
72635
  };
72587
72636
  }
72588
72637
  function rgbToHex(r2, g2, b2) {
72589
- const clamp2 = (v) => Math.max(0, Math.min(255, Math.round(v)));
72590
- return `#${clamp2(r2).toString(16).padStart(2, "0")}${clamp2(g2).toString(16).padStart(2, "0")}${clamp2(b2).toString(16).padStart(2, "0")}`;
72638
+ const clamp3 = (v) => Math.max(0, Math.min(255, Math.round(v)));
72639
+ return `#${clamp3(r2).toString(16).padStart(2, "0")}${clamp3(g2).toString(16).padStart(2, "0")}${clamp3(b2).toString(16).padStart(2, "0")}`;
72591
72640
  }
72592
72641
  function rgbToHsl(r2, g2, b2) {
72593
72642
  const rn = r2 / 255;
@@ -74797,6 +74846,11 @@ function getShapeClipPath(shapeType, adjustments, width, height) {
74797
74846
  }
74798
74847
  const normalized = shapeType.toLowerCase();
74799
74848
  if (normalized === "round1rect" || normalized === "round2samerect" || normalized === "round2diagrect" || normalized === "sniproundrect" || normalized === "snip1rect" || normalized === "snip2diagrect") {
74849
+ if (adjustments?.adj !== void 0 && width && height) {
74850
+ const ratio = Math.min(Math.max(adjustments.adj / 1e5, 0), 0.5);
74851
+ const radiusPx = Math.round(Math.min(width, height) * ratio);
74852
+ return `inset(0 round ${radiusPx}px)`;
74853
+ }
74800
74854
  return "inset(0 round 18px)";
74801
74855
  }
74802
74856
  if (normalized === "can" || normalized === "cylinder") {
@@ -75443,6 +75497,128 @@ function mapDagBlendModeToCss(blend) {
75443
75497
  return void 0;
75444
75498
  }
75445
75499
  }
75500
+ function getImageAlphaFilterId(elementId) {
75501
+ return `imgalpha-${elementId}`;
75502
+ }
75503
+ function hasAdvancedImageAlphaEffects(element2) {
75504
+ if (!pptxViewerCore.isImageLikeElement(element2)) {
75505
+ return false;
75506
+ }
75507
+ const e2 = element2.imageEffects;
75508
+ if (!e2) {
75509
+ return false;
75510
+ }
75511
+ return Boolean(
75512
+ typeof e2.alphaModFix === "number" || e2.alphaInv || e2.alphaCeiling || e2.alphaFloor || typeof e2.alphaRepl === "number" || typeof e2.alphaBiLevel === "number" || typeof e2.biLevel === "number" || e2.lum && (typeof e2.lum.bright === "number" || typeof e2.lum.contrast === "number") || e2.hsl && (typeof e2.hsl.sat === "number" || typeof e2.hsl.lum === "number") || e2.tint && typeof e2.tint.amt === "number" || e2.clrRepl
75513
+ );
75514
+ }
75515
+ function renderImageAlphaSvgFilter(element2) {
75516
+ if (!pptxViewerCore.isImageLikeElement(element2)) {
75517
+ return null;
75518
+ }
75519
+ const e2 = element2.imageEffects;
75520
+ if (!e2 || !hasAdvancedImageAlphaEffects(element2)) {
75521
+ return null;
75522
+ }
75523
+ const filterId = getImageAlphaFilterId(element2.id);
75524
+ const primitives = [];
75525
+ let resultIdx = 0;
75526
+ let inputRef = "SourceGraphic";
75527
+ const next = (jsx235) => {
75528
+ const result = `r${resultIdx++}`;
75529
+ primitives.push(jsx235(inputRef, result));
75530
+ inputRef = result;
75531
+ };
75532
+ if (typeof e2.alphaModFix === "number") {
75533
+ const mul = clamp(e2.alphaModFix / 100, 0, 1);
75534
+ next((inp, out) => /* @__PURE__ */ jsxRuntime.jsx(
75535
+ "feColorMatrix",
75536
+ {
75537
+ in: inp,
75538
+ result: out,
75539
+ type: "matrix",
75540
+ values: `1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 ${mul} 0`
75541
+ },
75542
+ out
75543
+ ));
75544
+ }
75545
+ if (e2.alphaInv) {
75546
+ next((inp, out) => /* @__PURE__ */ jsxRuntime.jsx("feComponentTransfer", { in: inp, result: out, children: /* @__PURE__ */ jsxRuntime.jsx("feFuncA", { type: "linear", slope: -1, intercept: 1 }) }, out));
75547
+ }
75548
+ if (e2.alphaCeiling) {
75549
+ next((inp, out) => /* @__PURE__ */ jsxRuntime.jsx("feComponentTransfer", { in: inp, result: out, children: /* @__PURE__ */ jsxRuntime.jsx("feFuncA", { type: "discrete", tableValues: "0 1 1 1 1 1 1 1 1 1" }) }, out));
75550
+ }
75551
+ if (e2.alphaFloor) {
75552
+ next((inp, out) => /* @__PURE__ */ jsxRuntime.jsx("feComponentTransfer", { in: inp, result: out, children: /* @__PURE__ */ jsxRuntime.jsx("feFuncA", { type: "discrete", tableValues: "0 0 0 0 0 0 0 0 0 1" }) }, out));
75553
+ }
75554
+ if (typeof e2.alphaRepl === "number") {
75555
+ const a2 = clamp(e2.alphaRepl / 100, 0, 1);
75556
+ next((inp, out) => /* @__PURE__ */ jsxRuntime.jsx("feComponentTransfer", { in: inp, result: out, children: /* @__PURE__ */ jsxRuntime.jsx("feFuncA", { type: "linear", slope: 0, intercept: a2 }) }, out));
75557
+ }
75558
+ if (typeof e2.alphaBiLevel === "number") {
75559
+ const t2 = clamp(e2.alphaBiLevel / 100, 0, 1);
75560
+ const table = Array.from({ length: 10 }, (_, i3) => i3 / 10 >= t2 ? "1" : "0").join(" ");
75561
+ next((inp, out) => /* @__PURE__ */ jsxRuntime.jsx("feComponentTransfer", { in: inp, result: out, children: /* @__PURE__ */ jsxRuntime.jsx("feFuncA", { type: "discrete", tableValues: table }) }, out));
75562
+ }
75563
+ if (typeof e2.biLevel === "number") {
75564
+ next((inp, out) => /* @__PURE__ */ jsxRuntime.jsx("feColorMatrix", { in: inp, result: out, type: "saturate", values: "0" }, out));
75565
+ const t2 = clamp(e2.biLevel / 100, 0, 1);
75566
+ const tbl = t2 < 0.5 ? "0 1" : "0 1";
75567
+ next((inp, out) => /* @__PURE__ */ jsxRuntime.jsxs("feComponentTransfer", { in: inp, result: out, children: [
75568
+ /* @__PURE__ */ jsxRuntime.jsx("feFuncR", { type: "discrete", tableValues: tbl }),
75569
+ /* @__PURE__ */ jsxRuntime.jsx("feFuncG", { type: "discrete", tableValues: tbl }),
75570
+ /* @__PURE__ */ jsxRuntime.jsx("feFuncB", { type: "discrete", tableValues: tbl })
75571
+ ] }, out));
75572
+ }
75573
+ if (e2.lum && (typeof e2.lum.bright === "number" || typeof e2.lum.contrast === "number")) {
75574
+ const b2 = (e2.lum.bright ?? 0) / 100;
75575
+ const c2 = 1 + (e2.lum.contrast ?? 0) / 100;
75576
+ const slope = c2;
75577
+ const intercept = b2 + (1 - c2) / 2;
75578
+ next((inp, out) => /* @__PURE__ */ jsxRuntime.jsxs("feComponentTransfer", { in: inp, result: out, children: [
75579
+ /* @__PURE__ */ jsxRuntime.jsx("feFuncR", { type: "linear", slope, intercept }),
75580
+ /* @__PURE__ */ jsxRuntime.jsx("feFuncG", { type: "linear", slope, intercept }),
75581
+ /* @__PURE__ */ jsxRuntime.jsx("feFuncB", { type: "linear", slope, intercept })
75582
+ ] }, out));
75583
+ }
75584
+ if (e2.hsl && typeof e2.hsl.sat === "number") {
75585
+ const v = clamp(1 + e2.hsl.sat / 100, 0, 2);
75586
+ next((inp, out) => /* @__PURE__ */ jsxRuntime.jsx("feColorMatrix", { in: inp, result: out, type: "saturate", values: String(v) }, out));
75587
+ }
75588
+ if (e2.tint && typeof e2.tint.amt === "number" && e2.tint.amt < 0) {
75589
+ const v = clamp(1 + e2.tint.amt / 100, 0, 1);
75590
+ next((inp, out) => /* @__PURE__ */ jsxRuntime.jsx("feColorMatrix", { in: inp, result: out, type: "saturate", values: String(v) }, out));
75591
+ }
75592
+ if (e2.clrRepl) {
75593
+ const c2 = hexToRgbUnit(e2.clrRepl.color);
75594
+ next((inp, out) => /* @__PURE__ */ jsxRuntime.jsx(
75595
+ "feColorMatrix",
75596
+ {
75597
+ in: inp,
75598
+ result: out,
75599
+ type: "matrix",
75600
+ values: `0 0 0 0 ${c2.r} 0 0 0 0 ${c2.g} 0 0 0 0 ${c2.b} 0 0 0 1 0`
75601
+ },
75602
+ out
75603
+ ));
75604
+ }
75605
+ if (primitives.length === 0) {
75606
+ return null;
75607
+ }
75608
+ return /* @__PURE__ */ jsxRuntime.jsx(
75609
+ "svg",
75610
+ {
75611
+ width: 0,
75612
+ height: 0,
75613
+ style: { position: "absolute", overflow: "hidden" },
75614
+ "aria-hidden": "true",
75615
+ children: /* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsx("filter", { id: filterId, colorInterpolationFilters: "sRGB", children: primitives }) })
75616
+ }
75617
+ );
75618
+ }
75619
+ function clamp(v, lo, hi) {
75620
+ return v < lo ? lo : v > hi ? hi : v;
75621
+ }
75446
75622
  function getDagDuotoneFilterId(elementId) {
75447
75623
  return `dag-duotone-${elementId}`;
75448
75624
  }
@@ -75526,6 +75702,9 @@ function getImageEffectsFilter(element2, options) {
75526
75702
  const filterId = getDuotoneFilterId(element2.id);
75527
75703
  filters.push(`url(#${filterId})`);
75528
75704
  }
75705
+ if (hasAdvancedImageAlphaEffects(element2)) {
75706
+ filters.push(`url(#${getImageAlphaFilterId(element2.id)})`);
75707
+ }
75529
75708
  if (effects.artisticEffect) {
75530
75709
  const radius = effects.artisticRadius ?? 5;
75531
75710
  if (needsSvgArtisticFilter(effects.artisticEffect)) {
@@ -75699,6 +75878,39 @@ function getEffectDagCssFilter(style, elementId) {
75699
75878
  return filters.length > 0 ? filters.join(" ") : void 0;
75700
75879
  }
75701
75880
  var getEffectDagFilter = getEffectDagCssFilter;
75881
+ function getResolvedShapeClipPathFor(shapeType, width, height, adjustments) {
75882
+ if (!shapeType) {
75883
+ return void 0;
75884
+ }
75885
+ if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) {
75886
+ return getShapeClipPath(shapeType, adjustments, width, height);
75887
+ }
75888
+ if (adjustments && Object.keys(adjustments).length > 0) {
75889
+ const adjusted = pptxViewerCore.getAdjustmentAwareShapeClipPath(shapeType, width, height, adjustments);
75890
+ if (adjusted !== void 0) {
75891
+ return adjusted;
75892
+ }
75893
+ }
75894
+ const fromPreset = pptxViewerCore.getShapeClipPathFromPreset(shapeType, width, height, adjustments);
75895
+ if (fromPreset !== void 0) {
75896
+ return fromPreset;
75897
+ }
75898
+ const cloud = pptxViewerCore.getCloudPathForRendering(shapeType, width, height);
75899
+ if (cloud !== void 0) {
75900
+ return cloud;
75901
+ }
75902
+ return getShapeClipPath(shapeType, adjustments, width, height);
75903
+ }
75904
+ function getResolvedShapeClipPath(element2, width, height) {
75905
+ const shapeType = element2.shapeType;
75906
+ if (!shapeType) {
75907
+ return void 0;
75908
+ }
75909
+ const w = element2.width;
75910
+ const h2 = element2.height;
75911
+ const adjustments = element2.shapeAdjustments;
75912
+ return getResolvedShapeClipPathFor(shapeType, w, h2, adjustments);
75913
+ }
75702
75914
 
75703
75915
  // src/viewer/utils/shape-round-rect.ts
75704
75916
  function localClampAdjustment(value) {
@@ -75770,6 +75982,27 @@ var MATERIAL_MAP = {
75770
75982
  filter: "brightness(1.1) contrast(0.85)",
75771
75983
  // Translucent powder: slight translucent glow
75772
75984
  backgroundImage: "radial-gradient(ellipse at 30% 30%, rgba(255,255,255,0.1) 0%, transparent 60%)"
75985
+ },
75986
+ // Legacy materials (PowerPoint 2007 / earlier). Render as muted variants
75987
+ // of the modern equivalents so legacy decks still resemble the originals.
75988
+ legacyMatte: {
75989
+ filter: "brightness(0.92) saturate(0.85)",
75990
+ backgroundImage: "linear-gradient(180deg, rgba(255,255,255,0.03) 0%, transparent 50%, rgba(0,0,0,0.04) 100%)"
75991
+ },
75992
+ legacyPlastic: {
75993
+ filter: "brightness(1.02) contrast(1.03)",
75994
+ boxShadow: "inset -2px -2px 5px rgba(255,255,255,0.3)",
75995
+ backgroundImage: "radial-gradient(ellipse 35% 25% at 25% 20%, rgba(255,255,255,0.15) 0%, transparent 70%)"
75996
+ },
75997
+ legacyMetal: {
75998
+ filter: "brightness(1.05) contrast(1.1) saturate(1.1)",
75999
+ boxShadow: "inset -2px -2px 6px rgba(255,255,255,0.35), inset 1px 1px 3px rgba(255,255,255,0.15)",
76000
+ backgroundImage: "linear-gradient(135deg, rgba(255,255,255,0.18) 0%, rgba(255,255,255,0.06) 25%, transparent 50%, rgba(0,0,0,0.05) 80%)"
76001
+ },
76002
+ legacyWireframe: {
76003
+ filter: "brightness(1) contrast(1.4) saturate(0.6)",
76004
+ // Wireframe: high contrast outline-emphasising look
76005
+ boxShadow: "inset 0 0 0 1px rgba(0,0,0,0.4)"
75773
76006
  }
75774
76007
  };
75775
76008
  function getMaterialCssOverrides(material) {
@@ -76724,8 +76957,7 @@ function getShapeVisualStyle(element2, hasFill, fillColor, strokeWidth, strokeCo
76724
76957
  return {};
76725
76958
  }
76726
76959
  const normalizedShapeType = getShapeType(element2.shapeType);
76727
- const shapeType = element2.shapeType || normalizedShapeType;
76728
- const clipPath = getShapeClipPath(shapeType);
76960
+ const clipPath = getResolvedShapeClipPath(element2);
76729
76961
  const fillOpacity = element2.shapeStyle?.fillOpacity;
76730
76962
  const strokeOpacity = element2.shapeStyle?.strokeOpacity;
76731
76963
  const strokeDash = normalizeStrokeDashType(element2.shapeStyle?.strokeDash);
@@ -77327,7 +77559,7 @@ function getImageMaskStyle(element2) {
77327
77559
  if (normalized === "can" || normalized === "cylinder") {
77328
77560
  return { borderRadius: "48% / 12%" };
77329
77561
  }
77330
- const clipPath = getShapeClipPath(shapeType);
77562
+ const clipPath = getResolvedShapeClipPath(element2);
77331
77563
  if (!clipPath) {
77332
77564
  return void 0;
77333
77565
  }
@@ -77990,8 +78222,8 @@ function hexToRgb3(hex) {
77990
78222
  };
77991
78223
  }
77992
78224
  function rgbToHex2(r2, g2, b2) {
77993
- const clamp2 = (v) => Math.max(0, Math.min(255, Math.round(v)));
77994
- return `#${clamp2(r2).toString(16).padStart(2, "0").toUpperCase()}${clamp2(g2).toString(16).padStart(2, "0").toUpperCase()}${clamp2(b2).toString(16).padStart(2, "0").toUpperCase()}`;
78225
+ const clamp3 = (v) => Math.max(0, Math.min(255, Math.round(v)));
78226
+ return `#${clamp3(r2).toString(16).padStart(2, "0").toUpperCase()}${clamp3(g2).toString(16).padStart(2, "0").toUpperCase()}${clamp3(b2).toString(16).padStart(2, "0").toUpperCase()}`;
77995
78227
  }
77996
78228
  function tintColor(hex, tintFactor) {
77997
78229
  const { r: r2, g: g2, b: b2 } = hexToRgb3(hex);
@@ -78922,13 +79154,13 @@ function cellStyleToCss(style) {
78922
79154
  }
78923
79155
  if (style.textDirection) {
78924
79156
  switch (style.textDirection) {
78925
- case "vertical":
79157
+ case "vert":
78926
79158
  case "eaVert":
78927
79159
  case "wordArtVert":
78928
79160
  case "wordArtVertRtl":
78929
79161
  css.writingMode = "vertical-rl";
78930
79162
  break;
78931
- case "vertical270":
79163
+ case "vert270":
78932
79164
  case "mongolianVert":
78933
79165
  css.writingMode = "vertical-lr";
78934
79166
  break;
@@ -79335,8 +79567,8 @@ function renderTableElement(element2, textStyle, options) {
79335
79567
  {
79336
79568
  style: rowHeight ? { height: rowHeight } : void 0,
79337
79569
  children: cells.map((cell, cellIndex) => {
79338
- const isHMerged = cell["@_hMerge"] === "1" || cell["@_hMerge"] === true;
79339
- const isVMerged = cell["@_vMerge"] === "1" || cell["@_vMerge"] === true;
79570
+ const isHMerged = cell["@_hMerge"] === "1";
79571
+ const isVMerged = cell["@_vMerge"] === "1";
79340
79572
  if (isHMerged || isVMerged) {
79341
79573
  return null;
79342
79574
  }
@@ -79455,8 +79687,8 @@ function hexToRgb4(hex) {
79455
79687
  ];
79456
79688
  }
79457
79689
  function rgbToHex3(r2, g2, b2) {
79458
- const clamp2 = (v) => Math.max(0, Math.min(255, Math.round(v)));
79459
- return `#${clamp2(r2).toString(16).padStart(2, "0")}${clamp2(g2).toString(16).padStart(2, "0")}${clamp2(b2).toString(16).padStart(2, "0")}`;
79690
+ const clamp3 = (v) => Math.max(0, Math.min(255, Math.round(v)));
79691
+ return `#${clamp3(r2).toString(16).padStart(2, "0")}${clamp3(g2).toString(16).padStart(2, "0")}${clamp3(b2).toString(16).padStart(2, "0")}`;
79460
79692
  }
79461
79693
  function tint(hex, amount) {
79462
79694
  const [r2, g2, b2] = hexToRgb4(hex);
@@ -81374,7 +81606,7 @@ function resolveRegionCode(label) {
81374
81606
  return REGION_ALIAS_MAP[normalized];
81375
81607
  }
81376
81608
  function lerpColor(a2, b2, t2) {
81377
- const clamp2 = (v) => Math.max(0, Math.min(255, Math.round(v)));
81609
+ const clamp3 = (v) => Math.max(0, Math.min(255, Math.round(v)));
81378
81610
  const parse = (hex) => {
81379
81611
  const h2 = hex.replace("#", "");
81380
81612
  return [
@@ -81385,9 +81617,9 @@ function lerpColor(a2, b2, t2) {
81385
81617
  };
81386
81618
  const [r1, g1, b1] = parse(a2);
81387
81619
  const [r2, g2, b22] = parse(b2);
81388
- const r3 = clamp2(r1 + (r2 - r1) * t2);
81389
- const g3 = clamp2(g1 + (g2 - g1) * t2);
81390
- const bl = clamp2(b1 + (b22 - b1) * t2);
81620
+ const r3 = clamp3(r1 + (r2 - r1) * t2);
81621
+ const g3 = clamp3(g1 + (g2 - g1) * t2);
81622
+ const bl = clamp3(b1 + (b22 - b1) * t2);
81391
81623
  return `#${r3.toString(16).padStart(2, "0")}${g3.toString(16).padStart(2, "0")}${bl.toString(16).padStart(2, "0")}`;
81392
81624
  }
81393
81625
  function sequentialColorScale(t2) {
@@ -85345,6 +85577,15 @@ function copyFormatFromElement(element2) {
85345
85577
  }
85346
85578
  return result;
85347
85579
  }
85580
+ function definedEntries(obj) {
85581
+ const out = {};
85582
+ for (const key in obj) {
85583
+ if (obj[key] !== void 0) {
85584
+ out[key] = obj[key];
85585
+ }
85586
+ }
85587
+ return out;
85588
+ }
85348
85589
  function applyFormatToElement(element2, format) {
85349
85590
  let updated = { ...element2 };
85350
85591
  if (format.shapeStyle && pptxViewerCore.hasShapeProperties(updated)) {
@@ -85352,7 +85593,7 @@ function applyFormatToElement(element2, format) {
85352
85593
  ...updated,
85353
85594
  shapeStyle: {
85354
85595
  ...updated.shapeStyle,
85355
- ...format.shapeStyle
85596
+ ...definedEntries(format.shapeStyle)
85356
85597
  }
85357
85598
  };
85358
85599
  }
@@ -85361,12 +85602,18 @@ function applyFormatToElement(element2, format) {
85361
85602
  ...updated,
85362
85603
  textStyle: {
85363
85604
  ...updated.textStyle,
85364
- ...format.textStyle
85605
+ ...definedEntries(format.textStyle)
85365
85606
  }
85366
85607
  };
85367
85608
  }
85368
85609
  return updated;
85369
85610
  }
85611
+ function hasCopyableFormat(element2) {
85612
+ if (!element2) {
85613
+ return false;
85614
+ }
85615
+ return pptxViewerCore.hasShapeProperties(element2) || pptxViewerCore.hasTextProperties(element2);
85616
+ }
85370
85617
 
85371
85618
  // src/viewer/utils/animation-preview.ts
85372
85619
  var PRESET_TO_EFFECT = {
@@ -86715,8 +86962,8 @@ function ThumbnailTable({
86715
86962
  {
86716
86963
  style: rowHeight ? { height: rowHeight } : void 0,
86717
86964
  children: cells.map((cell, ci) => {
86718
- const isHMerged = cell["@_hMerge"] === "1" || cell["@_hMerge"] === true;
86719
- const isVMerged = cell["@_vMerge"] === "1" || cell["@_vMerge"] === true;
86965
+ const isHMerged = cell["@_hMerge"] === "1";
86966
+ const isVMerged = cell["@_vMerge"] === "1";
86720
86967
  if (isHMerged || isVMerged) {
86721
86968
  return null;
86722
86969
  }
@@ -88139,6 +88386,59 @@ function WarpedText({
88139
88386
  }
88140
88387
  );
88141
88388
  }
88389
+ var GLYPH_BY_SHAPE = Object.fromEntries(
88390
+ ACTION_BUTTON_PRESETS.map((p3) => [p3.shapeType, p3.iconPath])
88391
+ );
88392
+ GLYPH_BY_SHAPE["actionButtonForwardOrNext"] = GLYPH_BY_SHAPE["actionButtonForwardNext"];
88393
+ GLYPH_BY_SHAPE["actionButtonBackOrPrevious"] = GLYPH_BY_SHAPE["actionButtonBackPrevious"];
88394
+ function isActionButtonShape(shapeType) {
88395
+ return Boolean(shapeType && shapeType in GLYPH_BY_SHAPE);
88396
+ }
88397
+ function getActionButtonGlyphPath(shapeType) {
88398
+ if (!shapeType) {
88399
+ return void 0;
88400
+ }
88401
+ const path = GLYPH_BY_SHAPE[shapeType];
88402
+ return path && path.length > 0 ? path : void 0;
88403
+ }
88404
+ function ActionButtonGlyphOverlay({
88405
+ element: element2,
88406
+ color
88407
+ }) {
88408
+ const shapeType = "shapeType" in element2 ? element2.shapeType : void 0;
88409
+ const path = getActionButtonGlyphPath(shapeType);
88410
+ if (!path) {
88411
+ return null;
88412
+ }
88413
+ const stroke = color ?? ("textStyle" in element2 && element2.textStyle?.color || "#ffffff");
88414
+ return /* @__PURE__ */ jsxRuntime.jsx(
88415
+ "svg",
88416
+ {
88417
+ viewBox: "0 0 24 24",
88418
+ width: "100%",
88419
+ height: "100%",
88420
+ preserveAspectRatio: "xMidYMid meet",
88421
+ style: {
88422
+ position: "absolute",
88423
+ inset: 0,
88424
+ pointerEvents: "none",
88425
+ padding: "20%"
88426
+ },
88427
+ "aria-hidden": "true",
88428
+ children: /* @__PURE__ */ jsxRuntime.jsx(
88429
+ "path",
88430
+ {
88431
+ d: path,
88432
+ fill: "none",
88433
+ stroke,
88434
+ strokeWidth: 2,
88435
+ strokeLinecap: "round",
88436
+ strokeLinejoin: "round"
88437
+ }
88438
+ )
88439
+ }
88440
+ );
88441
+ }
88142
88442
  function ColorChangedImage({
88143
88443
  src,
88144
88444
  clrChange,
@@ -88409,6 +88709,7 @@ function renderImg(el, style, filter, alt, opacity) {
88409
88709
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
88410
88710
  tileDuotoneColors && renderDuotoneSvgFilter(el.id, tileDuotoneColors.color1, tileDuotoneColors.color2),
88411
88711
  renderArtisticEffectSvgFilter(el.id, artisticEffectName, artisticRadius),
88712
+ renderImageAlphaSvgFilter(el),
88412
88713
  /* @__PURE__ */ jsxRuntime.jsx(
88413
88714
  "div",
88414
88715
  {
@@ -88430,6 +88731,7 @@ function renderImg(el, style, filter, alt, opacity) {
88430
88731
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
88431
88732
  duotoneColors && !useDuotoneCanvas && renderDuotoneSvgFilter(el.id, duotoneColors.color1, duotoneColors.color2),
88432
88733
  renderArtisticEffectSvgFilter(el.id, artisticEffectName, artisticRadius),
88734
+ renderImageAlphaSvgFilter(el),
88433
88735
  useDuotoneCanvas && duotoneColors ? /* @__PURE__ */ jsxRuntime.jsx(
88434
88736
  DuotoneImage,
88435
88737
  {
@@ -90938,8 +91240,11 @@ function renderBody(el, isImg, isEditing, editText, spellCheck, txtSE, txtS, vec
90938
91240
  ...scene3dStyle.perspective ? { perspective: scene3dStyle.perspective } : {},
90939
91241
  ...scene3dStyle.transformStyle ? { transformStyle: scene3dStyle.transformStyle } : {}
90940
91242
  } : void 0;
91243
+ const shapeTypeForGlyph = "shapeType" in el ? el.shapeType : void 0;
91244
+ const showActionButtonGlyph = isActionButtonShape(shapeTypeForGlyph);
90941
91245
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
90942
91246
  vecShape,
91247
+ showActionButtonGlyph && /* @__PURE__ */ jsxRuntime.jsx(ActionButtonGlyphOverlay, { element: el }),
90943
91248
  isTxtEl ? useSvgWarp ? /* @__PURE__ */ jsxRuntime.jsx(
90944
91249
  "div",
90945
91250
  {
@@ -91749,11 +92054,16 @@ function usePresenceTracking({
91749
92054
  if (cid === localClientId) {
91750
92055
  return;
91751
92056
  }
91752
- const raw = state2?.presence;
92057
+ const stateRecord = state2;
92058
+ const raw = stateRecord?.presence;
91753
92059
  if (!raw || typeof raw !== "object") {
91754
92060
  return;
91755
92061
  }
91756
- const sanitized = sanitizePresence({ ...raw, clientId: cid }, canvasWidth, canvasHeight);
92062
+ const sanitized = sanitizePresence(
92063
+ { ...raw, clientId: cid },
92064
+ canvasWidth,
92065
+ canvasHeight
92066
+ );
91757
92067
  if (!sanitized) {
91758
92068
  return;
91759
92069
  }
@@ -91821,15 +92131,9 @@ function useYjsProvider({ config }) {
91821
92131
  try {
91822
92132
  const [Y, { WebsocketProvider: WebsocketProvider2 }] = await Promise.all([Promise.resolve().then(() => (init_yjs(), yjs_exports)), Promise.resolve().then(() => (init_y_websocket(), y_websocket_exports))]);
91823
92133
  const yDoc = new Y.Doc();
91824
- const provider = new WebsocketProvider2(
91825
- config.serverUrl,
91826
- roomId,
91827
- yDoc,
91828
- // eslint-disable-line @typescript-eslint/no-explicit-any
91829
- {
91830
- params: config.authToken ? { token: config.authToken } : void 0
91831
- }
91832
- );
92134
+ const provider = new WebsocketProvider2(config.serverUrl, roomId, yDoc, {
92135
+ params: config.authToken ? { token: config.authToken } : void 0
92136
+ });
91833
92137
  let connected = false;
91834
92138
  const handleStatus = (event) => {
91835
92139
  if (event.status === "connected") {
@@ -95490,90 +95794,101 @@ var SlideNotesPanel = ({
95490
95794
  });
95491
95795
  const hasNotes = draft.trim().length > 0;
95492
95796
  const slideLabel = activeSlide ? t2("pptx.notes.slideN", { n: activeSlide.slideNumber }) : t2("pptx.notes.noSlide");
95493
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col border-t border-border/60 bg-background select-none", children: [
95494
- /* @__PURE__ */ jsxRuntime.jsxs(
95495
- "button",
95496
- {
95497
- type: "button",
95498
- onClick: onToggle,
95499
- className: "flex items-center gap-1.5 px-3 py-1 text-[11px] text-muted-foreground hover:text-foreground hover:bg-accent/30 transition-colors w-full text-left shrink-0",
95500
- "aria-expanded": isExpanded,
95501
- "aria-controls": "slide-notes-content",
95502
- children: [
95503
- "Notes",
95504
- !isExpanded && hasNotes && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground/50 text-[10px]", children: "(has notes)" })
95505
- ]
95506
- }
95507
- ),
95508
- isExpanded && /* @__PURE__ */ jsxRuntime.jsxs(
95509
- "div",
95510
- {
95511
- id: "slide-notes-content",
95512
- className: "px-3 pb-2 overflow-y-auto",
95513
- style: { maxHeight: panelHeight ?? EXPANDED_MAX_HEIGHT + 40 },
95514
- children: [
95515
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[10px] text-muted-foreground mb-1", children: slideLabel }),
95516
- canEdit ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
95517
- /* @__PURE__ */ jsxRuntime.jsx(
95518
- NotesToolbar,
95519
- {
95520
- isRichEditEnabled,
95521
- showLinkPopover,
95522
- savedSelectionText: savedSelectionRef.current?.text ?? "",
95523
- hasAllSlides: allSlides !== void 0 && allSlides.length > 0,
95524
- onApplyRichCommand: applyRichCommand,
95525
- onToggleBulletList: toggleBulletList,
95526
- onToggleNumberedList: toggleNumberedList,
95527
- onIndent: handleIndent,
95528
- onOutdent: handleOutdent,
95529
- onLinkButtonClick: handleLinkButtonClick,
95530
- onInsertLink: handleInsertLink,
95531
- onCloseLinkPopover: () => setShowLinkPopover(false),
95532
- onPrintClick: () => setShowPrintDialog(true),
95533
- onToggleRichEdit: () => setIsRichEditEnabled((prev) => !prev)
95534
- }
95535
- ),
95536
- isRichEditEnabled ? /* @__PURE__ */ jsxRuntime.jsx(
95537
- "div",
95538
- {
95539
- ref: richEditorRef,
95540
- contentEditable: true,
95541
- suppressContentEditableWarning: true,
95542
- onInput: handleRichInput,
95543
- onBlur: handleBlur,
95544
- onKeyDown: handleKeyDownRich,
95545
- onClick: handleEditorClick,
95546
- className: "w-full overflow-y-auto rounded-md border border-border/50 bg-muted/60 px-2.5 py-1.5 text-xs text-foreground focus:border-primary/50 focus:outline-none focus:ring-1 focus:ring-primary/30 transition-colors whitespace-pre-wrap",
95547
- style: { maxHeight: EXPANDED_MAX_HEIGHT - 8, minHeight: 72 }
95548
- }
95549
- ) : /* @__PURE__ */ jsxRuntime.jsx(
95550
- "textarea",
95551
- {
95552
- ref: textareaRef,
95553
- name: "slide-notes",
95554
- value: draft,
95555
- onChange: handlePlainChange,
95556
- onBlur: handleBlur,
95557
- onKeyDown: handleKeyDownPlain,
95558
- placeholder: t2("pptx.notes.clickToAddNotes"),
95559
- rows: 4,
95560
- className: "w-full resize-none rounded-md border border-border/50 bg-muted/60 px-2.5 py-1.5 text-xs text-foreground placeholder:text-muted-foreground focus:border-primary/50 focus:outline-none focus:ring-1 focus:ring-primary/30 transition-colors",
95561
- style: { maxHeight: EXPANDED_MAX_HEIGHT - 8 }
95562
- }
95563
- )
95564
- ] }) : /* @__PURE__ */ jsxRuntime.jsx(
95565
- "div",
95566
- {
95567
- className: "w-full rounded-md border border-border/30 bg-muted/40 px-2.5 py-1.5 text-xs text-muted-foreground overflow-y-auto whitespace-pre-wrap",
95568
- style: { maxHeight: EXPANDED_MAX_HEIGHT - 32, minHeight: 60 },
95569
- children: hasNotes ? renderRichNotesSegments(draftSegments) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "italic text-muted-foreground", children: t2("pptx.notes.noNotes") })
95570
- }
95571
- )
95572
- ]
95573
- }
95574
- ),
95575
- showPrintDialog && allSlides && /* @__PURE__ */ jsxRuntime.jsx(NotesPrintDialog, { slides: allSlides, onClose: () => setShowPrintDialog(false) })
95576
- ] });
95797
+ return /* @__PURE__ */ jsxRuntime.jsxs(
95798
+ "div",
95799
+ {
95800
+ className: cn(
95801
+ "flex flex-col border-t border-border/60 bg-background select-none",
95802
+ // On mobile, hide the entire notes strip when collapsed — the
95803
+ // MobileBottomBar's Notes button is the entry point instead.
95804
+ !isExpanded && "max-md:hidden"
95805
+ ),
95806
+ children: [
95807
+ /* @__PURE__ */ jsxRuntime.jsxs(
95808
+ "button",
95809
+ {
95810
+ type: "button",
95811
+ onClick: onToggle,
95812
+ className: "flex items-center gap-1.5 px-3 py-1 text-[11px] text-muted-foreground hover:text-foreground hover:bg-accent/30 transition-colors w-full text-left shrink-0 max-md:hidden",
95813
+ "aria-expanded": isExpanded,
95814
+ "aria-controls": "slide-notes-content",
95815
+ children: [
95816
+ "Notes",
95817
+ !isExpanded && hasNotes && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground/50 text-[10px]", children: "(has notes)" })
95818
+ ]
95819
+ }
95820
+ ),
95821
+ isExpanded && /* @__PURE__ */ jsxRuntime.jsxs(
95822
+ "div",
95823
+ {
95824
+ id: "slide-notes-content",
95825
+ className: "px-3 pb-2 overflow-y-auto",
95826
+ style: { maxHeight: panelHeight ?? EXPANDED_MAX_HEIGHT + 40 },
95827
+ children: [
95828
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[10px] text-muted-foreground mb-1", children: slideLabel }),
95829
+ canEdit ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
95830
+ /* @__PURE__ */ jsxRuntime.jsx(
95831
+ NotesToolbar,
95832
+ {
95833
+ isRichEditEnabled,
95834
+ showLinkPopover,
95835
+ savedSelectionText: savedSelectionRef.current?.text ?? "",
95836
+ hasAllSlides: allSlides !== void 0 && allSlides.length > 0,
95837
+ onApplyRichCommand: applyRichCommand,
95838
+ onToggleBulletList: toggleBulletList,
95839
+ onToggleNumberedList: toggleNumberedList,
95840
+ onIndent: handleIndent,
95841
+ onOutdent: handleOutdent,
95842
+ onLinkButtonClick: handleLinkButtonClick,
95843
+ onInsertLink: handleInsertLink,
95844
+ onCloseLinkPopover: () => setShowLinkPopover(false),
95845
+ onPrintClick: () => setShowPrintDialog(true),
95846
+ onToggleRichEdit: () => setIsRichEditEnabled((prev) => !prev)
95847
+ }
95848
+ ),
95849
+ isRichEditEnabled ? /* @__PURE__ */ jsxRuntime.jsx(
95850
+ "div",
95851
+ {
95852
+ ref: richEditorRef,
95853
+ contentEditable: true,
95854
+ suppressContentEditableWarning: true,
95855
+ onInput: handleRichInput,
95856
+ onBlur: handleBlur,
95857
+ onKeyDown: handleKeyDownRich,
95858
+ onClick: handleEditorClick,
95859
+ className: "w-full overflow-y-auto rounded-md border border-border/50 bg-muted/60 px-2.5 py-1.5 text-xs text-foreground focus:border-primary/50 focus:outline-none focus:ring-1 focus:ring-primary/30 transition-colors whitespace-pre-wrap",
95860
+ style: { maxHeight: EXPANDED_MAX_HEIGHT - 8, minHeight: 72 }
95861
+ }
95862
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
95863
+ "textarea",
95864
+ {
95865
+ ref: textareaRef,
95866
+ name: "slide-notes",
95867
+ value: draft,
95868
+ onChange: handlePlainChange,
95869
+ onBlur: handleBlur,
95870
+ onKeyDown: handleKeyDownPlain,
95871
+ placeholder: t2("pptx.notes.clickToAddNotes"),
95872
+ rows: 4,
95873
+ className: "w-full resize-none rounded-md border border-border/50 bg-muted/60 px-2.5 py-1.5 text-xs text-foreground placeholder:text-muted-foreground focus:border-primary/50 focus:outline-none focus:ring-1 focus:ring-primary/30 transition-colors",
95874
+ style: { maxHeight: EXPANDED_MAX_HEIGHT - 8 }
95875
+ }
95876
+ )
95877
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx(
95878
+ "div",
95879
+ {
95880
+ className: "w-full rounded-md border border-border/30 bg-muted/40 px-2.5 py-1.5 text-xs text-muted-foreground overflow-y-auto whitespace-pre-wrap",
95881
+ style: { maxHeight: EXPANDED_MAX_HEIGHT - 32, minHeight: 60 },
95882
+ children: hasNotes ? renderRichNotesSegments(draftSegments) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "italic text-muted-foreground", children: t2("pptx.notes.noNotes") })
95883
+ }
95884
+ )
95885
+ ]
95886
+ }
95887
+ ),
95888
+ showPrintDialog && allSlides && /* @__PURE__ */ jsxRuntime.jsx(NotesPrintDialog, { slides: allSlides, onClose: () => setShowPrintDialog(false) })
95889
+ ]
95890
+ }
95891
+ );
95577
95892
  };
95578
95893
  var DB_NAME = "pptx-viewer-autosave";
95579
95894
  var DB_VERSION = 1;
@@ -98110,7 +98425,8 @@ function ArrangeSection(p3) {
98110
98425
  {
98111
98426
  type: "button",
98112
98427
  onClick: p3.onToggleFormatPainter,
98113
- disabled: !p3.canEdit,
98428
+ disabled: !p3.canEdit || p3.canActivateFormatPainter === false && !p3.formatPainterActive,
98429
+ "data-testid": "format-painter-toggle",
98114
98430
  className: cn(
98115
98431
  pill,
98116
98432
  p3.formatPainterActive ? "bg-amber-600 hover:bg-amber-500 text-amber-50" : ""
@@ -98562,7 +98878,8 @@ function HomeSection(p3) {
98562
98878
  const { fontFamily, fontSize } = extractFontInfo(p3.selectedElement);
98563
98879
  const handleNewSlide = React10.useCallback(() => {
98564
98880
  if (p3.layoutOptions.length > 0) {
98565
- p3.onInsertSlideFromLayout(p3.layoutOptions[0].path);
98881
+ const first = p3.layoutOptions[0];
98882
+ p3.onInsertSlideFromLayout(first.path, first.name);
98566
98883
  }
98567
98884
  }, [p3]);
98568
98885
  React10.useEffect(() => {
@@ -98649,7 +98966,8 @@ function HomeSection(p3) {
98649
98966
  {
98650
98967
  type: "button",
98651
98968
  onClick: p3.onToggleFormatPainter,
98652
- disabled: !p3.canEdit,
98969
+ disabled: !p3.canEdit || p3.canActivateFormatPainter === false && !p3.formatPainterActive,
98970
+ "data-testid": "format-painter-toggle",
98653
98971
  className: cn(
98654
98972
  gL,
98655
98973
  p3.formatPainterActive ? "bg-amber-600 hover:bg-amber-500 text-amber-50" : ""
@@ -98699,7 +99017,7 @@ function HomeSection(p3) {
98699
99017
  type: "button",
98700
99018
  className: "flex items-center gap-2 w-full px-3 py-1.5 text-xs text-foreground hover:bg-muted transition-colors",
98701
99019
  onClick: () => {
98702
- p3.onInsertSlideFromLayout(lo.path);
99020
+ p3.onInsertSlideFromLayout(lo.path, lo.name);
98703
99021
  setLayoutMenuOpen(false);
98704
99022
  },
98705
99023
  children: lo.name
@@ -99599,6 +99917,561 @@ function TextSection(p3) {
99599
99917
  ] })
99600
99918
  ] });
99601
99919
  }
99920
+ function ViewSection(p3) {
99921
+ const { t: t2 } = reactI18next.useTranslation();
99922
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
99923
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-0.5", children: [
99924
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-0.5", children: [
99925
+ /* @__PURE__ */ jsxRuntime.jsx("button", { className: pill, title: "Normal view", children: "Normal" }),
99926
+ p3.onToggleSlideSorter ? /* @__PURE__ */ jsxRuntime.jsx("button", { className: pill, onClick: p3.onToggleSlideSorter, title: "Slide Sorter view", children: "Slide Sorter" }) : /* @__PURE__ */ jsxRuntime.jsx("button", { className: pill, title: "Slide Sorter view", children: "Slide Sorter" }),
99927
+ /* @__PURE__ */ jsxRuntime.jsx("button", { className: pill, title: "Reading View", children: "Reading View" })
99928
+ ] }),
99929
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[9px] text-muted-foreground leading-none", children: "Presentation Views" })
99930
+ ] }),
99931
+ sep,
99932
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-0.5", children: [
99933
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-0.5", children: /* @__PURE__ */ jsxRuntime.jsx(
99934
+ "button",
99935
+ {
99936
+ onClick: p3.onEnterMasterView,
99937
+ disabled: !p3.canEdit,
99938
+ className: pill,
99939
+ title: "Edit slide masters and layouts",
99940
+ children: "Slide Master"
99941
+ }
99942
+ ) }),
99943
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[9px] text-muted-foreground leading-none", children: "Master Views" })
99944
+ ] }),
99945
+ sep,
99946
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-0.5", children: [
99947
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-0.5", children: p3.onZoomToFit && /* @__PURE__ */ jsxRuntime.jsx("button", { className: pill, onClick: p3.onZoomToFit, title: "Zoom to fit slide in window", children: "Zoom to Fit" }) }),
99948
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[9px] text-muted-foreground leading-none", children: "Zoom" })
99949
+ ] }),
99950
+ sep,
99951
+ /* @__PURE__ */ jsxRuntime.jsx(
99952
+ "button",
99953
+ {
99954
+ onClick: () => p3.onSetEditTemplateMode(!p3.editTemplateMode),
99955
+ disabled: !p3.canEdit,
99956
+ className: cn(
99957
+ pill,
99958
+ p3.editTemplateMode ? "bg-amber-600 hover:bg-amber-500 text-amber-50" : ""
99959
+ ),
99960
+ title: "Toggle template/master element editing",
99961
+ children: p3.editTemplateMode ? "Templates On" : "Templates Off"
99962
+ }
99963
+ ),
99964
+ p3.onToggleSelectionPane && /* @__PURE__ */ jsxRuntime.jsxs(
99965
+ "button",
99966
+ {
99967
+ type: "button",
99968
+ onClick: p3.onToggleSelectionPane,
99969
+ className: cn(
99970
+ pill,
99971
+ p3.isSelectionPaneOpen ? "bg-primary hover:bg-primary/80 text-primary-foreground" : ""
99972
+ ),
99973
+ title: "Selection Pane",
99974
+ children: [
99975
+ /* @__PURE__ */ jsxRuntime.jsx(lu.LuList, { className: ic2 }),
99976
+ "Selection"
99977
+ ]
99978
+ }
99979
+ ),
99980
+ p3.onToggleEyedropper && /* @__PURE__ */ jsxRuntime.jsxs(
99981
+ "button",
99982
+ {
99983
+ type: "button",
99984
+ onClick: p3.onToggleEyedropper,
99985
+ disabled: !p3.canEdit,
99986
+ className: cn(
99987
+ pill,
99988
+ p3.eyedropperActive ? "bg-purple-600 hover:bg-purple-500 text-purple-50" : ""
99989
+ ),
99990
+ title: "Eyedropper \u2014 sample a colour from the slide",
99991
+ children: [
99992
+ /* @__PURE__ */ jsxRuntime.jsx(lu.LuPipette, { className: ic2 }),
99993
+ "Eyedropper"
99994
+ ]
99995
+ }
99996
+ ),
99997
+ /* @__PURE__ */ jsxRuntime.jsx(
99998
+ "button",
99999
+ {
100000
+ onClick: () => p3.onSetShowGrid(!p3.showGrid),
100001
+ className: cn(pill, p3.showGrid ? "bg-primary text-primary-foreground" : ""),
100002
+ title: t2("pptx.grid.toggleGrid"),
100003
+ children: t2("pptx.grid.grid")
100004
+ }
100005
+ ),
100006
+ /* @__PURE__ */ jsxRuntime.jsx(
100007
+ "button",
100008
+ {
100009
+ onClick: () => p3.onSetShowRulers(!p3.showRulers),
100010
+ className: cn(pill, p3.showRulers ? "bg-primary text-primary-foreground" : ""),
100011
+ title: t2("pptx.ruler.toggleRulers"),
100012
+ children: t2("pptx.ruler.rulers")
100013
+ }
100014
+ ),
100015
+ /* @__PURE__ */ jsxRuntime.jsx(
100016
+ "button",
100017
+ {
100018
+ onClick: () => p3.onSetSnapToGrid(!p3.snapToGrid),
100019
+ className: cn(pill, p3.snapToGrid ? "bg-primary text-primary-foreground" : ""),
100020
+ title: t2("pptx.grid.snapToGrid"),
100021
+ children: t2("pptx.grid.snapToGrid")
100022
+ }
100023
+ ),
100024
+ /* @__PURE__ */ jsxRuntime.jsx(
100025
+ "button",
100026
+ {
100027
+ onClick: () => p3.onSetSnapToShape(!p3.snapToShape),
100028
+ className: cn(pill, p3.snapToShape ? "bg-primary text-primary-foreground" : ""),
100029
+ title: t2("pptx.grid.snapToShape"),
100030
+ children: t2("pptx.grid.snapToShape")
100031
+ }
100032
+ ),
100033
+ /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: () => p3.onAddGuide("h"), className: pill, title: "Add horizontal guide", children: "H Guide" }),
100034
+ /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: () => p3.onAddGuide("v"), className: pill, title: "Add vertical guide", children: "V Guide" }),
100035
+ /* @__PURE__ */ jsxRuntime.jsx(
100036
+ "button",
100037
+ {
100038
+ onClick: () => p3.onSetSpellCheckEnabled(!p3.spellCheckEnabled),
100039
+ className: cn(pill, p3.spellCheckEnabled ? "bg-primary text-primary-foreground" : ""),
100040
+ title: "Toggle spell check",
100041
+ children: "Spell"
100042
+ }
100043
+ )
100044
+ ] });
100045
+ }
100046
+ function MobileSheet({
100047
+ open,
100048
+ onClose,
100049
+ title,
100050
+ children,
100051
+ heightFraction = 0.6,
100052
+ fullScreen = false,
100053
+ className,
100054
+ headerRight
100055
+ }) {
100056
+ const sheetRef = React10.useRef(null);
100057
+ const [dragY, setDragY] = React10.useState(0);
100058
+ const dragStartRef = React10.useRef(null);
100059
+ const onPointerDown = React10.useCallback((e2) => {
100060
+ dragStartRef.current = e2.clientY;
100061
+ e2.target.setPointerCapture?.(e2.pointerId);
100062
+ }, []);
100063
+ const onPointerMove = React10.useCallback((e2) => {
100064
+ if (dragStartRef.current === null) {
100065
+ return;
100066
+ }
100067
+ const delta = e2.clientY - dragStartRef.current;
100068
+ setDragY(Math.max(0, delta));
100069
+ }, []);
100070
+ const onPointerUp = React10.useCallback(
100071
+ (e2) => {
100072
+ if (dragStartRef.current === null) {
100073
+ return;
100074
+ }
100075
+ const delta = e2.clientY - dragStartRef.current;
100076
+ dragStartRef.current = null;
100077
+ e2.target.releasePointerCapture?.(e2.pointerId);
100078
+ if (delta > 120) {
100079
+ onClose();
100080
+ }
100081
+ setDragY(0);
100082
+ },
100083
+ [onClose]
100084
+ );
100085
+ React10.useEffect(() => {
100086
+ if (!open) {
100087
+ return;
100088
+ }
100089
+ const handleKey = (e2) => {
100090
+ if (e2.key === "Escape") {
100091
+ onClose();
100092
+ }
100093
+ };
100094
+ window.addEventListener("keydown", handleKey);
100095
+ return () => window.removeEventListener("keydown", handleKey);
100096
+ }, [open, onClose]);
100097
+ if (!open) {
100098
+ return null;
100099
+ }
100100
+ const heightStyle = fullScreen ? { height: "calc(100dvh - env(safe-area-inset-top))" } : { height: `${Math.round(heightFraction * 100)}dvh` };
100101
+ return /* @__PURE__ */ jsxRuntime.jsxs(
100102
+ "div",
100103
+ {
100104
+ className: "fixed inset-0 z-50 flex flex-col justify-end md:hidden",
100105
+ role: "dialog",
100106
+ "aria-modal": "true",
100107
+ children: [
100108
+ /* @__PURE__ */ jsxRuntime.jsx(
100109
+ "button",
100110
+ {
100111
+ type: "button",
100112
+ "aria-label": "Close",
100113
+ className: "absolute inset-0 bg-black/40 backdrop-blur-[2px] animate-in fade-in duration-150",
100114
+ onClick: onClose
100115
+ }
100116
+ ),
100117
+ /* @__PURE__ */ jsxRuntime.jsxs(
100118
+ "div",
100119
+ {
100120
+ ref: sheetRef,
100121
+ className: cn(
100122
+ "relative bg-background border-t border-border rounded-t-2xl shadow-2xl flex flex-col overflow-hidden",
100123
+ "animate-in slide-in-from-bottom duration-200",
100124
+ className
100125
+ ),
100126
+ style: {
100127
+ ...heightStyle,
100128
+ transform: dragY > 0 ? `translateY(${dragY}px)` : void 0,
100129
+ transition: dragStartRef.current === null ? "transform 150ms ease-out" : "none"
100130
+ },
100131
+ children: [
100132
+ /* @__PURE__ */ jsxRuntime.jsx(
100133
+ "div",
100134
+ {
100135
+ className: "flex items-center justify-center pt-2 pb-1 cursor-grab active:cursor-grabbing touch-none",
100136
+ onPointerDown,
100137
+ onPointerMove,
100138
+ onPointerUp,
100139
+ onPointerCancel: onPointerUp,
100140
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-1 w-10 rounded-full bg-muted-foreground/40" })
100141
+ }
100142
+ ),
100143
+ (title || headerRight) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2 px-4 pb-2 border-b border-border/60", children: [
100144
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm font-semibold text-foreground truncate", children: title }),
100145
+ headerRight
100146
+ ] }),
100147
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-y-auto overscroll-contain", children })
100148
+ ]
100149
+ }
100150
+ )
100151
+ ]
100152
+ }
100153
+ );
100154
+ }
100155
+ var MENU_ITEMS = [
100156
+ { key: "home", label: "Home", icon: lu.LuClipboardCopy },
100157
+ { key: "insert", label: "Insert", icon: lu.LuPlus },
100158
+ { key: "text", label: "Text", icon: lu.LuType },
100159
+ { key: "draw", label: "Draw", icon: lu.LuPaintbrush },
100160
+ { key: "arrange", label: "Arrange", icon: lu.LuShapes },
100161
+ { key: "design", label: "Design", icon: lu.LuLayoutGrid },
100162
+ { key: "transitions", label: "Transitions", icon: lu.LuSparkles },
100163
+ { key: "animations", label: "Animations", icon: lu.LuWand },
100164
+ { key: "slideShow", label: "Slide Show", icon: lu.LuPresentation },
100165
+ { key: "review", label: "Review", icon: lu.LuTextCursorInput },
100166
+ { key: "view", label: "View", icon: lu.LuSettings },
100167
+ { key: "file", label: "File", icon: lu.LuFile }
100168
+ ];
100169
+ function MobileMenuSheet(props) {
100170
+ const { open, onClose } = props;
100171
+ const [active, setActive] = React10.useState("home");
100172
+ return /* @__PURE__ */ jsxRuntime.jsx(MobileSheet, { open, onClose, fullScreen: true, title: "Menu", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
100173
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sticky top-0 z-10 bg-background border-b border-border", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-1.5 overflow-x-auto px-3 py-2 scrollbar-none", children: MENU_ITEMS.map(({ key, label, icon: Icon }) => /* @__PURE__ */ jsxRuntime.jsxs(
100174
+ "button",
100175
+ {
100176
+ type: "button",
100177
+ onClick: () => setActive(active === key ? null : key),
100178
+ className: cn(
100179
+ "inline-flex items-center gap-1.5 shrink-0 px-3 py-2 rounded-full text-[12px] font-medium border transition-colors min-h-[36px]",
100180
+ active === key ? "bg-primary text-primary-foreground border-primary" : "border-border text-muted-foreground hover:text-foreground hover:bg-accent/40"
100181
+ ),
100182
+ children: [
100183
+ /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "w-4 h-4" }),
100184
+ label
100185
+ ]
100186
+ },
100187
+ key
100188
+ )) }) }),
100189
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-3", children: /* @__PURE__ */ jsxRuntime.jsx(MobileSectionBody, { active, ...props }) })
100190
+ ] }) });
100191
+ }
100192
+ function MobileSectionBody({
100193
+ active,
100194
+ ...p3
100195
+ }) {
100196
+ const wrap = "flex flex-wrap items-center gap-2";
100197
+ switch (active) {
100198
+ case "home":
100199
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: wrap, children: /* @__PURE__ */ jsxRuntime.jsx(
100200
+ HomeSection,
100201
+ {
100202
+ canEdit: p3.canEdit,
100203
+ clipboardPayload: p3.clipboardPayload,
100204
+ formatPainterActive: p3.formatPainterActive,
100205
+ canActivateFormatPainter: p3.canActivateFormatPainter,
100206
+ onCopy: p3.onCopy,
100207
+ onCut: p3.onCut,
100208
+ onPaste: p3.onPaste,
100209
+ onToggleFormatPainter: p3.onToggleFormatPainter,
100210
+ layoutOptions: p3.layoutOptions,
100211
+ onInsertSlideFromLayout: p3.onInsertSlideFromLayout,
100212
+ selectedElement: p3.selectedElement,
100213
+ onUpdateTextStyle: p3.onUpdateTextStyle
100214
+ }
100215
+ ) });
100216
+ case "insert":
100217
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: wrap, children: /* @__PURE__ */ jsxRuntime.jsx(
100218
+ InsertSection,
100219
+ {
100220
+ canEdit: p3.canEdit,
100221
+ newShapeType: p3.newShapeType,
100222
+ onSetNewShapeType: p3.onSetNewShapeType,
100223
+ onAddTextBox: p3.onAddTextBox,
100224
+ onAddShape: p3.onAddShape,
100225
+ onAddTable: p3.onAddTable,
100226
+ onAddSmartArt: p3.onAddSmartArt,
100227
+ onAddEquation: p3.onAddEquation,
100228
+ onAddActionButton: p3.onAddActionButton,
100229
+ onInsertField: p3.onInsertField,
100230
+ onOpenImagePicker: p3.onOpenImagePicker,
100231
+ onOpenMediaPicker: p3.onOpenMediaPicker
100232
+ }
100233
+ ) });
100234
+ case "text":
100235
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: wrap, children: /* @__PURE__ */ jsxRuntime.jsx(
100236
+ TextSection,
100237
+ {
100238
+ canEdit: p3.canEdit,
100239
+ selectedElement: p3.selectedElement,
100240
+ tableEditorState: p3.tableEditorState,
100241
+ onUpdateTextStyle: p3.onUpdateTextStyle
100242
+ }
100243
+ ) });
100244
+ case "draw":
100245
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: wrap, children: /* @__PURE__ */ jsxRuntime.jsx(
100246
+ DrawSection,
100247
+ {
100248
+ activeTool: p3.activeTool,
100249
+ drawingColor: p3.drawingColor,
100250
+ drawingWidth: p3.drawingWidth,
100251
+ onSetActiveTool: p3.onSetActiveTool,
100252
+ onSetDrawingColor: p3.onSetDrawingColor,
100253
+ onSetDrawingWidth: p3.onSetDrawingWidth
100254
+ }
100255
+ ) });
100256
+ case "arrange":
100257
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: wrap, children: /* @__PURE__ */ jsxRuntime.jsx(
100258
+ ArrangeSection,
100259
+ {
100260
+ canEdit: p3.canEdit,
100261
+ selectedElement: p3.selectedElement,
100262
+ clipboardPayload: p3.clipboardPayload,
100263
+ onAlignElements: p3.onAlignElements,
100264
+ onCopy: p3.onCopy,
100265
+ onCut: p3.onCut,
100266
+ onPaste: p3.onPaste,
100267
+ onFlip: p3.onFlip,
100268
+ onMoveLayer: p3.onMoveLayer,
100269
+ onMoveLayerToEdge: p3.onMoveLayerToEdge,
100270
+ onDuplicate: p3.onDuplicate,
100271
+ onDelete: p3.onDelete,
100272
+ formatPainterActive: p3.formatPainterActive,
100273
+ onToggleFormatPainter: p3.onToggleFormatPainter,
100274
+ canActivateFormatPainter: p3.canActivateFormatPainter
100275
+ }
100276
+ ) });
100277
+ case "design":
100278
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: wrap, children: /* @__PURE__ */ jsxRuntime.jsx(
100279
+ DesignSection,
100280
+ {
100281
+ canEdit: p3.canEdit,
100282
+ onToggleThemeGallery: p3.onToggleThemeGallery,
100283
+ isThemeGalleryOpen: p3.isThemeGalleryOpen,
100284
+ onToggleThemeEditor: p3.onToggleThemeEditor,
100285
+ isThemeEditorOpen: p3.isThemeEditorOpen,
100286
+ onOpenDocumentProperties: p3.onOpenDocumentProperties,
100287
+ onToggleInspector: p3.onToggleInspector,
100288
+ isInspectorPaneOpen: p3.isInspectorPaneOpen
100289
+ }
100290
+ ) });
100291
+ case "transitions":
100292
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: wrap, children: /* @__PURE__ */ jsxRuntime.jsx(
100293
+ TransitionsSection,
100294
+ {
100295
+ isInspectorPaneOpen: p3.isInspectorPaneOpen,
100296
+ onToggleInspector: p3.onToggleInspector
100297
+ }
100298
+ ) });
100299
+ case "animations":
100300
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: wrap, children: /* @__PURE__ */ jsxRuntime.jsx(
100301
+ AnimationsSection,
100302
+ {
100303
+ canEdit: p3.canEdit,
100304
+ selectedElement: p3.selectedElement,
100305
+ isInspectorPaneOpen: p3.isInspectorPaneOpen,
100306
+ onToggleInspector: p3.onToggleInspector,
100307
+ onOpenAnimationPanel: p3.onOpenAnimationPanel,
100308
+ onAddAnimation: p3.onAddAnimation,
100309
+ onRemoveAnimation: p3.onRemoveAnimation
100310
+ }
100311
+ ) });
100312
+ case "slideShow":
100313
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: wrap, children: /* @__PURE__ */ jsxRuntime.jsx(
100314
+ SlideShowSection,
100315
+ {
100316
+ onPresent: () => p3.onSetMode("present"),
100317
+ onEnterPresenterView: p3.onEnterPresenterView ?? (() => {
100318
+ }),
100319
+ onEnterRehearsalMode: p3.onEnterRehearsalMode ?? (() => {
100320
+ }),
100321
+ onOpenSetUpSlideShow: p3.onOpenSetUpSlideShow ?? (() => {
100322
+ }),
100323
+ onOpenBroadcastDialog: p3.onOpenBroadcastDialog ?? (() => {
100324
+ }),
100325
+ onToggleSubtitles: p3.onToggleSubtitles ?? (() => {
100326
+ }),
100327
+ showSubtitles: p3.showSubtitles ?? false,
100328
+ onSetMode: p3.onSetMode
100329
+ }
100330
+ ) });
100331
+ case "review":
100332
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: wrap, children: /* @__PURE__ */ jsxRuntime.jsx(
100333
+ ReviewSection,
100334
+ {
100335
+ canEdit: p3.canEdit,
100336
+ spellCheckEnabled: p3.spellCheckEnabled,
100337
+ onSetSpellCheckEnabled: p3.onSetSpellCheckEnabled,
100338
+ onToggleComments: p3.onToggleComments,
100339
+ isCommentsPanelOpen: p3.isCommentsPanelOpen,
100340
+ slideCommentCount: p3.slideCommentCount,
100341
+ onCompare: p3.onCompare
100342
+ }
100343
+ ) });
100344
+ case "view":
100345
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: wrap, children: /* @__PURE__ */ jsxRuntime.jsx(
100346
+ ViewSection,
100347
+ {
100348
+ canEdit: p3.canEdit,
100349
+ editTemplateMode: p3.editTemplateMode,
100350
+ onSetEditTemplateMode: p3.onSetEditTemplateMode,
100351
+ spellCheckEnabled: p3.spellCheckEnabled,
100352
+ onSetSpellCheckEnabled: p3.onSetSpellCheckEnabled,
100353
+ showGrid: p3.showGrid,
100354
+ showRulers: p3.showRulers,
100355
+ snapToGrid: p3.snapToGrid,
100356
+ snapToShape: p3.snapToShape,
100357
+ onSetShowGrid: p3.onSetShowGrid,
100358
+ onSetShowRulers: p3.onSetShowRulers,
100359
+ onSetSnapToGrid: p3.onSetSnapToGrid,
100360
+ onSetSnapToShape: p3.onSetSnapToShape,
100361
+ onAddGuide: p3.onAddGuide,
100362
+ onEnterMasterView: p3.onEnterMasterView,
100363
+ isSelectionPaneOpen: p3.isSelectionPaneOpen,
100364
+ onToggleSelectionPane: p3.onToggleSelectionPane,
100365
+ eyedropperActive: p3.eyedropperActive,
100366
+ onToggleEyedropper: p3.onToggleEyedropper
100367
+ }
100368
+ ) });
100369
+ case "file":
100370
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: wrap, children: /* @__PURE__ */ jsxRuntime.jsx(
100371
+ FileSection,
100372
+ {
100373
+ onExportPng: p3.onExportPng,
100374
+ onExportPdf: p3.onExportPdf,
100375
+ onExportVideo: p3.onExportVideo,
100376
+ onExportGif: p3.onExportGif,
100377
+ onPackageForSharing: p3.onPackageForSharing,
100378
+ onSaveAsPptx: p3.onSaveAsPptx,
100379
+ onSaveAsPpsx: p3.onSaveAsPpsx,
100380
+ onSaveAsPptm: p3.onSaveAsPptm,
100381
+ hasMacros: p3.hasMacros,
100382
+ onCopySlideAsImage: p3.onCopySlideAsImage,
100383
+ onPrint: p3.onPrint,
100384
+ onOpenDocumentProperties: p3.onOpenDocumentProperties,
100385
+ onOpenPasswordProtection: p3.onOpenPasswordProtection,
100386
+ onOpenFontEmbedding: p3.onOpenFontEmbedding,
100387
+ onOpenDigitalSignatures: p3.onOpenDigitalSignatures
100388
+ }
100389
+ ) });
100390
+ default:
100391
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center text-sm text-muted-foreground py-8", children: [
100392
+ /* @__PURE__ */ jsxRuntime.jsx(lu.LuChevronRight, { className: "w-5 h-5 inline-block opacity-50" }),
100393
+ " Select a section above"
100394
+ ] });
100395
+ }
100396
+ }
100397
+ function MobileToolbar(props) {
100398
+ const { t: t2 } = reactI18next.useTranslation();
100399
+ const { mode, canUndo, canRedo, onUndo, onRedo, onSetMode } = props;
100400
+ const [menuOpen, setMenuOpen] = React10.useState(false);
100401
+ const showEdit = mode === "edit" || mode === "master";
100402
+ const btn = "inline-flex items-center justify-center min-w-[44px] min-h-[44px] rounded-md text-foreground/80 hover:bg-accent/60 disabled:opacity-40 disabled:cursor-not-allowed active:scale-95 transition-transform";
100403
+ return /* @__PURE__ */ jsxRuntime.jsxs(
100404
+ "div",
100405
+ {
100406
+ role: "toolbar",
100407
+ "aria-label": "Toolbar",
100408
+ className: "relative z-20 flex items-center gap-1 px-2 py-1 border-b border-border bg-secondary/50 min-h-[52px] pt-[max(env(safe-area-inset-top),0px)]",
100409
+ children: [
100410
+ showEdit && /* @__PURE__ */ jsxRuntime.jsx(
100411
+ "button",
100412
+ {
100413
+ type: "button",
100414
+ onClick: () => setMenuOpen(true),
100415
+ className: btn,
100416
+ title: "Menu",
100417
+ "aria-label": "Menu",
100418
+ children: /* @__PURE__ */ jsxRuntime.jsx(lu.LuMenu, { className: "w-5 h-5" })
100419
+ }
100420
+ ),
100421
+ showEdit && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
100422
+ /* @__PURE__ */ jsxRuntime.jsx(
100423
+ "button",
100424
+ {
100425
+ type: "button",
100426
+ onClick: onUndo,
100427
+ disabled: !canUndo,
100428
+ className: btn,
100429
+ title: t2("pptx.toolbar.undo"),
100430
+ "aria-label": t2("pptx.toolbar.undo"),
100431
+ children: /* @__PURE__ */ jsxRuntime.jsx(lu.LuUndo, { className: "w-5 h-5" })
100432
+ }
100433
+ ),
100434
+ /* @__PURE__ */ jsxRuntime.jsx(
100435
+ "button",
100436
+ {
100437
+ type: "button",
100438
+ onClick: onRedo,
100439
+ disabled: !canRedo,
100440
+ className: btn,
100441
+ title: t2("pptx.toolbar.redo"),
100442
+ "aria-label": t2("pptx.toolbar.redo"),
100443
+ children: /* @__PURE__ */ jsxRuntime.jsx(lu.LuRedo, { className: "w-5 h-5" })
100444
+ }
100445
+ )
100446
+ ] }),
100447
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1" }),
100448
+ /* @__PURE__ */ jsxRuntime.jsx(
100449
+ "button",
100450
+ {
100451
+ type: "button",
100452
+ onClick: () => onSetMode("present"),
100453
+ className: cn(btn, "text-primary"),
100454
+ title: t2("pptx.toolbar.present"),
100455
+ "aria-label": t2("pptx.toolbar.present"),
100456
+ children: /* @__PURE__ */ jsxRuntime.jsx(lu.LuPresentation, { className: "w-5 h-5" })
100457
+ }
100458
+ ),
100459
+ showEdit && /* @__PURE__ */ jsxRuntime.jsx(
100460
+ "button",
100461
+ {
100462
+ type: "button",
100463
+ onClick: props.onOpenShareDialog ?? props.onPackageForSharing,
100464
+ className: cn(btn, "bg-primary text-primary-foreground hover:bg-primary/90 px-3"),
100465
+ title: t2("pptx.toolbar.share"),
100466
+ "aria-label": t2("pptx.toolbar.share"),
100467
+ children: /* @__PURE__ */ jsxRuntime.jsx(lu.LuShare2, { className: "w-4 h-4" })
100468
+ }
100469
+ ),
100470
+ /* @__PURE__ */ jsxRuntime.jsx(MobileMenuSheet, { open: menuOpen, onClose: () => setMenuOpen(false), ...props })
100471
+ ]
100472
+ }
100473
+ );
100474
+ }
99602
100475
  function CustomShowsControls({
99603
100476
  customShows,
99604
100477
  activeCustomShowId,
@@ -100027,7 +100900,7 @@ function ToolbarPrimaryRow(p3) {
100027
100900
  onClick: p3.onToggleComments,
100028
100901
  className: cn(
100029
100902
  qab,
100030
- "max-md:hidden",
100903
+ "relative max-md:hidden",
100031
100904
  p3.isCommentsPanelOpen ? "text-foreground" : "text-muted-foreground"
100032
100905
  ),
100033
100906
  title: t2("pptx.toolbar.comments"),
@@ -100143,134 +101016,11 @@ function ToolbarPrimaryRow(p3) {
100143
101016
  /* @__PURE__ */ jsxRuntime.jsx(OverflowMenu, { ...p3 })
100144
101017
  ] });
100145
101018
  }
100146
- function ViewSection(p3) {
100147
- const { t: t2 } = reactI18next.useTranslation();
100148
- return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
100149
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-0.5", children: [
100150
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-0.5", children: [
100151
- /* @__PURE__ */ jsxRuntime.jsx("button", { className: pill, title: "Normal view", children: "Normal" }),
100152
- p3.onToggleSlideSorter ? /* @__PURE__ */ jsxRuntime.jsx("button", { className: pill, onClick: p3.onToggleSlideSorter, title: "Slide Sorter view", children: "Slide Sorter" }) : /* @__PURE__ */ jsxRuntime.jsx("button", { className: pill, title: "Slide Sorter view", children: "Slide Sorter" }),
100153
- /* @__PURE__ */ jsxRuntime.jsx("button", { className: pill, title: "Reading View", children: "Reading View" })
100154
- ] }),
100155
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[9px] text-muted-foreground leading-none", children: "Presentation Views" })
100156
- ] }),
100157
- sep,
100158
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-0.5", children: [
100159
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-0.5", children: /* @__PURE__ */ jsxRuntime.jsx(
100160
- "button",
100161
- {
100162
- onClick: p3.onEnterMasterView,
100163
- disabled: !p3.canEdit,
100164
- className: pill,
100165
- title: "Edit slide masters and layouts",
100166
- children: "Slide Master"
100167
- }
100168
- ) }),
100169
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[9px] text-muted-foreground leading-none", children: "Master Views" })
100170
- ] }),
100171
- sep,
100172
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-0.5", children: [
100173
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-0.5", children: p3.onZoomToFit && /* @__PURE__ */ jsxRuntime.jsx("button", { className: pill, onClick: p3.onZoomToFit, title: "Zoom to fit slide in window", children: "Zoom to Fit" }) }),
100174
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[9px] text-muted-foreground leading-none", children: "Zoom" })
100175
- ] }),
100176
- sep,
100177
- /* @__PURE__ */ jsxRuntime.jsx(
100178
- "button",
100179
- {
100180
- onClick: () => p3.onSetEditTemplateMode(!p3.editTemplateMode),
100181
- disabled: !p3.canEdit,
100182
- className: cn(
100183
- pill,
100184
- p3.editTemplateMode ? "bg-amber-600 hover:bg-amber-500 text-amber-50" : ""
100185
- ),
100186
- title: "Toggle template/master element editing",
100187
- children: p3.editTemplateMode ? "Templates On" : "Templates Off"
100188
- }
100189
- ),
100190
- p3.onToggleSelectionPane && /* @__PURE__ */ jsxRuntime.jsxs(
100191
- "button",
100192
- {
100193
- type: "button",
100194
- onClick: p3.onToggleSelectionPane,
100195
- className: cn(
100196
- pill,
100197
- p3.isSelectionPaneOpen ? "bg-primary hover:bg-primary/80 text-primary-foreground" : ""
100198
- ),
100199
- title: "Selection Pane",
100200
- children: [
100201
- /* @__PURE__ */ jsxRuntime.jsx(lu.LuList, { className: ic2 }),
100202
- "Selection"
100203
- ]
100204
- }
100205
- ),
100206
- p3.onToggleEyedropper && /* @__PURE__ */ jsxRuntime.jsxs(
100207
- "button",
100208
- {
100209
- type: "button",
100210
- onClick: p3.onToggleEyedropper,
100211
- disabled: !p3.canEdit,
100212
- className: cn(
100213
- pill,
100214
- p3.eyedropperActive ? "bg-purple-600 hover:bg-purple-500 text-purple-50" : ""
100215
- ),
100216
- title: "Eyedropper \u2014 sample a colour from the slide",
100217
- children: [
100218
- /* @__PURE__ */ jsxRuntime.jsx(lu.LuPipette, { className: ic2 }),
100219
- "Eyedropper"
100220
- ]
100221
- }
100222
- ),
100223
- /* @__PURE__ */ jsxRuntime.jsx(
100224
- "button",
100225
- {
100226
- onClick: () => p3.onSetShowGrid(!p3.showGrid),
100227
- className: cn(pill, p3.showGrid ? "bg-primary text-primary-foreground" : ""),
100228
- title: t2("pptx.grid.toggleGrid"),
100229
- children: t2("pptx.grid.grid")
100230
- }
100231
- ),
100232
- /* @__PURE__ */ jsxRuntime.jsx(
100233
- "button",
100234
- {
100235
- onClick: () => p3.onSetShowRulers(!p3.showRulers),
100236
- className: cn(pill, p3.showRulers ? "bg-primary text-primary-foreground" : ""),
100237
- title: t2("pptx.ruler.toggleRulers"),
100238
- children: t2("pptx.ruler.rulers")
100239
- }
100240
- ),
100241
- /* @__PURE__ */ jsxRuntime.jsx(
100242
- "button",
100243
- {
100244
- onClick: () => p3.onSetSnapToGrid(!p3.snapToGrid),
100245
- className: cn(pill, p3.snapToGrid ? "bg-primary text-primary-foreground" : ""),
100246
- title: t2("pptx.grid.snapToGrid"),
100247
- children: t2("pptx.grid.snapToGrid")
100248
- }
100249
- ),
100250
- /* @__PURE__ */ jsxRuntime.jsx(
100251
- "button",
100252
- {
100253
- onClick: () => p3.onSetSnapToShape(!p3.snapToShape),
100254
- className: cn(pill, p3.snapToShape ? "bg-primary text-primary-foreground" : ""),
100255
- title: t2("pptx.grid.snapToShape"),
100256
- children: t2("pptx.grid.snapToShape")
100257
- }
100258
- ),
100259
- /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: () => p3.onAddGuide("h"), className: pill, title: "Add horizontal guide", children: "H Guide" }),
100260
- /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: () => p3.onAddGuide("v"), className: pill, title: "Add vertical guide", children: "V Guide" }),
100261
- /* @__PURE__ */ jsxRuntime.jsx(
100262
- "button",
100263
- {
100264
- onClick: () => p3.onSetSpellCheckEnabled(!p3.spellCheckEnabled),
100265
- className: cn(pill, p3.spellCheckEnabled ? "bg-primary text-primary-foreground" : ""),
100266
- title: "Toggle spell check",
100267
- children: "Spell"
100268
- }
100269
- )
100270
- ] });
100271
- }
100272
101019
  function Toolbar(p3) {
100273
101020
  const { mode, isNarrowViewport, isCompactToolbarOpen, toolbarSection, onSetToolbarSection } = p3;
101021
+ if (isNarrowViewport && mode !== "present") {
101022
+ return /* @__PURE__ */ jsxRuntime.jsx(MobileToolbar, { ...p3 });
101023
+ }
100274
101024
  const sFil = toolbarSection === "file";
100275
101025
  const sHome = toolbarSection === "home";
100276
101026
  const sIns = toolbarSection === "insert";
@@ -100356,6 +101106,7 @@ function Toolbar(p3) {
100356
101106
  canEdit: p3.canEdit,
100357
101107
  clipboardPayload: p3.clipboardPayload,
100358
101108
  formatPainterActive: p3.formatPainterActive,
101109
+ canActivateFormatPainter: p3.canActivateFormatPainter,
100359
101110
  onCopy: p3.onCopy,
100360
101111
  onCut: p3.onCut,
100361
101112
  onPaste: p3.onPaste,
@@ -100419,7 +101170,8 @@ function Toolbar(p3) {
100419
101170
  onDuplicate: p3.onDuplicate,
100420
101171
  onDelete: p3.onDelete,
100421
101172
  formatPainterActive: p3.formatPainterActive,
100422
- onToggleFormatPainter: p3.onToggleFormatPainter
101173
+ onToggleFormatPainter: p3.onToggleFormatPainter,
101174
+ canActivateFormatPainter: p3.canActivateFormatPainter
100423
101175
  }
100424
101176
  ),
100425
101177
  sDes && /* @__PURE__ */ jsxRuntime.jsx(
@@ -106132,181 +106884,194 @@ function InspectorPane(props) {
106132
106884
  const fallback = themeOptions[0]?.path ?? "";
106133
106885
  setSelectedThemePath((previous) => previous || fallback);
106134
106886
  }, [slideMasters, themeOptions]);
106135
- return /* @__PURE__ */ jsxRuntime.jsxs(
106136
- "div",
106137
- {
106138
- className: cn(
106139
- // Shared styles
106140
- "bg-background flex flex-col text-xs text-foreground shadow-xl",
106141
- // Mobile: absolute bottom sheet overlay
106142
- "max-md:fixed max-md:inset-x-0 max-md:bottom-0 max-md:top-auto max-md:w-full max-md:max-h-[60vh] max-md:rounded-t-xl max-md:border-t max-md:border-border max-md:z-30",
106143
- "max-md:transition-transform max-md:duration-200 max-md:ease-in-out",
106144
- isOpen ? "max-md:translate-y-0" : "max-md:translate-y-full",
106145
- // Desktop: flow-based flex child (takes space from canvas)
106146
- "md:h-full md:border-l md:border-border",
106147
- !panelWidth && "md:w-72"
106148
- ),
106149
- style: panelWidth ? { width: panelWidth } : void 0,
106150
- children: [
106151
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2 px-3 py-2 border-b border-border", children: [
106152
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1 rounded bg-muted p-0.5", children: INSPECTOR_TABS.map(({ key, label, icon: Icon }) => /* @__PURE__ */ jsxRuntime.jsxs(
106153
- "button",
106154
- {
106155
- type: "button",
106156
- title: label,
106157
- className: cn(
106158
- "flex items-center gap-1 px-2 py-1 rounded text-[11px] transition-colors",
106159
- activeTab === key ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:text-foreground hover:bg-accent"
106160
- ),
106161
- onClick: () => onSetActiveTab(key),
106162
- children: [
106163
- /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "w-3.5 h-3.5" }),
106164
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden sm:inline", children: label })
106165
- ]
106166
- },
106167
- key
106168
- )) }),
106169
- /* @__PURE__ */ jsxRuntime.jsx(
106170
- "button",
106171
- {
106172
- type: "button",
106173
- onClick: onClose,
106174
- title: t2("common.close"),
106175
- className: "p-1 rounded text-muted-foreground hover:text-foreground hover:bg-muted transition-colors",
106176
- children: /* @__PURE__ */ jsxRuntime.jsx(lu.LuX, { className: "w-4 h-4" })
106177
- }
106178
- )
106179
- ] }),
106180
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 overflow-y-auto p-3 space-y-3", children: [
106181
- activeTab === "elements" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
106182
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(HEADING, "mb-2"), children: t2("pptx.inspector.layerOrder") }),
106183
- activeSlide ? [...activeSlide.elements || []].reverse().map((el, ri) => {
106184
- const idx = (activeSlide.elements || []).length - 1 - ri;
106185
- const sel = selectedElement?.id === el.id || selectedElementIds.includes(el.id);
106186
- const label = (pptxViewerCore.hasTextProperties(el) ? (el.text || "").slice(0, 24) : void 0) || el.type;
106187
- return /* @__PURE__ */ jsxRuntime.jsxs(
106188
- "div",
106189
- {
106190
- title: `${el.type} \u2014 ${el.id}`,
106191
- className: cn(
106192
- "flex items-center gap-2 px-2 py-1 rounded cursor-pointer transition-colors",
106193
- sel ? "bg-primary/30 text-primary" : "hover:bg-muted text-foreground"
106194
- ),
106195
- onClick: () => onSelectElement(el.id),
106196
- children: [
106197
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground w-4 text-right", children: idx + 1 }),
106198
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 truncate", children: label })
106199
- ]
106200
- },
106201
- el.id
106202
- );
106203
- }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground italic", children: t2("pptx.inspector.noSlideSelected") })
106204
- ] }),
106205
- activeTab === "properties" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-3", children: hasSelection && selectedElement ? /* @__PURE__ */ jsxRuntime.jsx(
106206
- ElementInspectorBody,
106207
- {
106208
- selectedElement,
106209
- canEdit,
106210
- slides,
106211
- tableEditorState,
106212
- mediaDataUrls,
106213
- onUpdateElement,
106214
- onUpdateElementStyle,
106215
- onUpdateTextStyle,
106216
- onMoveLayer
106217
- }
106218
- ) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
106887
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
106888
+ isOpen && /* @__PURE__ */ jsxRuntime.jsx(
106889
+ "button",
106890
+ {
106891
+ type: "button",
106892
+ "aria-label": t2("common.close"),
106893
+ onClick: onClose,
106894
+ className: "md:hidden fixed inset-0 z-20 bg-black/40 backdrop-blur-[2px] animate-in fade-in duration-150"
106895
+ }
106896
+ ),
106897
+ /* @__PURE__ */ jsxRuntime.jsxs(
106898
+ "div",
106899
+ {
106900
+ className: cn(
106901
+ // Shared styles
106902
+ "bg-background flex flex-col text-xs text-foreground shadow-xl",
106903
+ // Mobile: absolute bottom sheet overlay sized via dvh so it
106904
+ // adapts to the on-screen keyboard / dynamic browser chrome.
106905
+ "max-md:fixed max-md:inset-x-0 max-md:bottom-0 max-md:top-auto max-md:w-full max-md:max-h-[75dvh] max-md:rounded-t-2xl max-md:border-t max-md:border-border max-md:z-30 max-md:pb-[max(env(safe-area-inset-bottom),0px)]",
106906
+ "max-md:transition-transform max-md:duration-200 max-md:ease-in-out",
106907
+ isOpen ? "max-md:translate-y-0" : "max-md:translate-y-full",
106908
+ // Desktop: flow-based flex child (takes space from canvas)
106909
+ "md:h-full md:border-l md:border-border",
106910
+ !panelWidth && "md:w-72"
106911
+ ),
106912
+ style: panelWidth ? { width: panelWidth } : void 0,
106913
+ children: [
106914
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "md:hidden flex items-center justify-center pt-2 pb-1", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-1 w-10 rounded-full bg-muted-foreground/40" }) }),
106915
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2 px-3 py-2 border-b border-border", children: [
106916
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1 rounded bg-muted p-0.5", children: INSPECTOR_TABS.map(({ key, label, icon: Icon }) => /* @__PURE__ */ jsxRuntime.jsxs(
106917
+ "button",
106918
+ {
106919
+ type: "button",
106920
+ title: label,
106921
+ className: cn(
106922
+ "flex items-center gap-1 px-2 py-1 rounded text-[11px] transition-colors",
106923
+ activeTab === key ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:text-foreground hover:bg-accent"
106924
+ ),
106925
+ onClick: () => onSetActiveTab(key),
106926
+ children: [
106927
+ /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "w-3.5 h-3.5" }),
106928
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden sm:inline", children: label })
106929
+ ]
106930
+ },
106931
+ key
106932
+ )) }),
106219
106933
  /* @__PURE__ */ jsxRuntime.jsx(
106220
- PresentationPropertiesPanel,
106934
+ "button",
106221
106935
  {
106222
- canEdit,
106223
- canvasSize,
106224
- presentationProperties,
106225
- onUpdatePresentationProperties,
106226
- notesMaster,
106227
- handoutMaster,
106228
- notesCanvasSize,
106229
- coreProperties,
106230
- appProperties,
106231
- customProperties,
106232
- themeOptions,
106233
- selectedThemePath,
106234
- setSelectedThemePath,
106235
- onApplyTheme,
106236
- onUpdateCoreProperties,
106237
- onUpdateAppProperties,
106238
- onUpdateCustomProperties,
106239
- tagCollections,
106240
- onUpdateTagCollections,
106241
- onUpdateCanvasSize,
106242
- activeSlide,
106243
- theme,
106244
- onUpdateSlide
106936
+ type: "button",
106937
+ onClick: onClose,
106938
+ title: t2("common.close"),
106939
+ className: "p-1 rounded text-muted-foreground hover:text-foreground hover:bg-muted transition-colors",
106940
+ children: /* @__PURE__ */ jsxRuntime.jsx(lu.LuX, { className: "w-4 h-4" })
106245
106941
  }
106246
- ),
106247
- activeSlide && /* @__PURE__ */ jsxRuntime.jsx(
106248
- SlideBackgroundPanel,
106942
+ )
106943
+ ] }),
106944
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 overflow-y-auto p-3 space-y-3", children: [
106945
+ activeTab === "elements" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
106946
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(HEADING, "mb-2"), children: t2("pptx.inspector.layerOrder") }),
106947
+ activeSlide ? [...activeSlide.elements || []].reverse().map((el, ri) => {
106948
+ const idx = (activeSlide.elements || []).length - 1 - ri;
106949
+ const sel = selectedElement?.id === el.id || selectedElementIds.includes(el.id);
106950
+ const label = (pptxViewerCore.hasTextProperties(el) ? (el.text || "").slice(0, 24) : void 0) || el.type;
106951
+ return /* @__PURE__ */ jsxRuntime.jsxs(
106952
+ "div",
106953
+ {
106954
+ title: `${el.type} \u2014 ${el.id}`,
106955
+ className: cn(
106956
+ "flex items-center gap-2 px-2 py-1 rounded cursor-pointer transition-colors",
106957
+ sel ? "bg-primary/30 text-primary" : "hover:bg-muted text-foreground"
106958
+ ),
106959
+ onClick: () => onSelectElement(el.id),
106960
+ children: [
106961
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground w-4 text-right", children: idx + 1 }),
106962
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 truncate", children: label })
106963
+ ]
106964
+ },
106965
+ el.id
106966
+ );
106967
+ }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground italic", children: t2("pptx.inspector.noSlideSelected") })
106968
+ ] }),
106969
+ activeTab === "properties" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-3", children: hasSelection && selectedElement ? /* @__PURE__ */ jsxRuntime.jsx(
106970
+ ElementInspectorBody,
106249
106971
  {
106250
- activeSlide,
106972
+ selectedElement,
106251
106973
  canEdit,
106252
- onUpdateSlide,
106253
- editTemplateMode,
106254
- slideMasters,
106255
- onSetTemplateBackground,
106256
- onGetTemplateBackgroundColor
106974
+ slides,
106975
+ tableEditorState,
106976
+ mediaDataUrls,
106977
+ onUpdateElement,
106978
+ onUpdateElementStyle,
106979
+ onUpdateTextStyle,
106980
+ onMoveLayer
106257
106981
  }
106258
- )
106259
- ] }) }),
106260
- activeTab === "comments" && /* @__PURE__ */ jsxRuntime.jsx(
106261
- InspectorCommentsSection,
106262
- {
106263
- comments,
106264
- canEdit,
106265
- activeSlide,
106266
- selectedElement,
106267
- editingCommentId,
106268
- commentEditDraft,
106269
- commentDraft,
106270
- replyingToCommentId: replyingToCommentId ?? null,
106271
- replyDraftByCommentId: replyDraftByCommentId ?? {},
106272
- onSetCommentDraft,
106273
- onAddComment,
106274
- onDeleteComment,
106275
- onStartEditComment,
106276
- onSaveEditComment,
106277
- onCancelEditComment,
106278
- onSetCommentEditDraft,
106279
- onToggleCommentResolved,
106280
- onStartReply,
106281
- onCancelReply,
106282
- onReplyDraftChange,
106283
- onSubmitReply,
106284
- onSelectElement
106285
- }
106286
- )
106287
- ] }),
106288
- hasSelection && selectedElement && activeSlide && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
106289
- /* @__PURE__ */ jsxRuntime.jsx(ResizeHandle, { direction: "vertical", onResize: onResizeAnim }),
106290
- /* @__PURE__ */ jsxRuntime.jsx(
106291
- "div",
106292
- {
106293
- className: "border-t border-border p-3 overflow-y-auto flex-shrink-0",
106294
- style: { height: animPanelHeight },
106295
- children: /* @__PURE__ */ jsxRuntime.jsx(
106296
- AnimationPanel,
106982
+ ) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
106983
+ /* @__PURE__ */ jsxRuntime.jsx(
106984
+ PresentationPropertiesPanel,
106297
106985
  {
106298
- selectedElement,
106299
- activeSlide,
106300
106986
  canEdit,
106987
+ canvasSize,
106988
+ presentationProperties,
106989
+ onUpdatePresentationProperties,
106990
+ notesMaster,
106991
+ handoutMaster,
106992
+ notesCanvasSize,
106993
+ coreProperties,
106994
+ appProperties,
106995
+ customProperties,
106996
+ themeOptions,
106997
+ selectedThemePath,
106998
+ setSelectedThemePath,
106999
+ onApplyTheme,
107000
+ onUpdateCoreProperties,
107001
+ onUpdateAppProperties,
107002
+ onUpdateCustomProperties,
107003
+ tagCollections,
107004
+ onUpdateTagCollections,
107005
+ onUpdateCanvasSize,
107006
+ activeSlide,
107007
+ theme,
106301
107008
  onUpdateSlide
106302
107009
  }
107010
+ ),
107011
+ activeSlide && /* @__PURE__ */ jsxRuntime.jsx(
107012
+ SlideBackgroundPanel,
107013
+ {
107014
+ activeSlide,
107015
+ canEdit,
107016
+ onUpdateSlide,
107017
+ editTemplateMode,
107018
+ slideMasters,
107019
+ onSetTemplateBackground,
107020
+ onGetTemplateBackgroundColor
107021
+ }
106303
107022
  )
106304
- }
106305
- )
106306
- ] })
106307
- ]
106308
- }
106309
- );
107023
+ ] }) }),
107024
+ activeTab === "comments" && /* @__PURE__ */ jsxRuntime.jsx(
107025
+ InspectorCommentsSection,
107026
+ {
107027
+ comments,
107028
+ canEdit,
107029
+ activeSlide,
107030
+ selectedElement,
107031
+ editingCommentId,
107032
+ commentEditDraft,
107033
+ commentDraft,
107034
+ replyingToCommentId: replyingToCommentId ?? null,
107035
+ replyDraftByCommentId: replyDraftByCommentId ?? {},
107036
+ onSetCommentDraft,
107037
+ onAddComment,
107038
+ onDeleteComment,
107039
+ onStartEditComment,
107040
+ onSaveEditComment,
107041
+ onCancelEditComment,
107042
+ onSetCommentEditDraft,
107043
+ onToggleCommentResolved,
107044
+ onStartReply,
107045
+ onCancelReply,
107046
+ onReplyDraftChange,
107047
+ onSubmitReply,
107048
+ onSelectElement
107049
+ }
107050
+ )
107051
+ ] }),
107052
+ hasSelection && selectedElement && activeSlide && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
107053
+ /* @__PURE__ */ jsxRuntime.jsx(ResizeHandle, { direction: "vertical", onResize: onResizeAnim }),
107054
+ /* @__PURE__ */ jsxRuntime.jsx(
107055
+ "div",
107056
+ {
107057
+ className: "border-t border-border p-3 overflow-y-auto flex-shrink-0",
107058
+ style: { height: animPanelHeight },
107059
+ children: /* @__PURE__ */ jsxRuntime.jsx(
107060
+ AnimationPanel,
107061
+ {
107062
+ selectedElement,
107063
+ activeSlide,
107064
+ canEdit,
107065
+ onUpdateSlide
107066
+ }
107067
+ )
107068
+ }
107069
+ )
107070
+ ] })
107071
+ ]
107072
+ }
107073
+ )
107074
+ ] });
106310
107075
  }
106311
107076
  function buildPathD(points) {
106312
107077
  if (points.length === 0) {
@@ -110440,7 +111205,8 @@ function ViewerBottomPanels({
110440
111205
  onZoomToFit,
110441
111206
  mode,
110442
111207
  onSetMode,
110443
- onToggleSlideSorter
111208
+ onToggleSlideSorter,
111209
+ hideStatusBar = false
110444
111210
  }) {
110445
111211
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
110446
111212
  onResizeBottom && !isSlideNotesCollapsed && /* @__PURE__ */ jsxRuntime.jsx(ResizeHandle, { direction: "vertical", onResize: onResizeBottom }),
@@ -110456,7 +111222,7 @@ function ViewerBottomPanels({
110456
111222
  panelHeight: notesPanelHeight
110457
111223
  }
110458
111224
  ),
110459
- /* @__PURE__ */ jsxRuntime.jsx(
111225
+ !hideStatusBar && /* @__PURE__ */ jsxRuntime.jsx(
110460
111226
  StatusBar,
110461
111227
  {
110462
111228
  slideCount,
@@ -110613,6 +111379,45 @@ function ViewerInspector({
110613
111379
  }
110614
111380
  );
110615
111381
  }
111382
+
111383
+ // src/viewer/hooks/useScopedLayoutOptions.ts
111384
+ function scopeLayoutOptionsToActiveSlide(options, activeSlide) {
111385
+ if (!activeSlide?.layoutPath) {
111386
+ return options;
111387
+ }
111388
+ const hasAnyMasterInfo = options.some((o3) => o3.masterPath);
111389
+ if (!hasAnyMasterInfo) {
111390
+ return options;
111391
+ }
111392
+ const activeOption = options.find((o3) => o3.path === activeSlide.layoutPath);
111393
+ const activeMaster = activeOption?.masterPath;
111394
+ if (!activeMaster) {
111395
+ return options;
111396
+ }
111397
+ const scoped = options.filter((o3) => o3.masterPath === activeMaster);
111398
+ const seen = /* @__PURE__ */ new Map();
111399
+ for (const opt of scoped) {
111400
+ const isActive = opt.path === activeSlide.layoutPath;
111401
+ const existing = seen.get(opt.name);
111402
+ if (!existing || isActive) {
111403
+ seen.set(opt.name, opt);
111404
+ }
111405
+ }
111406
+ const chosen = new Set(Array.from(seen.values()).map((o3) => o3.path));
111407
+ const result = [];
111408
+ const usedNames = /* @__PURE__ */ new Set();
111409
+ for (const opt of scoped) {
111410
+ if (!chosen.has(opt.path)) {
111411
+ continue;
111412
+ }
111413
+ if (usedNames.has(opt.name)) {
111414
+ continue;
111415
+ }
111416
+ usedNames.add(opt.name);
111417
+ result.push(opt);
111418
+ }
111419
+ return result;
111420
+ }
110616
111421
  function ViewerToolbarSection(props) {
110617
111422
  const {
110618
111423
  mode,
@@ -110682,6 +111487,10 @@ function ViewerToolbarSection(props) {
110682
111487
  },
110683
111488
  [activeSlide, propertyHandlers]
110684
111489
  );
111490
+ const scopedLayoutOptions = React10__namespace.default.useMemo(
111491
+ () => scopeLayoutOptionsToActiveSlide(s.layoutOptions, activeSlide),
111492
+ [s.layoutOptions, activeSlide]
111493
+ );
110685
111494
  const handleApplyTransitionToAll = React10.useCallback(() => {
110686
111495
  const transition = activeSlide?.transition;
110687
111496
  if (!transition) {
@@ -110788,7 +111597,7 @@ function ViewerToolbarSection(props) {
110788
111597
  onUpdateTextStyle: ops.updateSelectedTextStyle,
110789
111598
  isOverflowMenuOpen: s.isOverflowMenuOpen,
110790
111599
  onSetOverflowMenuOpen: s.setIsOverflowMenuOpen,
110791
- layoutOptions: s.layoutOptions,
111600
+ layoutOptions: scopedLayoutOptions,
110792
111601
  onInsertSlideFromLayout: slideOps.handleInsertSlideFromLayout,
110793
111602
  customShows: s.customShows,
110794
111603
  activeCustomShowId: s.activeCustomShowId,
@@ -110821,6 +111630,7 @@ function ViewerToolbarSection(props) {
110821
111630
  isCommentsPanelOpen: s.isInspectorPaneOpen,
110822
111631
  slideCommentCount: activeSlide?.comments?.length ?? 0,
110823
111632
  formatPainterActive: s.formatPainterActive,
111633
+ canActivateFormatPainter: hasCopyableFormat(selectedElement),
110824
111634
  onToggleFormatPainter: onToggleFormatPainterProp ?? (() => s.setFormatPainterActive((p3) => !p3)),
110825
111635
  isSelectionPaneOpen: s.isSelectionPaneOpen,
110826
111636
  onToggleSelectionPane: () => s.setIsSelectionPaneOpen((p3) => !p3),
@@ -113969,6 +114779,166 @@ function ViewerMainContent(props) {
113969
114779
  )
113970
114780
  ] });
113971
114781
  }
114782
+ function MobileBottomBar({
114783
+ onOpenSlides,
114784
+ onOpenInsert,
114785
+ onOpenInspector,
114786
+ onOpenComments,
114787
+ onToggleNotes,
114788
+ activeSheet,
114789
+ commentCount
114790
+ }) {
114791
+ const actions = [
114792
+ {
114793
+ key: "slides",
114794
+ label: "Slides",
114795
+ icon: lu.LuLayers,
114796
+ onClick: onOpenSlides
114797
+ },
114798
+ {
114799
+ key: "insert",
114800
+ label: "Insert",
114801
+ icon: lu.LuPlus,
114802
+ onClick: onOpenInsert
114803
+ },
114804
+ {
114805
+ key: "inspector",
114806
+ label: "Format",
114807
+ icon: lu.LuSettings2,
114808
+ onClick: onOpenInspector
114809
+ },
114810
+ {
114811
+ key: "comments",
114812
+ label: "Comments",
114813
+ icon: lu.LuMessageSquare,
114814
+ onClick: onOpenComments,
114815
+ badge: commentCount
114816
+ },
114817
+ {
114818
+ key: "notes",
114819
+ label: "Notes",
114820
+ icon: lu.LuStickyNote,
114821
+ onClick: onToggleNotes
114822
+ }
114823
+ ];
114824
+ return /* @__PURE__ */ jsxRuntime.jsx(
114825
+ "nav",
114826
+ {
114827
+ "aria-label": "Editor actions",
114828
+ className: "md:hidden flex items-stretch justify-around border-t border-border bg-secondary/80 backdrop-blur supports-[backdrop-filter]:bg-secondary/60 pb-[max(env(safe-area-inset-bottom),0px)]",
114829
+ children: actions.map(({ key, label, icon: Icon, onClick, badge }) => {
114830
+ const active = activeSheet === key;
114831
+ return /* @__PURE__ */ jsxRuntime.jsxs(
114832
+ "button",
114833
+ {
114834
+ type: "button",
114835
+ onClick,
114836
+ className: cn(
114837
+ "relative flex flex-col items-center justify-center gap-0.5 flex-1 min-h-[56px] py-1.5 text-[10px] font-medium transition-colors active:scale-95",
114838
+ active ? "text-primary" : "text-muted-foreground hover:text-foreground"
114839
+ ),
114840
+ "aria-pressed": active,
114841
+ children: [
114842
+ /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "w-5 h-5" }),
114843
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: label }),
114844
+ badge !== void 0 && badge > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute top-1 right-1/4 flex items-center justify-center min-w-[16px] h-4 px-1 rounded-full bg-primary text-[9px] font-semibold text-primary-foreground", children: badge > 99 ? "99+" : badge }),
114845
+ active && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute top-0 left-1/2 -translate-x-1/2 w-8 h-0.5 rounded-full bg-primary" })
114846
+ ]
114847
+ },
114848
+ key
114849
+ );
114850
+ })
114851
+ }
114852
+ );
114853
+ }
114854
+ function MobileSlidesSheet({
114855
+ open,
114856
+ onClose,
114857
+ ...sidebar
114858
+ }) {
114859
+ return /* @__PURE__ */ jsxRuntime.jsx(MobileSheet, { open, onClose, heightFraction: 0.7, title: "Slides", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full", children: /* @__PURE__ */ jsxRuntime.jsx(SlidesPaneSidebar, { ...sidebar }) }) });
114860
+ }
114861
+ function MobileChromeOverlay(props) {
114862
+ const {
114863
+ state: s,
114864
+ editorOps,
114865
+ presentation,
114866
+ slides,
114867
+ activeSlideIndex,
114868
+ canvasSize,
114869
+ slideSectionGroups,
114870
+ canEdit,
114871
+ commentCount
114872
+ } = props;
114873
+ const activeSheet = s.isSlidesPaneOpen ? "slides" : s.isInspectorPaneOpen ? s.sidebarPanelMode === "comments" ? "comments" : "inspector" : !s.isSlideNotesCollapsed ? "notes" : null;
114874
+ const closeAllSheets = () => {
114875
+ s.setIsSlidesPaneOpen(false);
114876
+ s.setIsInspectorPaneOpen(false);
114877
+ s.setIsSlideNotesCollapsed(true);
114878
+ };
114879
+ const openSheet = (which) => {
114880
+ closeAllSheets();
114881
+ switch (which) {
114882
+ case "slides":
114883
+ s.setIsSlidesPaneOpen(true);
114884
+ break;
114885
+ case "inspector":
114886
+ s.setSidebarPanelMode("properties");
114887
+ s.setIsInspectorPaneOpen(true);
114888
+ break;
114889
+ case "comments":
114890
+ s.setSidebarPanelMode("comments");
114891
+ s.setIsInspectorPaneOpen(true);
114892
+ break;
114893
+ case "notes":
114894
+ s.setIsSlideNotesCollapsed(false);
114895
+ break;
114896
+ }
114897
+ };
114898
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
114899
+ /* @__PURE__ */ jsxRuntime.jsx(
114900
+ MobileSlidesSheet,
114901
+ {
114902
+ open: s.isSlidesPaneOpen,
114903
+ onClose: () => s.setIsSlidesPaneOpen(false),
114904
+ slides,
114905
+ activeSlideIndex,
114906
+ canvasSize,
114907
+ sectionGroups: slideSectionGroups,
114908
+ isOpen: true,
114909
+ canEdit,
114910
+ onSelectSlide: (index) => {
114911
+ s.setActiveSlideIndex(index);
114912
+ s.setIsSlidesPaneOpen(false);
114913
+ },
114914
+ onSlideContextMenu: editorOps.slideOps.handleSlideContextMenu,
114915
+ onMoveSlide: editorOps.slideOps.handleMoveSlide,
114916
+ onAddSlide: editorOps.slideOps.handleAddSlide,
114917
+ onCollapse: () => s.setIsSlidesPaneOpen(false),
114918
+ onAddSection: editorOps.sectionOps.addSection,
114919
+ onRenameSection: editorOps.sectionOps.renameSection,
114920
+ onDeleteSection: editorOps.sectionOps.deleteSection,
114921
+ onMoveSectionUp: editorOps.sectionOps.moveSectionUp,
114922
+ onMoveSectionDown: editorOps.sectionOps.moveSectionDown,
114923
+ rehearsalTimings: Object.keys(presentation.recordedTimings).length > 0 ? presentation.recordedTimings : void 0
114924
+ }
114925
+ ),
114926
+ /* @__PURE__ */ jsxRuntime.jsx(
114927
+ MobileBottomBar,
114928
+ {
114929
+ activeSheet,
114930
+ commentCount,
114931
+ onOpenSlides: () => s.isSlidesPaneOpen ? s.setIsSlidesPaneOpen(false) : openSheet("slides"),
114932
+ onOpenInsert: () => {
114933
+ editorOps.insertHandlers.handleAddTextBox();
114934
+ },
114935
+ onOpenInspector: () => s.isInspectorPaneOpen && s.sidebarPanelMode !== "comments" ? s.setIsInspectorPaneOpen(false) : openSheet("inspector"),
114936
+ onOpenComments: () => s.isInspectorPaneOpen && s.sidebarPanelMode === "comments" ? s.setIsInspectorPaneOpen(false) : openSheet("comments"),
114937
+ onToggleNotes: () => !s.isSlideNotesCollapsed ? s.setIsSlideNotesCollapsed(true) : openSheet("notes")
114938
+ }
114939
+ )
114940
+ ] });
114941
+ }
113972
114942
  function ToggleSwitch({
113973
114943
  label,
113974
114944
  enabled,
@@ -114190,14 +115160,10 @@ function useYjsDocumentSync({
114190
115160
  const lastSyncedRef = React10.useRef("");
114191
115161
  const hasInitializedRef = React10.useRef(false);
114192
115162
  const getDocMap = React10.useCallback(() => {
114193
- if (!doc2 || typeof doc2 !== "object") {
115163
+ if (!doc2) {
114194
115164
  return null;
114195
115165
  }
114196
- const d = doc2;
114197
- if (typeof d.getMap !== "function") {
114198
- return null;
114199
- }
114200
- return d.getMap("slides-data");
115166
+ return doc2.getMap("slides-data");
114201
115167
  }, [doc2]);
114202
115168
  React10.useEffect(() => {
114203
115169
  if (!isConnected || !doc2) {
@@ -114218,10 +115184,9 @@ function useYjsDocumentSync({
114218
115184
  return;
114219
115185
  }
114220
115186
  lastSyncedRef.current = serialized;
114221
- const d = doc2;
114222
- d.transact(() => {
115187
+ doc2.transact(() => {
114223
115188
  const currentCount = map3.get("count");
114224
- if (currentCount && currentCount > slides.length) {
115189
+ if (typeof currentCount === "number" && currentCount > slides.length) {
114225
115190
  for (let i3 = slides.length; i3 < currentCount; i3++) {
114226
115191
  map3.delete(`slide-${i3}`);
114227
115192
  }
@@ -114246,13 +115211,13 @@ function useYjsDocumentSync({
114246
115211
  }
114247
115212
  const handleUpdate = () => {
114248
115213
  const count = map3.get("count");
114249
- if (!count || count === 0) {
115214
+ if (typeof count !== "number" || count === 0) {
114250
115215
  return;
114251
115216
  }
114252
115217
  const remoteSlides = [];
114253
115218
  for (let i3 = 0; i3 < count; i3++) {
114254
115219
  const slideJson = map3.get(`slide-${i3}`);
114255
- if (slideJson) {
115220
+ if (typeof slideJson === "string") {
114256
115221
  try {
114257
115222
  remoteSlides.push(JSON.parse(slideJson));
114258
115223
  } catch {
@@ -114277,7 +115242,7 @@ function useYjsDocumentSync({
114277
115242
  if (!hasInitializedRef.current) {
114278
115243
  hasInitializedRef.current = true;
114279
115244
  const count = map3.get("count");
114280
- if (count && count > 0) {
115245
+ if (typeof count === "number" && count > 0) {
114281
115246
  handleUpdate();
114282
115247
  }
114283
115248
  }
@@ -114838,13 +115803,14 @@ function useCanvasInteractions(input) {
114838
115803
  if (e2.button !== 0) {
114839
115804
  return;
114840
115805
  }
114841
- if (!selectedElementIdSet.has(elementId)) {
115806
+ const wasSelected = selectedElementIdSet.has(elementId);
115807
+ if (!wasSelected) {
114842
115808
  ops.applySelection(elementId);
114843
115809
  justSelectedRef.current = true;
114844
115810
  } else {
114845
115811
  justSelectedRef.current = false;
114846
115812
  }
114847
- const ids = effectiveSelectedIds.length ? effectiveSelectedIds : [elementId];
115813
+ const ids = !wasSelected ? [elementId] : effectiveSelectedIds.length ? effectiveSelectedIds : [elementId];
114848
115814
  const startPositions = {};
114849
115815
  const domEls = /* @__PURE__ */ new Map();
114850
115816
  for (const id2 of ids) {
@@ -116881,8 +117847,14 @@ function useSectionOperations(input) {
116881
117847
  }
116882
117848
 
116883
117849
  // src/viewer/hooks/useSlideManagement.ts
117850
+ function insertSlideFromLayoutUpdater(slides, activeIndex, draft) {
117851
+ const next = [...slides];
117852
+ const insertAt = Math.max(0, Math.min(activeIndex + 1, next.length));
117853
+ next.splice(insertAt, 0, draft);
117854
+ return next;
117855
+ }
116884
117856
  function useSlideManagement(input) {
116885
- const { slides, activeSlideIndex, setActiveSlideIndex, ops, history } = input;
117857
+ const { slides, activeSlideIndex, setActiveSlideIndex, ops, history, handlerRef } = input;
116886
117858
  const handleAddSlide = () => {
116887
117859
  const newSlide = {
116888
117860
  id: `slide-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`,
@@ -116981,8 +117953,42 @@ function useSlideManagement(input) {
116981
117953
  });
116982
117954
  history.markDirty();
116983
117955
  };
116984
- const handleInsertSlideFromLayout = (_layoutPath) => {
116985
- handleAddSlide();
117956
+ const handleInsertSlideFromLayout = (layoutPath, layoutName) => {
117957
+ const insertAt = activeSlideIndex + 1;
117958
+ const draft = {
117959
+ id: `slide-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`,
117960
+ rId: "",
117961
+ slideNumber: slides.length + 1,
117962
+ elements: [],
117963
+ layoutPath,
117964
+ ...layoutName ? { layoutName } : {}
117965
+ };
117966
+ let inserted = [];
117967
+ ops.updateSlides((prev) => {
117968
+ inserted = insertSlideFromLayoutUpdater(prev, activeSlideIndex, draft);
117969
+ return inserted;
117970
+ });
117971
+ setActiveSlideIndex(insertAt);
117972
+ history.markDirty();
117973
+ const handler = handlerRef?.current;
117974
+ if (handler) {
117975
+ void handler.applyLayoutToSlide(insertAt, layoutPath, inserted).then(
117976
+ (updated) => {
117977
+ ops.updateSlides((prev) => {
117978
+ if (prev[insertAt]?.id !== draft.id) {
117979
+ return prev;
117980
+ }
117981
+ const next = [...prev];
117982
+ next[insertAt] = updated;
117983
+ return next;
117984
+ });
117985
+ return void 0;
117986
+ },
117987
+ () => {
117988
+ return void 0;
117989
+ }
117990
+ );
117991
+ }
116986
117992
  };
116987
117993
  return {
116988
117994
  handleAddSlide,
@@ -117518,7 +118524,8 @@ function useEditorOperations(input) {
117518
118524
  canvasSize,
117519
118525
  dialogs,
117520
118526
  presentation,
117521
- userName
118527
+ userName,
118528
+ handlerRef
117522
118529
  } = input;
117523
118530
  const ops = useElementOperations({
117524
118531
  activeSlide,
@@ -117620,7 +118627,8 @@ function useEditorOperations(input) {
117620
118627
  activeSlideIndex,
117621
118628
  setActiveSlideIndex: state2.setActiveSlideIndex,
117622
118629
  ops,
117623
- history
118630
+ history,
118631
+ handlerRef
117624
118632
  });
117625
118633
  const tableOps = useTableOperations({
117626
118634
  selectedElement,
@@ -117649,21 +118657,34 @@ function useEditorOperations(input) {
117649
118657
  );
117650
118658
  const copiedFormatRef = React10.useRef(null);
117651
118659
  const prevFormatPainterRef = React10.useRef(false);
118660
+ const { formatPainterActive, setFormatPainterActive, elementLookup } = state2;
117652
118661
  React10.useEffect(() => {
117653
- if (state2.formatPainterActive && !prevFormatPainterRef.current && selectedElement) {
118662
+ if (formatPainterActive && !prevFormatPainterRef.current && selectedElement) {
117654
118663
  copiedFormatRef.current = copyFormatFromElement(selectedElement);
117655
- } else if (!state2.formatPainterActive) {
118664
+ } else if (!formatPainterActive) {
117656
118665
  copiedFormatRef.current = null;
117657
118666
  }
117658
- prevFormatPainterRef.current = state2.formatPainterActive;
117659
- }, [state2.formatPainterActive, selectedElement]);
118667
+ prevFormatPainterRef.current = formatPainterActive;
118668
+ }, [formatPainterActive, selectedElement]);
118669
+ React10.useEffect(() => {
118670
+ if (!formatPainterActive) {
118671
+ return;
118672
+ }
118673
+ const onKey = (e2) => {
118674
+ if (e2.key === "Escape") {
118675
+ setFormatPainterActive(false);
118676
+ }
118677
+ };
118678
+ window.addEventListener("keydown", onKey);
118679
+ return () => window.removeEventListener("keydown", onKey);
118680
+ }, [formatPainterActive, setFormatPainterActive]);
117660
118681
  const formatPainterCanvasHandlers = React10.useMemo(
117661
118682
  () => ({
117662
118683
  ...canvasHandlers,
117663
118684
  handleElementClick: (elementId, e2) => {
117664
- if (state2.formatPainterActive && copiedFormatRef.current) {
118685
+ if (formatPainterActive && copiedFormatRef.current) {
117665
118686
  e2.stopPropagation();
117666
- const element2 = state2.elementLookup.get(elementId);
118687
+ const element2 = elementLookup.get(elementId);
117667
118688
  if (element2) {
117668
118689
  const updated = applyFormatToElement(element2, copiedFormatRef.current);
117669
118690
  const updates = {};
@@ -117676,14 +118697,21 @@ function useEditorOperations(input) {
117676
118697
  ops.updateElementById(elementId, updates);
117677
118698
  }
117678
118699
  copiedFormatRef.current = null;
117679
- state2.setFormatPainterActive(false);
118700
+ setFormatPainterActive(false);
117680
118701
  ops.applySelection(elementId);
117681
118702
  return;
117682
118703
  }
117683
118704
  canvasHandlers.handleElementClick(elementId, e2);
118705
+ },
118706
+ handleCanvasMouseDown: (e2) => {
118707
+ if (formatPainterActive) {
118708
+ setFormatPainterActive(false);
118709
+ return;
118710
+ }
118711
+ canvasHandlers.handleCanvasMouseDown(e2);
117684
118712
  }
117685
118713
  }),
117686
- [canvasHandlers, ops, state2]
118714
+ [canvasHandlers, ops, formatPainterActive, setFormatPainterActive, elementLookup]
117687
118715
  );
117688
118716
  return {
117689
118717
  ops: combinedOps,
@@ -119861,21 +120889,35 @@ function useViewerDialogs(input) {
119861
120889
  null
119862
120890
  );
119863
120891
  const [embedFontsEnabled, setEmbedFontsEnabled] = React10.useState(false);
119864
- const [isNarrowViewport, setIsNarrowViewport] = React10.useState(false);
120892
+ const [isNarrowViewport, setIsNarrowViewport] = React10.useState(
120893
+ () => typeof window !== "undefined" ? window.innerWidth < 768 : false
120894
+ );
119865
120895
  React10.useEffect(() => {
119866
- const el = containerRef.current;
119867
- if (!el) {
119868
- return;
119869
- }
119870
- const observer = new ResizeObserver((entries) => {
119871
- const entry = entries[0];
119872
- if (entry) {
119873
- setIsNarrowViewport(entry.contentRect.width < 768);
120896
+ const handleWindow = () => setIsNarrowViewport(window.innerWidth < 768);
120897
+ let observer = null;
120898
+ let raf = 0;
120899
+ const attach2 = () => {
120900
+ const el = containerRef.current;
120901
+ if (!el) {
120902
+ raf = requestAnimationFrame(attach2);
120903
+ return;
119874
120904
  }
119875
- });
119876
- observer.observe(el);
119877
- setIsNarrowViewport(el.clientWidth < 768);
119878
- return () => observer.disconnect();
120905
+ observer = new ResizeObserver((entries) => {
120906
+ const entry = entries[0];
120907
+ if (entry) {
120908
+ setIsNarrowViewport(entry.contentRect.width < 768);
120909
+ }
120910
+ });
120911
+ observer.observe(el);
120912
+ setIsNarrowViewport(el.clientWidth < 768);
120913
+ };
120914
+ attach2();
120915
+ window.addEventListener("resize", handleWindow);
120916
+ return () => {
120917
+ cancelAnimationFrame(raf);
120918
+ observer?.disconnect();
120919
+ window.removeEventListener("resize", handleWindow);
120920
+ };
119879
120921
  }, []);
119880
120922
  React10.useEffect(() => {
119881
120923
  if (isDirty && hasDigitalSignatures && !signatureStripAcknowledgedRef.current) {
@@ -124347,7 +125389,9 @@ function useViewerCoreState(_input) {
124347
125389
  function useViewerUIState() {
124348
125390
  const [isCompactToolbarOpen, setIsCompactToolbarOpen] = React10.useState(false);
124349
125391
  const [toolbarSection, setToolbarSection] = React10.useState("home");
124350
- const [isSlidesPaneOpen, setIsSlidesPaneOpen] = React10.useState(true);
125392
+ const [isSlidesPaneOpen, setIsSlidesPaneOpen] = React10.useState(
125393
+ () => typeof window === "undefined" ? true : window.innerWidth >= 768
125394
+ );
124351
125395
  const [isInspectorPaneOpen, setIsInspectorPaneOpen] = React10.useState(false);
124352
125396
  const [isSlideNotesCollapsed, setIsSlideNotesCollapsed] = React10.useState(true);
124353
125397
  const [isOverflowMenuOpen, setIsOverflowMenuOpen] = React10.useState(false);
@@ -124790,7 +125834,8 @@ var PowerPointViewer = React10.forwardRef(
124790
125834
  canvasSize,
124791
125835
  dialogs,
124792
125836
  presentation,
124793
- userName: authorName ?? collaboration?.userName
125837
+ userName: authorName ?? collaboration?.userName,
125838
+ handlerRef: actionSoundHandlerRef
124794
125839
  });
124795
125840
  const {
124796
125841
  exportHandlers,
@@ -124913,7 +125958,7 @@ var PowerPointViewer = React10.forwardRef(
124913
125958
  {
124914
125959
  activeSlide,
124915
125960
  allSlides: slides,
124916
- isSlideNotesCollapsed: isMobile || state2.isSlideNotesCollapsed,
125961
+ isSlideNotesCollapsed: state2.isSlideNotesCollapsed,
124917
125962
  canEdit,
124918
125963
  slideCount: slides.length,
124919
125964
  activeSlideIndex,
@@ -124930,7 +125975,22 @@ var PowerPointViewer = React10.forwardRef(
124930
125975
  onZoomToFit: zoom.handleZoomToFit,
124931
125976
  mode,
124932
125977
  onSetMode: handleSetMode,
124933
- onToggleSlideSorter: () => state2.setShowSlideSorter((p3) => !p3)
125978
+ onToggleSlideSorter: () => state2.setShowSlideSorter((p3) => !p3),
125979
+ hideStatusBar: isMobile
125980
+ }
125981
+ ),
125982
+ mode !== "present" && isMobile && /* @__PURE__ */ jsxRuntime.jsx(
125983
+ MobileChromeOverlay,
125984
+ {
125985
+ state: state2,
125986
+ editorOps,
125987
+ presentation,
125988
+ slides,
125989
+ activeSlideIndex,
125990
+ canvasSize,
125991
+ slideSectionGroups,
125992
+ canEdit,
125993
+ commentCount: activeSlide?.comments?.length ?? 0
124934
125994
  }
124935
125995
  ),
124936
125996
  /* @__PURE__ */ jsxRuntime.jsx(