@ponchia/ui 0.5.0 → 0.6.3

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 (196) hide show
  1. package/CHANGELOG.md +386 -4
  2. package/MIGRATIONS.json +14 -0
  3. package/README.md +29 -6
  4. package/annotations/index.d.ts +398 -276
  5. package/annotations/index.d.ts.map +1 -0
  6. package/annotations/index.js +350 -77
  7. package/behaviors/carousel.d.ts +28 -0
  8. package/behaviors/carousel.d.ts.map +1 -0
  9. package/behaviors/carousel.js +20 -16
  10. package/behaviors/combobox.d.ts +40 -0
  11. package/behaviors/combobox.d.ts.map +1 -0
  12. package/behaviors/combobox.js +111 -29
  13. package/behaviors/command.d.ts +41 -0
  14. package/behaviors/command.d.ts.map +1 -0
  15. package/behaviors/command.js +27 -15
  16. package/behaviors/connectors.d.ts +17 -0
  17. package/behaviors/connectors.d.ts.map +1 -0
  18. package/behaviors/connectors.js +7 -5
  19. package/behaviors/crosshair.d.ts +42 -0
  20. package/behaviors/crosshair.d.ts.map +1 -0
  21. package/behaviors/crosshair.js +23 -6
  22. package/behaviors/dialog.d.ts +20 -0
  23. package/behaviors/dialog.d.ts.map +1 -0
  24. package/behaviors/dialog.js +6 -2
  25. package/behaviors/disclosure.d.ts +10 -0
  26. package/behaviors/disclosure.d.ts.map +1 -0
  27. package/behaviors/disclosure.js +6 -2
  28. package/behaviors/dismissible.d.ts +10 -0
  29. package/behaviors/dismissible.d.ts.map +1 -0
  30. package/behaviors/dismissible.js +6 -2
  31. package/behaviors/forms.d.ts +27 -0
  32. package/behaviors/forms.d.ts.map +1 -0
  33. package/behaviors/forms.js +54 -13
  34. package/behaviors/glyph.d.ts +14 -0
  35. package/behaviors/glyph.d.ts.map +1 -0
  36. package/behaviors/glyph.js +28 -5
  37. package/behaviors/index.d.ts +31 -237
  38. package/behaviors/index.d.ts.map +1 -0
  39. package/behaviors/index.js +17 -0
  40. package/behaviors/inert.d.ts +20 -0
  41. package/behaviors/inert.d.ts.map +1 -0
  42. package/behaviors/inert.js +46 -0
  43. package/behaviors/internal.d.ts +25 -0
  44. package/behaviors/internal.d.ts.map +1 -0
  45. package/behaviors/internal.js +77 -1
  46. package/behaviors/legend.d.ts +35 -0
  47. package/behaviors/legend.d.ts.map +1 -0
  48. package/behaviors/legend.js +32 -2
  49. package/behaviors/menu.d.ts +16 -0
  50. package/behaviors/menu.d.ts.map +1 -0
  51. package/behaviors/menu.js +6 -2
  52. package/behaviors/modal.d.ts +41 -0
  53. package/behaviors/modal.d.ts.map +1 -0
  54. package/behaviors/modal.js +124 -0
  55. package/behaviors/popover.d.ts +28 -0
  56. package/behaviors/popover.d.ts.map +1 -0
  57. package/behaviors/popover.js +78 -7
  58. package/behaviors/spotlight.d.ts +17 -0
  59. package/behaviors/spotlight.d.ts.map +1 -0
  60. package/behaviors/spotlight.js +7 -5
  61. package/behaviors/table.d.ts +36 -0
  62. package/behaviors/table.d.ts.map +1 -0
  63. package/behaviors/table.js +84 -17
  64. package/behaviors/tabs.d.ts +20 -0
  65. package/behaviors/tabs.d.ts.map +1 -0
  66. package/behaviors/tabs.js +17 -14
  67. package/behaviors/theme.d.ts +54 -0
  68. package/behaviors/theme.d.ts.map +1 -0
  69. package/behaviors/theme.js +22 -3
  70. package/behaviors/toast.d.ts +49 -0
  71. package/behaviors/toast.d.ts.map +1 -0
  72. package/behaviors/toast.js +47 -3
  73. package/classes/classes.json +2527 -0
  74. package/classes/index.d.ts +134 -15
  75. package/classes/index.js +280 -80
  76. package/classes/vscode.css-custom-data.json +12 -0
  77. package/connectors/index.d.ts +201 -69
  78. package/connectors/index.d.ts.map +1 -0
  79. package/connectors/index.js +142 -25
  80. package/css/app.css +69 -13
  81. package/css/base.css +15 -10
  82. package/css/bullet.css +108 -0
  83. package/css/code.css +98 -0
  84. package/css/connectors.css +17 -0
  85. package/css/content.css +22 -3
  86. package/css/crosshair.css +7 -7
  87. package/css/dataviz.css +5 -1
  88. package/css/diff.css +153 -0
  89. package/css/disclosure.css +53 -7
  90. package/css/dots.css +94 -7
  91. package/css/feedback.css +97 -7
  92. package/css/forms.css +113 -4
  93. package/css/legend.css +16 -9
  94. package/css/marks.css +38 -8
  95. package/css/motion.css +98 -53
  96. package/css/navigation.css +7 -0
  97. package/css/overlay.css +90 -3
  98. package/css/primitives.css +158 -13
  99. package/css/report.css +73 -56
  100. package/css/sidenote.css +67 -0
  101. package/css/site.css +16 -2
  102. package/css/sources.css +43 -1
  103. package/css/spark.css +62 -0
  104. package/css/spotlight.css +1 -1
  105. package/css/table.css +9 -2
  106. package/css/term.css +110 -0
  107. package/css/textref.css +63 -0
  108. package/css/toc.css +91 -0
  109. package/css/tokens.css +49 -1
  110. package/css/tree.css +134 -0
  111. package/css/workbench.css +1 -1
  112. package/dist/bronto.css +1 -1
  113. package/dist/css/analytical.css +1 -1
  114. package/dist/css/app.css +1 -1
  115. package/dist/css/base.css +1 -1
  116. package/dist/css/bullet.css +1 -0
  117. package/dist/css/code.css +1 -0
  118. package/dist/css/connectors.css +1 -1
  119. package/dist/css/content.css +1 -1
  120. package/dist/css/crosshair.css +1 -1
  121. package/dist/css/diff.css +1 -0
  122. package/dist/css/disclosure.css +1 -1
  123. package/dist/css/dots.css +1 -1
  124. package/dist/css/feedback.css +1 -1
  125. package/dist/css/forms.css +1 -1
  126. package/dist/css/legend.css +1 -1
  127. package/dist/css/marks.css +1 -1
  128. package/dist/css/motion.css +1 -1
  129. package/dist/css/navigation.css +1 -1
  130. package/dist/css/overlay.css +1 -1
  131. package/dist/css/primitives.css +1 -1
  132. package/dist/css/report.css +1 -1
  133. package/dist/css/sidenote.css +1 -0
  134. package/dist/css/site.css +1 -1
  135. package/dist/css/sources.css +1 -1
  136. package/dist/css/spark.css +1 -0
  137. package/dist/css/spotlight.css +1 -1
  138. package/dist/css/table.css +1 -1
  139. package/dist/css/term.css +1 -0
  140. package/dist/css/textref.css +1 -0
  141. package/dist/css/toc.css +1 -0
  142. package/dist/css/tokens.css +1 -1
  143. package/dist/css/tree.css +1 -0
  144. package/dist/css/workbench.css +1 -1
  145. package/docs/adr/0003-theme-model.md +1 -1
  146. package/docs/annotations.md +133 -14
  147. package/docs/architecture.md +49 -6
  148. package/docs/bullet.md +78 -0
  149. package/docs/code.md +76 -0
  150. package/docs/contrast.md +116 -92
  151. package/docs/d2.md +196 -0
  152. package/docs/diff.md +146 -0
  153. package/docs/legends.md +23 -3
  154. package/docs/marks.md +9 -2
  155. package/docs/mermaid.md +169 -0
  156. package/docs/reference.md +201 -26
  157. package/docs/reporting.md +416 -57
  158. package/docs/sidenote.md +64 -0
  159. package/docs/sources.md +27 -0
  160. package/docs/spark.md +78 -0
  161. package/docs/stability.md +10 -2
  162. package/docs/term.md +81 -0
  163. package/docs/textref.md +78 -0
  164. package/docs/theming.md +44 -5
  165. package/docs/toc.md +83 -0
  166. package/docs/tree.md +74 -0
  167. package/docs/usage.md +354 -16
  168. package/docs/vega.md +244 -0
  169. package/docs/workbench.md +7 -1
  170. package/glyphs/glyphs.js +13 -5
  171. package/llms.txt +285 -14
  172. package/package.json +95 -17
  173. package/qwik/index.d.ts +44 -59
  174. package/qwik/index.d.ts.map +1 -0
  175. package/qwik/index.js +65 -3
  176. package/react/index.d.ts +41 -61
  177. package/react/index.d.ts.map +1 -0
  178. package/react/index.js +63 -3
  179. package/solid/index.d.ts +68 -61
  180. package/solid/index.d.ts.map +1 -0
  181. package/solid/index.js +66 -3
  182. package/tokens/d2.d.ts +38 -0
  183. package/tokens/d2.js +71 -0
  184. package/tokens/d2.json +43 -0
  185. package/tokens/index.d.ts +5 -5
  186. package/tokens/index.js +15 -1
  187. package/tokens/index.json +9 -0
  188. package/tokens/mermaid.d.ts +23 -0
  189. package/tokens/mermaid.js +181 -0
  190. package/tokens/mermaid.json +163 -0
  191. package/tokens/resolved.json +45 -1
  192. package/tokens/skins.js +3 -2
  193. package/tokens/tokens.dtcg.json +26 -0
  194. package/tokens/vega.d.ts +34 -0
  195. package/tokens/vega.js +155 -0
  196. package/tokens/vega.json +179 -0
@@ -1,71 +1,203 @@
1
+ export function finite(name: any, value: any, fallback: any): any;
2
+ export function dimension(name: any, value: any, fallback: any): any;
3
+ export function roundNumber(value: any): number;
4
+ export function fmt(value: any): string;
5
+ export function point(x: any, y: any): string;
6
+ export function clamp(value: any, min: any, max: any): any;
1
7
  /**
2
- * @ponchia/ui/connectors dependency-free SVG geometry for leader lines.
3
- * Pure functions: points/rects in, SVG path strings (or coordinates) out.
8
+ * A point on a rect's edge (or centre). `rect` is `{ x, y, width, height }`.
9
+ * @param {Rect} rect
10
+ * @param {Side} [side]
11
+ * @returns {Point}
4
12
  */
5
-
6
- export interface Point {
7
- x: number;
8
- y: number;
9
- }
10
-
11
- export interface Rect {
12
- x: number;
13
- y: number;
14
- width: number;
15
- height: number;
16
- }
17
-
18
- export type Side = 'top' | 'right' | 'bottom' | 'left' | 'center';
19
- export type ConnectorShape = 'straight' | 'elbow' | 'curve';
20
-
21
- export interface ConnectorPathOptions {
22
- from: Point;
23
- to: Point;
24
- shape?: ConnectorShape;
25
- /** Curve control-point reach along the dominant axis (curve shape). Default 0.5. */
26
- curvature?: number;
27
- /** Turn position 0..1 along the span (elbow shape). Default 0.5. */
28
- mid?: number;
29
- }
30
-
31
- export interface ConnectRectsOptions {
32
- fromRect: Rect;
33
- toRect: Rect;
34
- /** Anchor edges. Omit both to auto-pick facing edges from the rects. */
35
- fromSide?: Side;
36
- toSide?: Side;
37
- shape?: ConnectorShape;
38
- curvature?: number;
39
- mid?: number;
40
- }
41
-
42
- export interface ConnectRectsResult {
43
- /** SVG path data. */
44
- d: string;
45
- from: Point;
46
- to: Point;
47
- /**
48
- * The path's **end-tangent** at `to` in radians (`endTangentAngle(from, to,
49
- * shape)`) the direction the path arrives, so rotating an arrowhead at `to`
50
- * by this points it along the path. Equals the straight `from`→`to` angle for
51
- * `shape: 'straight'`; axis-aligned for `elbow`/`curve`.
52
- */
53
- angle: number;
54
- }
55
-
56
- export declare function anchorPoint(rect: Rect, side?: Side): Point;
57
- export declare function angleBetween(from: Point, to: Point): number;
58
- export declare function straightPath(from: Point, to: Point): string;
59
- export declare function elbowPath(from: Point, to: Point, opts?: { mid?: number }): string;
60
- export declare function curvePath(from: Point, to: Point, opts?: { curvature?: number }): string;
61
- export declare function connectorPath(opts: ConnectorPathOptions): string;
62
- export declare function arrowHead(p: Point, angle: number, size?: number): string;
63
- export declare function dotMark(p: Point, radius?: number): string;
64
- export declare function autoSides(
65
- fromRect: Rect,
66
- toRect: Rect,
67
- ): { from: Side; to: Side };
68
- /** Angle (radians) at which a `shape` path arrives at `to` — the chord for
69
- * `straight`, axis-aligned for `elbow`/`curve`. Use it to rotate an end marker. */
70
- export declare function endTangentAngle(from: Point, to: Point, shape?: ConnectorShape): number;
71
- export declare function connectRects(opts: ConnectRectsOptions): ConnectRectsResult;
13
+ export function anchorPoint(rect: Rect, side?: Side): Point;
14
+ /**
15
+ * Angle (radians) from `from` to `to`.
16
+ * @param {Point} from
17
+ * @param {Point} to
18
+ * @returns {number}
19
+ */
20
+ export function angleBetween(from: Point, to: Point): number;
21
+ /**
22
+ * Straight line from `from` to `to`.
23
+ * @param {Point} from
24
+ * @param {Point} to
25
+ * @returns {string}
26
+ */
27
+ export function straightPath(from: Point, to: Point): string;
28
+ /**
29
+ * Right-angle dogleg. Turns on the dominant axis at `mid` (0..1) of the span.
30
+ * @param {Point} from
31
+ * @param {Point} to
32
+ * @param {{ mid?: number }} [opts]
33
+ * @returns {string}
34
+ */
35
+ export function elbowPath(from: Point, to: Point, opts?: {
36
+ mid?: number;
37
+ }): string;
38
+ /**
39
+ * Cubic curve; control points extend along the dominant axis by `curvature`.
40
+ * @param {Point} from
41
+ * @param {Point} to
42
+ * @param {{ curvature?: number }} [opts]
43
+ * @returns {string}
44
+ */
45
+ export function curvePath(from: Point, to: Point, opts?: {
46
+ curvature?: number;
47
+ }): string;
48
+ /**
49
+ * Build a path between two points by `shape` (`straight` | `elbow` | `curve`).
50
+ * @param {ConnectorPathOptions} [opts]
51
+ * @returns {string}
52
+ */
53
+ export function connectorPath(opts?: ConnectorPathOptions): string;
54
+ /**
55
+ * A filled triangle arrowhead at `p`, pointing along `angle` (radians).
56
+ * @param {Point} p
57
+ * @param {number} angle
58
+ * @param {number} [size]
59
+ * @param {number} [spread] Half-angle of the head in radians (default 0.45).
60
+ * Smaller is crisper/sharper; must be in (0, π/2).
61
+ * @returns {string}
62
+ */
63
+ export function arrowHead(p: Point, angle: number, size?: number, spread?: number): string;
64
+ /**
65
+ * A filled dot at `p`.
66
+ * @param {Point} p
67
+ * @param {number} [radius]
68
+ * @returns {string}
69
+ */
70
+ export function dotMark(p: Point, radius?: number): string;
71
+ /**
72
+ * An axis-aligned rectangle path from its corners (callers derive the corners
73
+ * from a centre or a top-left as they need). Shared by the annotation
74
+ * rect/band and evidence-marker subjects. (code-quality audit Q5.)
75
+ * @param {number} left
76
+ * @param {number} top
77
+ * @param {number} right
78
+ * @param {number} bottom
79
+ * @returns {string}
80
+ */
81
+ export function rectPath(left: number, top: number, right: number, bottom: number): string;
82
+ /**
83
+ * Pick facing edges from the rects' relative centres.
84
+ * @param {Rect} fromRect
85
+ * @param {Rect} toRect
86
+ * @returns {{ from: Side, to: Side }}
87
+ */
88
+ export function autoSides(fromRect: Rect, toRect: Rect): {
89
+ from: Side;
90
+ to: Side;
91
+ };
92
+ /**
93
+ * Angle (radians) at which a `shape` path *arrives* at `to` — straight is the
94
+ * chord; elbow/curve arrive axis-aligned along the dominant axis. Rotate an
95
+ * end marker by this so it points along the path, not the chord.
96
+ * @param {Point} from
97
+ * @param {Point} to
98
+ * @param {ConnectorShape} [shape]
99
+ * @returns {number}
100
+ */
101
+ export function endTangentAngle(from: Point, to: Point, shape?: ConnectorShape): number;
102
+ /**
103
+ * Connect two rects. Resolves anchor points (explicit `fromSide`/`toSide`, else
104
+ * auto), builds the path, and returns `{ d, from, to, angle }` so the caller can
105
+ * place an arrowhead/dot at `to` rotated by `angle`.
106
+ * @param {ConnectRectsOptions} [opts]
107
+ * @returns {ConnectRectsResult}
108
+ */
109
+ export function connectRects(opts?: ConnectRectsOptions): ConnectRectsResult;
110
+ /**
111
+ * @ponchia/ui/connectors — dependency-free SVG geometry for connecting two
112
+ * elements (or two points) with a leader line.
113
+ *
114
+ * Pure functions only: they take points/rects and return SVG path strings (or
115
+ * resolved coordinates). They own no DOM, no scales, and no live tracking —
116
+ * that optional glue lives in `@ponchia/ui/behaviors` (`initConnectors`). This
117
+ * is the page-coordinate, element-to-element cousin of the figure-coordinate
118
+ * `@ponchia/ui/annotations` helpers.
119
+ *
120
+ * import { connectRects } from '@ponchia/ui/connectors';
121
+ * const { d } = connectRects({ fromRect: a, toRect: b, shape: 'elbow' });
122
+ *
123
+ * The public types below are JSDoc `@typedef`s; the shipped `index.d.ts` is
124
+ * generated from them (and these signatures) by `tsc --emitDeclarationOnly`.
125
+ *
126
+ * @typedef {{ x: number, y: number }} Point
127
+ * @typedef {{ x: number, y: number, width: number, height: number }} Rect
128
+ * @typedef {'top' | 'right' | 'bottom' | 'left' | 'center'} Side
129
+ * @typedef {'straight' | 'elbow' | 'curve'} ConnectorShape
130
+ *
131
+ * @typedef {object} ConnectorPathOptions
132
+ * @property {Point} from
133
+ * @property {Point} to
134
+ * @property {ConnectorShape} [shape]
135
+ * @property {number} [curvature] Curve control-point reach along the dominant axis (curve shape). Default 0.5.
136
+ * @property {number} [mid] Turn position 0..1 along the span (elbow shape). Default 0.5.
137
+ *
138
+ * @typedef {object} ConnectRectsOptions
139
+ * @property {Rect} fromRect
140
+ * @property {Rect} toRect
141
+ * @property {Side} [fromSide] Anchor edges. Omit both to auto-pick facing edges from the rects.
142
+ * @property {Side} [toSide]
143
+ * @property {ConnectorShape} [shape]
144
+ * @property {number} [curvature]
145
+ * @property {number} [mid]
146
+ *
147
+ * @typedef {object} ConnectRectsResult
148
+ * @property {string} d SVG path data.
149
+ * @property {Point} from
150
+ * @property {Point} to
151
+ * @property {number} angle The path's end-tangent at `to` in radians — the direction the path arrives, so rotating an arrowhead at `to` by this points it along the path. Equals the straight `from`→`to` angle for `shape: 'straight'`; axis-aligned for `elbow`/`curve`.
152
+ */
153
+ export const PRECISION: 1000;
154
+ export type Point = {
155
+ x: number;
156
+ y: number;
157
+ };
158
+ export type Rect = {
159
+ x: number;
160
+ y: number;
161
+ width: number;
162
+ height: number;
163
+ };
164
+ export type Side = "top" | "right" | "bottom" | "left" | "center";
165
+ export type ConnectorShape = "straight" | "elbow" | "curve";
166
+ export type ConnectorPathOptions = {
167
+ from: Point;
168
+ to: Point;
169
+ shape?: ConnectorShape | undefined;
170
+ /**
171
+ * Curve control-point reach along the dominant axis (curve shape). Default 0.5.
172
+ */
173
+ curvature?: number | undefined;
174
+ /**
175
+ * Turn position 0..1 along the span (elbow shape). Default 0.5.
176
+ */
177
+ mid?: number | undefined;
178
+ };
179
+ export type ConnectRectsOptions = {
180
+ fromRect: Rect;
181
+ toRect: Rect;
182
+ /**
183
+ * Anchor edges. Omit both to auto-pick facing edges from the rects.
184
+ */
185
+ fromSide?: Side | undefined;
186
+ toSide?: Side | undefined;
187
+ shape?: ConnectorShape | undefined;
188
+ curvature?: number | undefined;
189
+ mid?: number | undefined;
190
+ };
191
+ export type ConnectRectsResult = {
192
+ /**
193
+ * SVG path data.
194
+ */
195
+ d: string;
196
+ from: Point;
197
+ to: Point;
198
+ /**
199
+ * The path's end-tangent at `to` in radians — the direction the path arrives, so rotating an arrowhead at `to` by this points it along the path. Equals the straight `from`→`to` angle for `shape: 'straight'`; axis-aligned for `elbow`/`curve`.
200
+ */
201
+ angle: number;
202
+ };
203
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.js"],"names":[],"mappings":"AAkDA,kEAIC;AAED,qEAIC;AAKD,gDAGC;AAED,wCAEC;AAED,8CAEC;AAID,2DAGC;AAED;;;;;GAKG;AACH,kCAJW,IAAI,SACJ,IAAI,GACF,KAAK,CAoBjB;AAED;;;;;GAKG;AACH,mCAJW,KAAK,MACL,KAAK,GACH,MAAM,CAOlB;AAED;;;;;GAKG;AACH,mCAJW,KAAK,MACL,KAAK,GACH,MAAM,CAOlB;AAED;;;;;;GAMG;AACH,gCALW,KAAK,MACL,KAAK,SACL;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GACd,MAAM,CAgBlB;AAED;;;;;;GAMG;AACH,gCALW,KAAK,MACL,KAAK,SACL;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GACpB,MAAM,CAclB;AAED;;;;GAIG;AACH,qCAHW,oBAAoB,GAClB,MAAM,CAOlB;AAED;;;;;;;;GAQG;AACH,6BAPW,KAAK,SACL,MAAM,SACN,MAAM,WACN,MAAM,GAEJ,MAAM,CAalB;AAED;;;;;GAKG;AACH,2BAJW,KAAK,WACL,MAAM,GACJ,MAAM,CAUlB;AAED;;;;;;;;;GASG;AACH,+BANW,MAAM,OACN,MAAM,SACN,MAAM,UACN,MAAM,GACJ,MAAM,CAIlB;AAED;;;;;GAKG;AACH,oCAJW,IAAI,UACJ,IAAI,GACF;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,EAAE,EAAE,IAAI,CAAA;CAAE,CAWpC;AAED;;;;;;;;GAQG;AACH,sCALW,KAAK,MACL,KAAK,UACL,cAAc,GACZ,MAAM,CAQlB;AAED;;;;;;GAMG;AACH,oCAHW,mBAAmB,GACjB,kBAAkB,CAW9B;AAvSD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAMH,wBAAyB,IAAI,CAAC;oBAhCjB;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE;mBACxB;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE;mBACvD,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ;6BAC9C,UAAU,GAAG,OAAO,GAAG,OAAO;;UAG7B,KAAK;QACL,KAAK;;;;;;;;;;;;cAML,IAAI;YACJ,IAAI;;;;;;;;;;;;;;OAQJ,MAAM;UACN,KAAK;QACL,KAAK;;;;WACL,MAAM"}
@@ -10,36 +10,85 @@
10
10
  *
11
11
  * import { connectRects } from '@ponchia/ui/connectors';
12
12
  * const { d } = connectRects({ fromRect: a, toRect: b, shape: 'elbow' });
13
+ *
14
+ * The public types below are JSDoc `@typedef`s; the shipped `index.d.ts` is
15
+ * generated from them (and these signatures) by `tsc --emitDeclarationOnly`.
16
+ *
17
+ * @typedef {{ x: number, y: number }} Point
18
+ * @typedef {{ x: number, y: number, width: number, height: number }} Rect
19
+ * @typedef {'top' | 'right' | 'bottom' | 'left' | 'center'} Side
20
+ * @typedef {'straight' | 'elbow' | 'curve'} ConnectorShape
21
+ *
22
+ * @typedef {object} ConnectorPathOptions
23
+ * @property {Point} from
24
+ * @property {Point} to
25
+ * @property {ConnectorShape} [shape]
26
+ * @property {number} [curvature] Curve control-point reach along the dominant axis (curve shape). Default 0.5.
27
+ * @property {number} [mid] Turn position 0..1 along the span (elbow shape). Default 0.5.
28
+ *
29
+ * @typedef {object} ConnectRectsOptions
30
+ * @property {Rect} fromRect
31
+ * @property {Rect} toRect
32
+ * @property {Side} [fromSide] Anchor edges. Omit both to auto-pick facing edges from the rects.
33
+ * @property {Side} [toSide]
34
+ * @property {ConnectorShape} [shape]
35
+ * @property {number} [curvature]
36
+ * @property {number} [mid]
37
+ *
38
+ * @typedef {object} ConnectRectsResult
39
+ * @property {string} d SVG path data.
40
+ * @property {Point} from
41
+ * @property {Point} to
42
+ * @property {number} angle The path's end-tangent at `to` in radians — the direction the path arrives, so rotating an arrowhead at `to` by this points it along the path. Equals the straight `from`→`to` angle for `shape: 'straight'`; axis-aligned for `elbow`/`curve`.
13
43
  */
14
44
 
15
- const PRECISION = 1000;
45
+ // Shared scalar/geometry primitives. Exported so the annotations layer composes
46
+ // on the SAME kernel instead of copy-pasting it (the copies had silently
47
+ // diverged — see `clamp`). Low-level helpers; the documented API is the path
48
+ // builders below.
49
+ export const PRECISION = 1000;
16
50
 
17
- function finite(name, value, fallback) {
51
+ export function finite(name, value, fallback) {
18
52
  const v = value ?? fallback;
19
53
  if (!Number.isFinite(v)) throw new TypeError(`${name} must be a finite number`);
20
54
  return v;
21
55
  }
22
56
 
23
- function dimension(name, value, fallback) {
57
+ export function dimension(name, value, fallback) {
24
58
  const v = finite(name, value, fallback);
25
59
  if (v < 0) throw new RangeError(`${name} must be greater than or equal to 0`);
26
60
  return v;
27
61
  }
28
62
 
29
- function fmt(value) {
63
+ // Round to PRECISION, normalising -0 → 0, and return the NUMBER (the numeric
64
+ // core `fmt` stringifies). Shared with the annotations layer for the rounded
65
+ // coordinates it echoes back to the host. (code-quality audit Q5.)
66
+ export function roundNumber(value) {
30
67
  const rounded = Math.round((Object.is(value, -0) ? 0 : value) * PRECISION) / PRECISION;
31
- return String(Object.is(rounded, -0) ? 0 : rounded);
68
+ return Object.is(rounded, -0) ? 0 : rounded;
32
69
  }
33
70
 
34
- function point(x, y) {
71
+ export function fmt(value) {
72
+ return String(roundNumber(value));
73
+ }
74
+
75
+ export function point(x, y) {
35
76
  return `${fmt(x)},${fmt(y)}`;
36
77
  }
37
78
 
38
- function clamp(value, min, max) {
79
+ // Guarded form (returns min when the range is inverted) — the reconciled body;
80
+ // connectors only ever calls clamp(v, 0, 1) so this is output-identical here.
81
+ export function clamp(value, min, max) {
82
+ if (max < min) return min;
39
83
  return Math.min(max, Math.max(min, value));
40
84
  }
41
85
 
42
- /** A point on a rect's edge (or centre). `rect` is `{ x, y, width, height }`. */
86
+ /**
87
+ * A point on a rect's edge (or centre). `rect` is `{ x, y, width, height }`.
88
+ * @param {Rect} rect
89
+ * @param {Side} [side]
90
+ * @returns {Point}
91
+ */
43
92
  export function anchorPoint(rect, side = 'center') {
44
93
  const x = finite('rect.x', rect?.x, 0);
45
94
  const y = finite('rect.y', rect?.y, 0);
@@ -60,7 +109,12 @@ export function anchorPoint(rect, side = 'center') {
60
109
  }
61
110
  }
62
111
 
63
- /** Angle (radians) from `from` to `to`. */
112
+ /**
113
+ * Angle (radians) from `from` to `to`.
114
+ * @param {Point} from
115
+ * @param {Point} to
116
+ * @returns {number}
117
+ */
64
118
  export function angleBetween(from, to) {
65
119
  return Math.atan2(
66
120
  finite('to.y', to?.y) - finite('from.y', from?.y),
@@ -68,6 +122,12 @@ export function angleBetween(from, to) {
68
122
  );
69
123
  }
70
124
 
125
+ /**
126
+ * Straight line from `from` to `to`.
127
+ * @param {Point} from
128
+ * @param {Point} to
129
+ * @returns {string}
130
+ */
71
131
  export function straightPath(from, to) {
72
132
  return `M${point(finite('from.x', from?.x), finite('from.y', from?.y))}L${point(
73
133
  finite('to.x', to?.x),
@@ -75,7 +135,13 @@ export function straightPath(from, to) {
75
135
  )}`;
76
136
  }
77
137
 
78
- /** Right-angle dogleg. Turns on the dominant axis at `mid` (0..1) of the span. */
138
+ /**
139
+ * Right-angle dogleg. Turns on the dominant axis at `mid` (0..1) of the span.
140
+ * @param {Point} from
141
+ * @param {Point} to
142
+ * @param {{ mid?: number }} [opts]
143
+ * @returns {string}
144
+ */
79
145
  export function elbowPath(from, to, opts = {}) {
80
146
  const fx = finite('from.x', from?.x);
81
147
  const fy = finite('from.y', from?.y);
@@ -92,7 +158,13 @@ export function elbowPath(from, to, opts = {}) {
92
158
  return `M${point(fx, fy)}V${fmt(my)}H${fmt(tx)}V${fmt(ty)}`;
93
159
  }
94
160
 
95
- /** Cubic curve; control points extend along the dominant axis by `curvature`. */
161
+ /**
162
+ * Cubic curve; control points extend along the dominant axis by `curvature`.
163
+ * @param {Point} from
164
+ * @param {Point} to
165
+ * @param {{ curvature?: number }} [opts]
166
+ * @returns {string}
167
+ */
96
168
  export function curvePath(from, to, opts = {}) {
97
169
  const fx = finite('from.x', from?.x);
98
170
  const fy = finite('from.y', from?.y);
@@ -107,7 +179,11 @@ export function curvePath(from, to, opts = {}) {
107
179
  return `M${point(fx, fy)}C${point(c1.x, c1.y)} ${point(c2.x, c2.y)} ${point(tx, ty)}`;
108
180
  }
109
181
 
110
- /** Build a path between two points by `shape` (`straight` | `elbow` | `curve`). */
182
+ /**
183
+ * Build a path between two points by `shape` (`straight` | `elbow` | `curve`).
184
+ * @param {ConnectorPathOptions} [opts]
185
+ * @returns {string}
186
+ */
111
187
  export function connectorPath(opts = {}) {
112
188
  const { from, to, shape = 'straight' } = opts;
113
189
  if (shape === 'elbow') return elbowPath(from, to, opts);
@@ -115,20 +191,34 @@ export function connectorPath(opts = {}) {
115
191
  return straightPath(from, to);
116
192
  }
117
193
 
118
- /** A filled triangle arrowhead at `p`, pointing along `angle` (radians). */
119
- export function arrowHead(p, angle, size = 8) {
194
+ /**
195
+ * A filled triangle arrowhead at `p`, pointing along `angle` (radians).
196
+ * @param {Point} p
197
+ * @param {number} angle
198
+ * @param {number} [size]
199
+ * @param {number} [spread] Half-angle of the head in radians (default 0.45).
200
+ * Smaller is crisper/sharper; must be in (0, π/2).
201
+ * @returns {string}
202
+ */
203
+ export function arrowHead(p, angle, size = 8, spread = 0.45) {
120
204
  const px = finite('p.x', p?.x);
121
205
  const py = finite('p.y', p?.y);
122
206
  const a = finite('angle', angle, 0);
123
207
  const s = dimension('size', size, 8);
208
+ const sp = finite('spread', spread, 0.45);
209
+ if (sp <= 0 || sp >= Math.PI / 2) throw new RangeError('spread must be in (0, π/2)');
124
210
  const back = a + Math.PI;
125
- const spread = 0.45;
126
- const p1 = { x: px + Math.cos(back - spread) * s, y: py + Math.sin(back - spread) * s };
127
- const p2 = { x: px + Math.cos(back + spread) * s, y: py + Math.sin(back + spread) * s };
211
+ const p1 = { x: px + Math.cos(back - sp) * s, y: py + Math.sin(back - sp) * s };
212
+ const p2 = { x: px + Math.cos(back + sp) * s, y: py + Math.sin(back + sp) * s };
128
213
  return `M${point(px, py)}L${point(p1.x, p1.y)}L${point(p2.x, p2.y)}Z`;
129
214
  }
130
215
 
131
- /** A filled dot at `p`. */
216
+ /**
217
+ * A filled dot at `p`.
218
+ * @param {Point} p
219
+ * @param {number} [radius]
220
+ * @returns {string}
221
+ */
132
222
  export function dotMark(p, radius = 3) {
133
223
  const px = finite('p.x', p?.x);
134
224
  const py = finite('p.y', p?.y);
@@ -139,7 +229,26 @@ export function dotMark(p, radius = 3) {
139
229
  )} 0 1 1 ${point(px, py - r)}Z`;
140
230
  }
141
231
 
142
- /** Pick facing edges from the rects' relative centres. */
232
+ /**
233
+ * An axis-aligned rectangle path from its corners (callers derive the corners
234
+ * from a centre or a top-left as they need). Shared by the annotation
235
+ * rect/band and evidence-marker subjects. (code-quality audit Q5.)
236
+ * @param {number} left
237
+ * @param {number} top
238
+ * @param {number} right
239
+ * @param {number} bottom
240
+ * @returns {string}
241
+ */
242
+ export function rectPath(left, top, right, bottom) {
243
+ return `M${point(left, top)}H${fmt(right)}V${fmt(bottom)}H${fmt(left)}Z`;
244
+ }
245
+
246
+ /**
247
+ * Pick facing edges from the rects' relative centres.
248
+ * @param {Rect} fromRect
249
+ * @param {Rect} toRect
250
+ * @returns {{ from: Side, to: Side }}
251
+ */
143
252
  export function autoSides(fromRect, toRect) {
144
253
  const fc = anchorPoint(fromRect, 'center');
145
254
  const tc = anchorPoint(toRect, 'center');
@@ -152,13 +261,14 @@ export function autoSides(fromRect, toRect) {
152
261
  }
153
262
 
154
263
  /**
155
- * Connect two rects. Resolves anchor points (explicit `fromSide`/`toSide`, else
156
- * auto), builds the path, and returns `{ d, from, to, angle }` so the caller can
157
- * place an arrowhead/dot at `to` rotated by `angle`.
264
+ * Angle (radians) at which a `shape` path *arrives* at `to` — straight is the
265
+ * chord; elbow/curve arrive axis-aligned along the dominant axis. Rotate an
266
+ * end marker by this so it points along the path, not the chord.
267
+ * @param {Point} from
268
+ * @param {Point} to
269
+ * @param {ConnectorShape} [shape]
270
+ * @returns {number}
158
271
  */
159
- /** Angle (radians) at which a `shape` path *arrives* at `to` — straight is the
160
- * chord; elbow/curve arrive axis-aligned along the dominant axis. Rotate an
161
- * end marker by this so it points along the path, not the chord. */
162
272
  export function endTangentAngle(from, to, shape = 'straight') {
163
273
  if (shape === 'straight') return angleBetween(from, to);
164
274
  const dx = finite('to.x', to?.x) - finite('from.x', from?.x);
@@ -167,6 +277,13 @@ export function endTangentAngle(from, to, shape = 'straight') {
167
277
  return dy >= 0 ? Math.PI / 2 : -Math.PI / 2;
168
278
  }
169
279
 
280
+ /**
281
+ * Connect two rects. Resolves anchor points (explicit `fromSide`/`toSide`, else
282
+ * auto), builds the path, and returns `{ d, from, to, angle }` so the caller can
283
+ * place an arrowhead/dot at `to` rotated by `angle`.
284
+ * @param {ConnectRectsOptions} [opts]
285
+ * @returns {ConnectRectsResult}
286
+ */
170
287
  export function connectRects(opts = {}) {
171
288
  const { fromRect, toRect, shape = 'straight', curvature, mid } = opts;
172
289
  // Honor each side override independently; auto-pick whichever is unset.