@flesler/cursor-canvas-web 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 (42) hide show
  1. package/dist/cursor-canvas-web.css +1 -0
  2. package/dist/cursor-canvas.cjs +1 -1
  3. package/dist/cursor-canvas.js +753 -766
  4. package/dist/pie-donut-DNbA0GeH.cjs +1 -0
  5. package/dist/pie-donut-qRBFP0tT.js +63 -0
  6. package/package.json +10 -3
  7. package/src/runtime/index.tsx +64 -0
  8. package/src/shim/__tests__/barChart.test.ts +61 -0
  9. package/src/shim/__tests__/canvas.smoke.test.tsx +209 -0
  10. package/src/shim/__tests__/category-theme.test.tsx +58 -0
  11. package/src/shim/__tests__/dag.test.ts +49 -0
  12. package/src/shim/__tests__/host-tokens.test.ts +106 -0
  13. package/src/shim/__tests__/lineChart.test.ts +28 -0
  14. package/src/shim/__tests__/useCanvasState.test.tsx +35 -0
  15. package/src/shim/__tests__/useHostTheme.test.tsx +43 -0
  16. package/src/shim/__tests__/valueAxis.test.ts +39 -0
  17. package/src/shim/bar-chart.tsx +77 -0
  18. package/src/shim/canvas-hooks.tsx +57 -0
  19. package/src/shim/canvas-mantine-root.tsx +129 -0
  20. package/src/shim/chart-shared.tsx +252 -0
  21. package/src/shim/cursor-canvas.tsx +136 -0
  22. package/src/shim/dag.ts +179 -0
  23. package/src/shim/diff.tsx +161 -0
  24. package/src/shim/host-tokens.ts +614 -0
  25. package/src/shim/line-chart.tsx +62 -0
  26. package/src/shim/pie-chart.tsx +127 -0
  27. package/src/shim/pie-donut.tsx +79 -0
  28. package/src/shim/theme.ts +77 -0
  29. package/src/shim/todo.tsx +184 -0
  30. package/src/shim/ui/actions.tsx +58 -0
  31. package/src/shim/ui/card-context.tsx +11 -0
  32. package/src/shim/ui/card.tsx +79 -0
  33. package/src/shim/ui/chevron.tsx +23 -0
  34. package/src/shim/ui/display.tsx +83 -0
  35. package/src/shim/ui/form.tsx +102 -0
  36. package/src/shim/ui/layout.tsx +67 -0
  37. package/src/shim/ui/rich.tsx +136 -0
  38. package/src/shim/ui/table.tsx +71 -0
  39. package/src/shim/ui/typography.tsx +129 -0
  40. package/src/shim/use-tokens.ts +13 -0
  41. package/src/superset/chart-extra.d.ts +13 -7
  42. package/src/superset/index.d.ts +4 -4
@@ -0,0 +1,614 @@
1
+ /**
2
+ * Runtime mirror of vendored `canvas-tokens.d.ts` + `theme.d.ts` token helpers.
3
+ */
4
+ import type { CanvasHostThemeBrand, CanvasHostThemeOverrides, CanvasPalette, CanvasTokens, CategoryPalette, Color } from '../vendor/canvas-sdk/canvas-tokens.js'
5
+ import type { CanvasHostTheme } from '../vendor/canvas-sdk/hooks.js'
6
+ import type { CanvasRadius, CanvasTypography } from '../vendor/canvas-sdk/theme.js'
7
+
8
+ export type {
9
+ CanvasHostThemeBrand,
10
+ CanvasHostThemeOverrides,
11
+ CanvasPalette,
12
+ CanvasTokens,
13
+ CategoryPalette,
14
+ Color,
15
+ } from '../vendor/canvas-sdk/canvas-tokens.js'
16
+
17
+ export const canvasPaletteDark: CanvasPalette = {
18
+ foreground: '#E4E4E4EB',
19
+ foregroundSecondary: '#E4E4E48D',
20
+ foregroundTertiary: '#E4E4E45E',
21
+ foregroundQuaternary: '#E4E4E442',
22
+ editor: '#181818',
23
+ chrome: '#141414',
24
+ sidebar: '#141414',
25
+ elevated: '#181818',
26
+ fillPrimary: '#E4E4E430',
27
+ fillSecondary: '#E4E4E41E',
28
+ fillTertiary: '#E4E4E411',
29
+ fillQuaternary: '#E4E4E40A',
30
+ strokePrimary: '#E4E4E433',
31
+ strokeSecondary: '#E4E4E41F',
32
+ strokeTertiary: '#E4E4E414',
33
+ strokeFocused: '#599CE7',
34
+ accent: '#599CE7',
35
+ buttonBackground: '#599CE7',
36
+ buttonForeground: '#191c22',
37
+ buttonHoverBackground: '#6AABE9',
38
+ link: '#87c3ff',
39
+ diffInsertedLine: '#3FA26633',
40
+ diffRemovedLine: '#B8004933',
41
+ diffStripAdded: '#3FA2668F',
42
+ diffStripRemoved: '#FC6B838F',
43
+ }
44
+
45
+ export const canvasPaletteLight: CanvasPalette = {
46
+ foreground: '#141414F0',
47
+ foregroundSecondary: '#141414BD',
48
+ foregroundTertiary: '#1414148A',
49
+ foregroundQuaternary: '#1414145C',
50
+ editor: '#FCFCFC',
51
+ chrome: '#F8F8F8',
52
+ sidebar: '#F3F3F3',
53
+ elevated: '#FCFCFC',
54
+ fillPrimary: '#14141433',
55
+ fillSecondary: '#14141424',
56
+ fillTertiary: '#14141414',
57
+ fillQuaternary: '#1414140F',
58
+ strokePrimary: '#14141433',
59
+ strokeSecondary: '#1414141F',
60
+ strokeTertiary: '#14141414',
61
+ strokeFocused: '#3685BF',
62
+ accent: '#3685BF',
63
+ buttonBackground: '#3685BF',
64
+ buttonForeground: '#FCFCFC',
65
+ buttonHoverBackground: '#2E76AB',
66
+ link: '#3685BF',
67
+ diffInsertedLine: '#1F8A651F',
68
+ diffRemovedLine: '#CF2D5614',
69
+ diffStripAdded: '#1F8A65CC',
70
+ diffStripRemoved: '#CF2D56CC',
71
+ }
72
+
73
+ const grokAccentDark = {
74
+ accent: '#1084FE',
75
+ buttonBackground: '#1084FE',
76
+ buttonForeground: '#070707',
77
+ buttonHoverBackground: '#459FFE',
78
+ link: '#80BEFE',
79
+ strokeFocused: '#1084FE',
80
+ } as const
81
+
82
+ const grokAccentLight = {
83
+ accent: '#0C64C1',
84
+ buttonBackground: '#0C64C1',
85
+ buttonForeground: '#FAFAFA',
86
+ buttonHoverBackground: '#1084FE',
87
+ link: '#0C64C1',
88
+ strokeFocused: '#0C64C1',
89
+ } as const
90
+
91
+ export const canvasPaletteGrokDark: CanvasPalette = {
92
+ ...canvasPaletteDark,
93
+ ...grokAccentDark,
94
+ }
95
+
96
+ export const canvasPaletteGrokLight: CanvasPalette = {
97
+ ...canvasPaletteLight,
98
+ ...grokAccentLight,
99
+ }
100
+
101
+ /** Chromatic category hues only; `gray` is taken from the active canvas palette. */
102
+ type CategoryChromatic = Readonly<Record<Exclude<Color, 'gray'>, string>>
103
+
104
+ const cursorCategoryChromaticDark: CategoryChromatic = {
105
+ purple: '#7B64B8F0',
106
+ green: '#1F8A65E8',
107
+ yellow: '#E8C030E0',
108
+ cyan: '#2A9A8AE0',
109
+ pink: '#C85898E0',
110
+ blue: '#2E79B5E0',
111
+ orange: '#F0A040E0',
112
+ red: '#C04848E0',
113
+ }
114
+
115
+ const cursorCategoryChromaticLight: CategoryChromatic = {
116
+ ...cursorCategoryChromaticDark,
117
+ orange: '#F0A088E0',
118
+ red: '#CF2D56E0',
119
+ }
120
+
121
+ const grokCategoryChromatic: CategoryChromatic = {
122
+ purple: '#9159FEF0',
123
+ green: '#00C972E8',
124
+ yellow: '#FF9800E0',
125
+ cyan: '#00BCA6E0',
126
+ pink: '#FF309BE0',
127
+ blue: '#1084FEE0',
128
+ orange: '#FF6700E0',
129
+ red: '#FF263CE0',
130
+ }
131
+
132
+ function categoryPaletteFor(
133
+ chromatic: CategoryChromatic,
134
+ palette: CanvasPalette,
135
+ ): CategoryPalette {
136
+ return {
137
+ gray: palette.foregroundTertiary,
138
+ ...chromatic,
139
+ }
140
+ }
141
+
142
+ export const categoryPaletteDark = categoryPaletteFor(
143
+ cursorCategoryChromaticDark,
144
+ canvasPaletteDark,
145
+ )
146
+ export const categoryPaletteLight = categoryPaletteFor(
147
+ cursorCategoryChromaticLight,
148
+ canvasPaletteLight,
149
+ )
150
+ export const categoryPaletteGrokDark = categoryPaletteFor(
151
+ grokCategoryChromatic,
152
+ canvasPaletteGrokDark,
153
+ )
154
+ export const categoryPaletteGrokLight = categoryPaletteFor(
155
+ grokCategoryChromatic,
156
+ canvasPaletteGrokLight,
157
+ )
158
+
159
+ export const colorPalette = categoryPaletteDark
160
+
161
+ export const usageColorSequence: readonly Color[] = [
162
+ 'blue',
163
+ 'purple',
164
+ 'green',
165
+ 'yellow',
166
+ 'cyan',
167
+ 'pink',
168
+ 'orange',
169
+ 'red',
170
+ 'gray',
171
+ ]
172
+
173
+ export const chartPalette = {
174
+ green: '#1F8A65E8',
175
+ darkGreen: '#0D855AE0',
176
+ lightGreen: '#52B896E0',
177
+ mintGreen: '#7DCAB0E0',
178
+ blue: '#2E79B5E0',
179
+ lightBlue: '#70B0D8E0',
180
+ indigo: '#5A6CC0F0',
181
+ lightIndigo: '#9AAADCE0',
182
+ purple: '#7B64B8F0',
183
+ lightPurple: '#AA98D8E0',
184
+ warmPink: '#C85898E0',
185
+ lightPink: '#E8A0C4E0',
186
+ brightOrange: '#F0A040E0',
187
+ deepOrange: '#C06028E0',
188
+ goldenYellow: '#E8C030E0',
189
+ darkAmber: '#C04848E0',
190
+ warmPeach: '#F0A088E0',
191
+ vibrantTeal: '#2A9A8AE0',
192
+ muted: '#8888A8E0',
193
+ neutralLine: '#888899D0',
194
+ } as const
195
+
196
+ export type ChartPalette = typeof chartPalette
197
+
198
+ export const chartPaletteGrok = {
199
+ green: '#00C972E8',
200
+ darkGreen: '#009957E0',
201
+ lightGreen: '#38D591E0',
202
+ mintGreen: '#78E2B4E0',
203
+ blue: '#1084FEE0',
204
+ lightBlue: '#459FFEE0',
205
+ indigo: '#0C64C1F0',
206
+ lightIndigo: '#80BEFEE0',
207
+ purple: '#9159FEF0',
208
+ lightPurple: '#A97EFEE0',
209
+ warmPink: '#FF309BE0',
210
+ lightPink: '#FF5EB1E0',
211
+ brightOrange: '#FF6700E0',
212
+ deepOrange: '#C24E00E0',
213
+ goldenYellow: '#FF9800E0',
214
+ darkAmber: '#FF263CE0',
215
+ warmPeach: '#FF8838E0',
216
+ vibrantTeal: '#00BCA6E0',
217
+ muted: '#777777E0',
218
+ neutralLine: '#777777D0',
219
+ } as const
220
+
221
+ export const chartColorSequence: readonly string[] = [
222
+ chartPalette.green,
223
+ chartPalette.lightBlue,
224
+ chartPalette.indigo,
225
+ chartPalette.brightOrange,
226
+ chartPalette.deepOrange,
227
+ chartPalette.goldenYellow,
228
+ chartPalette.warmPink,
229
+ chartPalette.warmPeach,
230
+ chartPalette.purple,
231
+ chartPalette.mintGreen,
232
+ chartPalette.muted,
233
+ chartPalette.vibrantTeal,
234
+ ]
235
+
236
+ export const chartColorSequenceGrok: readonly string[] = [
237
+ chartPaletteGrok.green,
238
+ chartPaletteGrok.lightBlue,
239
+ chartPaletteGrok.indigo,
240
+ chartPaletteGrok.brightOrange,
241
+ chartPaletteGrok.deepOrange,
242
+ chartPaletteGrok.goldenYellow,
243
+ chartPaletteGrok.warmPink,
244
+ chartPaletteGrok.warmPeach,
245
+ chartPaletteGrok.purple,
246
+ chartPaletteGrok.mintGreen,
247
+ chartPaletteGrok.muted,
248
+ chartPaletteGrok.vibrantTeal,
249
+ ]
250
+
251
+ export const canvasTypography = {
252
+ fontFamily: 'inherit' as const,
253
+ h1: { fontSize: '24px', lineHeight: '30px', fontWeight: 590 },
254
+ h2: { fontSize: '18px', lineHeight: '24px', fontWeight: 590 },
255
+ h3: { fontSize: '16px', lineHeight: '22px', fontWeight: 590 },
256
+ body: { fontSize: '14px', lineHeight: '20px', fontWeight: 400 },
257
+ small: { fontSize: '12px', lineHeight: '16px', fontWeight: 400 },
258
+ }
259
+
260
+ export const canvasFontFamilyCursor = 'inherit' as const
261
+
262
+ export const canvasFontFamilyGrok =
263
+ 'ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif'
264
+
265
+ export const canvasSpacing = {
266
+ '0.5': 2,
267
+ '1': 4,
268
+ '1.5': 6,
269
+ '2': 8,
270
+ '2.5': 10,
271
+ '3': 12,
272
+ '3.5': 14,
273
+ '4': 16,
274
+ '4.5': 18,
275
+ '5': 20,
276
+ '6': 24,
277
+ '7': 28,
278
+ '8': 32,
279
+ '9': 36,
280
+ '10': 40,
281
+ } as const
282
+
283
+ export const canvasRadius = {
284
+ none: 0,
285
+ xs: 2,
286
+ sm: 4,
287
+ md: 6,
288
+ lg: 8,
289
+ xl: 12,
290
+ full: 9999,
291
+ } as const
292
+
293
+ export const canvasRadiusGrok: CanvasRadius = {
294
+ ...canvasRadius,
295
+ md: 8,
296
+ lg: 10,
297
+ xl: 14,
298
+ }
299
+
300
+ export const canvasTypographyGrok: CanvasTypography = {
301
+ ...canvasTypography,
302
+ fontFamily: canvasFontFamilyGrok,
303
+ }
304
+
305
+ function tokensFromPalette(
306
+ palette: CanvasPalette,
307
+ category: CategoryPalette,
308
+ ): CanvasTokens {
309
+ return {
310
+ bg: {
311
+ editor: palette.editor,
312
+ chrome: palette.chrome,
313
+ elevated: palette.elevated,
314
+ },
315
+ text: {
316
+ primary: palette.foreground,
317
+ secondary: palette.foregroundSecondary,
318
+ tertiary: palette.foregroundTertiary,
319
+ quaternary: palette.foregroundQuaternary,
320
+ link: palette.link,
321
+ onAccent: palette.buttonForeground,
322
+ },
323
+ stroke: {
324
+ primary: palette.strokePrimary,
325
+ secondary: palette.strokeSecondary,
326
+ tertiary: palette.strokeTertiary,
327
+ focused: palette.strokeFocused,
328
+ },
329
+ fill: {
330
+ primary: palette.fillPrimary,
331
+ secondary: palette.fillSecondary,
332
+ tertiary: palette.fillTertiary,
333
+ quaternary: palette.fillQuaternary,
334
+ },
335
+ accent: {
336
+ primary: palette.accent,
337
+ control: palette.buttonBackground,
338
+ controlHover: palette.buttonHoverBackground,
339
+ },
340
+ diff: {
341
+ insertedLine: palette.diffInsertedLine,
342
+ removedLine: palette.diffRemovedLine,
343
+ stripAdded: palette.diffStripAdded,
344
+ stripRemoved: palette.diffStripRemoved,
345
+ },
346
+ category,
347
+ }
348
+ }
349
+
350
+ export const canvasTokens = tokensFromPalette(
351
+ canvasPaletteDark,
352
+ categoryPaletteDark,
353
+ )
354
+ export const canvasTokensLight = tokensFromPalette(
355
+ canvasPaletteLight,
356
+ categoryPaletteLight,
357
+ )
358
+
359
+ export function parseHexColor(value: string): { r: number; g: number; b: number } | undefined {
360
+ const trimmed = value.trim()
361
+ const match = /^#([0-9a-f]{3,8})$/i.exec(trimmed)
362
+ if (!match) {
363
+ return undefined
364
+ }
365
+ const hex = match[1]
366
+ if (hex.length === 3 || hex.length === 4) {
367
+ const expand = (c: string) => c + c
368
+ const r = parseInt(expand(hex[0]), 16)
369
+ const g = parseInt(expand(hex[1]), 16)
370
+ const b = parseInt(expand(hex[2]), 16)
371
+ return { r, g, b }
372
+ }
373
+ if (hex.length === 6 || hex.length === 8) {
374
+ const r = parseInt(hex.slice(0, 2), 16)
375
+ const g = parseInt(hex.slice(2, 4), 16)
376
+ const b = parseInt(hex.slice(4, 6), 16)
377
+ return { r, g, b }
378
+ }
379
+ return undefined
380
+ }
381
+
382
+ function relativeLuminance(rgb: { r: number; g: number; b: number }): number {
383
+ const channel = (c: number) => {
384
+ const s = c / 255
385
+ return s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4
386
+ }
387
+ return (
388
+ 0.2126 * channel(rgb.r) +
389
+ 0.7152 * channel(rgb.g) +
390
+ 0.0722 * channel(rgb.b)
391
+ )
392
+ }
393
+
394
+ function mixRgb(
395
+ a: { r: number; g: number; b: number },
396
+ b: { r: number; g: number; b: number },
397
+ weightB: number,
398
+ ): { r: number; g: number; b: number } {
399
+ const w = Math.min(1, Math.max(0, weightB))
400
+ return {
401
+ r: Math.round(a.r * (1 - w) + b.r * w),
402
+ g: Math.round(a.g * (1 - w) + b.g * w),
403
+ b: Math.round(a.b * (1 - w) + b.b * w),
404
+ }
405
+ }
406
+
407
+ function rgbToHex(rgb: { r: number; g: number; b: number }): string {
408
+ const part = (n: number) => n.toString(16).padStart(2, '0')
409
+ return `#${part(rgb.r)}${part(rgb.g)}${part(rgb.b)}`
410
+ }
411
+
412
+ export function parseCanvasHostThemeBrand(
413
+ value: unknown,
414
+ ): CanvasHostThemeBrand {
415
+ return value === 'grok' ? 'grok' : 'cursor'
416
+ }
417
+
418
+ export function applyWorkbenchSurfaces(
419
+ palette: CanvasPalette,
420
+ surfaces: Pick<
421
+ CanvasHostThemeOverrides,
422
+ 'editorBackground' | 'editorForeground'
423
+ >,
424
+ ): CanvasPalette {
425
+ let next = palette
426
+ if (
427
+ typeof surfaces.editorBackground === 'string' &&
428
+ parseHexColor(surfaces.editorBackground)
429
+ ) {
430
+ const bg = surfaces.editorBackground
431
+ next = {
432
+ ...next,
433
+ editor: bg,
434
+ chrome: bg,
435
+ sidebar: bg,
436
+ elevated: bg,
437
+ }
438
+ }
439
+ if (
440
+ typeof surfaces.editorForeground === 'string' &&
441
+ parseHexColor(surfaces.editorForeground)
442
+ ) {
443
+ const fg = surfaces.editorForeground
444
+ next = {
445
+ ...next,
446
+ foreground: fg,
447
+ foregroundSecondary: fg,
448
+ foregroundTertiary: fg,
449
+ foregroundQuaternary: fg,
450
+ }
451
+ }
452
+ return next
453
+ }
454
+
455
+ export function applyPrimaryColor(
456
+ palette: CanvasPalette,
457
+ primary: string,
458
+ ): CanvasPalette {
459
+ const rgb = parseHexColor(primary)
460
+ if (!rgb) {
461
+ return palette
462
+ }
463
+ const hover = mixRgb(rgb, { r: 255, g: 255, b: 255 }, 0.12)
464
+ const onAccent =
465
+ relativeLuminance(rgb) > 0.45 ? '#141414' : '#FAFAFA'
466
+ return {
467
+ ...palette,
468
+ accent: primary,
469
+ buttonBackground: primary,
470
+ buttonHoverBackground: rgbToHex(hover),
471
+ link: primary,
472
+ strokeFocused: primary,
473
+ buttonForeground: onAccent,
474
+ }
475
+ }
476
+
477
+ const LIGHT_KINDS = new Set(['light', 'hc-light'])
478
+
479
+ function isLightKind(kind: string): boolean {
480
+ return LIGHT_KINDS.has(kind)
481
+ }
482
+
483
+ export function buildHostTokens(
484
+ kind: string,
485
+ overrides?: CanvasHostThemeOverrides,
486
+ ): {
487
+ tokens: CanvasTokens;
488
+ palette: CanvasPalette;
489
+ brand: CanvasHostThemeBrand
490
+ } {
491
+ const brand = parseCanvasHostThemeBrand(overrides?.brand)
492
+ const light = isLightKind(kind)
493
+ let palette: CanvasPalette
494
+ if (brand === 'grok') {
495
+ palette = light ? canvasPaletteGrokLight : canvasPaletteGrokDark
496
+ } else {
497
+ palette = light ? canvasPaletteLight : canvasPaletteDark
498
+ }
499
+ palette = applyWorkbenchSurfaces(palette, overrides ?? {})
500
+ if (brand !== 'grok' && typeof overrides?.primary === 'string') {
501
+ palette = applyPrimaryColor(palette, overrides.primary)
502
+ }
503
+ const chromatic =
504
+ brand === 'grok'
505
+ ? grokCategoryChromatic
506
+ : light
507
+ ? cursorCategoryChromaticLight
508
+ : cursorCategoryChromaticDark
509
+ const category = categoryPaletteFor(chromatic, palette)
510
+ const tokens = tokensFromPalette(palette, category)
511
+ return { tokens, palette, brand }
512
+ }
513
+
514
+ export function chartThemeForBrand(brand: CanvasHostThemeBrand): {
515
+ palette: ChartPalette;
516
+ sequence: readonly string[]
517
+ } {
518
+ if (brand === 'grok') {
519
+ return {
520
+ palette: chartPaletteGrok as unknown as ChartPalette,
521
+ sequence: chartColorSequenceGrok,
522
+ }
523
+ }
524
+ return { palette: chartPalette, sequence: chartColorSequence }
525
+ }
526
+
527
+ export function canvasRadiusForBrand(
528
+ brand: CanvasHostThemeBrand,
529
+ ): CanvasRadius {
530
+ return brand === 'grok' ? canvasRadiusGrok : canvasRadius
531
+ }
532
+
533
+ export function canvasTypographyForBrand(
534
+ brand: CanvasHostThemeBrand,
535
+ ): CanvasTypography {
536
+ return brand === 'grok' ? canvasTypographyGrok : canvasTypography
537
+ }
538
+
539
+ export type ShimHostTheme = CanvasHostTheme & {
540
+ readonly category: CategoryPalette;
541
+ readonly spacing: typeof canvasSpacing
542
+ }
543
+
544
+ type RawHostThemeState = {
545
+ readonly kind?: unknown;
546
+ readonly brand?: unknown;
547
+ readonly primary?: unknown;
548
+ readonly editorBackground?: unknown;
549
+ readonly editorForeground?: unknown
550
+ }
551
+
552
+ function readHostThemeRaw(): RawHostThemeState | undefined {
553
+ if (typeof window === 'undefined') {
554
+ return undefined
555
+ }
556
+ const bridge = (window as Window & { __cursorCanvas?: { state?: { theme?: RawHostThemeState } } })
557
+ .__cursorCanvas
558
+ return bridge?.state?.theme
559
+ }
560
+
561
+ export function resolveTheme(
562
+ raw: RawHostThemeState | undefined,
563
+ fallbackKind?: 'light' | 'dark',
564
+ ): ShimHostTheme {
565
+ let kind =
566
+ typeof raw?.kind === 'string' && raw.kind.length > 0
567
+ ? raw.kind
568
+ : undefined
569
+ if (!kind) {
570
+ if (fallbackKind) {
571
+ kind = fallbackKind
572
+ } else if (typeof window !== 'undefined' && window.matchMedia) {
573
+ kind = window.matchMedia('(prefers-color-scheme: dark)').matches
574
+ ? 'dark'
575
+ : 'light'
576
+ } else {
577
+ kind = 'dark'
578
+ }
579
+ }
580
+ const overrides: CanvasHostThemeOverrides = {
581
+ brand: parseCanvasHostThemeBrand(raw?.brand),
582
+ primary:
583
+ typeof raw?.primary === 'string' ? raw.primary : undefined,
584
+ editorBackground:
585
+ typeof raw?.editorBackground === 'string'
586
+ ? raw.editorBackground
587
+ : undefined,
588
+ editorForeground:
589
+ typeof raw?.editorForeground === 'string'
590
+ ? raw.editorForeground
591
+ : undefined,
592
+ }
593
+ const { tokens, palette, brand } = buildHostTokens(kind, overrides)
594
+ const chart = chartThemeForBrand(brand)
595
+ return {
596
+ ...tokens,
597
+ kind,
598
+ brand,
599
+ tokens,
600
+ palette,
601
+ category: tokens.category,
602
+ radius: canvasRadiusForBrand(brand),
603
+ typography: canvasTypographyForBrand(brand),
604
+ chart,
605
+ spacing: canvasSpacing,
606
+ }
607
+ }
608
+
609
+ export function resolveThemeForColorScheme(
610
+ scheme: 'light' | 'dark',
611
+ ): ShimHostTheme {
612
+ const host = readHostThemeRaw()
613
+ return resolveTheme(host, scheme)
614
+ }
@@ -0,0 +1,62 @@
1
+ import type { LineChartCurveType } from '@mantine/charts'
2
+ import { AreaChart, LineChart as MantineLineChart } from '@mantine/charts'
3
+ import '@mantine/charts/styles.css'
4
+ import type { LineChartProps } from '../superset/index'
5
+ import { CHART_LEGEND_PROPS, CHART_LEGEND_STYLES, reshapeLineChartData, toMantineSeries, useChartColorProps, useSeriesColor, valueAxisChartProps, valueFormatter } from './chart-shared'
6
+
7
+ export function LineChart({
8
+ categories,
9
+ series,
10
+ height = 240,
11
+ fill,
12
+ valueSuffix,
13
+ valuePrefix,
14
+ showValues,
15
+ showHoverGuide = true,
16
+ beginAtZero,
17
+ yMin,
18
+ yMax,
19
+ referenceLines,
20
+ style,
21
+ extra,
22
+ smooth: legacySmooth,
23
+ }: LineChartProps) {
24
+ const smooth = extra?.smooth ?? legacySmooth
25
+ const seriesColor = useSeriesColor()
26
+ const chartColors = useChartColorProps()
27
+ const data = reshapeLineChartData(categories, series)
28
+ const mantineSeries = toMantineSeries(series, seriesColor)
29
+ const stacked = Boolean(fill && extra?.stacked)
30
+ const axis = valueAxisChartProps({
31
+ beginAtZero,
32
+ yMin,
33
+ yMax,
34
+ referenceLines,
35
+ horizontal: false,
36
+ stacked,
37
+ valueAxis: extra?.valueAxis,
38
+ })
39
+ const common = {
40
+ h: height,
41
+ data,
42
+ dataKey: 'category',
43
+ series: mantineSeries,
44
+ curveType: (smooth ? 'monotone' : 'linear') as LineChartCurveType,
45
+ withLegend: series.length > 1,
46
+ legendProps: CHART_LEGEND_PROPS,
47
+ valueFormatter: valueFormatter(valueSuffix, valuePrefix),
48
+ withPointLabels: showValues ?? categories.length <= 20,
49
+ tooltipProps: showHoverGuide ? undefined : { cursor: false },
50
+ styles: {
51
+ ...CHART_LEGEND_STYLES,
52
+ legendItemName: { color: chartColors.textColor },
53
+ },
54
+ ...axis,
55
+ style,
56
+ }
57
+ return fill ? (
58
+ <AreaChart {...common} type={stacked ? 'stacked' : 'default'} />
59
+ ) : (
60
+ <MantineLineChart {...common} />
61
+ )
62
+ }