@carto/ps-react-ui 6.4.0 → 6.5.1

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 (93) hide show
  1. package/dist/{actions-DyWNwvLu.js → actions-D_PVFZaM.js} +4 -4
  2. package/dist/{actions-DyWNwvLu.js.map → actions-D_PVFZaM.js.map} +1 -1
  3. package/dist/{category-BHBd5Pcc.js → category-UIGvFN3D.js} +4 -4
  4. package/dist/{category-BHBd5Pcc.js.map → category-UIGvFN3D.js.map} +1 -1
  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/{spread-CQwFIwuz.js → spread-BRfPPIep.js} +3 -3
  19. package/dist/{spread-CQwFIwuz.js.map → spread-BRfPPIep.js.map} +1 -1
  20. package/dist/style-DTLuIo84.js +87 -0
  21. package/dist/style-DTLuIo84.js.map +1 -0
  22. package/dist/{styles-BCEBm7xh.js → styles-yKcpfyNV.js} +5 -5
  23. package/dist/styles-yKcpfyNV.js.map +1 -0
  24. package/dist/{table-DEdW_fDj.js → table-Col_FRvb.js} +2 -2
  25. package/dist/{table-DEdW_fDj.js.map → table-Col_FRvb.js.map} +1 -1
  26. package/dist/theme/tailwind.css +373 -0
  27. package/dist/theme.js +123 -0
  28. package/dist/theme.js.map +1 -0
  29. package/dist/types/components/lasso-tool/styles.d.ts +4 -4
  30. package/dist/types/theme/create-carto-theme.d.ts +7 -0
  31. package/dist/types/theme/deep-merge.d.ts +6 -0
  32. package/dist/types/theme/generate-tailwind-css.d.ts +8 -0
  33. package/dist/types/theme/index.d.ts +2 -0
  34. package/dist/types/widgets/markdown/style.d.ts +74 -0
  35. package/dist/types/widgets/utils/spacing-px.d.ts +13 -0
  36. package/dist/types/widgets/wrapper/collapsed-context.d.ts +7 -0
  37. package/dist/{utils-C-eWwOhE.js → utils-Dw4y8tiq.js} +2 -2
  38. package/dist/{utils-C-eWwOhE.js.map → utils-Dw4y8tiq.js.map} +1 -1
  39. package/dist/widgets/actions.js +3 -3
  40. package/dist/widgets/bar.js +54 -54
  41. package/dist/widgets/bar.js.map +1 -1
  42. package/dist/widgets/category.js +1 -1
  43. package/dist/widgets/formula.js +1 -1
  44. package/dist/widgets/histogram.js +70 -70
  45. package/dist/widgets/histogram.js.map +1 -1
  46. package/dist/widgets/markdown.js +1 -1
  47. package/dist/widgets/pie.js +78 -78
  48. package/dist/widgets/pie.js.map +1 -1
  49. package/dist/widgets/scatterplot.js +82 -82
  50. package/dist/widgets/scatterplot.js.map +1 -1
  51. package/dist/widgets/spread.js +1 -1
  52. package/dist/widgets/table.js +1 -1
  53. package/dist/widgets/timeseries.js +62 -62
  54. package/dist/widgets/timeseries.js.map +1 -1
  55. package/dist/widgets/utils.js +1 -1
  56. package/dist/widgets.js +309 -299
  57. package/dist/widgets.js.map +1 -1
  58. package/dist/{zoom-toggle-MmLjMTEw.js → zoom-toggle-DqrV_0Ji.js} +2 -2
  59. package/dist/{zoom-toggle-MmLjMTEw.js.map → zoom-toggle-DqrV_0Ji.js.map} +1 -1
  60. package/package.json +10 -3
  61. package/src/chat/bubbles/styles.ts +2 -0
  62. package/src/components/lasso-tool/lasso-tool-inline.test.tsx +4 -4
  63. package/src/components/lasso-tool/lasso-tool-inline.tsx +6 -6
  64. package/src/components/lasso-tool/styles.ts +4 -4
  65. package/src/theme/create-carto-theme.test.ts +53 -0
  66. package/src/theme/create-carto-theme.ts +21 -0
  67. package/src/theme/deep-merge.test.ts +25 -0
  68. package/src/theme/deep-merge.ts +22 -0
  69. package/src/theme/generate-tailwind-css.test.ts +87 -0
  70. package/src/theme/generate-tailwind-css.ts +178 -0
  71. package/src/theme/index.ts +2 -0
  72. package/src/theme/tailwind-compile.test.ts +71 -0
  73. package/src/theme/tailwind.css +373 -0
  74. package/src/widgets/bar/options.ts +7 -6
  75. package/src/widgets/histogram/options.ts +7 -6
  76. package/src/widgets/markdown/style.ts +40 -0
  77. package/src/widgets/note/widget-note.tsx +4 -1
  78. package/src/widgets/pie/options.ts +5 -4
  79. package/src/widgets/scatterplot/options.ts +7 -6
  80. package/src/widgets/timeseries/options.ts +7 -6
  81. package/src/widgets/toolbox/toolbox.test.tsx +28 -0
  82. package/src/widgets/toolbox/toolbox.tsx +9 -0
  83. package/src/widgets/utils/css-variables-theme.test.ts +32 -0
  84. package/src/widgets/utils/option-builders.ts +4 -6
  85. package/src/widgets/utils/spacing-px.test.ts +42 -0
  86. package/src/widgets/utils/spacing-px.ts +24 -0
  87. package/src/widgets/wrapper/collapsed-context.ts +12 -0
  88. package/src/widgets/wrapper/widget-wrapper.tsx +6 -1
  89. package/dist/components-CTUpdQuj.js.map +0 -1
  90. package/dist/item-color-B7xkIpDZ.js.map +0 -1
  91. package/dist/markdown-DmvLi3vx.js +0 -159
  92. package/dist/markdown-DmvLi3vx.js.map +0 -1
  93. package/dist/styles-BCEBm7xh.js.map +0 -1
@@ -12,6 +12,7 @@ import {
12
12
  import { ZOOM_LAYOUT } from '../actions/zoom-toggle'
13
13
  import type { OptionFactory } from '../echart'
14
14
  import { mergeOptions, resolveThemeColor } from '../utils'
15
+ import { spacingPx } from '../utils/spacing-px'
15
16
  import { createItemColorResolver } from '../utils/item-color'
16
17
  import { getScatterplotXY } from './points'
17
18
  import type {
@@ -45,9 +46,9 @@ export function scatterplotOptions({
45
46
  }: ScatterplotOptionsInput): ScatterplotEChartsOption {
46
47
  return {
47
48
  grid: {
48
- left: parseInt(theme.spacing(1)),
49
- top: parseInt(theme.spacing(3)),
50
- right: parseInt(theme.spacing(1)),
49
+ left: spacingPx(theme, 1),
50
+ top: spacingPx(theme, 3),
51
+ right: spacingPx(theme, 1),
51
52
  // Default: no legend. Merger bumps `bottom` when there are >1 series.
52
53
  ...buildGridConfig(false, theme),
53
54
  containLabel: true,
@@ -58,7 +59,7 @@ export function scatterplotOptions({
58
59
  trigger: 'item',
59
60
  backgroundColor: theme.palette.grey[900],
60
61
  borderWidth: 0,
61
- padding: [parseInt(theme.spacing(1)), parseInt(theme.spacing(1))],
62
+ padding: [spacingPx(theme, 1), spacingPx(theme, 1)],
62
63
  textStyle: {
63
64
  color: theme.palette.common.white,
64
65
  fontSize: 11,
@@ -86,7 +87,7 @@ export function scatterplotOptions({
86
87
  axisTick: { show: false },
87
88
  axisLabel: {
88
89
  ...buildAxisLabelStyle(theme),
89
- margin: parseInt(theme.spacing(1)),
90
+ margin: spacingPx(theme, 1),
90
91
  hideOverlap: true,
91
92
  showMinLabel: true,
92
93
  showMaxLabel: true,
@@ -103,7 +104,7 @@ export function scatterplotOptions({
103
104
  axisTick: { show: false },
104
105
  axisLabel: {
105
106
  ...buildAxisLabelStyle(theme),
106
- margin: parseInt(theme.spacing(1)),
107
+ margin: spacingPx(theme, 1),
107
108
  hideOverlap: true,
108
109
  showMinLabel: true,
109
110
  showMaxLabel: true,
@@ -12,6 +12,7 @@ import {
12
12
  import { ZOOM_LAYOUT } from '../actions/zoom-toggle'
13
13
  import type { OptionFactory } from '../echart'
14
14
  import { mergeOptions, resolveThemeColor } from '../utils'
15
+ import { spacingPx } from '../utils/spacing-px'
15
16
  import { createItemColorResolver } from '../utils/item-color'
16
17
  import { positionDataZoomForLegend } from '../utils/data-zoom-layout'
17
18
  import type {
@@ -53,9 +54,9 @@ export function timeseriesOptions({
53
54
 
54
55
  return {
55
56
  grid: {
56
- left: parseInt(theme.spacing(1)),
57
- top: parseInt(theme.spacing(3)),
58
- right: parseInt(theme.spacing(1)),
57
+ left: spacingPx(theme, 1),
58
+ top: spacingPx(theme, 3),
59
+ right: spacingPx(theme, 1),
59
60
  // Default: no legend. Merger bumps this when there are >1 series.
60
61
  ...buildGridConfig(false, theme),
61
62
  containLabel: true,
@@ -64,7 +65,7 @@ export function timeseriesOptions({
64
65
  trigger: 'axis',
65
66
  backgroundColor: theme.palette.grey[900],
66
67
  borderWidth: 0,
67
- padding: [parseInt(theme.spacing(1)), parseInt(theme.spacing(1))],
68
+ padding: [spacingPx(theme, 1), spacingPx(theme, 1)],
68
69
  textStyle: {
69
70
  color: theme.palette.common.white,
70
71
  fontSize: 11,
@@ -93,7 +94,7 @@ export function timeseriesOptions({
93
94
  axisTick: { show: false },
94
95
  axisLabel: {
95
96
  ...buildAxisLabelStyle(theme),
96
- padding: [parseInt(theme.spacing(0.5)), 0, 0, 0],
97
+ padding: [spacingPx(theme, 0.5), 0, 0, 0],
97
98
  margin: 0,
98
99
  hideOverlap: true,
99
100
  ...(labelFormatter && {
@@ -119,7 +120,7 @@ export function timeseriesOptions({
119
120
  },
120
121
  axisLabel: {
121
122
  ...buildAxisLabelStyle(theme),
122
- margin: parseInt(theme.spacing(1)),
123
+ margin: spacingPx(theme, 1),
123
124
  show: true,
124
125
  showMaxLabel: true,
125
126
  showMinLabel: true,
@@ -4,6 +4,9 @@ import { fireEvent, render, screen } from '@testing-library/react'
4
4
  import { IconButton } from '@mui/material'
5
5
  import { Star as StarIcon } from '@mui/icons-material'
6
6
  import { Toolbox } from './toolbox'
7
+ import { Provider } from '../provider/widget-provider'
8
+ import { Wrapper } from '../wrapper/widget-wrapper'
9
+ import { Content } from '../wrapper/widget-content'
7
10
 
8
11
  function makeChildren(n: number) {
9
12
  return Array.from({ length: n }).map((_, i) => (
@@ -197,4 +200,29 @@ describe('<Toolbox>', () => {
197
200
  expect(isItemVisible(`Tool ${i}`)).toBe(true)
198
201
  }
199
202
  })
203
+
204
+ it('closes the overflow popper when its Wrapper collapses', () => {
205
+ render(
206
+ <Provider id='toolbox-collapse' data={[]}>
207
+ <Wrapper title='Spam'>
208
+ <Content>
209
+ <Toolbox visibleCount={2}>{makeChildren(5)}</Toolbox>
210
+ </Content>
211
+ </Wrapper>
212
+ </Provider>,
213
+ )
214
+ fireEvent.click(screen.getByLabelText('More actions'))
215
+ expect(isItemVisible('Tool 5')).toBe(true)
216
+
217
+ // The Accordion keeps its details mounted, so without this the portalled
218
+ // popper stayed floating over the page after the widget collapsed.
219
+ fireEvent.click(screen.getByRole('button', { name: 'Collapse' }))
220
+ expect(screen.queryByLabelText('Close')).toBeNull()
221
+ expect(isItemVisible('Tool 5')).toBe(false)
222
+
223
+ // Expanding again shows the closed toolbox, not the popper.
224
+ fireEvent.click(screen.getByRole('button', { name: 'Expand' }))
225
+ expect(screen.getByLabelText('More actions')).toBeTruthy()
226
+ expect(isItemVisible('Tool 5')).toBe(false)
227
+ })
200
228
  })
@@ -26,6 +26,7 @@ import { Close as CloseIcon } from '@mui/icons-material'
26
26
  import { WidgetOptions } from '@carto/meridian-ds/custom-icons'
27
27
  import { Tooltip } from '../../components'
28
28
  import { DEFAULT_TOOLBOX_LABELS, type ToolboxLabels } from './labels'
29
+ import { useWrapperCollapsed } from '../wrapper/collapsed-context'
29
30
  import { styles } from './style'
30
31
 
31
32
  export interface ToolboxProps {
@@ -166,6 +167,14 @@ export function Toolbox({
166
167
  setOpen(false)
167
168
  }
168
169
 
170
+ // Same pattern when the enclosing Wrapper collapses: its Accordion keeps
171
+ // the details mounted, so the portalled popper would otherwise stay open
172
+ // over the page with no visible trigger.
173
+ const collapsed = useWrapperCollapsed()
174
+ if (collapsed && open) {
175
+ setOpen(false)
176
+ }
177
+
169
178
  // Reparent the host into the active shell whenever `open` (or either
170
179
  // shell) changes. `useLayoutEffect` runs synchronously after commit
171
180
  // (after refs have been written), so the popover Paper ref is already
@@ -0,0 +1,32 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import { createCartoTheme } from '../../theme/create-carto-theme'
3
+ import { barOptions } from '../bar/options'
4
+ import { histogramOptions } from '../histogram/options'
5
+ import { pieOptions } from '../pie/options'
6
+ import { scatterplotOptions } from '../scatterplot/options'
7
+ import { timeseriesOptions } from '../timeseries/options'
8
+
9
+ const theme = createCartoTheme()
10
+
11
+ function nanPaths(value: unknown, path = '$'): string[] {
12
+ if (typeof value === 'number') return Number.isNaN(value) ? [path] : []
13
+ if (Array.isArray(value))
14
+ return value.flatMap((v, i) => nanPaths(v, `${path}[${i}]`))
15
+ if (value && typeof value === 'object')
16
+ return Object.entries(value).flatMap(([k, v]) =>
17
+ nanPaths(v, `${path}.${k}`),
18
+ )
19
+ return []
20
+ }
21
+
22
+ describe('ECharts options with a cssVariables theme', () => {
23
+ it.each([
24
+ ['bar', () => barOptions({ theme })],
25
+ ['histogram', () => histogramOptions({ theme })],
26
+ ['pie', () => pieOptions({ theme })],
27
+ ['scatterplot', () => scatterplotOptions({ theme })],
28
+ ['timeseries', () => timeseriesOptions({ theme })],
29
+ ])('%s has no NaN in its options', (_name, build) => {
30
+ expect(nanPaths(build())).toEqual([])
31
+ })
32
+ })
@@ -4,6 +4,7 @@ import type {
4
4
  CallbackDataParams,
5
5
  TopLevelFormatterParams,
6
6
  } from 'echarts/types/dist/shared'
7
+ import { spacingPx } from './spacing-px'
7
8
 
8
9
  /**
9
10
  * Shared EChart configuration builders for chart widgets
@@ -61,8 +62,8 @@ export function buildLegendConfig({
61
62
  */
62
63
  export function buildGridConfig(hasLegend: boolean, theme: Theme) {
63
64
  return {
64
- ...(!hasLegend && { bottom: parseInt(theme.spacing(3)) }),
65
- ...(hasLegend && { bottom: parseInt(theme.spacing(7)) }),
65
+ ...(!hasLegend && { bottom: spacingPx(theme, 3) }),
66
+ ...(hasLegend && { bottom: spacingPx(theme, 7) }),
66
67
  }
67
68
  }
68
69
 
@@ -106,10 +107,7 @@ export function createTooltipPositioner(theme: Theme) {
106
107
  _rect: unknown,
107
108
  size: { contentSize: [number, number]; viewSize: [number, number] },
108
109
  ) {
109
- const position = { top: parseInt(theme.spacing(0.5)) } as Record<
110
- string,
111
- number
112
- >
110
+ const position = { top: spacingPx(theme, 0.5) } as Record<string, number>
113
111
 
114
112
  // Position tooltip left or right based on available space
115
113
  if (size.contentSize[0] < size.viewSize[0] - point[0]) {
@@ -0,0 +1,42 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import { createTheme, responsiveFontSizes, type Theme } from '@mui/material'
3
+ import {
4
+ cartoThemeOptions,
5
+ theme as cartoTheme,
6
+ } from '@carto/meridian-ds/theme'
7
+ import { createCartoTheme } from '../../theme/create-carto-theme'
8
+ import { spacingPx } from './spacing-px'
9
+
10
+ const FACTORS = [0.5, 1, 3, 4, 7]
11
+
12
+ describe('spacingPx', () => {
13
+ it('matches the previous parseInt(theme.spacing(n)) for the current CARTO theme', () => {
14
+ const theme = createTheme(cartoTheme)
15
+ for (const factor of FACTORS) {
16
+ expect(spacingPx(theme, factor)).toBe(parseInt(theme.spacing(factor)))
17
+ }
18
+ })
19
+
20
+ it('resolves numbers for a CARTO theme with cssVariables', () => {
21
+ const theme = responsiveFontSizes(
22
+ createTheme({ ...cartoThemeOptions, cssVariables: true }),
23
+ )
24
+ expect(theme.spacing(1)).toContain('var(')
25
+ expect(FACTORS.map((f) => spacingPx(theme, f))).toEqual([4, 8, 24, 32, 56])
26
+ })
27
+
28
+ it('falls back to 8px per unit for a plain MUI theme with cssVariables', () => {
29
+ const theme = createTheme({ cssVariables: true }) as unknown as Theme
30
+ expect(FACTORS.map((f) => spacingPx(theme, f))).toEqual([4, 8, 24, 32, 56])
31
+ })
32
+
33
+ it('honours a numeric spacing override on createCartoTheme', () => {
34
+ const theme = createCartoTheme({ spacing: 4 })
35
+ expect(FACTORS.map((f) => spacingPx(theme, f))).toEqual([2, 4, 12, 16, 28])
36
+ })
37
+
38
+ it('honours a function spacing override under cssVariables', () => {
39
+ const theme = createCartoTheme({ spacing: (f: number) => f * 6 })
40
+ expect(spacingPx(theme, 1)).toBe(6)
41
+ })
42
+ })
@@ -0,0 +1,24 @@
1
+ import type { Theme } from '@mui/material'
2
+
3
+ /**
4
+ * Theme spacing as a pixel number, for APIs that need numbers (ECharts).
5
+ *
6
+ * `theme.spacing(n)` returns `"8px"` for a regular theme but
7
+ * `"var(--mui-spacing, 8px)"` / `"calc(...)"` once the theme uses
8
+ * `cssVariables`, which does not parse. Resolution order:
9
+ * 1. `parseFloat` of `theme.spacing(factor)` (regular themes);
10
+ * 2. the px unit MUI writes into `theme.spacing(1)` (`var(--mui-spacing, Npx)`),
11
+ * which honours a `spacing` override such as `createCartoTheme({ spacing: 4 })`;
12
+ * 3. meridian's numeric `spacingValue`, or MUI's default 8px.
13
+ */
14
+ export function spacingPx(theme: Theme, factor: number): number {
15
+ const parsed = parseFloat(theme.spacing(factor))
16
+ if (Number.isFinite(parsed)) return parsed
17
+ // `spacing(1)` is `var(--mui-spacing, Npx)`; larger factors are
18
+ // `calc(f * var(--mui-spacing, Npx))`, so read the unit from the former.
19
+ const fallback = /,\s*(-?[\d.]+)px\)\s*$/.exec(theme.spacing(1))
20
+ const px = fallback ? Number(fallback[1]) : NaN
21
+ if (Number.isFinite(px)) return px * factor
22
+ const unit = (theme.spacingValue as number | undefined) ?? 8
23
+ return unit * factor
24
+ }
@@ -0,0 +1,12 @@
1
+ import { createContext, useContext } from 'react'
2
+
3
+ /**
4
+ * Whether the enclosing `<Wrapper>` is collapsed. The Accordion keeps its
5
+ * details mounted, so content that opens portalled UI (the Toolbox popper)
6
+ * reads this to close it. `false` outside a Wrapper.
7
+ */
8
+ export const WrapperCollapsedContext = createContext(false)
9
+
10
+ export function useWrapperCollapsed(): boolean {
11
+ return useContext(WrapperCollapsedContext)
12
+ }
@@ -24,6 +24,7 @@ import { useWidget, useWidgetId } from '../stores'
24
24
  import { Actions, Options } from './widget-actions'
25
25
  import { styles } from './style'
26
26
  import { DEFAULT_WRAPPER_LABELS, type WrapperLabels } from './labels'
27
+ import { WrapperCollapsedContext } from './collapsed-context'
27
28
 
28
29
  export interface WrapperProps {
29
30
  title: string
@@ -192,7 +193,11 @@ export function Wrapper({
192
193
  </Box>
193
194
  )}
194
195
  </Box>
195
- <AccordionDetails sx={styles.detail}>{detailsSlots}</AccordionDetails>
196
+ <AccordionDetails sx={styles.detail}>
197
+ <WrapperCollapsedContext.Provider value={effectiveCollapsed}>
198
+ {detailsSlots}
199
+ </WrapperCollapsedContext.Provider>
200
+ </AccordionDetails>
196
201
  </Accordion>
197
202
  )
198
203
  }