@blukavantui/charts-community 0.0.0-stage → 1.2.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 (262) hide show
  1. package/LICENSE.txt +103 -0
  2. package/README.md +98 -2
  3. package/THIRD_PARTY_NOTICES.txt +288 -0
  4. package/dist/accessibility.d.ts +53 -0
  5. package/dist/async.d.ts +2 -0
  6. package/dist/bar.css +1 -0
  7. package/dist/bar.d.ts +5 -0
  8. package/dist/bar.js +1 -0
  9. package/dist/browser/charts-community.css +1 -0
  10. package/dist/browser/charts-community.js +52 -0
  11. package/dist/build-audit.json +209 -0
  12. package/dist/builders/bar.d.ts +6 -0
  13. package/dist/builders/doughnut.d.ts +6 -0
  14. package/dist/builders/heatmap.d.ts +16 -0
  15. package/dist/builders/line.d.ts +6 -0
  16. package/dist/builders/pie.d.ts +6 -0
  17. package/dist/builders/radar.d.ts +6 -0
  18. package/dist/builders/scatter.d.ts +6 -0
  19. package/dist/catalogue-model.d.ts +11 -0
  20. package/dist/catalogue-runtime.d.ts +23 -0
  21. package/dist/catalogue-types.d.ts +167 -0
  22. package/dist/chart-state.d.ts +18 -0
  23. package/dist/chunk-2GUWWKHW.js +1 -0
  24. package/dist/chunk-3PITHTEO.js +1 -0
  25. package/dist/chunk-4B5MQ6GZ.js +1 -0
  26. package/dist/chunk-4EQMOBBN.js +1 -0
  27. package/dist/chunk-4WDZUJDS.js +1 -0
  28. package/dist/chunk-5NUOOMHV.js +1 -0
  29. package/dist/chunk-7OCMRHIH.js +1 -0
  30. package/dist/chunk-CF5Q2DDP.js +1 -0
  31. package/dist/chunk-EITBQBN2.js +1 -0
  32. package/dist/chunk-FXNKAHRG.js +1 -0
  33. package/dist/chunk-IDMAFTWV.js +1 -0
  34. package/dist/chunk-ILTENI35.js +1 -0
  35. package/dist/chunk-KRMM7EWI.js +1 -0
  36. package/dist/chunk-LUUPBBD4.js +1 -0
  37. package/dist/chunk-MR5VITXX.js +1 -0
  38. package/dist/chunk-NASBRHIW.js +1 -0
  39. package/dist/chunk-NXDBBMF5.js +1 -0
  40. package/dist/chunk-OQ6MP7PY.js +1 -0
  41. package/dist/chunk-RC2TCMJF.js +1 -0
  42. package/dist/chunk-RXOGAN23.js +1 -0
  43. package/dist/chunk-UGXWOWAG.js +2 -0
  44. package/dist/chunk-UO2KNHTU.js +2 -0
  45. package/dist/chunk-UQMMBG26.js +3 -0
  46. package/dist/chunk-VTJ4XPRV.js +1 -0
  47. package/dist/chunk-WJ3UHH6J.js +1 -0
  48. package/dist/chunk-XLJUSNGV.js +1 -0
  49. package/dist/colors.d.ts +15 -0
  50. package/dist/community.d.ts +11 -0
  51. package/dist/doughnut.css +1 -0
  52. package/dist/doughnut.d.ts +5 -0
  53. package/dist/doughnut.js +1 -0
  54. package/dist/export.d.ts +5 -0
  55. package/dist/fonts/dm-sans-LICENSE.txt +93 -0
  56. package/dist/fonts/dm-sans-latin-ext-wght-italic.woff2 +0 -0
  57. package/dist/fonts/dm-sans-latin-ext-wght-normal.woff2 +0 -0
  58. package/dist/fonts/dm-sans-latin-wght-italic.woff2 +0 -0
  59. package/dist/fonts/dm-sans-latin-wght-normal.woff2 +0 -0
  60. package/dist/fonts/ibm-plex-mono-LICENSE.txt +93 -0
  61. package/dist/fonts/ibm-plex-mono-latin-100-italic.woff2 +0 -0
  62. package/dist/fonts/ibm-plex-mono-latin-100-normal.woff2 +0 -0
  63. package/dist/fonts/ibm-plex-mono-latin-200-italic.woff2 +0 -0
  64. package/dist/fonts/ibm-plex-mono-latin-200-normal.woff2 +0 -0
  65. package/dist/fonts/ibm-plex-mono-latin-300-italic.woff2 +0 -0
  66. package/dist/fonts/ibm-plex-mono-latin-300-normal.woff2 +0 -0
  67. package/dist/fonts/ibm-plex-mono-latin-400-italic.woff2 +0 -0
  68. package/dist/fonts/ibm-plex-mono-latin-400-normal.woff2 +0 -0
  69. package/dist/fonts/ibm-plex-mono-latin-500-italic.woff2 +0 -0
  70. package/dist/fonts/ibm-plex-mono-latin-500-normal.woff2 +0 -0
  71. package/dist/fonts/ibm-plex-mono-latin-600-italic.woff2 +0 -0
  72. package/dist/fonts/ibm-plex-mono-latin-600-normal.woff2 +0 -0
  73. package/dist/fonts/ibm-plex-mono-latin-700-italic.woff2 +0 -0
  74. package/dist/fonts/ibm-plex-mono-latin-700-normal.woff2 +0 -0
  75. package/dist/fonts/ibm-plex-mono-latin-ext-100-italic.woff2 +0 -0
  76. package/dist/fonts/ibm-plex-mono-latin-ext-100-normal.woff2 +0 -0
  77. package/dist/fonts/ibm-plex-mono-latin-ext-200-italic.woff2 +0 -0
  78. package/dist/fonts/ibm-plex-mono-latin-ext-200-normal.woff2 +0 -0
  79. package/dist/fonts/ibm-plex-mono-latin-ext-300-italic.woff2 +0 -0
  80. package/dist/fonts/ibm-plex-mono-latin-ext-300-normal.woff2 +0 -0
  81. package/dist/fonts/ibm-plex-mono-latin-ext-400-italic.woff2 +0 -0
  82. package/dist/fonts/ibm-plex-mono-latin-ext-400-normal.woff2 +0 -0
  83. package/dist/fonts/ibm-plex-mono-latin-ext-500-italic.woff2 +0 -0
  84. package/dist/fonts/ibm-plex-mono-latin-ext-500-normal.woff2 +0 -0
  85. package/dist/fonts/ibm-plex-mono-latin-ext-600-italic.woff2 +0 -0
  86. package/dist/fonts/ibm-plex-mono-latin-ext-600-normal.woff2 +0 -0
  87. package/dist/fonts/ibm-plex-mono-latin-ext-700-italic.woff2 +0 -0
  88. package/dist/fonts/ibm-plex-mono-latin-ext-700-normal.woff2 +0 -0
  89. package/dist/fonts/inter-LICENSE.txt +93 -0
  90. package/dist/fonts/inter-latin-ext-wght-italic.woff2 +0 -0
  91. package/dist/fonts/inter-latin-ext-wght-normal.woff2 +0 -0
  92. package/dist/fonts/inter-latin-wght-italic.woff2 +0 -0
  93. package/dist/fonts/inter-latin-wght-normal.woff2 +0 -0
  94. package/dist/fonts/jetbrains-mono-LICENSE.txt +93 -0
  95. package/dist/fonts/jetbrains-mono-latin-ext-wght-italic.woff2 +0 -0
  96. package/dist/fonts/jetbrains-mono-latin-ext-wght-normal.woff2 +0 -0
  97. package/dist/fonts/jetbrains-mono-latin-wght-italic.woff2 +0 -0
  98. package/dist/fonts/jetbrains-mono-latin-wght-normal.woff2 +0 -0
  99. package/dist/fonts/lora-LICENSE.txt +93 -0
  100. package/dist/fonts/lora-latin-ext-wght-italic.woff2 +0 -0
  101. package/dist/fonts/lora-latin-ext-wght-normal.woff2 +0 -0
  102. package/dist/fonts/lora-latin-wght-italic.woff2 +0 -0
  103. package/dist/fonts/lora-latin-wght-normal.woff2 +0 -0
  104. package/dist/fonts/manifest.json +618 -0
  105. package/dist/fonts/manrope-LICENSE.txt +93 -0
  106. package/dist/fonts/manrope-latin-ext-wght-normal.woff2 +0 -0
  107. package/dist/fonts/manrope-latin-wght-normal.woff2 +0 -0
  108. package/dist/fonts/merriweather-LICENSE.txt +93 -0
  109. package/dist/fonts/merriweather-latin-ext-wght-italic.woff2 +0 -0
  110. package/dist/fonts/merriweather-latin-ext-wght-normal.woff2 +0 -0
  111. package/dist/fonts/merriweather-latin-wght-italic.woff2 +0 -0
  112. package/dist/fonts/merriweather-latin-wght-normal.woff2 +0 -0
  113. package/dist/fonts/montserrat-LICENSE.txt +93 -0
  114. package/dist/fonts/montserrat-latin-ext-wght-italic.woff2 +0 -0
  115. package/dist/fonts/montserrat-latin-ext-wght-normal.woff2 +0 -0
  116. package/dist/fonts/montserrat-latin-wght-italic.woff2 +0 -0
  117. package/dist/fonts/montserrat-latin-wght-normal.woff2 +0 -0
  118. package/dist/fonts/playfair-display-LICENSE.txt +93 -0
  119. package/dist/fonts/playfair-display-latin-ext-wght-italic.woff2 +0 -0
  120. package/dist/fonts/playfair-display-latin-ext-wght-normal.woff2 +0 -0
  121. package/dist/fonts/playfair-display-latin-wght-italic.woff2 +0 -0
  122. package/dist/fonts/playfair-display-latin-wght-normal.woff2 +0 -0
  123. package/dist/fonts/roboto-LICENSE.txt +93 -0
  124. package/dist/fonts/roboto-latin-ext-wght-italic.woff2 +0 -0
  125. package/dist/fonts/roboto-latin-ext-wght-normal.woff2 +0 -0
  126. package/dist/fonts/roboto-latin-wght-italic.woff2 +0 -0
  127. package/dist/fonts/roboto-latin-wght-normal.woff2 +0 -0
  128. package/dist/fonts/source-sans-3-LICENSE.txt +93 -0
  129. package/dist/fonts/source-sans-3-latin-ext-wght-italic.woff2 +0 -0
  130. package/dist/fonts/source-sans-3-latin-ext-wght-normal.woff2 +0 -0
  131. package/dist/fonts/source-sans-3-latin-wght-italic.woff2 +0 -0
  132. package/dist/fonts/source-sans-3-latin-wght-normal.woff2 +0 -0
  133. package/dist/heatmap.css +1 -0
  134. package/dist/heatmap.d.ts +3 -0
  135. package/dist/heatmap.js +1 -0
  136. package/dist/index.css +1 -0
  137. package/dist/index.d.ts +11 -0
  138. package/dist/index.js +1 -0
  139. package/dist/legend-export.d.ts +9 -0
  140. package/dist/legend-model.d.ts +39 -0
  141. package/dist/legend.d.ts +19 -0
  142. package/dist/limits.d.ts +16 -0
  143. package/dist/line.css +1 -0
  144. package/dist/line.d.ts +5 -0
  145. package/dist/line.js +1 -0
  146. package/dist/loading-state.d.ts +6 -0
  147. package/dist/map-assets.d.ts +4 -0
  148. package/dist/map-resources.d.ts +24 -0
  149. package/dist/messages.d.ts +3 -0
  150. package/dist/model.d.ts +41 -0
  151. package/dist/motion/bar.css +1 -0
  152. package/dist/motion/bar.d.ts +8 -0
  153. package/dist/motion/bar.js +1 -0
  154. package/dist/motion/doughnut.css +1 -0
  155. package/dist/motion/doughnut.d.ts +8 -0
  156. package/dist/motion/doughnut.js +1 -0
  157. package/dist/motion/heatmap.css +1 -0
  158. package/dist/motion/heatmap.d.ts +7 -0
  159. package/dist/motion/heatmap.js +1 -0
  160. package/dist/motion/line.css +1 -0
  161. package/dist/motion/line.d.ts +8 -0
  162. package/dist/motion/line.js +1 -0
  163. package/dist/motion/pie.css +1 -0
  164. package/dist/motion/pie.d.ts +8 -0
  165. package/dist/motion/pie.js +1 -0
  166. package/dist/motion/radar.css +1 -0
  167. package/dist/motion/radar.d.ts +8 -0
  168. package/dist/motion/radar.js +1 -0
  169. package/dist/motion/scatter.css +1 -0
  170. package/dist/motion/scatter.d.ts +8 -0
  171. package/dist/motion/scatter.js +1 -0
  172. package/dist/motion/sparkline.d.ts +7 -0
  173. package/dist/motion/sparkline.js +1 -0
  174. package/dist/motion-collection.d.ts +7 -0
  175. package/dist/motion-community.d.ts +40 -0
  176. package/dist/motion-policy.d.ts +14 -0
  177. package/dist/motion.css +1 -0
  178. package/dist/motion.d.ts +40 -0
  179. package/dist/motion.js +1 -0
  180. package/dist/options.d.ts +11 -0
  181. package/dist/pie.css +1 -0
  182. package/dist/pie.d.ts +5 -0
  183. package/dist/pie.js +1 -0
  184. package/dist/radar.css +1 -0
  185. package/dist/radar.d.ts +4 -0
  186. package/dist/radar.js +1 -0
  187. package/dist/runtime.d.ts +4 -0
  188. package/dist/scatter.css +1 -0
  189. package/dist/scatter.d.ts +5 -0
  190. package/dist/scatter.js +1 -0
  191. package/dist/sparkline-runtime/runtime.d.ts +10 -0
  192. package/dist/sparkline-validation.d.ts +3 -0
  193. package/dist/sparkline.css +25 -0
  194. package/dist/sparkline.d.ts +44 -0
  195. package/dist/sparkline.js +1 -0
  196. package/dist/state-announcement.d.ts +6 -0
  197. package/dist/styles.css +496 -0
  198. package/dist/theme.css +1391 -0
  199. package/dist/types.d.ts +137 -0
  200. package/dist/validation.d.ts +8 -0
  201. package/dist/web-api.json +4305 -0
  202. package/dist/web-motion-sparkline.d.ts +4 -0
  203. package/edition.json +48 -0
  204. package/package.json +103 -4
  205. package/src/accessibility.ts +81 -0
  206. package/src/assets.d.ts +1 -0
  207. package/src/async.ts +12 -0
  208. package/src/bar.ts +13 -0
  209. package/src/builders/bar.ts +39 -0
  210. package/src/builders/doughnut.ts +66 -0
  211. package/src/builders/heatmap.ts +60 -0
  212. package/src/builders/line.ts +39 -0
  213. package/src/builders/pie.ts +66 -0
  214. package/src/builders/radar.ts +65 -0
  215. package/src/builders/scatter.ts +34 -0
  216. package/src/catalogue-model.ts +235 -0
  217. package/src/catalogue-runtime.ts +244 -0
  218. package/src/catalogue-types.ts +163 -0
  219. package/src/chart-state.ts +35 -0
  220. package/src/charts.css +135 -0
  221. package/src/colors.ts +277 -0
  222. package/src/community.ts +11 -0
  223. package/src/doughnut.ts +12 -0
  224. package/src/export.ts +50 -0
  225. package/src/heatmap.ts +11 -0
  226. package/src/index.ts +11 -0
  227. package/src/legend-export.ts +36 -0
  228. package/src/legend-model.ts +76 -0
  229. package/src/legend.css +64 -0
  230. package/src/legend.ts +90 -0
  231. package/src/limits.ts +7 -0
  232. package/src/line.ts +13 -0
  233. package/src/loading-state.ts +39 -0
  234. package/src/map-assets.ts +1 -0
  235. package/src/map-resources.ts +46 -0
  236. package/src/messages.ts +5 -0
  237. package/src/model.ts +32 -0
  238. package/src/motion/bar.ts +15 -0
  239. package/src/motion/doughnut.ts +14 -0
  240. package/src/motion/heatmap.ts +14 -0
  241. package/src/motion/line.ts +15 -0
  242. package/src/motion/pie.ts +14 -0
  243. package/src/motion/radar.ts +15 -0
  244. package/src/motion/scatter.ts +15 -0
  245. package/src/motion/sparkline.ts +10 -0
  246. package/src/motion-collection.ts +20 -0
  247. package/src/motion-community.ts +22 -0
  248. package/src/motion-policy.ts +36 -0
  249. package/src/options.ts +24 -0
  250. package/src/pie.ts +12 -0
  251. package/src/radar.ts +12 -0
  252. package/src/runtime.ts +7 -0
  253. package/src/scatter.ts +13 -0
  254. package/src/sparkline-runtime/runtime.d.ts +10 -0
  255. package/src/sparkline-runtime/runtime.js +263 -0
  256. package/src/sparkline-validation.ts +19 -0
  257. package/src/sparkline.css +25 -0
  258. package/src/sparkline.ts +68 -0
  259. package/src/state-announcement.ts +17 -0
  260. package/src/types.ts +104 -0
  261. package/src/validation.ts +75 -0
  262. package/src/web-motion-sparkline.ts +37 -0
@@ -0,0 +1,163 @@
1
+ import type { ChartOptions, ChartCategory, ChartColor, ChartIdentity, ChartDatum } from './types.ts';
2
+ export type CatalogueKind = 'line' | 'radar' | 'bar' | 'pie' | 'doughnut' | 'nightingale' | 'polar' | 'scatter' | 'treemap' | 'sankey' | 'funnel' | 'geo-map' | 'calendar-heatmap';
3
+ export interface ValueSeries extends ChartIdentity {
4
+ Values: (number | null)[];
5
+ }
6
+ export interface CartesianOptions extends ChartOptions {
7
+ Categories: ChartCategory[];
8
+ Series: ValueSeries[];
9
+ Orientation?: 'Vertical' | 'Horizontal';
10
+ Stacking?: 'None' | 'Stacked' | 'Percent';
11
+ LineStyle?: 'Straight' | 'Smooth' | 'Step';
12
+ ShowArea?: boolean;
13
+ PolarType?: 'Bar' | 'Line';
14
+ }
15
+ /** Per-axis bounds keep comparisons stable as datasets change. */
16
+ export interface RadarCategory extends ChartCategory { Max?: number }
17
+ export interface RadarOptions extends ChartOptions {
18
+ Categories: RadarCategory[];
19
+ Series: ValueSeries[];
20
+ GridShape?: 'Polygon' | 'Circle';
21
+ SplitNumber?: number;
22
+ ShowArea?: boolean;
23
+ ShowAxisBounds?: boolean;
24
+ }
25
+ export interface Slice extends ChartDatum {
26
+ RingKey?: string;
27
+ }
28
+ export interface Ring extends ChartIdentity {
29
+ }
30
+ export interface CircularOptions extends ChartOptions {
31
+ Items: Slice[];
32
+ Rings?: Ring[];
33
+ Nested?: boolean;
34
+ Shape?: 'Full' | 'Half';
35
+ /** Nested inner levels stay inside; the outermost level uses this position. */
36
+ LabelPosition?: 'Outside' | 'Inside';
37
+ InnerRadius?: number;
38
+ RoseMode?: 'Area' | 'Radius';
39
+ CenterLabel?: string;
40
+ }
41
+ export interface ScatterPoint extends ChartIdentity {
42
+ X: number;
43
+ Y: number;
44
+ Size?: number;
45
+ Group?: string;
46
+ }
47
+ export interface ScatterOptions extends ChartOptions {
48
+ Points: ScatterPoint[];
49
+ Bubble?: boolean;
50
+ XLabel?: string;
51
+ YLabel?: string;
52
+ }
53
+ /** Flat parent keys map directly to OutSystems lists. Branch totals are derived from descendant leaves. */
54
+ export interface TreeNode extends ChartDatum {
55
+ ParentKey: string | null;
56
+ }
57
+ export interface TreemapOptions extends ChartOptions {
58
+ Nodes: TreeNode[];
59
+ Drilldown?: boolean;
60
+ }
61
+ export interface FlowNode extends ChartIdentity {
62
+ }
63
+ export interface FlowLink {
64
+ Key: string;
65
+ SourceKey: string;
66
+ TargetKey: string;
67
+ Value: number;
68
+ }
69
+ export interface SankeyOptions extends ChartOptions {
70
+ Nodes: FlowNode[];
71
+ Links: FlowLink[];
72
+ Orientation?: 'Horizontal' | 'Vertical';
73
+ NodeAlign?: 'Justify' | 'Left' | 'Right';
74
+ }
75
+ export interface FunnelOptions extends ChartOptions {
76
+ Items: Slice[];
77
+ Sort?: 'Input' | 'Descending' | 'Ascending';
78
+ ShowConversion?: boolean;
79
+ }
80
+ export interface GeoRegion extends ChartDatum {
81
+ }
82
+ export interface GeoLocation extends ChartIdentity {
83
+ Longitude: number;
84
+ Latitude: number;
85
+ Value: number;
86
+ }
87
+ export interface GeoFeature {
88
+ type: 'Feature';
89
+ properties: {
90
+ name: string;
91
+ label?: string;
92
+ [key: string]: unknown;
93
+ };
94
+ geometry: {
95
+ type: 'Polygon' | 'MultiPolygon';
96
+ coordinates: number[][][] | number[][][][];
97
+ };
98
+ }
99
+ export interface GeoJSON {
100
+ type: 'FeatureCollection';
101
+ features: GeoFeature[];
102
+ }
103
+ export interface GeoMapOptions extends ChartOptions {
104
+ Map?: 'World' | 'US' | 'Custom';
105
+ GeoJSON?: GeoJSON;
106
+ /** Custom geometry resource, mutually exclusive with GeoJSON. */
107
+ MapURL?: string;
108
+ /** US defaults to Mainland; Full includes all geometry in the bundled asset. */
109
+ MapView?: 'Mainland' | 'Full';
110
+ Regions: GeoRegion[];
111
+ Locations: GeoLocation[];
112
+ MapMode?: 'Regions' | 'Locations' | 'Combined';
113
+ Roam?: boolean;
114
+ ColorScale?: ChartColor | 'Automatic';
115
+ }
116
+ /** Date-only ISO strings avoid time-zone shifts in OutSystems Date values. */
117
+ export interface CalendarDay extends ChartDatum { Date: string }
118
+ export interface CalendarHeatmapOptions extends ChartOptions {
119
+ Items: CalendarDay[];
120
+ RangeStart: string;
121
+ RangeEnd: string;
122
+ FirstDay?: 'Monday' | 'Sunday';
123
+ ColorScale?: ChartColor | 'Automatic';
124
+ ShowMonthLabels?: boolean;
125
+ ShowDayLabels?: boolean;
126
+ }
127
+ export interface OptionsByKind {
128
+ 'calendar-heatmap': CalendarHeatmapOptions;
129
+ line: CartesianOptions;
130
+ radar: RadarOptions;
131
+ bar: CartesianOptions;
132
+ polar: CartesianOptions;
133
+ pie: CircularOptions;
134
+ doughnut: CircularOptions;
135
+ nightingale: CircularOptions;
136
+ scatter: ScatterOptions;
137
+ treemap: TreemapOptions;
138
+ sankey: SankeyOptions;
139
+ funnel: FunnelOptions;
140
+ 'geo-map': GeoMapOptions;
141
+ }
142
+ export type CatalogueOptions = OptionsByKind[CatalogueKind];
143
+ /** Stable scalar payload suitable for JSON serialization or a native OutSystems structure. */
144
+ export interface ChartPoint {
145
+ Key: string;
146
+ Label: string;
147
+ Value: number | null;
148
+ SeriesKey?: string;
149
+ CategoryKey?: string;
150
+ SeriesName?: string;
151
+ RingKey?: string;
152
+ Date?: string;
153
+ ParentKey?: string | null;
154
+ X?: number;
155
+ Y?: number;
156
+ Size?: number;
157
+ Group?: string;
158
+ SourceKey?: string;
159
+ TargetKey?: string;
160
+ Longitude?: number;
161
+ Latitude?: number;
162
+ PointType?: 'Region' | 'Location' | 'Node' | 'Link' | 'Series';
163
+ }
@@ -0,0 +1,35 @@
1
+ import type { ChartOptions, MixedChartOptions, HeatmapOptions } from './types.ts';
2
+ import type { CatalogueKind, CatalogueOptions, ChartPoint } from './catalogue-types.ts';
3
+ import { cataloguePoints, validateCatalogue } from './catalogue-model.ts';
4
+ import { validateMixed, validateHeatmap } from './validation.ts';
5
+ import { mixedPoint, heatmapPoint } from './model.ts';
6
+ export type RuntimeKind = CatalogueKind | 'mixed' | 'heatmap';
7
+ export type RuntimeOptions = CatalogueOptions | MixedChartOptions | HeatmapOptions;
8
+ export function validateChart(kind:RuntimeKind,o:RuntimeOptions) { if(kind==='mixed') validateMixed(o as MixedChartOptions); else if(kind==='heatmap') validateHeatmap(o as HeatmapOptions); else validateCatalogue(kind,o as CatalogueOptions); }
9
+ export function chartPoints(kind:RuntimeKind,o:RuntimeOptions): ChartPoint[] {
10
+ if(kind==='mixed') { const c=o as MixedChartOptions; return c.Series.flatMap((s,si)=>c.Categories.map((cat,ci)=>({...mixedPoint(c,ci,si)!,Label:cat.Label,CategoryKey:cat.Key}))); }
11
+ if(kind==='heatmap') return (o as HeatmapOptions).Cells.map((_,i)=>{const p=heatmapPoint(o as HeatmapOptions,i)!;return {...p,Label:`${p.YLabel}, ${p.XLabel}`};});
12
+ return cataloguePoints(kind,o as CatalogueOptions);
13
+ }
14
+ export function pointIdentity(kind:RuntimeKind,p:ChartPoint) { return JSON.stringify([kind,p.Key,p.SeriesKey||'',p.CategoryKey||'',p.RingKey||'',p.PointType||'']); }
15
+ export function prepareUpdate<O extends RuntimeOptions>(kind:RuntimeKind,current:O,patch:Partial<O>) {
16
+ const next = {...current,...structuredClone(patch)};
17
+ // Validate data before deriving selection, so malformed records cannot reach point lookup.
18
+ validateChart(kind,{...next,SelectedKey:null});
19
+ const missing = next.SelectedKey != null && !chartPoints(kind,next).some(p=>p.Key===next.SelectedKey);
20
+ const cleared = missing && (!Object.hasOwn(patch,'SelectedKey') || patch.SelectedKey === current.SelectedKey);
21
+ if(cleared) next.SelectedKey=null;
22
+ validateChart(kind,next);
23
+ return {next,cleared};
24
+ }
25
+ /** Resolve ECharts targets from actual rendered data; display labels never identify a point. */
26
+ export function highlightTargets(config:any,key:string) {
27
+ const targets:{seriesIndex:number;dataIndex:number;dataType?:string}[]=[];
28
+ (config?.series||[]).forEach((s:any,seriesIndex:number)=>{
29
+ if(s.type==='treemap') { let index=1; const visit=(nodes:any[])=>nodes.forEach(n=>{const dataIndex=index++;if(n.id===key)targets.push({seriesIndex,dataIndex});visit(n.children||[]);});visit(s.data||[]); }
30
+ else (s.data||[]).forEach((d:any,dataIndex:number)=>{if(d?.point?.Key===key)targets.push({seriesIndex,dataIndex,...(s.type==='sankey'?{dataType:'node'}:{})});});
31
+ (s.links||[]).forEach((d:any,dataIndex:number)=>{if(d?.point?.Key===key)targets.push({seriesIndex,dataIndex,dataType:'edge'});});
32
+ });
33
+ return targets;
34
+ }
35
+ export function message(o:ChartOptions,key:string,fallback:string) {return o.Messages?.[key]??fallback;}
package/src/charts.css ADDED
@@ -0,0 +1,135 @@
1
+ .blu-chart { width:100%; min-width:0; color:var(--bluui-text,#182230); background:var(--bluui-surface,#fff); font:13px/1.5 var(--blu-font-family,Inter,system-ui,sans-serif); }
2
+ .blu-chart [hidden] { display:none!important; }
3
+ .blu-chart__heading { display:flex; align-items:flex-start; justify-content:space-between; gap:16px; padding:18px 16px 12px; }
4
+ .blu-chart__heading>div:first-child { min-width:0; }
5
+ .blu-chart__heading h3 { margin:0; color:inherit; font-size:16px; font-weight:650; letter-spacing:-.3px; overflow-wrap:anywhere; }
6
+ .blu-chart__heading p { margin:5px 0 0; font-size:11px; color:var(--bluui-text-muted,#667085); line-height:1.6; overflow-wrap:anywhere; }
7
+ .blu-chart__export { display:flex; gap:5px; flex-shrink:0; margin-left:auto; }
8
+ .blu-chart__export :is(select,button) { font:inherit; font-size:11px; border:1px solid var(--bluui-border,#ddd); color:inherit; border-radius:6px; background:var(--bluui-surface,#fff); min-height:34px; padding:6px 8px; cursor:pointer; }
9
+ .blu-chart__export button:disabled { opacity:.5; cursor:default; }
10
+ .blu-chart__stage { position:relative; min-width:0; }
11
+ .blu-chart__plot { width:100%; min-width:0; }
12
+ .blu-chart__state { position:absolute; inset:0; display:grid; place-items:center; background:var(--bluui-surface-muted,#f8f8fa); color:var(--bluui-text-muted,#667085); padding:20px; text-align:center; }
13
+ .blu-chart__state--loading {grid-template-rows:minmax(0,1fr) auto;gap:14px;place-items:stretch;background:var(--bluui-surface,#fff);padding:16px}
14
+ .blu-chart__skeleton {display:flex;flex-direction:column;gap:24px;min-width:0;min-height:0}
15
+ .blu-chart__skeleton-key {display:flex;gap:16px;align-items:center;flex-wrap:wrap}
16
+ .blu-chart__skeleton-plot {flex:1;min-height:0}
17
+ .blu-chart__skeleton-plot>div {height:100%}
18
+ .blu-chart__state-message {font-size:12px}
19
+ .blu-chart__data { margin:12px 16px 0; border-top:1px solid var(--bluui-border,#ddd); font-size:11px; }
20
+ .blu-chart__data summary { cursor:pointer; padding:12px 0; color:var(--bluui-text-muted,#667085); }
21
+ .blu-chart__data--compact { margin-top:0; border-top:0; }
22
+ .blu-chart__data--compact summary { padding:6px 0; }
23
+ .blu-chart__table { overflow:auto; max-height:320px; }
24
+ .blu-chart__table table { width:100%; border-collapse:collapse; white-space:nowrap; font-size:11px; font-variant-numeric:tabular-nums; }
25
+ .blu-chart__table caption { text-align:left; color:var(--bluui-text-muted,#667085); padding:8px; }
26
+ .blu-chart__table th,.blu-chart__table td { padding:8px; border-bottom:1px solid var(--bluui-border,#ddd); text-align:right; }
27
+ .blu-chart__table th:first-child { text-align:left; }
28
+ .blu-chart__table button { font:inherit; color:var(--bluui-primary,#6557e8); background:transparent; border:0; border-radius:3px; padding:5px; cursor:pointer; }
29
+ .blu-chart__table button[aria-pressed=true] { background:var(--bluui-selected,#eeeaff); text-decoration:underline; text-decoration-thickness:2px; text-underline-offset:3px; font-weight:700; }
30
+ .blu-chart :is(button,select,summary,[tabindex]):focus-visible { outline:2px solid var(--bluui-primary,#6557e8); outline-offset:2px; }
31
+ .blu-chart__status { font-size:11px; color:var(--bluui-text-muted,#667085); margin:0 16px; }
32
+ .blu-chart__status:not(:empty) { padding:8px 0; }
33
+ @media(max-width:640px) { .blu-chart__heading { flex-wrap:wrap; padding-inline:12px; }.blu-chart__export { margin-left:0; }.blu-chart__data { margin-inline:12px; } }
34
+
35
+ .blu-chart__navigation {display:flex;flex-wrap:wrap;gap:6px;padding:8px 16px}
36
+ .blu-chart__navigation button {min-width:32px;min-height:32px;padding:5px 9px;font:inherit;font-size:12px;color:var(--bluui-text);background:var(--bluui-surface);border:1px solid var(--bluui-control-border);border-radius:5px;cursor:pointer}
37
+ .blu-chart__stage[tabindex]:focus-visible {outline-offset:-3px}
38
+
39
+
40
+ .blu-chart__state-announcement { position:absolute; width:1px; height:1px; overflow:hidden; clip-path:inset(50%); white-space:nowrap; }
41
+ .blu-chart__patterns {display:flex;align-items:center;gap:8px;font-size:12px;padding:6px 0 12px;cursor:pointer}
42
+ .blu-chart__patterns input {width:24px;height:24px;margin:0;accent-color:var(--bluui-color-primary-solid)}
43
+
44
+ .blu-chart__missing-note {margin:8px 12px;color:var(--bluui-text-muted);font-size:12px;line-height:1.5}
45
+
46
+ /* BEGIN GENERATED SHARED CHECKBOX — scripts/build-checkbox-styles.mjs */
47
+ /* One checkbox design, emitted into each owning Block. Keep native input/tree/grid semantics. */
48
+ .blu-chart .blu-chart__patterns input[type="checkbox"] {
49
+ -webkit-appearance:none;
50
+ appearance:none;
51
+ box-sizing:border-box;
52
+ position:relative;
53
+ display:inline-block;
54
+ flex:0 0 22px;
55
+ width:22px;
56
+ height:22px;
57
+ min-width:22px;
58
+ min-height:22px;
59
+ margin:0;
60
+ padding:0;
61
+ border:1.5px solid var(--bluui-control-border,#7b8799);
62
+ border-radius:6px;
63
+ background-color:var(--bluui-surface,#fff);
64
+ background-image:none;
65
+ box-shadow:0 1px 2px rgb(15 23 42 / 6%);
66
+ vertical-align:middle;
67
+ cursor:pointer;
68
+ opacity:1;
69
+ filter:none;
70
+ transition:background-color 120ms ease,border-color 120ms ease,box-shadow 120ms ease;
71
+ }
72
+ .blu-chart .blu-chart__patterns input[type="checkbox"]::after { content:none; }
73
+ .blu-chart .blu-chart__patterns input[type="checkbox"]:checked,
74
+ .blu-chart .blu-chart__patterns input[type="checkbox"]:indeterminate {
75
+ border-color:var(--bluui-color-primary-solid,#4f46e5);
76
+ background-color:var(--bluui-color-primary-solid,#4f46e5);
77
+ }
78
+ .blu-chart .blu-chart__patterns input[type="checkbox"]:checked::after,
79
+ .blu-chart .blu-chart__patterns input[type="checkbox"]:indeterminate::after {
80
+ content:"";
81
+ box-sizing:content-box;
82
+ position:absolute;
83
+ inset:auto;
84
+ width:10px;
85
+ height:6px;
86
+ left:4px;
87
+ top:5px;
88
+ border:solid var(--bluui-color-primary-contrast,#fff);
89
+ border-width:0 0 2px 2px;
90
+ border-radius:0;
91
+ background:none;
92
+ -webkit-mask:none;
93
+ mask:none;
94
+ transform:rotate(-45deg);
95
+ pointer-events:none;
96
+ }
97
+ .blu-chart .blu-chart__patterns input[type="checkbox"]:indeterminate::after {
98
+ height:0;
99
+ top:8px;
100
+ border-width:0 0 2px;
101
+ transform:none;
102
+ }
103
+ .blu-chart .blu-chart__patterns input[type="checkbox"]:hover:not(:disabled) {
104
+ border-color:var(--bluui-color-primary-solid,#4f46e5);
105
+ box-shadow:0 0 0 3px var(--bluui-color-primary-soft,#eef2ff);
106
+ }
107
+ .blu-chart .blu-chart__patterns input[type="checkbox"]:focus-visible {
108
+ outline:2px solid var(--bluui-color-primary-solid,#4f46e5);
109
+ outline-offset:3px;
110
+ }
111
+ .blu-chart .blu-chart__patterns input[type="checkbox"]:disabled {
112
+ border-color:var(--bluui-border-strong,#b8c4d4);
113
+ background-color:var(--bluui-surface-muted,#f7f8fb);
114
+ box-shadow:none;
115
+ cursor:not-allowed;
116
+ }
117
+ .blu-chart .blu-chart__patterns input[type="checkbox"]:disabled:checked,
118
+ .blu-chart .blu-chart__patterns input[type="checkbox"]:disabled:indeterminate {
119
+ border-color:var(--bluui-text-muted,#5c6b80);
120
+ background-color:var(--bluui-text-muted,#5c6b80);
121
+ }
122
+ @media (prefers-reduced-motion:reduce) {
123
+ .blu-chart .blu-chart__patterns input[type="checkbox"] { transition:none; }
124
+ }
125
+ .blu-chart .blu-chart__patterns input[type="checkbox"]::before { content:none; }
126
+ @media (forced-colors:active) {
127
+ .blu-chart .blu-chart__patterns input[type="checkbox"],
128
+ .blu-chart .blu-chart__patterns input[type="checkbox"]:checked,
129
+ .blu-chart .blu-chart__patterns input[type="checkbox"]:indeterminate,
130
+ .blu-chart .blu-chart__patterns input[type="checkbox"]:disabled,
131
+ .blu-chart .blu-chart__patterns input[type="checkbox"]:disabled:checked,
132
+ .blu-chart .blu-chart__patterns input[type="checkbox"]:disabled:indeterminate { -webkit-appearance:checkbox; appearance:auto; background:revert; border:revert; box-shadow:none; forced-color-adjust:auto; }
133
+ .blu-chart .blu-chart__patterns input[type="checkbox"]:checked::after, .blu-chart .blu-chart__patterns input[type="checkbox"]:indeterminate::after { content:none; }
134
+ }
135
+ /* END GENERATED SHARED CHECKBOX */
package/src/colors.ts ADDED
@@ -0,0 +1,277 @@
1
+ import type { ComponentColor, ChartColor } from './types.ts';
2
+
3
+ // Automatic series colors use vivid hues; renderers still enforce contrast.
4
+ export function automaticPalette(dark: boolean): string[] {
5
+ return dark
6
+ ? ['#a16aff', '#00cfff', '#ff2b91', '#ff8a00', '#36e377', '#e13dff', '#4285ff', '#ff4056']
7
+ : ['#7020ff', '#0094ff', '#ff006e', '#ff6a00', '#00b94f', '#c000ff', '#004fff', '#ff1738'];
8
+ }
9
+
10
+ // Snapshot of the main website's canonical ComponentColor catalogue.
11
+ // Resolve the shared CSS tokens at render time so appearance changes stay in sync.
12
+ export const componentColors = ["Default", "Primary", "Secondary", "Success", "Processing", "Warning", "Error", "Danger", "Magenta", "Red", "Volcano", "Orange", "Gold", "Lime", "Green", "Cyan", "Blue", "GeekBlue", "Purple"] as const satisfies readonly ComponentColor[];
13
+ const fallback = {
14
+ "Default": [
15
+ [
16
+ "#f5f5f5",
17
+ "#000000",
18
+ "#1d1d1d"
19
+ ],
20
+ [
21
+ "#272727",
22
+ "rgba(255, 255, 255, 0.95)",
23
+ "#dfdfdf"
24
+ ]
25
+ ],
26
+ "Primary": [
27
+ [
28
+ "#eef2ff",
29
+ "#4f46e5",
30
+ "#4338ca"
31
+ ],
32
+ [
33
+ "#282445",
34
+ "#8070ed",
35
+ "#b6acff"
36
+ ]
37
+ ],
38
+ "Secondary": [
39
+ [
40
+ "#e2e8f0",
41
+ "#475569",
42
+ "#334155"
43
+ ],
44
+ [
45
+ "#2b3240",
46
+ "#526077",
47
+ "#d6dce5"
48
+ ]
49
+ ],
50
+ "Success": [
51
+ [
52
+ "#f6ffed",
53
+ "#52c41a",
54
+ "#2d6c0e"
55
+ ],
56
+ [
57
+ "#162312",
58
+ "#49aa19",
59
+ "#73be4e"
60
+ ]
61
+ ],
62
+ "Processing": [
63
+ [
64
+ "#e6f4ff",
65
+ "#2681ff",
66
+ "#1054b5"
67
+ ],
68
+ [
69
+ "#111a2c",
70
+ "#145ec6",
71
+ "#78a7eb"
72
+ ]
73
+ ],
74
+ "Warning": [
75
+ [
76
+ "#fffbe6",
77
+ "#faad14",
78
+ "#7d560a"
79
+ ],
80
+ [
81
+ "#2b2111",
82
+ "#d89614",
83
+ "#dda535"
84
+ ]
85
+ ],
86
+ "Error": [
87
+ [
88
+ "#fff2f0",
89
+ "#ff4d4f",
90
+ "#a33133"
91
+ ],
92
+ [
93
+ "#2c1618",
94
+ "#dc4446",
95
+ "#ea8d8e"
96
+ ]
97
+ ],
98
+ "Danger": [
99
+ [
100
+ "#fff2f0",
101
+ "#ff4d4f",
102
+ "#a33133"
103
+ ],
104
+ [
105
+ "#2c1618",
106
+ "#dc4446",
107
+ "#ea8d8e"
108
+ ]
109
+ ],
110
+ "Magenta": [
111
+ [
112
+ "#fff0f6",
113
+ "#ed409e",
114
+ "#a9196d"
115
+ ],
116
+ [
117
+ "#291321",
118
+ "#cf3a8c",
119
+ "#e984b9"
120
+ ]
121
+ ],
122
+ "Red": [
123
+ [
124
+ "#fff1f0",
125
+ "#e4202a",
126
+ "#b4111e"
127
+ ],
128
+ [
129
+ "#2a1215",
130
+ "#cd1f28",
131
+ "#f08485"
132
+ ]
133
+ ],
134
+ "Volcano": [
135
+ [
136
+ "#fff2e8",
137
+ "#fa541c",
138
+ "#aa2d0a"
139
+ ],
140
+ [
141
+ "#2b1611",
142
+ "#d84a1b",
143
+ "#ed8e68"
144
+ ]
145
+ ],
146
+ "Orange": [
147
+ [
148
+ "#fff7e6",
149
+ "#fa8c16",
150
+ "#904905"
151
+ ],
152
+ [
153
+ "#2b1d11",
154
+ "#d87a16",
155
+ "#e89b3e"
156
+ ]
157
+ ],
158
+ "Gold": [
159
+ [
160
+ "#fffbe6",
161
+ "#faad14",
162
+ "#835404"
163
+ ],
164
+ [
165
+ "#2b2111",
166
+ "#d89614",
167
+ "#e8b339"
168
+ ]
169
+ ],
170
+ "Lime": [
171
+ [
172
+ "#fcffe6",
173
+ "#a0d911",
174
+ "#486803"
175
+ ],
176
+ [
177
+ "#1f2611",
178
+ "#8bbb11",
179
+ "#a9d134"
180
+ ]
181
+ ],
182
+ "Green": [
183
+ [
184
+ "#f6ffed",
185
+ "#52c41a",
186
+ "#276d09"
187
+ ],
188
+ [
189
+ "#162312",
190
+ "#49aa19",
191
+ "#6bbf3b"
192
+ ]
193
+ ],
194
+ "Cyan": [
195
+ [
196
+ "#e6fffb",
197
+ "#13c2c2",
198
+ "#06686c"
199
+ ],
200
+ [
201
+ "#112123",
202
+ "#13a8a8",
203
+ "#33bcb7"
204
+ ]
205
+ ],
206
+ "Blue": [
207
+ [
208
+ "#e6f4ff",
209
+ "#2681ff",
210
+ "#0851c8"
211
+ ],
212
+ [
213
+ "#111a2c",
214
+ "#145ec6",
215
+ "#6fa8ee"
216
+ ]
217
+ ],
218
+ "GeekBlue": [
219
+ [
220
+ "#f0f5ff",
221
+ "#2f54eb",
222
+ "#1d39c4"
223
+ ],
224
+ [
225
+ "#131629",
226
+ "#2b4acb",
227
+ "#89a0ea"
228
+ ]
229
+ ],
230
+ "Purple": [
231
+ [
232
+ "#f9f0ff",
233
+ "#722ed1",
234
+ "#531dab"
235
+ ],
236
+ [
237
+ "#1a1325",
238
+ "#642ab5",
239
+ "#b593df"
240
+ ]
241
+ ]
242
+ };
243
+ export const isComponentColor = (value: unknown): value is ComponentColor => typeof value === 'string' && (componentColors as readonly string[]).includes(value);
244
+ export const isChartColor = (value: unknown): value is ChartColor => isComponentColor(value) || (typeof value === 'string' && /^#(?:[\da-f]{3}|[\da-f]{4}|[\da-f]{6}|[\da-f]{8})$/i.test(value));
245
+ export function componentPalette(name: ComponentColor, dark: boolean, read: (token: string) => string = () => '') {
246
+ const shades = fallback[name][dark ? 1 : 0];
247
+ const token = name.toLowerCase();
248
+ return { soft: read(`--bluui-color-${token}-soft`).trim() || shades[0], solid: read(`--bluui-color-${token}-solid`).trim() || shades[1], text: read(`--bluui-color-${token}-text`).trim() || shades[2] };
249
+ }
250
+ export function resolveChartColor(color: ChartColor | undefined, automatic: string, dark: boolean, read?: (token: string) => string) {
251
+ return isComponentColor(color) ? componentPalette(color, dark, read).solid : color || automatic;
252
+ }
253
+
254
+ function rgbChannels(color: string): number[] {
255
+ if (color.startsWith('rgb')) return color.match(/[\d.]+/g)!.slice(0, 3).map(Number);
256
+ const raw = color.slice(1);
257
+ const hex = raw.length < 5 ? raw.slice(0, 3).split('').map(c => c + c).join('') : raw.slice(0, 6);
258
+ return [0, 2, 4].map(i => parseInt(hex.slice(i, i + 2), 16));
259
+ }
260
+
261
+ /** Match the linear RGB interpolation used by continuous ECharts color scales. */
262
+ export function interpolateColor(colors: string[], position: number): string {
263
+ const offset = Math.max(0, Math.min(1, position)) * (colors.length - 1);
264
+ const index = Math.min(Math.floor(offset), colors.length - 2), fraction = offset - index;
265
+ const start = rgbChannels(colors[index]), end = rgbChannels(colors[index + 1]);
266
+ return `rgb(${start.map((v, i) => Math.round(v + (end[i] - v) * fraction)).join(',')})`;
267
+ }
268
+
269
+ /** Pick dark or white text with at least 4.5:1 contrast against an opaque mark. */
270
+ export function contrastText(color: string): string {
271
+ const linear = rgbChannels(color).map(c => { const n = c / 255; return n <= .04045 ? n / 12.92 : ((n + .055) / 1.055) ** 2.4; });
272
+ const luminance = linear[0] * .2126 + linear[1] * .7152 + linear[2] * .0722;
273
+ // Prefer our ink tone when it passes; use black in the narrow mid-tone range.
274
+ if ((luminance + .05) / .0656 >= 4.5) return '#182230';
275
+ if (1.05 / (luminance + .05) >= 4.5) return '#fff';
276
+ return '#000';
277
+ }
@@ -0,0 +1,11 @@
1
+ export type * from './types.ts';
2
+ export type * from './catalogue-types.ts';
3
+ export { createLineChart } from './line.ts';
4
+ export { createBarChart } from './bar.ts';
5
+ export { createPieChart } from './pie.ts';
6
+ export { createDoughnutChart } from './doughnut.ts';
7
+ export { createScatterChart } from './scatter.ts';
8
+ export { createRadarChart } from './radar.ts';
9
+ export { createHeatmap } from './heatmap.ts';
10
+ export { createSparkline } from './sparkline.ts';
11
+ export type { BluSparklinePoint, SparklineOptions, SparklineEvents, SparklineInstance } from './sparkline.ts';
@@ -0,0 +1,12 @@
1
+ import { buildOption } from './builders/doughnut.ts';
2
+ import { use } from 'echarts/core';
3
+ import { PieChart } from 'echarts/charts';
4
+ import { createCatalogueChart } from './catalogue-runtime.ts';
5
+ import type { OptionsByKind, ChartPoint } from './catalogue-types.ts';
6
+ import type { ChartEvents } from './types.ts';
7
+ export type { OptionsByKind, ChartPoint } from './catalogue-types.ts';
8
+ export type DoughnutChartOptions = OptionsByKind['doughnut'];
9
+ export function createDoughnutChart(host: HTMLElement, options: DoughnutChartOptions, events: ChartEvents<ChartPoint> = {}) {
10
+ use([PieChart]);
11
+ return createCatalogueChart(host, 'doughnut', options, events, buildOption);
12
+ }