@emasoft/svg-matrix 1.0.30 → 1.0.31

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 (45) hide show
  1. package/bin/svg-matrix.js +310 -61
  2. package/bin/svglinter.cjs +102 -3
  3. package/bin/svgm.js +236 -27
  4. package/package.json +1 -1
  5. package/src/animation-optimization.js +137 -17
  6. package/src/animation-references.js +123 -6
  7. package/src/arc-length.js +213 -4
  8. package/src/bezier-analysis.js +217 -21
  9. package/src/bezier-intersections.js +275 -12
  10. package/src/browser-verify.js +237 -4
  11. package/src/clip-path-resolver.js +168 -0
  12. package/src/convert-path-data.js +479 -28
  13. package/src/css-specificity.js +73 -10
  14. package/src/douglas-peucker.js +219 -2
  15. package/src/flatten-pipeline.js +284 -26
  16. package/src/geometry-to-path.js +250 -25
  17. package/src/gjk-collision.js +236 -33
  18. package/src/index.js +261 -3
  19. package/src/inkscape-support.js +86 -28
  20. package/src/logger.js +48 -3
  21. package/src/marker-resolver.js +278 -74
  22. package/src/mask-resolver.js +265 -66
  23. package/src/matrix.js +44 -5
  24. package/src/mesh-gradient.js +352 -102
  25. package/src/off-canvas-detection.js +382 -13
  26. package/src/path-analysis.js +192 -18
  27. package/src/path-data-plugins.js +309 -5
  28. package/src/path-optimization.js +129 -5
  29. package/src/path-simplification.js +188 -32
  30. package/src/pattern-resolver.js +454 -106
  31. package/src/polygon-clip.js +324 -1
  32. package/src/svg-boolean-ops.js +226 -9
  33. package/src/svg-collections.js +7 -5
  34. package/src/svg-flatten.js +386 -62
  35. package/src/svg-parser.js +179 -8
  36. package/src/svg-rendering-context.js +235 -6
  37. package/src/svg-toolbox.js +45 -8
  38. package/src/svg2-polyfills.js +40 -10
  39. package/src/transform-decomposition.js +258 -32
  40. package/src/transform-optimization.js +259 -13
  41. package/src/transforms2d.js +82 -9
  42. package/src/transforms3d.js +62 -10
  43. package/src/use-symbol-resolver.js +286 -42
  44. package/src/vector.js +64 -8
  45. package/src/verification.js +392 -1
package/src/index.js CHANGED
@@ -5,7 +5,7 @@
5
5
  * SVG path conversion, and 2D/3D affine transformations using Decimal.js.
6
6
  *
7
7
  * @module @emasoft/svg-matrix
8
- * @version 1.0.30
8
+ * @version 1.0.31
9
9
  * @license MIT
10
10
  *
11
11
  * @example
@@ -93,7 +93,6 @@ import {
93
93
  Logger,
94
94
  LogLevel,
95
95
  setLogLevel,
96
- getLogLevel as _getLoggerLevel,
97
96
  enableFileLogging,
98
97
  disableFileLogging,
99
98
  } from "./logger.js";
@@ -135,7 +134,7 @@ Decimal.set({ precision: 80 });
135
134
  * Library version
136
135
  * @constant {string}
137
136
  */
138
- export const VERSION = '1.0.30';
137
+ export const VERSION = '1.0.31';
139
138
 
140
139
  /**
141
140
  * Default precision for path output (decimal places)
@@ -352,8 +351,15 @@ export { Logger, LogLevel, setLogLevel, enableFileLogging, disableFileLogging };
352
351
  * @param {number|string|Decimal} tx - X translation
353
352
  * @param {number|string|Decimal} ty - Y translation
354
353
  * @returns {Matrix} 3x3 translation matrix
354
+ * @throws {TypeError} If tx or ty is null or undefined
355
355
  */
356
356
  export function translate2D(tx, ty) {
357
+ if (tx == null) {
358
+ throw new TypeError("translate2D: tx cannot be null or undefined");
359
+ }
360
+ if (ty == null) {
361
+ throw new TypeError("translate2D: ty cannot be null or undefined");
362
+ }
357
363
  return Transforms2D.translation(tx, ty);
358
364
  }
359
365
 
@@ -362,8 +368,12 @@ export function translate2D(tx, ty) {
362
368
  * Convenience wrapper for Transforms2D.rotate().
363
369
  * @param {number|string|Decimal} angle - Rotation angle in radians
364
370
  * @returns {Matrix} 3x3 rotation matrix
371
+ * @throws {TypeError} If angle is null or undefined
365
372
  */
366
373
  export function rotate2D(angle) {
374
+ if (angle == null) {
375
+ throw new TypeError("rotate2D: angle cannot be null or undefined");
376
+ }
367
377
  return Transforms2D.rotate(angle);
368
378
  }
369
379
 
@@ -373,8 +383,12 @@ export function rotate2D(angle) {
373
383
  * @param {number|string|Decimal} sx - X scale factor
374
384
  * @param {number|string|Decimal} [sy=sx] - Y scale factor (defaults to sx for uniform scaling)
375
385
  * @returns {Matrix} 3x3 scale matrix
386
+ * @throws {TypeError} If sx is null or undefined
376
387
  */
377
388
  export function scale2D(sx, sy = null) {
389
+ if (sx == null) {
390
+ throw new TypeError("scale2D: sx cannot be null or undefined");
391
+ }
378
392
  return Transforms2D.scale(sx, sy);
379
393
  }
380
394
 
@@ -385,8 +399,18 @@ export function scale2D(sx, sy = null) {
385
399
  * @param {number|string|Decimal} x - X coordinate
386
400
  * @param {number|string|Decimal} y - Y coordinate
387
401
  * @returns {[Decimal, Decimal]} Transformed [x, y] coordinates
402
+ * @throws {TypeError} If matrix, x, or y is null or undefined
388
403
  */
389
404
  export function transform2D(matrix, x, y) {
405
+ if (matrix == null) {
406
+ throw new TypeError("transform2D: matrix cannot be null or undefined");
407
+ }
408
+ if (x == null) {
409
+ throw new TypeError("transform2D: x cannot be null or undefined");
410
+ }
411
+ if (y == null) {
412
+ throw new TypeError("transform2D: y cannot be null or undefined");
413
+ }
390
414
  return Transforms2D.applyTransform(matrix, x, y);
391
415
  }
392
416
 
@@ -397,8 +421,18 @@ export function transform2D(matrix, x, y) {
397
421
  * @param {number|string|Decimal} ty - Y translation
398
422
  * @param {number|string|Decimal} tz - Z translation
399
423
  * @returns {Matrix} 4x4 translation matrix
424
+ * @throws {TypeError} If tx, ty, or tz is null or undefined
400
425
  */
401
426
  export function translate3D(tx, ty, tz) {
427
+ if (tx == null) {
428
+ throw new TypeError("translate3D: tx cannot be null or undefined");
429
+ }
430
+ if (ty == null) {
431
+ throw new TypeError("translate3D: ty cannot be null or undefined");
432
+ }
433
+ if (tz == null) {
434
+ throw new TypeError("translate3D: tz cannot be null or undefined");
435
+ }
402
436
  return Transforms3D.translation(tx, ty, tz);
403
437
  }
404
438
 
@@ -409,8 +443,12 @@ export function translate3D(tx, ty, tz) {
409
443
  * @param {number|string|Decimal} [sy=sx] - Y scale factor
410
444
  * @param {number|string|Decimal} [sz=sx] - Z scale factor
411
445
  * @returns {Matrix} 4x4 scale matrix
446
+ * @throws {TypeError} If sx is null or undefined
412
447
  */
413
448
  export function scale3D(sx, sy = null, sz = null) {
449
+ if (sx == null) {
450
+ throw new TypeError("scale3D: sx cannot be null or undefined");
451
+ }
414
452
  return Transforms3D.scale(sx, sy, sz);
415
453
  }
416
454
 
@@ -422,8 +460,21 @@ export function scale3D(sx, sy = null, sz = null) {
422
460
  * @param {number|string|Decimal} y - Y coordinate
423
461
  * @param {number|string|Decimal} z - Z coordinate
424
462
  * @returns {[Decimal, Decimal, Decimal]} Transformed [x, y, z] coordinates
463
+ * @throws {TypeError} If matrix, x, y, or z is null or undefined
425
464
  */
426
465
  export function transform3D(matrix, x, y, z) {
466
+ if (matrix == null) {
467
+ throw new TypeError("transform3D: matrix cannot be null or undefined");
468
+ }
469
+ if (x == null) {
470
+ throw new TypeError("transform3D: x cannot be null or undefined");
471
+ }
472
+ if (y == null) {
473
+ throw new TypeError("transform3D: y cannot be null or undefined");
474
+ }
475
+ if (z == null) {
476
+ throw new TypeError("transform3D: z cannot be null or undefined");
477
+ }
427
478
  return Transforms3D.applyTransform(matrix, x, y, z);
428
479
  }
429
480
 
@@ -435,8 +486,25 @@ export function transform3D(matrix, x, y, z) {
435
486
  * @param {number|string|Decimal} r - Radius
436
487
  * @param {number} [precision=6] - Number of decimal places in output
437
488
  * @returns {string} SVG path data string
489
+ * @throws {TypeError} If cx, cy, or r is null/undefined, or precision is not a number
490
+ * @throws {RangeError} If precision is negative
438
491
  */
439
492
  export function circleToPath(cx, cy, r, precision = DEFAULT_PRECISION) {
493
+ if (cx == null) {
494
+ throw new TypeError("circleToPath: cx cannot be null or undefined");
495
+ }
496
+ if (cy == null) {
497
+ throw new TypeError("circleToPath: cy cannot be null or undefined");
498
+ }
499
+ if (r == null) {
500
+ throw new TypeError("circleToPath: r cannot be null or undefined");
501
+ }
502
+ if (typeof precision !== "number" || !Number.isFinite(precision)) {
503
+ throw new TypeError(`circleToPath: precision must be a finite number, got ${typeof precision}`);
504
+ }
505
+ if (precision < 0) {
506
+ throw new RangeError(`circleToPath: precision must be non-negative, got ${precision}`);
507
+ }
440
508
  return GeometryToPath.circleToPathData(cx, cy, r, precision);
441
509
  }
442
510
 
@@ -448,8 +516,28 @@ export function circleToPath(cx, cy, r, precision = DEFAULT_PRECISION) {
448
516
  * @param {number|string|Decimal} ry - Y-axis radius
449
517
  * @param {number} [precision=6] - Number of decimal places in output
450
518
  * @returns {string} SVG path data string
519
+ * @throws {TypeError} If cx, cy, rx, or ry is null/undefined, or precision is not a number
520
+ * @throws {RangeError} If precision is negative
451
521
  */
452
522
  export function ellipseToPath(cx, cy, rx, ry, precision = DEFAULT_PRECISION) {
523
+ if (cx == null) {
524
+ throw new TypeError("ellipseToPath: cx cannot be null or undefined");
525
+ }
526
+ if (cy == null) {
527
+ throw new TypeError("ellipseToPath: cy cannot be null or undefined");
528
+ }
529
+ if (rx == null) {
530
+ throw new TypeError("ellipseToPath: rx cannot be null or undefined");
531
+ }
532
+ if (ry == null) {
533
+ throw new TypeError("ellipseToPath: ry cannot be null or undefined");
534
+ }
535
+ if (typeof precision !== "number" || !Number.isFinite(precision)) {
536
+ throw new TypeError(`ellipseToPath: precision must be a finite number, got ${typeof precision}`);
537
+ }
538
+ if (precision < 0) {
539
+ throw new RangeError(`ellipseToPath: precision must be non-negative, got ${precision}`);
540
+ }
453
541
  return GeometryToPath.ellipseToPathData(cx, cy, rx, ry, precision);
454
542
  }
455
543
 
@@ -463,6 +551,8 @@ export function ellipseToPath(cx, cy, rx, ry, precision = DEFAULT_PRECISION) {
463
551
  * @param {number|string|Decimal} [ry=rx] - Corner Y radius
464
552
  * @param {number} [precision=6] - Number of decimal places in output
465
553
  * @returns {string} SVG path data string
554
+ * @throws {TypeError} If x, y, width, or height is null/undefined, or precision is not a number
555
+ * @throws {RangeError} If precision is negative
466
556
  */
467
557
  export function rectToPath(
468
558
  x,
@@ -473,6 +563,24 @@ export function rectToPath(
473
563
  ry = null,
474
564
  precision = DEFAULT_PRECISION,
475
565
  ) {
566
+ if (x == null) {
567
+ throw new TypeError("rectToPath: x cannot be null or undefined");
568
+ }
569
+ if (y == null) {
570
+ throw new TypeError("rectToPath: y cannot be null or undefined");
571
+ }
572
+ if (width == null) {
573
+ throw new TypeError("rectToPath: width cannot be null or undefined");
574
+ }
575
+ if (height == null) {
576
+ throw new TypeError("rectToPath: height cannot be null or undefined");
577
+ }
578
+ if (typeof precision !== "number" || !Number.isFinite(precision)) {
579
+ throw new TypeError(`rectToPath: precision must be a finite number, got ${typeof precision}`);
580
+ }
581
+ if (precision < 0) {
582
+ throw new RangeError(`rectToPath: precision must be non-negative, got ${precision}`);
583
+ }
476
584
  return GeometryToPath.rectToPathData(
477
585
  x,
478
586
  y,
@@ -493,8 +601,28 @@ export function rectToPath(
493
601
  * @param {number|string|Decimal} y2 - End Y coordinate
494
602
  * @param {number} [precision=6] - Number of decimal places in output
495
603
  * @returns {string} SVG path data string
604
+ * @throws {TypeError} If x1, y1, x2, or y2 is null/undefined, or precision is not a number
605
+ * @throws {RangeError} If precision is negative
496
606
  */
497
607
  export function lineToPath(x1, y1, x2, y2, precision = DEFAULT_PRECISION) {
608
+ if (x1 == null) {
609
+ throw new TypeError("lineToPath: x1 cannot be null or undefined");
610
+ }
611
+ if (y1 == null) {
612
+ throw new TypeError("lineToPath: y1 cannot be null or undefined");
613
+ }
614
+ if (x2 == null) {
615
+ throw new TypeError("lineToPath: x2 cannot be null or undefined");
616
+ }
617
+ if (y2 == null) {
618
+ throw new TypeError("lineToPath: y2 cannot be null or undefined");
619
+ }
620
+ if (typeof precision !== "number" || !Number.isFinite(precision)) {
621
+ throw new TypeError(`lineToPath: precision must be a finite number, got ${typeof precision}`);
622
+ }
623
+ if (precision < 0) {
624
+ throw new RangeError(`lineToPath: precision must be non-negative, got ${precision}`);
625
+ }
498
626
  return GeometryToPath.lineToPathData(x1, y1, x2, y2, precision);
499
627
  }
500
628
 
@@ -503,8 +631,19 @@ export function lineToPath(x1, y1, x2, y2, precision = DEFAULT_PRECISION) {
503
631
  * @param {string|Array<[number, number]>} points - SVG points attribute or array of [x, y] pairs
504
632
  * @param {number} [precision=6] - Number of decimal places in output
505
633
  * @returns {string} SVG path data string (closed)
634
+ * @throws {TypeError} If points is null/undefined, or precision is not a number
635
+ * @throws {RangeError} If precision is negative
506
636
  */
507
637
  export function polygonToPath(points, precision = DEFAULT_PRECISION) {
638
+ if (points == null) {
639
+ throw new TypeError("polygonToPath: points cannot be null or undefined");
640
+ }
641
+ if (typeof precision !== "number" || !Number.isFinite(precision)) {
642
+ throw new TypeError(`polygonToPath: precision must be a finite number, got ${typeof precision}`);
643
+ }
644
+ if (precision < 0) {
645
+ throw new RangeError(`polygonToPath: precision must be non-negative, got ${precision}`);
646
+ }
508
647
  return GeometryToPath.polygonToPathData(points, precision);
509
648
  }
510
649
 
@@ -513,8 +652,19 @@ export function polygonToPath(points, precision = DEFAULT_PRECISION) {
513
652
  * @param {string|Array<[number, number]>} points - SVG points attribute or array of [x, y] pairs
514
653
  * @param {number} [precision=6] - Number of decimal places in output
515
654
  * @returns {string} SVG path data string (open)
655
+ * @throws {TypeError} If points is null/undefined, or precision is not a number
656
+ * @throws {RangeError} If precision is negative
516
657
  */
517
658
  export function polylineToPath(points, precision = DEFAULT_PRECISION) {
659
+ if (points == null) {
660
+ throw new TypeError("polylineToPath: points cannot be null or undefined");
661
+ }
662
+ if (typeof precision !== "number" || !Number.isFinite(precision)) {
663
+ throw new TypeError(`polylineToPath: precision must be a finite number, got ${typeof precision}`);
664
+ }
665
+ if (precision < 0) {
666
+ throw new RangeError(`polylineToPath: precision must be non-negative, got ${precision}`);
667
+ }
518
668
  return GeometryToPath.polylineToPathData(points, precision);
519
669
  }
520
670
 
@@ -531,8 +681,12 @@ export function getKappa() {
531
681
  * Parse SVG path data into an array of commands with Decimal arguments.
532
682
  * @param {string} pathData - SVG path data string
533
683
  * @returns {Array<{command: string, args: Decimal[]}>} Parsed commands
684
+ * @throws {TypeError} If pathData is null or undefined
534
685
  */
535
686
  export function parsePath(pathData) {
687
+ if (pathData == null) {
688
+ throw new TypeError("parsePath: pathData cannot be null or undefined");
689
+ }
536
690
  return GeometryToPath.parsePathData(pathData);
537
691
  }
538
692
 
@@ -541,8 +695,19 @@ export function parsePath(pathData) {
541
695
  * @param {Array<{command: string, args: Decimal[]}>} commands - Path commands
542
696
  * @param {number} [precision=6] - Number of decimal places in output
543
697
  * @returns {string} SVG path data string
698
+ * @throws {TypeError} If commands is null/undefined, or precision is not a number
699
+ * @throws {RangeError} If precision is negative
544
700
  */
545
701
  export function pathToString(commands, precision = DEFAULT_PRECISION) {
702
+ if (commands == null) {
703
+ throw new TypeError("pathToString: commands cannot be null or undefined");
704
+ }
705
+ if (typeof precision !== "number" || !Number.isFinite(precision)) {
706
+ throw new TypeError(`pathToString: precision must be a finite number, got ${typeof precision}`);
707
+ }
708
+ if (precision < 0) {
709
+ throw new RangeError(`pathToString: precision must be non-negative, got ${precision}`);
710
+ }
546
711
  return GeometryToPath.pathArrayToString(commands, precision);
547
712
  }
548
713
 
@@ -550,8 +715,12 @@ export function pathToString(commands, precision = DEFAULT_PRECISION) {
550
715
  * Convert relative path commands to absolute.
551
716
  * @param {string} pathData - SVG path data (may contain relative commands)
552
717
  * @returns {string} SVG path data with only absolute commands
718
+ * @throws {TypeError} If pathData is null or undefined
553
719
  */
554
720
  export function pathToAbsolute(pathData) {
721
+ if (pathData == null) {
722
+ throw new TypeError("pathToAbsolute: pathData cannot be null or undefined");
723
+ }
555
724
  return GeometryToPath.pathToAbsolute(pathData);
556
725
  }
557
726
 
@@ -560,8 +729,12 @@ export function pathToAbsolute(pathData) {
560
729
  * Lines become degenerate cubics, quadratics are elevated to cubics.
561
730
  * @param {string} pathData - SVG path data
562
731
  * @returns {string} SVG path data with only M, C, and Z commands
732
+ * @throws {TypeError} If pathData is null or undefined
563
733
  */
564
734
  export function pathToCubics(pathData) {
735
+ if (pathData == null) {
736
+ throw new TypeError("pathToCubics: pathData cannot be null or undefined");
737
+ }
565
738
  return GeometryToPath.pathToCubics(pathData);
566
739
  }
567
740
 
@@ -571,8 +744,22 @@ export function pathToCubics(pathData) {
571
744
  * @param {Matrix} matrix - 3x3 transformation matrix
572
745
  * @param {number} [precision=6] - Number of decimal places in output
573
746
  * @returns {string} Transformed SVG path data
747
+ * @throws {TypeError} If pathData or matrix is null/undefined, or precision is not a number
748
+ * @throws {RangeError} If precision is negative
574
749
  */
575
750
  export function transformPath(pathData, matrix, precision = DEFAULT_PRECISION) {
751
+ if (pathData == null) {
752
+ throw new TypeError("transformPath: pathData cannot be null or undefined");
753
+ }
754
+ if (matrix == null) {
755
+ throw new TypeError("transformPath: matrix cannot be null or undefined");
756
+ }
757
+ if (typeof precision !== "number" || !Number.isFinite(precision)) {
758
+ throw new TypeError(`transformPath: precision must be a finite number, got ${typeof precision}`);
759
+ }
760
+ if (precision < 0) {
761
+ throw new RangeError(`transformPath: precision must be non-negative, got ${precision}`);
762
+ }
576
763
  return GeometryToPath.transformPathData(pathData, matrix, precision);
577
764
  }
578
765
 
@@ -582,8 +769,19 @@ export function transformPath(pathData, matrix, precision = DEFAULT_PRECISION) {
582
769
  * @param {Object|Element} element - SVG element or object with tagName and attributes
583
770
  * @param {number} [precision=6] - Number of decimal places in output
584
771
  * @returns {string|null} SVG path data string, or null if element type not supported
772
+ * @throws {TypeError} If element is null/undefined, or precision is not a number
773
+ * @throws {RangeError} If precision is negative
585
774
  */
586
775
  export function elementToPath(element, precision = DEFAULT_PRECISION) {
776
+ if (element == null) {
777
+ throw new TypeError("elementToPath: element cannot be null or undefined");
778
+ }
779
+ if (typeof precision !== "number" || !Number.isFinite(precision)) {
780
+ throw new TypeError(`elementToPath: precision must be a finite number, got ${typeof precision}`);
781
+ }
782
+ if (precision < 0) {
783
+ throw new RangeError(`elementToPath: precision must be non-negative, got ${precision}`);
784
+ }
587
785
  return GeometryToPath.convertElementToPath(element, precision);
588
786
  }
589
787
 
@@ -591,8 +789,18 @@ export function elementToPath(element, precision = DEFAULT_PRECISION) {
591
789
  * Create an identity matrix of the given size.
592
790
  * @param {number} n - Matrix dimension (creates n x n identity matrix)
593
791
  * @returns {Matrix} Identity matrix
792
+ * @throws {TypeError} If n is not a number
793
+ * @throws {RangeError} If n is not a positive integer
594
794
  */
595
795
  export function identity(n) {
796
+ // Validate n is a number
797
+ if (typeof n !== "number" || !Number.isFinite(n)) {
798
+ throw new TypeError(`identity: n must be a finite number, got ${typeof n}`);
799
+ }
800
+ // Validate n is a positive integer
801
+ if (!Number.isInteger(n) || n < 1) {
802
+ throw new RangeError(`identity: n must be a positive integer, got ${n}`);
803
+ }
596
804
  return Matrix.identity(n);
597
805
  }
598
806
 
@@ -601,8 +809,30 @@ export function identity(n) {
601
809
  * @param {number} rows - Number of rows
602
810
  * @param {number} cols - Number of columns
603
811
  * @returns {Matrix} Zero matrix
812
+ * @throws {TypeError} If rows or cols is not a number
813
+ * @throws {RangeError} If rows or cols is not a positive integer
604
814
  */
605
815
  export function zeros(rows, cols) {
816
+ // Validate rows is a number
817
+ if (typeof rows !== "number" || !Number.isFinite(rows)) {
818
+ throw new TypeError(
819
+ `zeros: rows must be a finite number, got ${typeof rows}`,
820
+ );
821
+ }
822
+ // Validate cols is a number
823
+ if (typeof cols !== "number" || !Number.isFinite(cols)) {
824
+ throw new TypeError(
825
+ `zeros: cols must be a finite number, got ${typeof cols}`,
826
+ );
827
+ }
828
+ // Validate rows is a positive integer
829
+ if (!Number.isInteger(rows) || rows < 1) {
830
+ throw new RangeError(`zeros: rows must be a positive integer, got ${rows}`);
831
+ }
832
+ // Validate cols is a positive integer
833
+ if (!Number.isInteger(cols) || cols < 1) {
834
+ throw new RangeError(`zeros: cols must be a positive integer, got ${cols}`);
835
+ }
606
836
  return Matrix.zeros(rows, cols);
607
837
  }
608
838
 
@@ -610,8 +840,12 @@ export function zeros(rows, cols) {
610
840
  * Create a vector from an array of components.
611
841
  * @param {Array<number|string|Decimal>} components - Vector components
612
842
  * @returns {Vector} New vector instance
843
+ * @throws {TypeError} If components is null or undefined
613
844
  */
614
845
  export function vec(components) {
846
+ if (components == null) {
847
+ throw new TypeError("vec: components cannot be null or undefined");
848
+ }
615
849
  return Vector.from(components);
616
850
  }
617
851
 
@@ -619,16 +853,40 @@ export function vec(components) {
619
853
  * Create a matrix from a 2D array.
620
854
  * @param {Array<Array<number|string|Decimal>>} data - 2D array of matrix elements
621
855
  * @returns {Matrix} New matrix instance
856
+ * @throws {TypeError} If data is null or undefined
622
857
  */
623
858
  export function mat(data) {
859
+ if (data == null) {
860
+ throw new TypeError("mat: data cannot be null or undefined");
861
+ }
624
862
  return Matrix.from(data);
625
863
  }
626
864
 
627
865
  /**
628
866
  * Set the global precision for all Decimal operations.
629
867
  * @param {number} precision - Number of significant digits (1 to 1e9)
868
+ * @throws {TypeError} If precision is not a finite number or not an integer
869
+ * @throws {RangeError} If precision is not between 1 and 1e9
630
870
  */
631
871
  export function setPrecision(precision) {
872
+ // Validate precision is a number
873
+ if (typeof precision !== "number" || !Number.isFinite(precision)) {
874
+ throw new TypeError(
875
+ `setPrecision: precision must be a finite number, got ${typeof precision}`,
876
+ );
877
+ }
878
+ // Validate precision is an integer
879
+ if (!Number.isInteger(precision)) {
880
+ throw new TypeError(
881
+ `setPrecision: precision must be an integer, got ${precision}`,
882
+ );
883
+ }
884
+ // Validate precision range (Decimal.js requirement: 1 to 1e9)
885
+ if (precision < 1 || precision > 1e9) {
886
+ throw new RangeError(
887
+ `setPrecision: precision must be between 1 and 1e9, got ${precision}`,
888
+ );
889
+ }
632
890
  Decimal.set({ precision });
633
891
  }
634
892