@synnaxlabs/x 0.55.0 → 0.56.1

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 (146) hide show
  1. package/.turbo/turbo-build.log +10 -13
  2. package/dist/src/array/nullable.d.ts +1 -1
  3. package/dist/src/array/nullable.d.ts.map +1 -1
  4. package/dist/src/caseconv/caseconv.d.ts.map +1 -1
  5. package/dist/src/compare/compare.d.ts +14 -0
  6. package/dist/src/compare/compare.d.ts.map +1 -1
  7. package/dist/src/debounce/debounce.d.ts +7 -2
  8. package/dist/src/debounce/debounce.d.ts.map +1 -1
  9. package/dist/src/deep/merge.d.ts.map +1 -1
  10. package/dist/src/deep/set.d.ts.map +1 -1
  11. package/dist/src/destructor/destructor.d.ts +1 -0
  12. package/dist/src/destructor/destructor.d.ts.map +1 -1
  13. package/dist/src/errors/errors.d.ts +18 -10
  14. package/dist/src/errors/errors.d.ts.map +1 -1
  15. package/dist/src/index.d.ts +4 -1
  16. package/dist/src/index.d.ts.map +1 -1
  17. package/dist/src/migrate/migrate.d.ts.map +1 -1
  18. package/dist/src/notation/external.d.ts +3 -0
  19. package/dist/src/notation/external.d.ts.map +1 -0
  20. package/dist/src/notation/index.d.ts +1 -1
  21. package/dist/src/notation/notation.d.ts +5 -9
  22. package/dist/src/notation/notation.d.ts.map +1 -1
  23. package/dist/src/notation/types.gen.d.ts +9 -0
  24. package/dist/src/notation/types.gen.d.ts.map +1 -0
  25. package/dist/src/primitive/primitive.d.ts +16 -0
  26. package/dist/src/primitive/primitive.d.ts.map +1 -1
  27. package/dist/src/record/record.d.ts +8 -1
  28. package/dist/src/record/record.d.ts.map +1 -1
  29. package/dist/src/require/index.d.ts +2 -0
  30. package/dist/src/require/index.d.ts.map +1 -0
  31. package/dist/src/require/require.d.ts +2 -0
  32. package/dist/src/require/require.d.ts.map +1 -0
  33. package/dist/src/spatial/base.d.ts +1 -103
  34. package/dist/src/spatial/base.d.ts.map +1 -1
  35. package/dist/src/spatial/bounds/bounds.d.ts +3 -3
  36. package/dist/src/spatial/bounds/bounds.d.ts.map +1 -1
  37. package/dist/src/spatial/box/box.d.ts +7 -13
  38. package/dist/src/spatial/box/box.d.ts.map +1 -1
  39. package/dist/src/spatial/direction/direction.d.ts +17 -16
  40. package/dist/src/spatial/direction/direction.d.ts.map +1 -1
  41. package/dist/src/spatial/external.d.ts +1 -2
  42. package/dist/src/spatial/external.d.ts.map +1 -1
  43. package/dist/src/spatial/location/location.d.ts +28 -28
  44. package/dist/src/spatial/location/location.d.ts.map +1 -1
  45. package/dist/src/spatial/scale/scale.d.ts +2 -2
  46. package/dist/src/spatial/scale/scale.d.ts.map +1 -1
  47. package/dist/src/spatial/sticky/sticky.d.ts +15 -15
  48. package/dist/src/spatial/sticky/sticky.d.ts.map +1 -1
  49. package/dist/src/spatial/types.gen.d.ts +179 -2
  50. package/dist/src/spatial/types.gen.d.ts.map +1 -1
  51. package/dist/src/spatial/xy/xy.d.ts +4 -4
  52. package/dist/src/spatial/xy/xy.d.ts.map +1 -1
  53. package/dist/src/status/status.d.ts +11 -0
  54. package/dist/src/status/status.d.ts.map +1 -1
  55. package/dist/src/telem/external.d.ts +1 -0
  56. package/dist/src/telem/external.d.ts.map +1 -1
  57. package/dist/src/telem/series.d.ts +5 -2
  58. package/dist/src/telem/series.d.ts.map +1 -1
  59. package/dist/src/telem/telem.d.ts +42 -34
  60. package/dist/src/telem/telem.d.ts.map +1 -1
  61. package/dist/src/telem/types.gen.d.ts +19 -0
  62. package/dist/src/telem/types.gen.d.ts.map +1 -0
  63. package/dist/src/text/external.d.ts +3 -0
  64. package/dist/src/text/external.d.ts.map +1 -0
  65. package/dist/src/text/index.d.ts +2 -0
  66. package/dist/src/text/index.d.ts.map +1 -0
  67. package/dist/src/text/types.d.ts +21 -0
  68. package/dist/src/text/types.d.ts.map +1 -0
  69. package/dist/src/text/types.gen.d.ts +13 -0
  70. package/dist/src/text/types.gen.d.ts.map +1 -0
  71. package/dist/src/throttle/index.d.ts +2 -0
  72. package/dist/src/throttle/index.d.ts.map +1 -0
  73. package/dist/src/throttle/throttle.d.ts +3 -0
  74. package/dist/src/throttle/throttle.d.ts.map +1 -0
  75. package/dist/src/throttle/throttle.spec.d.ts +2 -0
  76. package/dist/src/throttle/throttle.spec.d.ts.map +1 -0
  77. package/dist/src/zod/parse.d.ts.map +1 -1
  78. package/dist/x.cjs +10 -10
  79. package/dist/x.js +1497 -1365
  80. package/package.json +11 -11
  81. package/src/array/nullable.ts +1 -4
  82. package/src/caseconv/caseconv.spec.ts +71 -0
  83. package/src/caseconv/caseconv.ts +15 -2
  84. package/src/compare/compare.spec.ts +115 -0
  85. package/src/compare/compare.ts +29 -0
  86. package/src/debounce/debounce.spec.ts +258 -24
  87. package/src/debounce/debounce.ts +49 -30
  88. package/src/deep/copy.spec.ts +13 -0
  89. package/src/deep/difference.ts +1 -1
  90. package/src/deep/merge.ts +2 -1
  91. package/src/deep/set.ts +2 -1
  92. package/src/destructor/destructor.ts +2 -0
  93. package/src/errors/errors.spec.ts +122 -0
  94. package/src/errors/errors.ts +51 -17
  95. package/src/index.ts +4 -1
  96. package/src/migrate/migrate.ts +2 -1
  97. package/src/notation/external.ts +11 -0
  98. package/src/notation/index.ts +1 -1
  99. package/src/notation/notation.spec.ts +260 -2
  100. package/src/notation/notation.ts +25 -7
  101. package/src/notation/types.gen.ts +16 -0
  102. package/src/primitive/primitive.spec.ts +58 -5
  103. package/src/primitive/primitive.ts +22 -0
  104. package/src/record/record.spec.ts +26 -0
  105. package/src/record/record.ts +20 -5
  106. package/src/require/index.ts +10 -0
  107. package/src/require/require.ts +10 -0
  108. package/src/spatial/base.ts +1 -93
  109. package/src/spatial/bounds/bounds.ts +10 -10
  110. package/src/spatial/box/box.ts +5 -5
  111. package/src/spatial/direction/direction.ts +16 -17
  112. package/src/spatial/external.ts +1 -2
  113. package/src/spatial/location/location.ts +19 -17
  114. package/src/spatial/scale/scale.ts +2 -2
  115. package/src/spatial/sticky/sticky.spec.ts +2 -2
  116. package/src/spatial/sticky/sticky.ts +6 -13
  117. package/src/spatial/types.gen.ts +140 -0
  118. package/src/spatial/xy/xy.ts +7 -7
  119. package/src/status/status.spec.ts +82 -2
  120. package/src/status/status.ts +35 -9
  121. package/src/telem/external.ts +8 -0
  122. package/src/telem/series.spec.ts +183 -0
  123. package/src/telem/series.ts +54 -16
  124. package/src/telem/telem.spec.ts +128 -9
  125. package/src/telem/telem.ts +91 -79
  126. package/src/telem/types.gen.ts +28 -0
  127. package/src/text/external.ts +11 -0
  128. package/src/text/index.ts +10 -0
  129. package/src/text/types.gen.ts +16 -0
  130. package/src/text/types.ts +37 -0
  131. package/src/{worker → throttle}/index.ts +1 -1
  132. package/src/throttle/throttle.spec.ts +147 -0
  133. package/src/throttle/throttle.ts +44 -0
  134. package/src/zod/parse.ts +2 -3
  135. package/tsconfig.tsbuildinfo +1 -1
  136. package/dist/src/spatial/spatial.d.ts +0 -3
  137. package/dist/src/spatial/spatial.d.ts.map +0 -1
  138. package/dist/src/worker/index.d.ts +0 -2
  139. package/dist/src/worker/index.d.ts.map +0 -1
  140. package/dist/src/worker/worker.d.ts +0 -33
  141. package/dist/src/worker/worker.d.ts.map +0 -1
  142. package/dist/src/worker/worker.spec.d.ts +0 -2
  143. package/dist/src/worker/worker.spec.d.ts.map +0 -1
  144. package/src/spatial/spatial.ts +0 -44
  145. package/src/worker/worker.spec.ts +0 -41
  146. package/src/worker/worker.ts +0 -86
@@ -9,99 +9,7 @@
9
9
 
10
10
  import { z } from "zod";
11
11
 
12
- // Tuples
12
+ export * from "@/spatial/types.gen";
13
13
 
14
14
  export const numberCouple = z.tuple([z.number(), z.number()]);
15
15
  export type NumberCouple<T extends number | bigint = number> = [T, T];
16
-
17
- // Direction
18
-
19
- export const DIRECTIONS = ["x", "y"] as const;
20
- export const directionZ = z.enum(DIRECTIONS);
21
- export type Direction = z.infer<typeof directionZ>;
22
-
23
- // Location
24
-
25
- export const OUTER_LOCATIONS = ["top", "right", "bottom", "left"] as const;
26
- export const outerLocationZ = z.enum(OUTER_LOCATIONS);
27
- export type OuterLocation = z.infer<typeof outerLocationZ>;
28
-
29
- export const X_LOCATIONS = ["left", "right"] as const;
30
- export const xLocationZ = z.enum(X_LOCATIONS);
31
- export type XLocation = z.infer<typeof xLocationZ>;
32
-
33
- export const Y_LOCATIONS = ["top", "bottom"] as const;
34
- export const yLocationZ = z.enum(Y_LOCATIONS);
35
- export type YLocation = z.infer<typeof yLocationZ>;
36
-
37
- export const CENTER_LOCATIONS = ["center"] as const;
38
- export const centerLocationZ = z.enum(CENTER_LOCATIONS);
39
- export type CenterLocation = z.infer<typeof centerLocationZ>;
40
-
41
- export const LOCATIONS = ["top", "right", "bottom", "left", "center"] as const;
42
- export const locationZ = z.enum(LOCATIONS);
43
- export type Location = z.infer<typeof locationZ>;
44
-
45
- // Alignment
46
-
47
- export const ALIGNMENTS = ["start", "center", "end"] as const;
48
- export const alignmentZ = z.enum(ALIGNMENTS);
49
- export type Alignment = z.infer<typeof alignmentZ>;
50
-
51
- // Order
52
-
53
- export const ORDERS = ["first", "last"] as const;
54
- export const orderZ = z.enum(ORDERS);
55
- export type Order = z.infer<typeof orderZ>;
56
-
57
- // XY
58
-
59
- export const clientXyZ = z.object({ clientX: z.number(), clientY: z.number() });
60
- export type ClientXY = z.infer<typeof clientXyZ>;
61
-
62
- // Dimensions
63
-
64
- export const dimensionsZ = z.object({ width: z.number(), height: z.number() });
65
- export type Dimensions = z.infer<typeof dimensionsZ>;
66
-
67
- export const signedDimensionsZ = z.object({
68
- signedWidth: z.number(),
69
- signedHeight: z.number(),
70
- });
71
- export type SignedDimensions = z.infer<typeof signedDimensionsZ>;
72
-
73
- export type Dimension = "width" | "height";
74
- export type SignedDimension = "signedWidth" | "signedHeight";
75
-
76
- // Bounds
77
-
78
- export const boundsZ = z.object({ lower: z.number(), upper: z.number() });
79
-
80
- // Generic bounds interface (supports bigint)
81
- export interface Bounds<T extends number | bigint = number> {
82
- lower: T;
83
- upper: T;
84
- }
85
-
86
- export type CrudeBounds<T extends number | bigint = number> =
87
- | Bounds<T>
88
- | NumberCouple<T>;
89
-
90
- // Derived/complex types
91
-
92
- export const crudeDirection = z.enum([
93
- "x",
94
- "y",
95
- ...OUTER_LOCATIONS,
96
- ...CENTER_LOCATIONS,
97
- ]);
98
- export type CrudeDirection = z.infer<typeof crudeDirection>;
99
- export type CrudeXDirection = "x" | "left" | "right";
100
- export type CrudeYDirection = "y" | "top" | "bottom";
101
- export type AngularDirection = "clockwise" | "counterclockwise";
102
- export const crudeLocation = z.union([
103
- directionZ,
104
- z.enum([...OUTER_LOCATIONS, ...CENTER_LOCATIONS]),
105
- z.instanceof(String),
106
- ]);
107
- export type CrudeLocation = z.infer<typeof crudeLocation>;
@@ -9,11 +9,11 @@
9
9
 
10
10
  import { abs, add, equal as mathEqual, min as mathMin, sub } from "@/math/math";
11
11
  import { type numeric } from "@/numeric";
12
- import { type Bounds, boundsZ, type CrudeBounds } from "@/spatial/base";
12
+ import { type Bounds, boundsZ, type NumberCouple } from "@/spatial/base";
13
13
 
14
14
  export { type Bounds, boundsZ };
15
15
 
16
- export type Crude<T extends numeric.Value = number> = CrudeBounds<T>;
16
+ export type Crude<T extends numeric.Value = number> = Bounds<T> | NumberCouple<T>;
17
17
 
18
18
  /** Options for the `construct` function. */
19
19
  interface ConstructOptions {
@@ -209,7 +209,7 @@ export const clamp = <T extends numeric.Value>(bounds: Crude<T>, target: T): T =
209
209
  */
210
210
  export const contains = <T extends numeric.Value>(
211
211
  bounds: Crude<T>,
212
- target: T | CrudeBounds<T>,
212
+ target: T | Crude<T>,
213
213
  ): boolean => {
214
214
  const _bounds = construct(bounds);
215
215
  if (typeof target === "number" || typeof target === "bigint")
@@ -594,7 +594,7 @@ export const traverse = <T extends numeric.Value = number>(
594
594
  if (dir === 0) return start;
595
595
 
596
596
  let remainingDist = dist;
597
- let currentPosition = start as number | bigint;
597
+ let currentPosition = start;
598
598
 
599
599
  while (mathEqual(remainingDist, 0) === false) {
600
600
  // Find the bound we're currently in or adjacent to
@@ -607,15 +607,15 @@ export const traverse = <T extends numeric.Value = number>(
607
607
  const b = _bounds[index];
608
608
  let distanceInBound: T;
609
609
  if (dir > 0) distanceInBound = sub(b.upper, currentPosition);
610
- else distanceInBound = sub(currentPosition, b.lower) as T;
610
+ else distanceInBound = sub(currentPosition, b.lower);
611
611
 
612
612
  if (distanceInBound > (0 as T)) {
613
613
  const moveDist = mathMin(abs(remainingDist), distanceInBound);
614
- currentPosition = add(currentPosition, dir > 0 ? moveDist : -moveDist) as T;
614
+ currentPosition = add(currentPosition, dir > 0 ? moveDist : -moveDist);
615
615
  remainingDist = sub<T>(remainingDist, dir > 0 ? moveDist : -moveDist);
616
616
 
617
617
  // If we've exhausted the distance, return the current position
618
- if (mathEqual(remainingDist, 0)) return currentPosition as T;
618
+ if (mathEqual(remainingDist, 0)) return currentPosition;
619
619
  continue;
620
620
  }
621
621
  }
@@ -626,17 +626,17 @@ export const traverse = <T extends numeric.Value = number>(
626
626
  const nextBounds = _bounds.filter((b) => b.lower > currentPosition);
627
627
  if (nextBounds.length > 0) currentPosition = nextBounds[0].lower;
628
628
  // No more bounds in this direction
629
- else return currentPosition as T;
629
+ else return currentPosition;
630
630
  } else {
631
631
  // Move to the previous bound's upper value
632
632
  const prevBounds = _bounds.filter((b) => b.upper < currentPosition);
633
633
  if (prevBounds.length > 0)
634
634
  currentPosition = prevBounds[prevBounds.length - 1].upper;
635
635
  // No more bounds in this direction
636
- else return currentPosition as T;
636
+ else return currentPosition;
637
637
  }
638
638
  }
639
- return currentPosition as T;
639
+ return currentPosition;
640
640
  };
641
641
 
642
642
  /**
@@ -32,7 +32,7 @@ export const domRect = z.object({
32
32
  export const box = z.object({
33
33
  one: xy.xyZ,
34
34
  two: xy.xyZ,
35
- root: location.corner,
35
+ root: location.cornerZ,
36
36
  });
37
37
 
38
38
  export type Box = z.infer<typeof box>;
@@ -50,7 +50,7 @@ export const ZERO = { one: xy.ZERO, two: xy.ZERO, root: location.TOP_LEFT };
50
50
  */
51
51
  export const DECIMAL = { one: xy.ZERO, two: xy.ONE, root: location.BOTTOM_LEFT };
52
52
 
53
- export const copy = (b: Box, root?: location.CornerXY): Box => ({
53
+ export const copy = (b: Box, root?: location.Corner): Box => ({
54
54
  one: b.one,
55
55
  two: b.two,
56
56
  root: root ?? b.root,
@@ -71,7 +71,7 @@ export const construct = (
71
71
  second?: number | xy.XY | dimensions.Dimensions | dimensions.Signed,
72
72
  width: number = 0,
73
73
  height: number = 0,
74
- coordinateRoot?: location.CornerXY,
74
+ coordinateRoot?: location.Corner,
75
75
  ): Box => {
76
76
  const b: Box = {
77
77
  one: { ...xy.ZERO },
@@ -339,7 +339,7 @@ export const yBounds = (b: Crude): bounds.Bounds => {
339
339
  return { lower: b_.one.y, upper: b_.two.y };
340
340
  };
341
341
 
342
- export const reRoot = (b: Box, corner: location.CornerXY): Box => copy(b, corner);
342
+ export const reRoot = (b: Box, corner: location.Corner): Box => copy(b, corner);
343
343
 
344
344
  export const edgePoints = (b: Crude, loc: location.Location): [xy.XY, xy.XY] => {
345
345
  const b_ = construct(b);
@@ -461,7 +461,7 @@ export const constructWithAlternateRoot = (
461
461
  width: number,
462
462
  height: number,
463
463
  currRoot: location.XY,
464
- newRoot: location.CornerXY,
464
+ newRoot: location.Corner,
465
465
  ): Box => {
466
466
  const first = { x, y };
467
467
  const second = { x: x + width, y: y + height };
@@ -7,30 +7,29 @@
7
7
  // License, use of this software will be governed by the Apache License, Version 2.0,
8
8
  // included in the file licenses/APL.txt.
9
9
 
10
+ import z from "zod";
11
+
10
12
  import {
11
13
  type AngularDirection,
12
- type CrudeDirection,
13
- crudeDirection,
14
- type CrudeXDirection,
15
- type CrudeYDirection,
14
+ CENTER_LOCATIONS,
16
15
  type Dimension,
17
16
  type Direction,
18
17
  DIRECTIONS,
19
18
  directionZ,
20
19
  type Location,
20
+ OUTER_LOCATIONS,
21
21
  type SignedDimension,
22
22
  Y_LOCATIONS,
23
23
  type YLocation,
24
- } from "@/spatial/base";
24
+ } from "@/spatial/types.gen";
25
25
 
26
26
  export { type Direction, DIRECTIONS, directionZ };
27
27
 
28
- export const crude = crudeDirection;
29
-
30
- export type Crude = CrudeDirection;
31
- export type CrudeX = CrudeXDirection;
32
- export type CrudeY = CrudeYDirection;
33
28
  export type Angular = AngularDirection;
29
+ export const crudeZ = z.enum(["x", "y", ...OUTER_LOCATIONS, ...CENTER_LOCATIONS]);
30
+ export type Crude = z.infer<typeof crudeZ>;
31
+ export type CrudeX = "x" | "left" | "right";
32
+ export type CrudeY = "y" | "top" | "bottom";
34
33
 
35
34
  export const construct = (c: Crude): Direction => {
36
35
  if (DIRECTIONS.includes(c as Direction)) return c as Direction;
@@ -38,24 +37,24 @@ export const construct = (c: Crude): Direction => {
38
37
  return "x";
39
38
  };
40
39
 
41
- export const swap = (direction: CrudeDirection): Direction =>
40
+ export const swap = (direction: Crude): Direction =>
42
41
  construct(direction) === "x" ? "y" : "x";
43
42
 
44
- export const dimension = (direction: CrudeDirection): Dimension =>
43
+ export const dimension = (direction: Crude): Dimension =>
45
44
  construct(direction) === "x" ? "width" : "height";
46
45
 
47
- export const location = (direction: CrudeDirection): Location =>
46
+ export const location = (direction: Crude): Location =>
48
47
  construct(direction) === "x" ? "left" : "top";
49
48
 
50
- export const isDirection = (c: unknown): c is Direction => crude.safeParse(c).success;
49
+ export const isDirection = (c: unknown): c is Direction => crudeZ.safeParse(c).success;
51
50
 
52
- export const signedDimension = (direction: CrudeDirection): SignedDimension =>
51
+ export const signedDimension = (direction: Crude): SignedDimension =>
53
52
  construct(direction) === "x" ? "signedWidth" : "signedHeight";
54
53
 
55
- export const isX = (direction: CrudeDirection): direction is CrudeXDirection => {
54
+ export const isX = (direction: Crude): direction is CrudeX => {
56
55
  if (direction === "center") return false;
57
56
  return construct(direction) === "x";
58
57
  };
59
58
 
60
- export const isY = (direction: CrudeDirection): direction is CrudeYDirection =>
59
+ export const isY = (direction: Crude): direction is CrudeY =>
61
60
  construct(direction) === "y";
@@ -13,7 +13,6 @@ export * from "@/spatial/dimensions";
13
13
  export * from "@/spatial/direction";
14
14
  export * from "@/spatial/location";
15
15
  export * from "@/spatial/scale";
16
- export * as spatial from "@/spatial/spatial";
17
16
  export * from "@/spatial/sticky";
18
- export * from "@/spatial/types.gen";
17
+ export * as spatial from "@/spatial/types.gen";
19
18
  export * from "@/spatial/xy";
@@ -15,10 +15,11 @@ import {
15
15
  CENTER_LOCATIONS,
16
16
  type CenterLocation,
17
17
  centerLocationZ,
18
- type CrudeLocation,
19
- crudeLocation,
18
+ type CornerLocation,
19
+ cornerLocationZ,
20
20
  type Direction,
21
21
  DIRECTIONS,
22
+ directionZ,
22
23
  type Location,
23
24
  LOCATIONS,
24
25
  locationZ,
@@ -43,15 +44,18 @@ export {
43
44
  Y_LOCATIONS,
44
45
  };
45
46
 
46
- export const x = xLocationZ;
47
- export const y = yLocationZ;
48
- export const center = centerLocationZ;
47
+ export const xZ = xLocationZ;
48
+ export const yZ = yLocationZ;
49
+ export const centerZ = centerLocationZ;
49
50
  export const outerZ = outerLocationZ;
51
+ export const cornerZ = cornerLocationZ;
50
52
 
51
53
  export type X = XLocation;
52
54
  export type Y = YLocation;
53
55
  export type Outer = OuterLocation;
54
56
  export type Center = CenterLocation;
57
+ export type Corner = CornerLocation;
58
+ export type CornerString = "topLeft" | "topRight" | "bottomLeft" | "bottomRight";
55
59
 
56
60
  const SWAPPED: Record<Location, Location> = {
57
61
  top: "bottom",
@@ -67,10 +71,12 @@ const ROTATIONS: Record<Outer, Record<AngularDirection, Outer>> = {
67
71
  bottom: { clockwise: "right", counterclockwise: "left" },
68
72
  left: { clockwise: "bottom", counterclockwise: "top" },
69
73
  };
70
-
71
- export const crude = crudeLocation;
72
-
73
- export type Crude = CrudeLocation;
74
+ export const crudeZ = z.union([
75
+ directionZ,
76
+ z.enum([...OUTER_LOCATIONS, ...CENTER_LOCATIONS]),
77
+ z.instanceof(String),
78
+ ]);
79
+ export type Crude = z.infer<typeof crudeZ>;
74
80
 
75
81
  export const construct = (cl: Crude): Location => {
76
82
  if (cl instanceof String) return cl as Location;
@@ -93,16 +99,12 @@ export const xy = z.object({
93
99
  x: xLocationZ.or(centerLocationZ),
94
100
  y: yLocationZ.or(centerLocationZ),
95
101
  });
96
- export const corner = z.object({ x: xLocationZ, y: yLocationZ });
97
-
98
102
  export type XY = z.infer<typeof xy>;
99
- export type CornerXY = z.infer<typeof corner>;
100
- export type CornerXYString = "topLeft" | "topRight" | "bottomLeft" | "bottomRight";
101
103
 
102
- export const TOP_LEFT: CornerXY = Object.freeze({ x: "left", y: "top" });
103
- export const TOP_RIGHT: CornerXY = Object.freeze({ x: "right", y: "top" });
104
- export const BOTTOM_LEFT: CornerXY = Object.freeze({ x: "left", y: "bottom" });
105
- export const BOTTOM_RIGHT: CornerXY = Object.freeze({ x: "right", y: "bottom" });
104
+ export const TOP_LEFT: Corner = Object.freeze({ x: "left", y: "top" });
105
+ export const TOP_RIGHT: Corner = Object.freeze({ x: "right", y: "top" });
106
+ export const BOTTOM_LEFT: Corner = Object.freeze({ x: "left", y: "bottom" });
107
+ export const BOTTOM_RIGHT: Corner = Object.freeze({ x: "right", y: "bottom" });
106
108
  export const CENTER: XY = Object.freeze({ x: "center", y: "center" });
107
109
  export const TOP_CENTER: XY = Object.freeze({ x: "center", y: "top" });
108
110
  export const BOTTOM_CENTER: XY = Object.freeze({ x: "center", y: "bottom" });
@@ -417,12 +417,12 @@ export class Scale<T extends numeric.Value = number> {
417
417
  export class XY {
418
418
  x: Scale<number>;
419
419
  y: Scale<number>;
420
- currRoot: location.CornerXY | null;
420
+ currRoot: location.Corner | null;
421
421
 
422
422
  constructor(
423
423
  x: Scale<number> = new Scale<number>(),
424
424
  y: Scale<number> = new Scale<number>(),
425
- root: location.CornerXY | null = null,
425
+ root: location.Corner | null = null,
426
426
  ) {
427
427
  this.x = x;
428
428
  this.y = y;
@@ -134,7 +134,7 @@ describe("sticky", () => {
134
134
  ];
135
135
  SPECS.forEach(({ value, valid }, i) => {
136
136
  test(`xy schema ${i}`, () => {
137
- const result = sticky.xy.safeParse(value);
137
+ const result = sticky.xyZ.safeParse(value);
138
138
  expect(result.success).toBe(valid);
139
139
  });
140
140
  });
@@ -196,7 +196,7 @@ describe("sticky", () => {
196
196
  ];
197
197
  SPECS.forEach(({ value, valid }, i) => {
198
198
  test(`completeXY schema ${i}`, () => {
199
- const result = sticky.completeXY.safeParse(value);
199
+ const result = sticky.completeXYZ.safeParse(value);
200
200
  expect(result.success).toBe(valid);
201
201
  });
202
202
  });
@@ -7,25 +7,18 @@
7
7
  // License, use of this software will be governed by the Apache License, Version 2.0,
8
8
  // included in the file licenses/APL.txt.
9
9
 
10
- import z from "zod";
10
+ import type z from "zod";
11
11
 
12
12
  import { box } from "@/spatial/box";
13
13
  import { location } from "@/spatial/location";
14
+ import { type StickyXY, stickyXYZ } from "@/spatial/types.gen";
14
15
  import { xy as base } from "@/spatial/xy";
15
16
 
16
- export const completeXY = base.xyZ.extend({
17
- root: location.corner,
18
- units: z.object({
19
- x: z.enum(["px", "decimal"]),
20
- y: z.enum(["px", "decimal"]),
21
- }),
22
- });
17
+ export const xyZ = stickyXYZ;
18
+ export type XY = StickyXY;
23
19
 
24
- export type CompleteXY = z.infer<typeof completeXY>;
25
-
26
- export const xy = completeXY.partial({ root: true, units: true });
27
-
28
- export interface XY extends z.infer<typeof xy> {}
20
+ export const completeXYZ = stickyXYZ.required({ root: true, units: true });
21
+ export type CompleteXY = z.infer<typeof completeXYZ>;
29
22
 
30
23
  interface ToCSSReturn extends Partial<Record<location.Outer, string>> {}
31
24
 
@@ -11,10 +11,56 @@
11
11
 
12
12
  import { z } from "zod";
13
13
 
14
+ import { type numeric } from "@/numeric";
15
+
16
+ export const X_LOCATIONS = ["left", "right"] as const;
17
+ export const xLocationZ = z.enum(X_LOCATIONS);
18
+ export type XLocation = z.infer<typeof xLocationZ>;
19
+
20
+ export const Y_LOCATIONS = ["top", "bottom"] as const;
21
+ export const yLocationZ = z.enum(Y_LOCATIONS);
22
+ export type YLocation = z.infer<typeof yLocationZ>;
23
+
24
+ export const STICKY_UNITS = ["px", "decimal"] as const;
25
+ export const stickyUnitZ = z.enum(STICKY_UNITS);
26
+ export type StickyUnit = z.infer<typeof stickyUnitZ>;
27
+
14
28
  export const OUTER_LOCATIONS = ["top", "right", "bottom", "left"] as const;
15
29
  export const outerLocationZ = z.enum(OUTER_LOCATIONS);
16
30
  export type OuterLocation = z.infer<typeof outerLocationZ>;
17
31
 
32
+ export const DIRECTIONS = ["x", "y"] as const;
33
+ export const directionZ = z.enum(DIRECTIONS);
34
+ export type Direction = z.infer<typeof directionZ>;
35
+
36
+ export const ANGULAR_DIRECTIONS = ["clockwise", "counterclockwise"] as const;
37
+ export const angularDirectionZ = z.enum(ANGULAR_DIRECTIONS);
38
+ export type AngularDirection = z.infer<typeof angularDirectionZ>;
39
+
40
+ export const CENTER_LOCATIONS = ["center"] as const;
41
+ export const centerLocationZ = z.enum(CENTER_LOCATIONS);
42
+ export type CenterLocation = z.infer<typeof centerLocationZ>;
43
+
44
+ export const LOCATIONS = ["top", "right", "bottom", "left", "center"] as const;
45
+ export const locationZ = z.enum(LOCATIONS);
46
+ export type Location = z.infer<typeof locationZ>;
47
+
48
+ export const ALIGNMENTS = ["start", "center", "end"] as const;
49
+ export const alignmentZ = z.enum(ALIGNMENTS);
50
+ export type Alignment = z.infer<typeof alignmentZ>;
51
+
52
+ export const ORDERS = ["first", "last"] as const;
53
+ export const orderZ = z.enum(ORDERS);
54
+ export type Order = z.infer<typeof orderZ>;
55
+
56
+ export const DIMENSIONS = ["width", "height"] as const;
57
+ export const dimensionZ = z.enum(DIMENSIONS);
58
+ export type Dimension = z.infer<typeof dimensionZ>;
59
+
60
+ export const SIGNED_DIMENSIONS = ["signedWidth", "signedHeight"] as const;
61
+ export const signedDimensionZ = z.enum(SIGNED_DIMENSIONS);
62
+ export type SignedDimension = z.infer<typeof signedDimensionZ>;
63
+
18
64
  /**
19
65
  * XY is a 2D coordinate point with x and y values. Used for positioning
20
66
  * elements in two-dimensional space.
@@ -26,3 +72,97 @@ export const xyZ = z.object({
26
72
  y: z.number(),
27
73
  });
28
74
  export interface XY extends z.infer<typeof xyZ> {}
75
+
76
+ /** CornerLocation is an anchor corner for positioning. */
77
+ export const cornerLocationZ = z.object({
78
+ /** x is the horizontal anchor. */
79
+ x: xLocationZ,
80
+ /** y is the vertical anchor. */
81
+ y: yLocationZ,
82
+ });
83
+ export interface CornerLocation extends z.infer<typeof cornerLocationZ> {}
84
+
85
+ /** StickyUnits specifies the measurement units for sticky positioning. */
86
+ export const stickyUnitsZ = z.object({
87
+ /** x is the horizontal unit. */
88
+ x: stickyUnitZ,
89
+ /** y is the vertical unit. */
90
+ y: stickyUnitZ,
91
+ });
92
+ export interface StickyUnits extends z.infer<typeof stickyUnitsZ> {}
93
+
94
+ /** Dimensions is a 2D size with width and height values. */
95
+ export const dimensionsZ = z.object({
96
+ /** width is the width in pixels. */
97
+ width: z.number(),
98
+ /** height is the height in pixels. */
99
+ height: z.number(),
100
+ });
101
+ export interface Dimensions extends z.infer<typeof dimensionsZ> {}
102
+
103
+ /**
104
+ * SignedDimensions is a 2D size whose width and height components carry sign, allowing
105
+ * negative values to express direction.
106
+ */
107
+ export const signedDimensionsZ = z.object({
108
+ /** signedWidth is the signed width. */
109
+ signedWidth: z.number(),
110
+ /** signedHeight is the signed height. */
111
+ signedHeight: z.number(),
112
+ });
113
+ export interface SignedDimensions extends z.infer<typeof signedDimensionsZ> {}
114
+
115
+ /**
116
+ * ClientXY is a 2D coordinate point expressed in client (viewport) space, matching
117
+ * the shape of DOM mouse events.
118
+ */
119
+ export const clientXYZ = z.object({
120
+ /** clientX is the horizontal coordinate in client (viewport) space. */
121
+ clientX: z.number(),
122
+ /** clientY is the vertical coordinate in client (viewport) space. */
123
+ clientY: z.number(),
124
+ });
125
+ export interface ClientXY extends z.infer<typeof clientXYZ> {}
126
+
127
+ /**
128
+ * Bounds is a closed-open interval [lower, upper) over an ordered numeric value
129
+ * space. The TypeScript binding is generic over T so callers can express
130
+ * bounds over either number or bigint values; other languages emit a
131
+ * concrete float64-based type.
132
+ */
133
+ export const boundsZ = <T extends numeric.Value = number>(t?: z.ZodType<T>) =>
134
+ z.object({
135
+ /** lower is the inclusive lower bound. */
136
+ lower: t ?? z.number(),
137
+ /** upper is the exclusive upper bound. */
138
+ upper: t ?? z.number(),
139
+ });
140
+ export interface Bounds<T extends numeric.Value = number> {
141
+ lower: T;
142
+ upper: T;
143
+ }
144
+
145
+ /** Viewport is the camera state of a viewport. */
146
+ export const viewportZ = z.object({
147
+ /** zoom is the zoom level where 1.0 equals 100%. */
148
+ zoom: z.number().default(1),
149
+ /** position is the (x, y) pan offset of the viewport. */
150
+ position: xyZ,
151
+ });
152
+ export interface Viewport extends z.infer<typeof viewportZ> {}
153
+
154
+ /**
155
+ * StickyXY is a position that can be anchored to different corners of a
156
+ * container with configurable units (pixels or decimal fractions).
157
+ */
158
+ export const stickyXYZ = z.object({
159
+ /** x is the horizontal coordinate. */
160
+ x: z.number(),
161
+ /** y is the vertical coordinate. */
162
+ y: z.number(),
163
+ /** root is the optional anchor corner for the position. */
164
+ root: cornerLocationZ.optional(),
165
+ /** units is the optional unit specification for the coordinates. */
166
+ units: stickyUnitsZ.optional(),
167
+ });
168
+ export interface StickyXY extends z.infer<typeof stickyXYZ> {}
@@ -12,19 +12,19 @@ import { z } from "zod";
12
12
  import {
13
13
  type AngularDirection,
14
14
  type ClientXY,
15
- clientXyZ,
16
- type CrudeDirection,
15
+ clientXYZ,
17
16
  dimensionsZ,
18
17
  type Direction,
19
18
  type NumberCouple,
20
19
  numberCouple,
21
20
  signedDimensionsZ,
21
+ type XY,
22
+ xyZ,
22
23
  } from "@/spatial/base";
23
- import { direction as dir } from "@/spatial/direction";
24
+ import { direction as dir, type direction } from "@/spatial/direction";
24
25
  import { type location } from "@/spatial/location";
25
- import { type XY, xyZ } from "@/spatial/types.gen";
26
26
 
27
- export { type ClientXY as Client, clientXyZ, type XY, xyZ };
27
+ export { type ClientXY as Client, clientXYZ, type XY, xyZ };
28
28
 
29
29
  /** A crude representation of a {@link XY} coordinate as a zod schema. */
30
30
  export const crudeZ = z.union([
@@ -33,7 +33,7 @@ export const crudeZ = z.union([
33
33
  numberCouple,
34
34
  dimensionsZ,
35
35
  signedDimensionsZ,
36
- clientXyZ,
36
+ clientXYZ,
37
37
  ]);
38
38
 
39
39
  /** A crude representation of a {@link XY} coordinate. */
@@ -141,7 +141,7 @@ export const translate: Translate = (a, b, v, ...cb): XY => {
141
141
  * @returns the given coordinate the given direction set to the given value.
142
142
  * @example set({ x: 1, y: 2 }, "x", 3) // { x: 3, y: 2 }
143
143
  */
144
- export const set = (c: Crude, direction: CrudeDirection, value: number): XY => {
144
+ export const set = (c: Crude, direction: direction.Crude, value: number): XY => {
145
145
  const xy = construct(c);
146
146
  const d = dir.construct(direction);
147
147
  if (d === "x") return { x: value, y: xy.y };