@carto/ps-react-ui 6.3.0 → 6.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 (113) hide show
  1. package/dist/actions-D_PVFZaM.js +1272 -0
  2. package/dist/actions-D_PVFZaM.js.map +1 -0
  3. package/dist/{category-DULnoxvk.js → category-UIGvFN3D.js} +263 -246
  4. package/dist/category-UIGvFN3D.js.map +1 -0
  5. package/dist/chat.js +472 -470
  6. package/dist/chat.js.map +1 -1
  7. package/dist/{components-CTUpdQuj.js → components-DDJU4m0t.js} +8 -8
  8. package/dist/components-DDJU4m0t.js.map +1 -0
  9. package/dist/components.js +2 -2
  10. package/dist/{download-B4sykOFm.js → download-DIj1Iz0t.js} +2 -2
  11. package/dist/{download-B4sykOFm.js.map → download-DIj1Iz0t.js.map} +1 -1
  12. package/dist/{formula-DJS-JLpk.js → formula-CSHhAoyW.js} +4 -4
  13. package/dist/{formula-DJS-JLpk.js.map → formula-CSHhAoyW.js.map} +1 -1
  14. package/dist/{item-color-B7xkIpDZ.js → item-color-7o7pFBR2.js} +26 -18
  15. package/dist/item-color-7o7pFBR2.js.map +1 -0
  16. package/dist/markdown-B8lLR-NY.js +106 -0
  17. package/dist/markdown-B8lLR-NY.js.map +1 -0
  18. package/dist/scale-Bhx8HKEB.js +29 -0
  19. package/dist/scale-Bhx8HKEB.js.map +1 -0
  20. package/dist/{spread-CQwFIwuz.js → spread-BRfPPIep.js} +3 -3
  21. package/dist/{spread-CQwFIwuz.js.map → spread-BRfPPIep.js.map} +1 -1
  22. package/dist/style-DTLuIo84.js +87 -0
  23. package/dist/style-DTLuIo84.js.map +1 -0
  24. package/dist/{styles-BCEBm7xh.js → styles-yKcpfyNV.js} +5 -5
  25. package/dist/styles-yKcpfyNV.js.map +1 -0
  26. package/dist/{table-DEdW_fDj.js → table-Col_FRvb.js} +2 -2
  27. package/dist/{table-DEdW_fDj.js.map → table-Col_FRvb.js.map} +1 -1
  28. package/dist/theme/tailwind.css +373 -0
  29. package/dist/theme.js +123 -0
  30. package/dist/theme.js.map +1 -0
  31. package/dist/types/components/lasso-tool/styles.d.ts +4 -4
  32. package/dist/types/theme/create-carto-theme.d.ts +7 -0
  33. package/dist/types/theme/deep-merge.d.ts +6 -0
  34. package/dist/types/theme/generate-tailwind-css.d.ts +8 -0
  35. package/dist/types/theme/index.d.ts +2 -0
  36. package/dist/types/widgets/actions/index.d.ts +1 -1
  37. package/dist/types/widgets/actions/relative-data/index.d.ts +1 -0
  38. package/dist/types/widgets/actions/relative-data/labels.d.ts +3 -0
  39. package/dist/types/widgets/actions/relative-data/relative-data.d.ts +16 -2
  40. package/dist/types/widgets/actions/relative-data/scale.d.ts +26 -0
  41. package/dist/types/widgets/actions/relative-data/style.d.ts +12 -0
  42. package/dist/types/widgets/category/category.d.ts +2 -1
  43. package/dist/types/widgets/index.d.ts +1 -1
  44. package/dist/types/widgets/markdown/style.d.ts +74 -0
  45. package/dist/types/widgets/utils/spacing-px.d.ts +13 -0
  46. package/dist/{utils-C-eWwOhE.js → utils-Dw4y8tiq.js} +2 -2
  47. package/dist/{utils-C-eWwOhE.js.map → utils-Dw4y8tiq.js.map} +1 -1
  48. package/dist/widgets/actions.js +3 -3
  49. package/dist/widgets/bar.js +85 -84
  50. package/dist/widgets/bar.js.map +1 -1
  51. package/dist/widgets/category.js +1 -1
  52. package/dist/widgets/formula.js +1 -1
  53. package/dist/widgets/histogram.js +109 -108
  54. package/dist/widgets/histogram.js.map +1 -1
  55. package/dist/widgets/markdown.js +1 -1
  56. package/dist/widgets/pie.js +78 -78
  57. package/dist/widgets/pie.js.map +1 -1
  58. package/dist/widgets/scatterplot.js +121 -120
  59. package/dist/widgets/scatterplot.js.map +1 -1
  60. package/dist/widgets/spread.js +1 -1
  61. package/dist/widgets/table.js +1 -1
  62. package/dist/widgets/timeseries.js +91 -90
  63. package/dist/widgets/timeseries.js.map +1 -1
  64. package/dist/widgets/utils.js +1 -1
  65. package/dist/widgets.js +283 -279
  66. package/dist/widgets.js.map +1 -1
  67. package/dist/{zoom-toggle-MmLjMTEw.js → zoom-toggle-DqrV_0Ji.js} +2 -2
  68. package/dist/{zoom-toggle-MmLjMTEw.js.map → zoom-toggle-DqrV_0Ji.js.map} +1 -1
  69. package/package.json +8 -1
  70. package/src/chat/bubbles/styles.ts +2 -0
  71. package/src/components/lasso-tool/lasso-tool-inline.test.tsx +4 -4
  72. package/src/components/lasso-tool/lasso-tool-inline.tsx +6 -6
  73. package/src/components/lasso-tool/styles.ts +4 -4
  74. package/src/theme/create-carto-theme.test.ts +53 -0
  75. package/src/theme/create-carto-theme.ts +21 -0
  76. package/src/theme/deep-merge.test.ts +25 -0
  77. package/src/theme/deep-merge.ts +22 -0
  78. package/src/theme/generate-tailwind-css.test.ts +87 -0
  79. package/src/theme/generate-tailwind-css.ts +178 -0
  80. package/src/theme/index.ts +2 -0
  81. package/src/theme/tailwind-compile.test.ts +71 -0
  82. package/src/theme/tailwind.css +373 -0
  83. package/src/widgets/actions/index.ts +1 -0
  84. package/src/widgets/actions/relative-data/index.ts +1 -0
  85. package/src/widgets/actions/relative-data/labels.ts +6 -0
  86. package/src/widgets/actions/relative-data/relative-data.test.tsx +78 -1
  87. package/src/widgets/actions/relative-data/relative-data.tsx +137 -20
  88. package/src/widgets/actions/relative-data/scale.ts +48 -0
  89. package/src/widgets/actions/relative-data/style.ts +10 -0
  90. package/src/widgets/bar/options.test.ts +16 -0
  91. package/src/widgets/bar/options.ts +13 -8
  92. package/src/widgets/category/category.relative-data.test.tsx +51 -63
  93. package/src/widgets/category/category.tsx +25 -11
  94. package/src/widgets/histogram/options.ts +13 -8
  95. package/src/widgets/index.ts +1 -0
  96. package/src/widgets/markdown/style.ts +40 -0
  97. package/src/widgets/note/widget-note.tsx +4 -1
  98. package/src/widgets/pie/options.ts +5 -4
  99. package/src/widgets/scatterplot/options.test.ts +12 -0
  100. package/src/widgets/scatterplot/options.ts +25 -10
  101. package/src/widgets/timeseries/options.ts +13 -8
  102. package/src/widgets/utils/css-variables-theme.test.ts +32 -0
  103. package/src/widgets/utils/option-builders.ts +4 -6
  104. package/src/widgets/utils/spacing-px.test.ts +42 -0
  105. package/src/widgets/utils/spacing-px.ts +24 -0
  106. package/dist/actions-CkxKe8-J.js +0 -1160
  107. package/dist/actions-CkxKe8-J.js.map +0 -1
  108. package/dist/category-DULnoxvk.js.map +0 -1
  109. package/dist/components-CTUpdQuj.js.map +0 -1
  110. package/dist/item-color-B7xkIpDZ.js.map +0 -1
  111. package/dist/markdown-DmvLi3vx.js +0 -159
  112. package/dist/markdown-DmvLi3vx.js.map +0 -1
  113. package/dist/styles-BCEBm7xh.js.map +0 -1
@@ -0,0 +1,71 @@
1
+ import { readFile } from 'node:fs/promises'
2
+ import { createRequire } from 'node:module'
3
+ import path from 'node:path'
4
+ import { fileURLToPath } from 'node:url'
5
+ import { compile } from 'tailwindcss'
6
+ import { beforeAll, describe, expect, it } from 'vitest'
7
+
8
+ const require = createRequire(import.meta.url)
9
+ const tailwindDir = path.dirname(require.resolve('tailwindcss/package.json'))
10
+ const themeDir = path.dirname(fileURLToPath(import.meta.url))
11
+
12
+ // Same order the docs tell consumers to use.
13
+ const ENTRY = `@layer theme, base, mui, components, utilities;
14
+ @import 'tailwindcss';
15
+ @import './tailwind.css';`
16
+
17
+ let build: (candidates: string[]) => string
18
+
19
+ beforeAll(async () => {
20
+ const compiler = await compile(ENTRY, {
21
+ base: themeDir,
22
+ loadStylesheet: async (id, base) => {
23
+ const file =
24
+ id === 'tailwindcss'
25
+ ? path.join(tailwindDir, 'index.css')
26
+ : path.resolve(base, id)
27
+ return {
28
+ path: file,
29
+ base: path.dirname(file),
30
+ content: await readFile(file, 'utf8'),
31
+ }
32
+ },
33
+ })
34
+ build = (candidates) => compiler.build(candidates)
35
+ })
36
+
37
+ describe('tailwind.css under Tailwind v4', () => {
38
+ it('compiles colour, shadow and radius utilities to MUI variables', () => {
39
+ const out = build([
40
+ 'bg-primary',
41
+ 'text-brand-navy-blue',
42
+ 'shadow-2',
43
+ 'rounded-theme',
44
+ ])
45
+ expect(out).toContain('background-color: var(--mui-palette-primary-main)')
46
+ expect(out).toContain('color: var(--mui-palette-brand-navyBlue)')
47
+ expect(out).toContain('--tw-shadow: var(--mui-shadows-2)')
48
+ expect(out).toContain('border-radius: var(--mui-shape-borderRadius)')
49
+ })
50
+
51
+ it('uses CARTO breakpoints over Tailwind defaults and drops 2xl', () => {
52
+ const out = build(['sm:bg-primary', 'md:bg-primary', '2xl:bg-primary'])
53
+ expect(out).toContain('@media (width >= 600px)')
54
+ expect(out).toContain('@media (width >= 960px)')
55
+ expect(out).not.toContain('40rem')
56
+ expect(out).not.toContain('2xl\\:bg-primary')
57
+ })
58
+
59
+ it('compiles responsive typography utilities', () => {
60
+ const out = build(['typography-h1'])
61
+ expect(out).toContain('font-size: 3.5rem')
62
+ expect(out).toContain('font-size: 6rem')
63
+ expect(out).toContain('letter-spacing: -1.5px')
64
+ })
65
+
66
+ it('derives the spacing unit from the theme', () => {
67
+ const out = build(['p-4'])
68
+ expect(out).toContain('padding: calc(var(--spacing) * 4)')
69
+ expect(out).toContain('--spacing: calc(var(--mui-spacing) / 2)')
70
+ })
71
+ })
@@ -0,0 +1,373 @@
1
+ /*
2
+ * Generated by generateTailwindCss() from @carto/ps-react-ui/theme.
3
+ * Do not edit by hand: regenerate it whenever the theme changes.
4
+ *
5
+ * Import after `tailwindcss`. Declare the cascade layer order yourself first:
6
+ * theme, base, mui, components, utilities (in that order).
7
+ */
8
+
9
+ @theme inline {
10
+ --color-primary: var(--mui-palette-primary-main);
11
+ --color-primary-light: var(--mui-palette-primary-light);
12
+ --color-primary-dark: var(--mui-palette-primary-dark);
13
+ --color-primary-contrast: var(--mui-palette-primary-contrastText);
14
+ --color-primary-related-light: var(--mui-palette-primary-relatedLight);
15
+ --color-primary-related-dark: var(--mui-palette-primary-relatedDark);
16
+ --color-primary-background: var(--mui-palette-primary-background);
17
+ --color-secondary: var(--mui-palette-secondary-main);
18
+ --color-secondary-light: var(--mui-palette-secondary-light);
19
+ --color-secondary-dark: var(--mui-palette-secondary-dark);
20
+ --color-secondary-contrast: var(--mui-palette-secondary-contrastText);
21
+ --color-secondary-related-light: var(--mui-palette-secondary-relatedLight);
22
+ --color-secondary-related-dark: var(--mui-palette-secondary-relatedDark);
23
+ --color-secondary-background: var(--mui-palette-secondary-background);
24
+ --color-tertiary: var(--mui-palette-tertiary-main);
25
+ --color-tertiary-light: var(--mui-palette-tertiary-light);
26
+ --color-tertiary-dark: var(--mui-palette-tertiary-dark);
27
+ --color-tertiary-contrast: var(--mui-palette-tertiary-contrastText);
28
+ --color-tertiary-related-light: var(--mui-palette-tertiary-relatedLight);
29
+ --color-tertiary-related-dark: var(--mui-palette-tertiary-relatedDark);
30
+ --color-tertiary-background: var(--mui-palette-tertiary-background);
31
+ --color-error: var(--mui-palette-error-main);
32
+ --color-error-light: var(--mui-palette-error-light);
33
+ --color-error-dark: var(--mui-palette-error-dark);
34
+ --color-error-contrast: var(--mui-palette-error-contrastText);
35
+ --color-error-related-light: var(--mui-palette-error-relatedLight);
36
+ --color-error-related-dark: var(--mui-palette-error-relatedDark);
37
+ --color-error-background: var(--mui-palette-error-background);
38
+ --color-warning: var(--mui-palette-warning-main);
39
+ --color-warning-light: var(--mui-palette-warning-light);
40
+ --color-warning-dark: var(--mui-palette-warning-dark);
41
+ --color-warning-contrast: var(--mui-palette-warning-contrastText);
42
+ --color-warning-related-light: var(--mui-palette-warning-relatedLight);
43
+ --color-warning-related-dark: var(--mui-palette-warning-relatedDark);
44
+ --color-warning-background: var(--mui-palette-warning-background);
45
+ --color-info: var(--mui-palette-info-main);
46
+ --color-info-light: var(--mui-palette-info-light);
47
+ --color-info-dark: var(--mui-palette-info-dark);
48
+ --color-info-contrast: var(--mui-palette-info-contrastText);
49
+ --color-info-related-light: var(--mui-palette-info-relatedLight);
50
+ --color-info-related-dark: var(--mui-palette-info-relatedDark);
51
+ --color-info-background: var(--mui-palette-info-background);
52
+ --color-success: var(--mui-palette-success-main);
53
+ --color-success-light: var(--mui-palette-success-light);
54
+ --color-success-dark: var(--mui-palette-success-dark);
55
+ --color-success-contrast: var(--mui-palette-success-contrastText);
56
+ --color-success-related-light: var(--mui-palette-success-relatedLight);
57
+ --color-success-related-dark: var(--mui-palette-success-relatedDark);
58
+ --color-success-background: var(--mui-palette-success-background);
59
+ --color-neutral: var(--mui-palette-neutral-main);
60
+ --color-neutral-light: var(--mui-palette-neutral-light);
61
+ --color-neutral-dark: var(--mui-palette-neutral-dark);
62
+ --color-neutral-contrast: var(--mui-palette-neutral-contrastText);
63
+ --color-neutral-related-light: var(--mui-palette-neutral-relatedLight);
64
+ --color-neutral-related-dark: var(--mui-palette-neutral-relatedDark);
65
+ --color-neutral-background: var(--mui-palette-neutral-background);
66
+ --color-default: var(--mui-palette-default-main);
67
+ --color-default-light: var(--mui-palette-default-light);
68
+ --color-default-dark: var(--mui-palette-default-dark);
69
+ --color-default-contrast: var(--mui-palette-default-contrastText);
70
+ --color-default-related-light: var(--mui-palette-default-relatedLight);
71
+ --color-default-related-dark: var(--mui-palette-default-relatedDark);
72
+ --color-default-background: var(--mui-palette-default-background);
73
+ --color-text-primary: var(--mui-palette-text-primary);
74
+ --color-text-secondary: var(--mui-palette-text-secondary);
75
+ --color-text-disabled: var(--mui-palette-text-disabled);
76
+ --color-background: var(--mui-palette-background-default);
77
+ --color-paper: var(--mui-palette-background-paper);
78
+ --color-divider: var(--mui-palette-divider);
79
+ --color-action-active: var(--mui-palette-action-active);
80
+ --color-action-hover: var(--mui-palette-action-hover);
81
+ --color-action-disabled-background: var(--mui-palette-action-disabledBackground);
82
+ --color-action-disabled: var(--mui-palette-action-disabled);
83
+ --color-action-selected: var(--mui-palette-action-selected);
84
+ --color-action-focus: var(--mui-palette-action-focus);
85
+ --color-common-white: var(--mui-palette-common-white);
86
+ --color-common-black: var(--mui-palette-common-black);
87
+ --color-grey-50: var(--mui-palette-grey-50);
88
+ --color-grey-100: var(--mui-palette-grey-100);
89
+ --color-grey-200: var(--mui-palette-grey-200);
90
+ --color-grey-300: var(--mui-palette-grey-300);
91
+ --color-grey-400: var(--mui-palette-grey-400);
92
+ --color-grey-500: var(--mui-palette-grey-500);
93
+ --color-grey-600: var(--mui-palette-grey-600);
94
+ --color-grey-700: var(--mui-palette-grey-700);
95
+ --color-grey-800: var(--mui-palette-grey-800);
96
+ --color-grey-900: var(--mui-palette-grey-900);
97
+ --color-grey-A100: var(--mui-palette-grey-A100);
98
+ --color-grey-A200: var(--mui-palette-grey-A200);
99
+ --color-grey-A400: var(--mui-palette-grey-A400);
100
+ --color-grey-A700: var(--mui-palette-grey-A700);
101
+ --color-brand-navy-blue: var(--mui-palette-brand-navyBlue);
102
+ --color-brand-location-red: var(--mui-palette-brand-locationRed);
103
+ --color-brand-prediction-blue: var(--mui-palette-brand-predictionBlue);
104
+ --color-brand-soft-blue: var(--mui-palette-brand-softBlue);
105
+ --color-brand-app-bar-main: var(--mui-palette-brand-appBarMain);
106
+ --color-brand-app-bar-contrast-text: var(--mui-palette-brand-appBarContrastText);
107
+ --color-white-4: var(--mui-palette-white-4);
108
+ --color-white-8: var(--mui-palette-white-8);
109
+ --color-white-12: var(--mui-palette-white-12);
110
+ --color-white-25: var(--mui-palette-white-25);
111
+ --color-white-40: var(--mui-palette-white-40);
112
+ --color-white-60: var(--mui-palette-white-60);
113
+ --color-white-90: var(--mui-palette-white-90);
114
+ --color-black-4: var(--mui-palette-black-4);
115
+ --color-black-8: var(--mui-palette-black-8);
116
+ --color-black-12: var(--mui-palette-black-12);
117
+ --color-black-25: var(--mui-palette-black-25);
118
+ --color-black-40: var(--mui-palette-black-40);
119
+ --color-black-60: var(--mui-palette-black-60);
120
+ --color-black-90: var(--mui-palette-black-90);
121
+ --color-qualitative-0: var(--mui-palette-qualitative-bold-0);
122
+ --color-qualitative-1: var(--mui-palette-qualitative-bold-1);
123
+ --color-qualitative-2: var(--mui-palette-qualitative-bold-2);
124
+ --color-qualitative-3: var(--mui-palette-qualitative-bold-3);
125
+ --color-qualitative-4: var(--mui-palette-qualitative-bold-4);
126
+ --color-qualitative-5: var(--mui-palette-qualitative-bold-5);
127
+ --color-qualitative-6: var(--mui-palette-qualitative-bold-6);
128
+ --color-qualitative-7: var(--mui-palette-qualitative-bold-7);
129
+ --color-qualitative-8: var(--mui-palette-qualitative-bold-8);
130
+ --color-qualitative-9: var(--mui-palette-qualitative-bold-9);
131
+ --color-qualitative-10: var(--mui-palette-qualitative-bold-10);
132
+ --color-qualitative-11: var(--mui-palette-qualitative-bold-11);
133
+ --shadow-1: var(--mui-shadows-1);
134
+ --shadow-2: var(--mui-shadows-2);
135
+ --shadow-3: var(--mui-shadows-3);
136
+ --shadow-4: var(--mui-shadows-4);
137
+ --shadow-5: var(--mui-shadows-5);
138
+ --shadow-6: var(--mui-shadows-6);
139
+ --shadow-7: var(--mui-shadows-7);
140
+ --shadow-8: var(--mui-shadows-8);
141
+ --shadow-9: var(--mui-shadows-9);
142
+ --shadow-10: var(--mui-shadows-10);
143
+ --shadow-11: var(--mui-shadows-11);
144
+ --shadow-12: var(--mui-shadows-12);
145
+ --shadow-13: var(--mui-shadows-13);
146
+ --shadow-14: var(--mui-shadows-14);
147
+ --shadow-15: var(--mui-shadows-15);
148
+ --shadow-16: var(--mui-shadows-16);
149
+ --shadow-17: var(--mui-shadows-17);
150
+ --shadow-18: var(--mui-shadows-18);
151
+ --shadow-19: var(--mui-shadows-19);
152
+ --shadow-20: var(--mui-shadows-20);
153
+ --shadow-21: var(--mui-shadows-21);
154
+ --shadow-22: var(--mui-shadows-22);
155
+ --shadow-23: var(--mui-shadows-23);
156
+ --shadow-24: var(--mui-shadows-24);
157
+ --radius-theme: var(--mui-shape-borderRadius);
158
+ --radius-theme-half: calc(var(--mui-shape-borderRadius) * 0.5);
159
+ --radius-theme-2: calc(var(--mui-shape-borderRadius) * 2);
160
+ --radius-theme-3: calc(var(--mui-shape-borderRadius) * 3);
161
+ --radius-theme-4: calc(var(--mui-shape-borderRadius) * 4);
162
+ --breakpoint-xs: 320px;
163
+ --breakpoint-sm: 600px;
164
+ --breakpoint-md: 960px;
165
+ --breakpoint-lg: 1280px;
166
+ --breakpoint-xl: 1600px;
167
+ --breakpoint-2xl: initial;
168
+ }
169
+
170
+ @theme {
171
+ --spacing: calc(var(--mui-spacing) / 2);
172
+ }
173
+
174
+ @utility typography-h1 {
175
+ font-family: Inter, sans-serif;
176
+ font-weight: 600;
177
+ font-size: 3.5rem;
178
+ line-height: 1.167;
179
+ letter-spacing: -1.5px;
180
+ @media (min-width:600px) {
181
+ font-size: 4.7129rem;
182
+ }
183
+ @media (min-width:960px) {
184
+ font-size: 5.3556rem;
185
+ }
186
+ @media (min-width:1280px) {
187
+ font-size: 6rem;
188
+ }
189
+ }
190
+
191
+ @utility typography-h2 {
192
+ font-family: Inter, sans-serif;
193
+ font-weight: 600;
194
+ font-size: 2.375rem;
195
+ line-height: 1.2;
196
+ letter-spacing: -0.5px;
197
+ @media (min-width:600px) {
198
+ font-size: 2.9167rem;
199
+ }
200
+ @media (min-width:960px) {
201
+ font-size: 3.3333rem;
202
+ }
203
+ @media (min-width:1280px) {
204
+ font-size: 3.75rem;
205
+ }
206
+ }
207
+
208
+ @utility typography-h3 {
209
+ font-family: Inter, sans-serif;
210
+ font-weight: 600;
211
+ font-size: 2rem;
212
+ line-height: 1.167;
213
+ letter-spacing: 0;
214
+ @media (min-width:600px) {
215
+ font-size: 2.5707rem;
216
+ }
217
+ @media (min-width:960px) {
218
+ font-size: 2.7849rem;
219
+ }
220
+ @media (min-width:1280px) {
221
+ font-size: 3rem;
222
+ }
223
+ }
224
+
225
+ @utility typography-h4 {
226
+ font-family: Inter, sans-serif;
227
+ font-weight: 600;
228
+ font-size: 1.5rem;
229
+ line-height: 1.25;
230
+ letter-spacing: 0;
231
+ @media (min-width:600px) {
232
+ font-size: 1.8rem;
233
+ }
234
+ @media (min-width:960px) {
235
+ font-size: 1.8rem;
236
+ }
237
+ @media (min-width:1280px) {
238
+ font-size: 2rem;
239
+ }
240
+ }
241
+
242
+ @utility typography-h5 {
243
+ font-family: Inter, sans-serif;
244
+ font-weight: 600;
245
+ font-size: 1.25rem;
246
+ line-height: 1.167;
247
+ letter-spacing: 0;
248
+ @media (min-width:600px) {
249
+ font-size: 1.2853rem;
250
+ }
251
+ @media (min-width:960px) {
252
+ font-size: 1.4996rem;
253
+ }
254
+ @media (min-width:1280px) {
255
+ font-size: 1.5rem;
256
+ }
257
+ }
258
+
259
+ @utility typography-h6 {
260
+ font-family: Inter, sans-serif;
261
+ font-weight: 500;
262
+ font-size: 1.0625rem;
263
+ line-height: 1.333;
264
+ letter-spacing: 0;
265
+ @media (min-width:600px) {
266
+ font-size: 1.1253rem;
267
+ }
268
+ @media (min-width:960px) {
269
+ font-size: 1.1253rem;
270
+ }
271
+ @media (min-width:1280px) {
272
+ font-size: 1.125rem;
273
+ }
274
+ }
275
+
276
+ @utility typography-subtitle1 {
277
+ font-family: Inter, sans-serif;
278
+ font-weight: 500;
279
+ font-size: 1rem;
280
+ line-height: 1.5;
281
+ letter-spacing: 0;
282
+ }
283
+
284
+ @utility typography-subtitle2 {
285
+ font-family: Inter, sans-serif;
286
+ font-weight: 600;
287
+ font-size: 0.8125rem;
288
+ line-height: 1.538;
289
+ letter-spacing: 0;
290
+ }
291
+
292
+ @utility typography-body1 {
293
+ font-family: Inter, sans-serif;
294
+ font-weight: 400;
295
+ font-size: 1rem;
296
+ line-height: 1.5;
297
+ letter-spacing: 0;
298
+ }
299
+
300
+ @utility typography-body2 {
301
+ font-family: Inter, sans-serif;
302
+ font-weight: 400;
303
+ font-size: 0.8125rem;
304
+ line-height: 1.538;
305
+ letter-spacing: 0;
306
+ }
307
+
308
+ @utility typography-button {
309
+ font-family: Inter, sans-serif;
310
+ font-weight: 500;
311
+ font-size: 0.8125rem;
312
+ line-height: 1.538;
313
+ letter-spacing: 0;
314
+ text-transform: inherit;
315
+ }
316
+
317
+ @utility typography-caption {
318
+ font-family: Inter, sans-serif;
319
+ font-weight: 400;
320
+ font-size: 0.6875rem;
321
+ line-height: 1.454;
322
+ letter-spacing: 0;
323
+ }
324
+
325
+ @utility typography-overline {
326
+ font-family: Inter, sans-serif;
327
+ font-weight: 500;
328
+ font-size: 0.625rem;
329
+ line-height: 1.2;
330
+ letter-spacing: 1.2px;
331
+ text-transform: uppercase;
332
+ }
333
+
334
+ @utility typography-caption-medium {
335
+ font-family: Inter, sans-serif;
336
+ font-weight: 500;
337
+ font-size: 0.6875rem;
338
+ line-height: 1.454;
339
+ letter-spacing: 0;
340
+ }
341
+
342
+ @utility typography-overline-delicate {
343
+ font-family: Inter, sans-serif;
344
+ font-weight: 400;
345
+ font-size: 0.625rem;
346
+ line-height: 1.2;
347
+ letter-spacing: 1.2px;
348
+ text-transform: uppercase;
349
+ }
350
+
351
+ @utility typography-code1 {
352
+ font-family: "Overpass Mono", monospace;
353
+ font-weight: 400;
354
+ font-size: 1rem;
355
+ line-height: 1.5;
356
+ letter-spacing: 0;
357
+ }
358
+
359
+ @utility typography-code2 {
360
+ font-family: "Overpass Mono", monospace;
361
+ font-weight: 400;
362
+ font-size: 0.875rem;
363
+ line-height: 1.428;
364
+ letter-spacing: 0;
365
+ }
366
+
367
+ @utility typography-code3 {
368
+ font-family: "Overpass Mono", monospace;
369
+ font-weight: 400;
370
+ font-size: 0.75rem;
371
+ line-height: 1.333;
372
+ letter-spacing: 0;
373
+ }
@@ -46,6 +46,7 @@ export {
46
46
  DEFAULT_RELATIVE_DATA_LABELS,
47
47
  type RelativeDataProps,
48
48
  type RelativeDataLabels,
49
+ type RelativeScale,
49
50
  } from './relative-data'
50
51
  export {
51
52
  Download,
@@ -1,3 +1,4 @@
1
1
  export { RelativeData, type RelativeDataProps } from './relative-data'
2
2
  export { toRelativeData, createPercentFormatter } from './transforms'
3
+ export type { RelativeScale } from './scale'
3
4
  export { DEFAULT_RELATIVE_DATA_LABELS, type RelativeDataLabels } from './labels'
@@ -1,9 +1,15 @@
1
1
  export interface RelativeDataLabels {
2
2
  on: string
3
3
  off: string
4
+ scaleMenu: string
5
+ scaleMax: string
6
+ scaleTotal: string
4
7
  }
5
8
 
6
9
  export const DEFAULT_RELATIVE_DATA_LABELS: RelativeDataLabels = {
7
10
  on: 'Show absolute values',
8
11
  off: 'Show relative values',
12
+ scaleMenu: 'Relative scale',
13
+ scaleMax: 'Relative to max',
14
+ scaleTotal: 'Relative to total',
9
15
  }
@@ -1,5 +1,5 @@
1
1
  import { describe, it, expect, beforeEach, afterEach } from 'vitest'
2
- import { render } from '@testing-library/react'
2
+ import { act, fireEvent, render, screen } from '@testing-library/react'
3
3
  import { Provider } from '../../provider/widget-provider'
4
4
  import { clearAllWidgetStores, getWidgetStore } from '../../stores'
5
5
  import { RelativeData } from './relative-data'
@@ -69,3 +69,80 @@ describe('<RelativeData> — rawFormatter-driven restoration', () => {
69
69
  expect(s.formatter).toBe(fmtA)
70
70
  })
71
71
  })
72
+
73
+ describe('<RelativeData> — scale', () => {
74
+ const DATA = [
75
+ [
76
+ { name: 'a', value: 50 },
77
+ { name: 'b', value: 150 },
78
+ ],
79
+ ]
80
+ const values = (id: string) =>
81
+ (getWidgetStore(id).getState().data as { value: number }[][])[0]!.map(
82
+ (d) => d.value,
83
+ )
84
+ // The value axis a structural option ends up with after the action's
85
+ // config transform.
86
+ const yAxis = (id: string) => {
87
+ const xf = getWidgetStore(id)
88
+ .getState()
89
+ .configTransforms.find((t) => t.id === 'relative-data-axis')!
90
+ return (xf.fn({ yAxis: { type: 'value' } }) as { yAxis: object }).yAxis
91
+ }
92
+ const slot = (id: string) =>
93
+ getWidgetStore(id).getState().transformStates['relative-data']
94
+
95
+ it("defaults to 'max': values are shares of the total, axis left to the data", () => {
96
+ render(
97
+ <Provider id='sc1' data={DATA}>
98
+ <RelativeData initialEnabled />
99
+ </Provider>,
100
+ )
101
+ expect(values('sc1')).toEqual([25, 75])
102
+ expect(yAxis('sc1')).toEqual({ type: 'value' })
103
+ expect(slot('sc1')).toMatchObject({ enabled: true, scale: 'max' })
104
+ })
105
+
106
+ it("scale='total' keeps the same values and pins the axis to ±100", () => {
107
+ render(
108
+ <Provider id='sc2' data={DATA}>
109
+ <RelativeData initialEnabled scale='total' />
110
+ </Provider>,
111
+ )
112
+ expect(values('sc2')).toEqual([25, 75])
113
+ expect(yAxis('sc2')).toEqual({ type: 'value', min: -100, max: 100 })
114
+ })
115
+
116
+ it('picking a scale in the menu switches it and turns relative on', () => {
117
+ render(
118
+ <Provider id='sc3' data={DATA}>
119
+ <RelativeData />
120
+ </Provider>,
121
+ )
122
+ fireEvent.click(screen.getByRole('button', { name: 'Relative scale' }))
123
+ fireEvent.click(screen.getByRole('menuitem', { name: 'Relative to total' }))
124
+ expect(slot('sc3')).toMatchObject({ enabled: true, scale: 'total' })
125
+ expect(values('sc3')).toEqual([25, 75])
126
+ expect(yAxis('sc3')).toMatchObject({ max: 100 })
127
+ })
128
+
129
+ it('follows a scale written to the store from outside', () => {
130
+ render(
131
+ <Provider id='sc4' data={DATA}>
132
+ <RelativeData initialEnabled />
133
+ </Provider>,
134
+ )
135
+ act(() => {
136
+ getWidgetStore('sc4').setState((s) => ({
137
+ transformStates: {
138
+ ...s.transformStates,
139
+ 'relative-data': {
140
+ ...s.transformStates['relative-data']!,
141
+ scale: 'total',
142
+ },
143
+ },
144
+ }))
145
+ })
146
+ expect(yAxis('sc4')).toMatchObject({ max: 100 })
147
+ })
148
+ })