@invinite-org/chartlang-adapter-kit 1.3.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/README.md +7 -0
  3. package/dist/canvas/index.d.ts +5 -0
  4. package/dist/canvas/index.d.ts.map +1 -0
  5. package/dist/canvas/index.js +5 -0
  6. package/dist/canvas/index.js.map +1 -0
  7. package/dist/canvas/mockContext.d.ts +168 -0
  8. package/dist/canvas/mockContext.d.ts.map +1 -0
  9. package/dist/canvas/mockContext.js +198 -0
  10. package/dist/canvas/mockContext.js.map +1 -0
  11. package/dist/canvas/paintPrimitive.d.ts +35 -0
  12. package/dist/canvas/paintPrimitive.d.ts.map +1 -0
  13. package/dist/canvas/paintPrimitive.js +171 -0
  14. package/dist/canvas/paintPrimitive.js.map +1 -0
  15. package/dist/canvas/renderCtx.d.ts +40 -0
  16. package/dist/canvas/renderCtx.d.ts.map +1 -0
  17. package/dist/canvas/renderCtx.js +4 -0
  18. package/dist/canvas/renderCtx.js.map +1 -0
  19. package/dist/geometry/_lib/arrowhead.d.ts +18 -0
  20. package/dist/geometry/_lib/arrowhead.d.ts.map +1 -0
  21. package/dist/geometry/_lib/arrowhead.js +38 -0
  22. package/dist/geometry/_lib/arrowhead.js.map +1 -0
  23. package/dist/geometry/_lib/bezier.d.ts +57 -0
  24. package/dist/geometry/_lib/bezier.d.ts.map +1 -0
  25. package/dist/geometry/_lib/bezier.js +84 -0
  26. package/dist/geometry/_lib/bezier.js.map +1 -0
  27. package/dist/geometry/_lib/chevron.d.ts +29 -0
  28. package/dist/geometry/_lib/chevron.d.ts.map +1 -0
  29. package/dist/geometry/_lib/chevron.js +37 -0
  30. package/dist/geometry/_lib/chevron.js.map +1 -0
  31. package/dist/geometry/_lib/dash.d.ts +30 -0
  32. package/dist/geometry/_lib/dash.d.ts.map +1 -0
  33. package/dist/geometry/_lib/dash.js +40 -0
  34. package/dist/geometry/_lib/dash.js.map +1 -0
  35. package/dist/geometry/_lib/fibLevels.d.ts +36 -0
  36. package/dist/geometry/_lib/fibLevels.d.ts.map +1 -0
  37. package/dist/geometry/_lib/fibLevels.js +44 -0
  38. package/dist/geometry/_lib/fibLevels.js.map +1 -0
  39. package/dist/geometry/_lib/gannLevels.d.ts +54 -0
  40. package/dist/geometry/_lib/gannLevels.d.ts.map +1 -0
  41. package/dist/geometry/_lib/gannLevels.js +88 -0
  42. package/dist/geometry/_lib/gannLevels.js.map +1 -0
  43. package/dist/geometry/_lib/lineExtend.d.ts +31 -0
  44. package/dist/geometry/_lib/lineExtend.d.ts.map +1 -0
  45. package/dist/geometry/_lib/lineExtend.js +48 -0
  46. package/dist/geometry/_lib/lineExtend.js.map +1 -0
  47. package/dist/geometry/_lib/namedPolyline.d.ts +25 -0
  48. package/dist/geometry/_lib/namedPolyline.d.ts.map +1 -0
  49. package/dist/geometry/_lib/namedPolyline.js +64 -0
  50. package/dist/geometry/_lib/namedPolyline.js.map +1 -0
  51. package/dist/geometry/_lib/pitchforkGeom.d.ts +46 -0
  52. package/dist/geometry/_lib/pitchforkGeom.d.ts.map +1 -0
  53. package/dist/geometry/_lib/pitchforkGeom.js +70 -0
  54. package/dist/geometry/_lib/pitchforkGeom.js.map +1 -0
  55. package/dist/geometry/_lib/shapeStyle.d.ts +21 -0
  56. package/dist/geometry/_lib/shapeStyle.d.ts.map +1 -0
  57. package/dist/geometry/_lib/shapeStyle.js +41 -0
  58. package/dist/geometry/_lib/shapeStyle.js.map +1 -0
  59. package/dist/geometry/_lib/strokeStyle.d.ts +34 -0
  60. package/dist/geometry/_lib/strokeStyle.d.ts.map +1 -0
  61. package/dist/geometry/_lib/strokeStyle.js +26 -0
  62. package/dist/geometry/_lib/strokeStyle.js.map +1 -0
  63. package/dist/geometry/_lib/textStyle.d.ts +70 -0
  64. package/dist/geometry/_lib/textStyle.d.ts.map +1 -0
  65. package/dist/geometry/_lib/textStyle.js +78 -0
  66. package/dist/geometry/_lib/textStyle.js.map +1 -0
  67. package/dist/geometry/decompose.d.ts +28 -0
  68. package/dist/geometry/decompose.d.ts.map +1 -0
  69. package/dist/geometry/decompose.js +176 -0
  70. package/dist/geometry/decompose.js.map +1 -0
  71. package/dist/geometry/index.d.ts +4 -0
  72. package/dist/geometry/index.d.ts.map +1 -0
  73. package/dist/geometry/index.js +5 -0
  74. package/dist/geometry/index.js.map +1 -0
  75. package/dist/geometry/kinds/annotations.d.ts +77 -0
  76. package/dist/geometry/kinds/annotations.d.ts.map +1 -0
  77. package/dist/geometry/kinds/annotations.js +219 -0
  78. package/dist/geometry/kinds/annotations.js.map +1 -0
  79. package/dist/geometry/kinds/boxes.d.ts +116 -0
  80. package/dist/geometry/kinds/boxes.d.ts.map +1 -0
  81. package/dist/geometry/kinds/boxes.js +285 -0
  82. package/dist/geometry/kinds/boxes.js.map +1 -0
  83. package/dist/geometry/kinds/channels.d.ts +72 -0
  84. package/dist/geometry/kinds/channels.d.ts.map +1 -0
  85. package/dist/geometry/kinds/channels.js +148 -0
  86. package/dist/geometry/kinds/channels.js.map +1 -0
  87. package/dist/geometry/kinds/containers.d.ts +54 -0
  88. package/dist/geometry/kinds/containers.d.ts.map +1 -0
  89. package/dist/geometry/kinds/containers.js +268 -0
  90. package/dist/geometry/kinds/containers.js.map +1 -0
  91. package/dist/geometry/kinds/curves.d.ts +53 -0
  92. package/dist/geometry/kinds/curves.d.ts.map +1 -0
  93. package/dist/geometry/kinds/curves.js +110 -0
  94. package/dist/geometry/kinds/curves.js.map +1 -0
  95. package/dist/geometry/kinds/cycles.d.ts +52 -0
  96. package/dist/geometry/kinds/cycles.d.ts.map +1 -0
  97. package/dist/geometry/kinds/cycles.js +158 -0
  98. package/dist/geometry/kinds/cycles.js.map +1 -0
  99. package/dist/geometry/kinds/elliott.d.ts +73 -0
  100. package/dist/geometry/kinds/elliott.d.ts.map +1 -0
  101. package/dist/geometry/kinds/elliott.js +116 -0
  102. package/dist/geometry/kinds/elliott.js.map +1 -0
  103. package/dist/geometry/kinds/fibonacci.d.ts +166 -0
  104. package/dist/geometry/kinds/fibonacci.d.ts.map +1 -0
  105. package/dist/geometry/kinds/fibonacci.js +458 -0
  106. package/dist/geometry/kinds/fibonacci.js.map +1 -0
  107. package/dist/geometry/kinds/freehand.d.ts +53 -0
  108. package/dist/geometry/kinds/freehand.d.ts.map +1 -0
  109. package/dist/geometry/kinds/freehand.js +115 -0
  110. package/dist/geometry/kinds/freehand.js.map +1 -0
  111. package/dist/geometry/kinds/gann.d.ts +63 -0
  112. package/dist/geometry/kinds/gann.d.ts.map +1 -0
  113. package/dist/geometry/kinds/gann.js +153 -0
  114. package/dist/geometry/kinds/gann.js.map +1 -0
  115. package/dist/geometry/kinds/lines.d.ts +90 -0
  116. package/dist/geometry/kinds/lines.d.ts.map +1 -0
  117. package/dist/geometry/kinds/lines.js +201 -0
  118. package/dist/geometry/kinds/lines.js.map +1 -0
  119. package/dist/geometry/kinds/marker.d.ts +21 -0
  120. package/dist/geometry/kinds/marker.d.ts.map +1 -0
  121. package/dist/geometry/kinds/marker.js +47 -0
  122. package/dist/geometry/kinds/marker.js.map +1 -0
  123. package/dist/geometry/kinds/patterns.d.ts +85 -0
  124. package/dist/geometry/kinds/patterns.d.ts.map +1 -0
  125. package/dist/geometry/kinds/patterns.js +133 -0
  126. package/dist/geometry/kinds/patterns.js.map +1 -0
  127. package/dist/geometry/kinds/pitchforks.d.ts +36 -0
  128. package/dist/geometry/kinds/pitchforks.d.ts.map +1 -0
  129. package/dist/geometry/kinds/pitchforks.js +109 -0
  130. package/dist/geometry/kinds/pitchforks.js.map +1 -0
  131. package/dist/geometry/project.d.ts +50 -0
  132. package/dist/geometry/project.d.ts.map +1 -0
  133. package/dist/geometry/project.js +62 -0
  134. package/dist/geometry/project.js.map +1 -0
  135. package/dist/geometry/types.d.ts +146 -0
  136. package/dist/geometry/types.d.ts.map +1 -0
  137. package/dist/geometry/types.js +4 -0
  138. package/dist/geometry/types.js.map +1 -0
  139. package/dist/index.d.ts +4 -0
  140. package/dist/index.d.ts.map +1 -1
  141. package/dist/index.js +2 -0
  142. package/dist/index.js.map +1 -1
  143. package/dist/interaction/domWiring.d.ts +90 -0
  144. package/dist/interaction/domWiring.d.ts.map +1 -0
  145. package/dist/interaction/domWiring.js +113 -0
  146. package/dist/interaction/domWiring.js.map +1 -0
  147. package/dist/interaction/index.d.ts +5 -0
  148. package/dist/interaction/index.d.ts.map +1 -0
  149. package/dist/interaction/index.js +5 -0
  150. package/dist/interaction/index.js.map +1 -0
  151. package/dist/interaction/viewController.d.ts +120 -0
  152. package/dist/interaction/viewController.d.ts.map +1 -0
  153. package/dist/interaction/viewController.js +112 -0
  154. package/dist/interaction/viewController.js.map +1 -0
  155. package/package.json +8 -1
@@ -0,0 +1,219 @@
1
+ // Copyright (c) 2026 Invinite. Licensed under the MIT License.
2
+ // See the LICENSE file in the repo root for full license text.
3
+ //
4
+ // Annotation geometry moved from the canvas2d adapter's per-kind
5
+ // renderers
6
+ // examples/canvas2d-adapter/src/render/draw/{text,arrow,arrowMarker,
7
+ // arrowMarkUp,arrowMarkDown}.ts.
8
+ // The originating math is invinite's text / arrow / arrow-marker /
9
+ // arrow-mark-up / arrow-mark-down tools (commit
10
+ // 078f41fe2569d659d5aba726da8bcb5d3e2ced02, © Invinite); re-licensed
11
+ // MIT for chartlang.
12
+ import { arrowheadPolygon } from "../_lib/arrowhead.js";
13
+ import { chevronPolygon } from "../_lib/chevron.js";
14
+ import { dashPattern } from "../_lib/dash.js";
15
+ import { resolveTextOpts } from "../_lib/textStyle.js";
16
+ import { worldPointToPixel } from "../project.js";
17
+ const DEFAULT_LINE_COLOR = "#000000";
18
+ const DEFAULT_LINE_WIDTH = 1;
19
+ const DEFAULT_ARROW_MARKER_COLOR = "#3b82f6"; // invinite toolbar blue
20
+ const DEFAULT_MARK_UP_COLOR = "#22c55e";
21
+ const DEFAULT_MARK_DOWN_COLOR = "#ef4444";
22
+ const SOLID_FILL_ALPHA = 1;
23
+ const ARROW_LABEL_FONT = "12px sans-serif";
24
+ const ARROW_LABEL_VERTICAL_OFFSET = 4;
25
+ const MARKER_DOT_RADIUS = 3;
26
+ const MARKER_STUB_DX = 16;
27
+ const MARKER_STUB_DY = -8;
28
+ const MARKER_TEXT_OFFSET_X = 6;
29
+ const MARKER_TEXT_FONT = "12px sans-serif";
30
+ const TWO_PI = Math.PI * 2;
31
+ /**
32
+ * Decompose a `text` drawing — a single label at the projected anchor,
33
+ * its font / alignment / colour resolved from `TextOpts`. `bgColor` is
34
+ * carried through onto the IR `text` primitive (adapters that can paint
35
+ * a background rect may use it; the canvas sink ignores it).
36
+ *
37
+ * @since 1.3
38
+ * @stable
39
+ * @example
40
+ * declare const s: TextState;
41
+ * declare const v: Viewport;
42
+ * const prims = decomposeText(s, v);
43
+ * // prims[0].kind === "text"
44
+ * void prims;
45
+ */
46
+ export function decomposeText(state, view) {
47
+ const anchor = worldPointToPixel(state.anchor, view);
48
+ const resolved = resolveTextOpts(state.style);
49
+ return [
50
+ {
51
+ kind: "text",
52
+ x: anchor.x,
53
+ y: anchor.y,
54
+ text: state.body,
55
+ color: resolved.color,
56
+ font: resolved.font,
57
+ align: resolved.align,
58
+ baseline: resolved.baseline,
59
+ ...(state.style.bgColor === undefined ? {} : { bgColor: state.style.bgColor }),
60
+ },
61
+ ];
62
+ }
63
+ /**
64
+ * Decompose an `arrow` drawing — a stroked shaft, a filled arrowhead
65
+ * triangle at the head anchor, and an optional label at the shaft
66
+ * midpoint. Stroke and arrowhead fill share `style.color`.
67
+ *
68
+ * @since 1.3
69
+ * @stable
70
+ * @example
71
+ * declare const s: ArrowState;
72
+ * declare const v: Viewport;
73
+ * const prims = decomposeArrow(s, v);
74
+ * // prims[0].kind === "polyline"; prims[1].kind === "polyline"
75
+ * void prims;
76
+ */
77
+ export function decomposeArrow(state, view) {
78
+ const from = worldPointToPixel(state.anchors[0], view);
79
+ const to = worldPointToPixel(state.anchors[1], view);
80
+ const color = state.style.color ?? DEFAULT_LINE_COLOR;
81
+ const out = [
82
+ {
83
+ kind: "polyline",
84
+ points: [from, to],
85
+ closed: false,
86
+ stroke: {
87
+ color,
88
+ width: state.style.lineWidth ?? DEFAULT_LINE_WIDTH,
89
+ dash: dashPattern(state.style.lineStyle ?? "solid"),
90
+ },
91
+ },
92
+ {
93
+ kind: "polyline",
94
+ points: arrowheadPolygon(from, to),
95
+ closed: true,
96
+ fill: { color, alpha: SOLID_FILL_ALPHA },
97
+ },
98
+ ];
99
+ if (state.style.label !== undefined) {
100
+ out.push({
101
+ kind: "text",
102
+ x: (from.x + to.x) / 2,
103
+ y: (from.y + to.y) / 2 - ARROW_LABEL_VERTICAL_OFFSET,
104
+ text: state.style.label,
105
+ color,
106
+ font: ARROW_LABEL_FONT,
107
+ align: "center",
108
+ baseline: "bottom",
109
+ });
110
+ }
111
+ return out;
112
+ }
113
+ /**
114
+ * Decompose an `arrow-marker` drawing — a self-contained compact glyph
115
+ * at the anchor: a filled dot, a short stub up + right, a filled
116
+ * arrowhead at the stub end, and optional text to the right. Default
117
+ * colour is `"#3b82f6"` (invinite toolbar blue).
118
+ *
119
+ * @since 1.3
120
+ * @stable
121
+ * @example
122
+ * declare const s: ArrowMarkerState;
123
+ * declare const v: Viewport;
124
+ * const prims = decomposeArrowMarker(s, v);
125
+ * void prims;
126
+ */
127
+ export function decomposeArrowMarker(state, view) {
128
+ const anchor = worldPointToPixel(state.anchor, view);
129
+ const color = state.style.color ?? DEFAULT_ARROW_MARKER_COLOR;
130
+ const stubEnd = { x: anchor.x + MARKER_STUB_DX, y: anchor.y + MARKER_STUB_DY };
131
+ const out = [
132
+ {
133
+ kind: "arc",
134
+ cx: anchor.x,
135
+ cy: anchor.y,
136
+ r: MARKER_DOT_RADIUS,
137
+ start: 0,
138
+ end: TWO_PI,
139
+ closed: false,
140
+ fill: { color, alpha: SOLID_FILL_ALPHA },
141
+ },
142
+ {
143
+ kind: "polyline",
144
+ points: [anchor, stubEnd],
145
+ closed: false,
146
+ stroke: { color, width: DEFAULT_LINE_WIDTH, dash: dashPattern("solid") },
147
+ },
148
+ {
149
+ kind: "polyline",
150
+ points: arrowheadPolygon(anchor, stubEnd),
151
+ closed: true,
152
+ fill: { color, alpha: SOLID_FILL_ALPHA },
153
+ },
154
+ ];
155
+ if (state.style.text !== undefined) {
156
+ out.push({
157
+ kind: "text",
158
+ x: anchor.x + MARKER_TEXT_OFFSET_X,
159
+ y: anchor.y,
160
+ text: state.style.text,
161
+ color,
162
+ font: MARKER_TEXT_FONT,
163
+ align: "left",
164
+ baseline: "middle",
165
+ });
166
+ }
167
+ return out;
168
+ }
169
+ /**
170
+ * Decompose an `arrow-mark-up` drawing — a filled up-chevron glyph at
171
+ * the anchor. Default fill colour is `"#22c55e"` (green); an explicit
172
+ * `style.color` overrides.
173
+ *
174
+ * @since 1.3
175
+ * @stable
176
+ * @example
177
+ * declare const s: ArrowMarkUpState;
178
+ * declare const v: Viewport;
179
+ * const prims = decomposeArrowMarkUp(s, v);
180
+ * void prims;
181
+ */
182
+ export function decomposeArrowMarkUp(state, view) {
183
+ const anchor = worldPointToPixel(state.anchor, view);
184
+ const color = state.style.color ?? DEFAULT_MARK_UP_COLOR;
185
+ return [
186
+ {
187
+ kind: "polyline",
188
+ points: chevronPolygon(anchor, "up"),
189
+ closed: true,
190
+ fill: { color, alpha: SOLID_FILL_ALPHA },
191
+ },
192
+ ];
193
+ }
194
+ /**
195
+ * Decompose an `arrow-mark-down` drawing — a filled down-chevron glyph
196
+ * at the anchor. Default fill colour is `"#ef4444"` (red); an explicit
197
+ * `style.color` overrides.
198
+ *
199
+ * @since 1.3
200
+ * @stable
201
+ * @example
202
+ * declare const s: ArrowMarkDownState;
203
+ * declare const v: Viewport;
204
+ * const prims = decomposeArrowMarkDown(s, v);
205
+ * void prims;
206
+ */
207
+ export function decomposeArrowMarkDown(state, view) {
208
+ const anchor = worldPointToPixel(state.anchor, view);
209
+ const color = state.style.color ?? DEFAULT_MARK_DOWN_COLOR;
210
+ return [
211
+ {
212
+ kind: "polyline",
213
+ points: chevronPolygon(anchor, "down"),
214
+ closed: true,
215
+ fill: { color, alpha: SOLID_FILL_ALPHA },
216
+ },
217
+ ];
218
+ }
219
+ //# sourceMappingURL=annotations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"annotations.js","sourceRoot":"","sources":["../../../src/geometry/kinds/annotations.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) 2026 Invinite. Licensed under the MIT License.\n// See the LICENSE file in the repo root for full license text.\n//\n// Annotation geometry moved from the canvas2d adapter's per-kind\n// renderers\n// examples/canvas2d-adapter/src/render/draw/{text,arrow,arrowMarker,\n// arrowMarkUp,arrowMarkDown}.ts.\n// The originating math is invinite's text / arrow / arrow-marker /\n// arrow-mark-up / arrow-mark-down tools (commit\n// 078f41fe2569d659d5aba726da8bcb5d3e2ced02, © Invinite); re-licensed\n// MIT for chartlang.\n\nimport type {\n ArrowMarkDownState,\n ArrowMarkUpState,\n ArrowMarkerState,\n ArrowState,\n TextState,\n} from \"@invinite-org/chartlang-core\";\n\nimport { arrowheadPolygon } from \"../_lib/arrowhead.js\";\nimport { chevronPolygon } from \"../_lib/chevron.js\";\nimport { dashPattern } from \"../_lib/dash.js\";\nimport { resolveTextOpts } from \"../_lib/textStyle.js\";\nimport { worldPointToPixel } from \"../project.js\";\nimport type { DrawPrimitive, Viewport } from \"../types.js\";\n\nconst DEFAULT_LINE_COLOR = \"#000000\";\nconst DEFAULT_LINE_WIDTH = 1;\nconst DEFAULT_ARROW_MARKER_COLOR = \"#3b82f6\"; // invinite toolbar blue\nconst DEFAULT_MARK_UP_COLOR = \"#22c55e\";\nconst DEFAULT_MARK_DOWN_COLOR = \"#ef4444\";\nconst SOLID_FILL_ALPHA = 1;\nconst ARROW_LABEL_FONT = \"12px sans-serif\";\nconst ARROW_LABEL_VERTICAL_OFFSET = 4;\nconst MARKER_DOT_RADIUS = 3;\nconst MARKER_STUB_DX = 16;\nconst MARKER_STUB_DY = -8;\nconst MARKER_TEXT_OFFSET_X = 6;\nconst MARKER_TEXT_FONT = \"12px sans-serif\";\nconst TWO_PI = Math.PI * 2;\n\n/**\n * Decompose a `text` drawing — a single label at the projected anchor,\n * its font / alignment / colour resolved from `TextOpts`. `bgColor` is\n * carried through onto the IR `text` primitive (adapters that can paint\n * a background rect may use it; the canvas sink ignores it).\n *\n * @since 1.3\n * @stable\n * @example\n * declare const s: TextState;\n * declare const v: Viewport;\n * const prims = decomposeText(s, v);\n * // prims[0].kind === \"text\"\n * void prims;\n */\nexport function decomposeText(state: TextState, view: Viewport): ReadonlyArray<DrawPrimitive> {\n const anchor = worldPointToPixel(state.anchor, view);\n const resolved = resolveTextOpts(state.style);\n return [\n {\n kind: \"text\",\n x: anchor.x,\n y: anchor.y,\n text: state.body,\n color: resolved.color,\n font: resolved.font,\n align: resolved.align,\n baseline: resolved.baseline,\n ...(state.style.bgColor === undefined ? {} : { bgColor: state.style.bgColor }),\n },\n ];\n}\n\n/**\n * Decompose an `arrow` drawing — a stroked shaft, a filled arrowhead\n * triangle at the head anchor, and an optional label at the shaft\n * midpoint. Stroke and arrowhead fill share `style.color`.\n *\n * @since 1.3\n * @stable\n * @example\n * declare const s: ArrowState;\n * declare const v: Viewport;\n * const prims = decomposeArrow(s, v);\n * // prims[0].kind === \"polyline\"; prims[1].kind === \"polyline\"\n * void prims;\n */\nexport function decomposeArrow(state: ArrowState, view: Viewport): ReadonlyArray<DrawPrimitive> {\n const from = worldPointToPixel(state.anchors[0], view);\n const to = worldPointToPixel(state.anchors[1], view);\n const color = state.style.color ?? DEFAULT_LINE_COLOR;\n const out: DrawPrimitive[] = [\n {\n kind: \"polyline\",\n points: [from, to],\n closed: false,\n stroke: {\n color,\n width: state.style.lineWidth ?? DEFAULT_LINE_WIDTH,\n dash: dashPattern(state.style.lineStyle ?? \"solid\"),\n },\n },\n {\n kind: \"polyline\",\n points: arrowheadPolygon(from, to),\n closed: true,\n fill: { color, alpha: SOLID_FILL_ALPHA },\n },\n ];\n if (state.style.label !== undefined) {\n out.push({\n kind: \"text\",\n x: (from.x + to.x) / 2,\n y: (from.y + to.y) / 2 - ARROW_LABEL_VERTICAL_OFFSET,\n text: state.style.label,\n color,\n font: ARROW_LABEL_FONT,\n align: \"center\",\n baseline: \"bottom\",\n });\n }\n return out;\n}\n\n/**\n * Decompose an `arrow-marker` drawing — a self-contained compact glyph\n * at the anchor: a filled dot, a short stub up + right, a filled\n * arrowhead at the stub end, and optional text to the right. Default\n * colour is `\"#3b82f6\"` (invinite toolbar blue).\n *\n * @since 1.3\n * @stable\n * @example\n * declare const s: ArrowMarkerState;\n * declare const v: Viewport;\n * const prims = decomposeArrowMarker(s, v);\n * void prims;\n */\nexport function decomposeArrowMarker(\n state: ArrowMarkerState,\n view: Viewport,\n): ReadonlyArray<DrawPrimitive> {\n const anchor = worldPointToPixel(state.anchor, view);\n const color = state.style.color ?? DEFAULT_ARROW_MARKER_COLOR;\n const stubEnd = { x: anchor.x + MARKER_STUB_DX, y: anchor.y + MARKER_STUB_DY };\n const out: DrawPrimitive[] = [\n {\n kind: \"arc\",\n cx: anchor.x,\n cy: anchor.y,\n r: MARKER_DOT_RADIUS,\n start: 0,\n end: TWO_PI,\n closed: false,\n fill: { color, alpha: SOLID_FILL_ALPHA },\n },\n {\n kind: \"polyline\",\n points: [anchor, stubEnd],\n closed: false,\n stroke: { color, width: DEFAULT_LINE_WIDTH, dash: dashPattern(\"solid\") },\n },\n {\n kind: \"polyline\",\n points: arrowheadPolygon(anchor, stubEnd),\n closed: true,\n fill: { color, alpha: SOLID_FILL_ALPHA },\n },\n ];\n if (state.style.text !== undefined) {\n out.push({\n kind: \"text\",\n x: anchor.x + MARKER_TEXT_OFFSET_X,\n y: anchor.y,\n text: state.style.text,\n color,\n font: MARKER_TEXT_FONT,\n align: \"left\",\n baseline: \"middle\",\n });\n }\n return out;\n}\n\n/**\n * Decompose an `arrow-mark-up` drawing — a filled up-chevron glyph at\n * the anchor. Default fill colour is `\"#22c55e\"` (green); an explicit\n * `style.color` overrides.\n *\n * @since 1.3\n * @stable\n * @example\n * declare const s: ArrowMarkUpState;\n * declare const v: Viewport;\n * const prims = decomposeArrowMarkUp(s, v);\n * void prims;\n */\nexport function decomposeArrowMarkUp(\n state: ArrowMarkUpState,\n view: Viewport,\n): ReadonlyArray<DrawPrimitive> {\n const anchor = worldPointToPixel(state.anchor, view);\n const color = state.style.color ?? DEFAULT_MARK_UP_COLOR;\n return [\n {\n kind: \"polyline\",\n points: chevronPolygon(anchor, \"up\"),\n closed: true,\n fill: { color, alpha: SOLID_FILL_ALPHA },\n },\n ];\n}\n\n/**\n * Decompose an `arrow-mark-down` drawing — a filled down-chevron glyph\n * at the anchor. Default fill colour is `\"#ef4444\"` (red); an explicit\n * `style.color` overrides.\n *\n * @since 1.3\n * @stable\n * @example\n * declare const s: ArrowMarkDownState;\n * declare const v: Viewport;\n * const prims = decomposeArrowMarkDown(s, v);\n * void prims;\n */\nexport function decomposeArrowMarkDown(\n state: ArrowMarkDownState,\n view: Viewport,\n): ReadonlyArray<DrawPrimitive> {\n const anchor = worldPointToPixel(state.anchor, view);\n const color = state.style.color ?? DEFAULT_MARK_DOWN_COLOR;\n return [\n {\n kind: \"polyline\",\n points: chevronPolygon(anchor, \"down\"),\n closed: true,\n fill: { color, alpha: SOLID_FILL_ALPHA },\n },\n ];\n}\n"]}
@@ -0,0 +1,116 @@
1
+ import type { CircleState, EllipseState, FillBetweenState, PathState, PolylineState, RectangleState, RotatedRectangleState, TriangleState } from "@invinite-org/chartlang-core";
2
+ import type { DrawPrimitive, Viewport } from "../types.js";
3
+ /**
4
+ * Decompose a `rectangle` drawing — a closed 4-corner polygon derived
5
+ * from the axis-aligned bounding box of the two projected anchors.
6
+ *
7
+ * @since 1.3
8
+ * @stable
9
+ * @example
10
+ * declare const s: RectangleState;
11
+ * declare const v: Viewport;
12
+ * const prims = decomposeRectangle(s, v);
13
+ * // prims[0].kind === "polyline"; prims[0].closed === true
14
+ * void prims;
15
+ */
16
+ export declare function decomposeRectangle(state: RectangleState, view: Viewport): ReadonlyArray<DrawPrimitive>;
17
+ /**
18
+ * Decompose a `rotated-rectangle` drawing — a closed polygon through
19
+ * the four projected anchors (carried in stroke order, so no matrix
20
+ * math is needed).
21
+ *
22
+ * @since 1.3
23
+ * @stable
24
+ * @example
25
+ * declare const s: RotatedRectangleState;
26
+ * declare const v: Viewport;
27
+ * const prims = decomposeRotatedRectangle(s, v);
28
+ * void prims;
29
+ */
30
+ export declare function decomposeRotatedRectangle(state: RotatedRectangleState, view: Viewport): ReadonlyArray<DrawPrimitive>;
31
+ /**
32
+ * Decompose a `triangle` drawing — a closed 3-vertex polygon.
33
+ *
34
+ * @since 1.3
35
+ * @stable
36
+ * @example
37
+ * declare const s: TriangleState;
38
+ * declare const v: Viewport;
39
+ * const prims = decomposeTriangle(s, v);
40
+ * void prims;
41
+ */
42
+ export declare function decomposeTriangle(state: TriangleState, view: Viewport): ReadonlyArray<DrawPrimitive>;
43
+ /**
44
+ * Decompose a `polyline` drawing — a closed N-vertex polyline carrying
45
+ * a `LineDrawStyle` (no fill).
46
+ *
47
+ * @since 1.3
48
+ * @stable
49
+ * @example
50
+ * declare const s: PolylineState;
51
+ * declare const v: Viewport;
52
+ * const prims = decomposePolyline(s, v);
53
+ * // prims[0].closed === true
54
+ * void prims;
55
+ */
56
+ export declare function decomposePolyline(state: PolylineState, view: Viewport): ReadonlyArray<DrawPrimitive>;
57
+ /**
58
+ * Decompose a `circle` drawing — an arc whose radius is the projected
59
+ * pixel distance between the centre anchor and the radius anchor (so
60
+ * the stroke keeps the same apparent thickness across zoom changes).
61
+ *
62
+ * @since 1.3
63
+ * @stable
64
+ * @example
65
+ * declare const s: CircleState;
66
+ * declare const v: Viewport;
67
+ * const prims = decomposeCircle(s, v);
68
+ * // prims[0].kind === "arc"
69
+ * void prims;
70
+ */
71
+ export declare function decomposeCircle(state: CircleState, view: Viewport): ReadonlyArray<DrawPrimitive>;
72
+ /**
73
+ * Decompose an axis-aligned `ellipse` drawing — a closed
74
+ * {@link ELLIPSE_SEGMENTS}-segment polyline inscribed in the bounding
75
+ * box of the two anchors. Rotated ellipses are out of scope.
76
+ *
77
+ * @since 1.3
78
+ * @stable
79
+ * @example
80
+ * declare const s: EllipseState;
81
+ * declare const v: Viewport;
82
+ * const prims = decomposeEllipse(s, v);
83
+ * void prims;
84
+ */
85
+ export declare function decomposeEllipse(state: EllipseState, view: Viewport): ReadonlyArray<DrawPrimitive>;
86
+ /**
87
+ * Decompose a `path` drawing — an OPEN N-vertex polyline (unless
88
+ * `style.closed === true`) carrying a `PathOpts` style (no fill).
89
+ *
90
+ * @since 1.3
91
+ * @stable
92
+ * @example
93
+ * declare const s: PathState;
94
+ * declare const v: Viewport;
95
+ * const prims = decomposePath(s, v);
96
+ * void prims;
97
+ */
98
+ export declare function decomposePath(state: PathState, view: Viewport): ReadonlyArray<DrawPrimitive>;
99
+ /**
100
+ * Decompose a `fill-between` drawing — a closed filled polygon walking
101
+ * `edgeA` forward then `edgeB` in reverse. The optional outline strokes
102
+ * only when `style.color` is set; the band fills only when `style.fill`
103
+ * is set. A degenerate edge (`< 1` point) or a non-finite mapped anchor
104
+ * is a silent no-op (returns `[]`), matching the source renderer's
105
+ * warmup behaviour.
106
+ *
107
+ * @since 1.3
108
+ * @stable
109
+ * @example
110
+ * declare const s: FillBetweenState;
111
+ * declare const v: Viewport;
112
+ * const prims = decomposeFillBetween(s, v);
113
+ * void prims;
114
+ */
115
+ export declare function decomposeFillBetween(state: FillBetweenState, view: Viewport): ReadonlyArray<DrawPrimitive>;
116
+ //# sourceMappingURL=boxes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boxes.d.ts","sourceRoot":"","sources":["../../../src/geometry/kinds/boxes.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EACR,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,SAAS,EACT,aAAa,EACb,cAAc,EACd,qBAAqB,EACrB,aAAa,EAChB,MAAM,8BAA8B,CAAC;AAKtC,OAAO,KAAK,EAAE,aAAa,EAAU,QAAQ,EAAE,MAAM,aAAa,CAAC;AAcnE;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAC9B,KAAK,EAAE,cAAc,EACrB,IAAI,EAAE,QAAQ,GACf,aAAa,CAAC,aAAa,CAAC,CAsB9B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,yBAAyB,CACrC,KAAK,EAAE,qBAAqB,EAC5B,IAAI,EAAE,QAAQ,GACf,aAAa,CAAC,aAAa,CAAC,CAY9B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAC7B,KAAK,EAAE,aAAa,EACpB,IAAI,EAAE,QAAQ,GACf,aAAa,CAAC,aAAa,CAAC,CAY9B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC7B,KAAK,EAAE,aAAa,EACpB,IAAI,EAAE,QAAQ,GACf,aAAa,CAAC,aAAa,CAAC,CAc9B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,GAAG,aAAa,CAAC,aAAa,CAAC,CAkBhG;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAC5B,KAAK,EAAE,YAAY,EACnB,IAAI,EAAE,QAAQ,GACf,aAAa,CAAC,aAAa,CAAC,CAsB9B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,GAAG,aAAa,CAAC,aAAa,CAAC,CAc5F;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,oBAAoB,CAChC,KAAK,EAAE,gBAAgB,EACvB,IAAI,EAAE,QAAQ,GACf,aAAa,CAAC,aAAa,CAAC,CA4B9B"}
@@ -0,0 +1,285 @@
1
+ // Copyright (c) 2026 Invinite. Licensed under the MIT License.
2
+ // See the LICENSE file in the repo root for full license text.
3
+ //
4
+ // Stroke + fill geometry moved from the canvas2d adapter's per-kind
5
+ // shape renderers
6
+ // examples/canvas2d-adapter/src/render/draw/{rectangle,
7
+ // rotatedRectangle,triangle,polyline,circle,ellipse,path,
8
+ // fillBetween}.ts.
9
+ // The originating math is invinite's rectangle / rotated-rectangle /
10
+ // triangle / polyline / circle / ellipse / path tools (commit
11
+ // 078f41fe2569d659d5aba726da8bcb5d3e2ced02, © Invinite); re-licensed
12
+ // MIT for chartlang.
13
+ import { dashPattern } from "../_lib/dash.js";
14
+ import { resolveShapeStyle } from "../_lib/shapeStyle.js";
15
+ import { worldPointToPixel } from "../project.js";
16
+ const DEFAULT_LINE_WIDTH = 1;
17
+ const DEFAULT_FILL_ALPHA = 1;
18
+ const TWO_PI = Math.PI * 2;
19
+ /**
20
+ * Number of polyline segments used to approximate an `ellipse`. 64
21
+ * segments give visually smooth strokes at typical viewport widths
22
+ * (≈800 px) while keeping the primitive list bounded — matching the
23
+ * canvas2d source renderer exactly.
24
+ */
25
+ const ELLIPSE_SEGMENTS = 64;
26
+ /**
27
+ * Decompose a `rectangle` drawing — a closed 4-corner polygon derived
28
+ * from the axis-aligned bounding box of the two projected anchors.
29
+ *
30
+ * @since 1.3
31
+ * @stable
32
+ * @example
33
+ * declare const s: RectangleState;
34
+ * declare const v: Viewport;
35
+ * const prims = decomposeRectangle(s, v);
36
+ * // prims[0].kind === "polyline"; prims[0].closed === true
37
+ * void prims;
38
+ */
39
+ export function decomposeRectangle(state, view) {
40
+ const a = worldPointToPixel(state.anchors[0], view);
41
+ const b = worldPointToPixel(state.anchors[1], view);
42
+ const xMin = Math.min(a.x, b.x);
43
+ const xMax = Math.max(a.x, b.x);
44
+ const yMin = Math.min(a.y, b.y);
45
+ const yMax = Math.max(a.y, b.y);
46
+ const { stroke, fill } = resolveShapeStyle(state.style);
47
+ return [
48
+ {
49
+ kind: "polyline",
50
+ points: [
51
+ { x: xMin, y: yMin },
52
+ { x: xMax, y: yMin },
53
+ { x: xMax, y: yMax },
54
+ { x: xMin, y: yMax },
55
+ ],
56
+ closed: true,
57
+ stroke,
58
+ ...(fill === undefined ? {} : { fill }),
59
+ },
60
+ ];
61
+ }
62
+ /**
63
+ * Decompose a `rotated-rectangle` drawing — a closed polygon through
64
+ * the four projected anchors (carried in stroke order, so no matrix
65
+ * math is needed).
66
+ *
67
+ * @since 1.3
68
+ * @stable
69
+ * @example
70
+ * declare const s: RotatedRectangleState;
71
+ * declare const v: Viewport;
72
+ * const prims = decomposeRotatedRectangle(s, v);
73
+ * void prims;
74
+ */
75
+ export function decomposeRotatedRectangle(state, view) {
76
+ const points = state.anchors.map((p) => worldPointToPixel(p, view));
77
+ const { stroke, fill } = resolveShapeStyle(state.style);
78
+ return [
79
+ {
80
+ kind: "polyline",
81
+ points,
82
+ closed: true,
83
+ stroke,
84
+ ...(fill === undefined ? {} : { fill }),
85
+ },
86
+ ];
87
+ }
88
+ /**
89
+ * Decompose a `triangle` drawing — a closed 3-vertex polygon.
90
+ *
91
+ * @since 1.3
92
+ * @stable
93
+ * @example
94
+ * declare const s: TriangleState;
95
+ * declare const v: Viewport;
96
+ * const prims = decomposeTriangle(s, v);
97
+ * void prims;
98
+ */
99
+ export function decomposeTriangle(state, view) {
100
+ const points = state.anchors.map((p) => worldPointToPixel(p, view));
101
+ const { stroke, fill } = resolveShapeStyle(state.style);
102
+ return [
103
+ {
104
+ kind: "polyline",
105
+ points,
106
+ closed: true,
107
+ stroke,
108
+ ...(fill === undefined ? {} : { fill }),
109
+ },
110
+ ];
111
+ }
112
+ /**
113
+ * Decompose a `polyline` drawing — a closed N-vertex polyline carrying
114
+ * a `LineDrawStyle` (no fill).
115
+ *
116
+ * @since 1.3
117
+ * @stable
118
+ * @example
119
+ * declare const s: PolylineState;
120
+ * declare const v: Viewport;
121
+ * const prims = decomposePolyline(s, v);
122
+ * // prims[0].closed === true
123
+ * void prims;
124
+ */
125
+ export function decomposePolyline(state, view) {
126
+ const points = state.anchors.map((p) => worldPointToPixel(p, view));
127
+ return [
128
+ {
129
+ kind: "polyline",
130
+ points,
131
+ closed: true,
132
+ stroke: {
133
+ color: state.style.color ?? "#000000",
134
+ width: state.style.lineWidth ?? DEFAULT_LINE_WIDTH,
135
+ dash: dashPattern(state.style.lineStyle ?? "solid"),
136
+ },
137
+ },
138
+ ];
139
+ }
140
+ /**
141
+ * Decompose a `circle` drawing — an arc whose radius is the projected
142
+ * pixel distance between the centre anchor and the radius anchor (so
143
+ * the stroke keeps the same apparent thickness across zoom changes).
144
+ *
145
+ * @since 1.3
146
+ * @stable
147
+ * @example
148
+ * declare const s: CircleState;
149
+ * declare const v: Viewport;
150
+ * const prims = decomposeCircle(s, v);
151
+ * // prims[0].kind === "arc"
152
+ * void prims;
153
+ */
154
+ export function decomposeCircle(state, view) {
155
+ const centre = worldPointToPixel(state.anchors[0], view);
156
+ const edge = worldPointToPixel(state.anchors[1], view);
157
+ const radius = Math.hypot(edge.x - centre.x, edge.y - centre.y);
158
+ const { stroke, fill } = resolveShapeStyle(state.style);
159
+ return [
160
+ {
161
+ kind: "arc",
162
+ cx: centre.x,
163
+ cy: centre.y,
164
+ r: radius,
165
+ start: 0,
166
+ end: TWO_PI,
167
+ closed: true,
168
+ stroke,
169
+ ...(fill === undefined ? {} : { fill }),
170
+ },
171
+ ];
172
+ }
173
+ /**
174
+ * Decompose an axis-aligned `ellipse` drawing — a closed
175
+ * {@link ELLIPSE_SEGMENTS}-segment polyline inscribed in the bounding
176
+ * box of the two anchors. Rotated ellipses are out of scope.
177
+ *
178
+ * @since 1.3
179
+ * @stable
180
+ * @example
181
+ * declare const s: EllipseState;
182
+ * declare const v: Viewport;
183
+ * const prims = decomposeEllipse(s, v);
184
+ * void prims;
185
+ */
186
+ export function decomposeEllipse(state, view) {
187
+ const a = worldPointToPixel(state.anchors[0], view);
188
+ const b = worldPointToPixel(state.anchors[1], view);
189
+ const cx = (a.x + b.x) / 2;
190
+ const cy = (a.y + b.y) / 2;
191
+ const rx = Math.abs(b.x - a.x) / 2;
192
+ const ry = Math.abs(b.y - a.y) / 2;
193
+ const points = [{ x: cx + rx, y: cy }];
194
+ for (let i = 1; i < ELLIPSE_SEGMENTS; i++) {
195
+ const theta = (i / ELLIPSE_SEGMENTS) * TWO_PI;
196
+ points.push({ x: cx + rx * Math.cos(theta), y: cy + ry * Math.sin(theta) });
197
+ }
198
+ const { stroke, fill } = resolveShapeStyle(state.style);
199
+ return [
200
+ {
201
+ kind: "polyline",
202
+ points,
203
+ closed: true,
204
+ stroke,
205
+ ...(fill === undefined ? {} : { fill }),
206
+ },
207
+ ];
208
+ }
209
+ /**
210
+ * Decompose a `path` drawing — an OPEN N-vertex polyline (unless
211
+ * `style.closed === true`) carrying a `PathOpts` style (no fill).
212
+ *
213
+ * @since 1.3
214
+ * @stable
215
+ * @example
216
+ * declare const s: PathState;
217
+ * declare const v: Viewport;
218
+ * const prims = decomposePath(s, v);
219
+ * void prims;
220
+ */
221
+ export function decomposePath(state, view) {
222
+ const points = state.anchors.map((p) => worldPointToPixel(p, view));
223
+ return [
224
+ {
225
+ kind: "polyline",
226
+ points,
227
+ closed: state.style.closed === true,
228
+ stroke: {
229
+ color: state.style.color ?? "#000000",
230
+ width: state.style.lineWidth ?? DEFAULT_LINE_WIDTH,
231
+ dash: dashPattern(state.style.lineStyle ?? "solid"),
232
+ },
233
+ },
234
+ ];
235
+ }
236
+ /**
237
+ * Decompose a `fill-between` drawing — a closed filled polygon walking
238
+ * `edgeA` forward then `edgeB` in reverse. The optional outline strokes
239
+ * only when `style.color` is set; the band fills only when `style.fill`
240
+ * is set. A degenerate edge (`< 1` point) or a non-finite mapped anchor
241
+ * is a silent no-op (returns `[]`), matching the source renderer's
242
+ * warmup behaviour.
243
+ *
244
+ * @since 1.3
245
+ * @stable
246
+ * @example
247
+ * declare const s: FillBetweenState;
248
+ * declare const v: Viewport;
249
+ * const prims = decomposeFillBetween(s, v);
250
+ * void prims;
251
+ */
252
+ export function decomposeFillBetween(state, view) {
253
+ const a = state.edgeA.map((p) => worldPointToPixel(p, view));
254
+ const b = state.edgeB.map((p) => worldPointToPixel(p, view));
255
+ if (a.length < 1 || b.length < 1)
256
+ return [];
257
+ if (a.some((p) => !Number.isFinite(p.x) || !Number.isFinite(p.y)))
258
+ return [];
259
+ if (b.some((p) => !Number.isFinite(p.x) || !Number.isFinite(p.y)))
260
+ return [];
261
+ const points = [...a];
262
+ for (let i = b.length - 1; i >= 0; i--)
263
+ points.push(b[i]);
264
+ const { color, fill } = state.style;
265
+ return [
266
+ {
267
+ kind: "polyline",
268
+ points,
269
+ closed: true,
270
+ ...(color === undefined
271
+ ? {}
272
+ : {
273
+ stroke: {
274
+ color,
275
+ width: state.style.lineWidth ?? DEFAULT_LINE_WIDTH,
276
+ dash: dashPattern(state.style.lineStyle ?? "solid"),
277
+ },
278
+ }),
279
+ ...(fill === undefined
280
+ ? {}
281
+ : { fill: { color: fill, alpha: state.style.fillAlpha ?? DEFAULT_FILL_ALPHA } }),
282
+ },
283
+ ];
284
+ }
285
+ //# sourceMappingURL=boxes.js.map