@carto/ps-react-ui 4.3.2 → 4.3.4
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.
- package/dist/components.js +3 -3
- package/dist/components.js.map +1 -1
- package/dist/{lasso-tool-BwRzEW7k.js → lasso-tool-wFqOD6wk.js} +13 -13
- package/dist/lasso-tool-wFqOD6wk.js.map +1 -0
- package/dist/types/components/common-types.d.ts +41 -0
- package/dist/types/components/types.d.ts +1 -1
- package/dist/types/widgets/toolbar-actions/toolbar-actions.d.ts +6 -3
- package/dist/widgets/actions.js +1 -1
- package/dist/widgets/bar.js +1 -1
- package/dist/widgets/category.js +1 -1
- package/dist/widgets/formula.js +1 -1
- package/dist/widgets/histogram.js +1 -1
- package/dist/widgets/markdown.js +1 -1
- package/dist/widgets/pie.js +1 -1
- package/dist/widgets/scatterplot.js +1 -1
- package/dist/widgets/spread.js +1 -1
- package/dist/widgets/table.js +1 -1
- package/dist/widgets/timeseries.js +1 -1
- package/dist/widgets/toolbar-actions.js +1343 -1332
- package/dist/widgets/toolbar-actions.js.map +1 -1
- package/dist/widgets/wrapper.js +1 -1
- package/package.json +8 -3
- package/src/components/basemaps/basemaps.test.tsx +196 -0
- package/src/components/basemaps/basemaps.tsx +128 -0
- package/src/components/basemaps/const.ts +13 -0
- package/src/components/basemaps/group-wrapper.test.tsx +38 -0
- package/src/components/basemaps/group-wrapper.tsx +28 -0
- package/src/components/basemaps/group.test.tsx +52 -0
- package/src/components/basemaps/group.tsx +42 -0
- package/src/components/basemaps/header.test.tsx +54 -0
- package/src/components/basemaps/header.tsx +36 -0
- package/src/components/basemaps/styles.ts +76 -0
- package/src/components/basemaps/types.ts +30 -0
- package/src/components/common-types.ts +1 -0
- package/src/components/geolocation-controls/const.ts +6 -0
- package/src/components/geolocation-controls/geolocation-controls.test.tsx +133 -0
- package/src/components/geolocation-controls/geolocation-controls.tsx +95 -0
- package/src/components/geolocation-controls/types.ts +17 -0
- package/src/components/index.ts +64 -0
- package/src/components/lasso-tool/chip.tsx +37 -0
- package/src/components/lasso-tool/const.tsx +70 -0
- package/src/components/lasso-tool/icons.tsx +91 -0
- package/src/components/lasso-tool/lasso-tool-inline.test.tsx +168 -0
- package/src/components/lasso-tool/lasso-tool-inline.tsx +245 -0
- package/src/components/lasso-tool/lasso-tool.test.tsx +212 -0
- package/src/components/lasso-tool/lasso-tool.tsx +479 -0
- package/src/components/lasso-tool/styles.ts +143 -0
- package/src/components/lasso-tool/types.ts +114 -0
- package/src/components/list-data/list-data-skeleton.test.tsx +10 -0
- package/src/components/list-data/list-data-skeleton.tsx +40 -0
- package/src/components/list-data/list-data.test.tsx +94 -0
- package/src/components/list-data/list-data.tsx +106 -0
- package/src/components/list-data/styles.ts +37 -0
- package/src/components/list-data/types.ts +25 -0
- package/src/components/measurement-tools/const.tsx +108 -0
- package/src/components/measurement-tools/icons.tsx +54 -0
- package/src/components/measurement-tools/measurement-tools.test.tsx +165 -0
- package/src/components/measurement-tools/measurement-tools.tsx +443 -0
- package/src/components/measurement-tools/styles.ts +91 -0
- package/src/components/measurement-tools/types.ts +77 -0
- package/src/components/no-data-alert/no-data-alert.test.tsx +31 -0
- package/src/components/no-data-alert/no-data-alert.tsx +59 -0
- package/src/components/responsive-drawer/responsive-drawer.test.tsx +91 -0
- package/src/components/responsive-drawer/responsive-drawer.tsx +53 -0
- package/src/components/smart-tooltip/smart-tooltip.test.tsx +168 -0
- package/src/components/smart-tooltip/smart-tooltip.tsx +40 -0
- package/src/components/tooltip/tooltip.test.tsx +86 -0
- package/src/components/tooltip/tooltip.tsx +30 -0
- package/src/components/types.ts +1 -0
- package/src/components/zoom-controls/styles.ts +27 -0
- package/src/components/zoom-controls/types.ts +19 -0
- package/src/components/zoom-controls/zoom-controls.test.tsx +101 -0
- package/src/components/zoom-controls/zoom-controls.tsx +114 -0
- package/src/hooks/index.ts +2 -0
- package/src/hooks/use-debounce.ts +55 -0
- package/src/hooks/use-skeleton.test.tsx +32 -0
- package/src/hooks/use-skeleton.ts +19 -0
- package/src/hooks/use-widget-ref.ts +33 -0
- package/src/widgets/README.md +277 -0
- package/src/widgets/_shared/chart-config/config-factory.ts +67 -0
- package/src/widgets/_shared/chart-config/csv-modifiers.ts +56 -0
- package/src/widgets/_shared/chart-config/index.ts +21 -0
- package/src/widgets/_shared/chart-config/option-builders.ts +203 -0
- package/src/widgets/_shared/skeleton/index.ts +5 -0
- package/src/widgets/_shared/skeleton/styles.ts +20 -0
- package/src/widgets/actions/change-column/change-column-icon.tsx +10 -0
- package/src/widgets/actions/change-column/change-column.test.tsx +163 -0
- package/src/widgets/actions/change-column/change-column.tsx +141 -0
- package/src/widgets/actions/change-column/sortable-column-item.tsx +49 -0
- package/src/widgets/actions/change-column/types.ts +20 -0
- package/src/widgets/actions/download/download.test.tsx +322 -0
- package/src/widgets/actions/download/download.tsx +118 -0
- package/src/widgets/actions/download/exports.test.tsx +275 -0
- package/src/widgets/actions/download/exports.tsx +103 -0
- package/src/widgets/actions/download/types.ts +21 -0
- package/src/widgets/actions/fullscreen/fullscreen.test.tsx +269 -0
- package/src/widgets/actions/fullscreen/fullscreen.tsx +82 -0
- package/src/widgets/actions/fullscreen/styles.ts +17 -0
- package/src/widgets/actions/fullscreen/types.ts +27 -0
- package/src/widgets/actions/index.ts +51 -0
- package/src/widgets/actions/lock-selection/lock-selection.test.tsx +186 -0
- package/src/widgets/actions/lock-selection/lock-selection.tsx +133 -0
- package/src/widgets/actions/lock-selection/types.ts +41 -0
- package/src/widgets/actions/relative-data/relative-data.test.tsx +267 -0
- package/src/widgets/actions/relative-data/relative-data.tsx +133 -0
- package/src/widgets/actions/relative-data/style.ts +9 -0
- package/src/widgets/actions/relative-data/types.ts +31 -0
- package/src/widgets/actions/relative-data/utils.test.ts +223 -0
- package/src/widgets/actions/relative-data/utils.ts +58 -0
- package/src/widgets/actions/searcher/searcher-toggle.test.tsx +354 -0
- package/src/widgets/actions/searcher/searcher-toggle.tsx +73 -0
- package/src/widgets/actions/searcher/searcher.tsx +205 -0
- package/src/widgets/actions/searcher/types.ts +72 -0
- package/src/widgets/actions/shared/styles.ts +12 -0
- package/src/widgets/actions/stack-toggle/grouped-bar-chart-icon.tsx +14 -0
- package/src/widgets/actions/stack-toggle/stack-toggle.test.tsx +270 -0
- package/src/widgets/actions/stack-toggle/stack-toggle.tsx +146 -0
- package/src/widgets/actions/stack-toggle/types.ts +29 -0
- package/src/widgets/actions/zoom-toggle/index.ts +2 -0
- package/src/widgets/actions/zoom-toggle/style.ts +14 -0
- package/src/widgets/actions/zoom-toggle/types.ts +44 -0
- package/src/widgets/actions/zoom-toggle/zoom-toggle.tsx +186 -0
- package/src/widgets/bar/config.ts +122 -0
- package/src/widgets/bar/index.ts +9 -0
- package/src/widgets/bar/skeleton.tsx +60 -0
- package/src/widgets/bar/style.ts +33 -0
- package/src/widgets/bar/types.ts +16 -0
- package/src/widgets/category/category-ui.test.tsx +399 -0
- package/src/widgets/category/category-ui.tsx +156 -0
- package/src/widgets/category/components/category-bar.tsx +28 -0
- package/src/widgets/category/components/category-legend.tsx +30 -0
- package/src/widgets/category/components/category-row-multi.tsx +50 -0
- package/src/widgets/category/components/category-row-other.tsx +23 -0
- package/src/widgets/category/components/category-row-single.tsx +47 -0
- package/src/widgets/category/components/index.ts +14 -0
- package/src/widgets/category/config.ts +85 -0
- package/src/widgets/category/index.ts +30 -0
- package/src/widgets/category/skeleton.tsx +24 -0
- package/src/widgets/category/style.ts +133 -0
- package/src/widgets/category/types.ts +40 -0
- package/src/widgets/echart/const.ts +1 -0
- package/src/widgets/echart/echart-ui.test.tsx +519 -0
- package/src/widgets/echart/echart-ui.tsx +80 -0
- package/src/widgets/echart/echart.test.tsx +537 -0
- package/src/widgets/echart/echart.tsx +60 -0
- package/src/widgets/echart/index.ts +16 -0
- package/src/widgets/echart/options.ts +53 -0
- package/src/widgets/echart/types.ts +41 -0
- package/src/widgets/echart/utils.ts +169 -0
- package/src/widgets/error/error.test.tsx +331 -0
- package/src/widgets/error/error.tsx +40 -0
- package/src/widgets/error/index.ts +2 -0
- package/src/widgets/error/types.ts +14 -0
- package/src/widgets/formula/components/item.test.tsx +249 -0
- package/src/widgets/formula/components/item.tsx +18 -0
- package/src/widgets/formula/components/prefix.test.tsx +341 -0
- package/src/widgets/formula/components/prefix.tsx +18 -0
- package/src/widgets/formula/components/row.test.tsx +364 -0
- package/src/widgets/formula/components/row.tsx +21 -0
- package/src/widgets/formula/components/series.tsx +34 -0
- package/src/widgets/formula/components/suffix.test.tsx +383 -0
- package/src/widgets/formula/components/suffix.tsx +28 -0
- package/src/widgets/formula/components/value.test.tsx +329 -0
- package/src/widgets/formula/components/value.tsx +29 -0
- package/src/widgets/formula/config.ts +27 -0
- package/src/widgets/formula/formula-ui.test.tsx +399 -0
- package/src/widgets/formula/formula-ui.tsx +27 -0
- package/src/widgets/formula/index.ts +24 -0
- package/src/widgets/formula/serializer.test.tsx +144 -0
- package/src/widgets/formula/serializer.ts +28 -0
- package/src/widgets/formula/skeleton.tsx +10 -0
- package/src/widgets/formula/style.ts +23 -0
- package/src/widgets/formula/types.ts +50 -0
- package/src/widgets/histogram/config.ts +143 -0
- package/src/widgets/histogram/index.ts +8 -0
- package/src/widgets/histogram/skeleton.tsx +52 -0
- package/src/widgets/histogram/style.ts +8 -0
- package/src/widgets/histogram/types.ts +17 -0
- package/src/widgets/index.ts +25 -0
- package/src/widgets/loader/index.ts +4 -0
- package/src/widgets/loader/loader.tsx +70 -0
- package/src/widgets/loader/types.ts +11 -0
- package/src/widgets/loader/utils.test.ts +112 -0
- package/src/widgets/loader/utils.ts +35 -0
- package/src/widgets/markdown/config.ts +18 -0
- package/src/widgets/markdown/index.ts +14 -0
- package/src/widgets/markdown/markdown-ui.test.tsx +341 -0
- package/src/widgets/markdown/markdown-ui.tsx +52 -0
- package/src/widgets/markdown/markdown.tsx +20 -0
- package/src/widgets/markdown/skeleton.tsx +12 -0
- package/src/widgets/markdown/style.ts +28 -0
- package/src/widgets/markdown/types.ts +28 -0
- package/src/widgets/no-data/index.ts +2 -0
- package/src/widgets/no-data/no-data.test.tsx +447 -0
- package/src/widgets/no-data/no-data.tsx +116 -0
- package/src/widgets/no-data/style.ts +18 -0
- package/src/widgets/no-data/types.ts +72 -0
- package/src/widgets/note/index.ts +2 -0
- package/src/widgets/note/note.test.tsx +391 -0
- package/src/widgets/note/note.tsx +114 -0
- package/src/widgets/note/style.ts +29 -0
- package/src/widgets/note/types.ts +9 -0
- package/src/widgets/pie/config.ts +177 -0
- package/src/widgets/pie/index.ts +8 -0
- package/src/widgets/pie/skeleton.tsx +70 -0
- package/src/widgets/pie/style.ts +8 -0
- package/src/widgets/pie/types.ts +16 -0
- package/src/widgets/range/components/range-item.tsx +213 -0
- package/src/widgets/range/config.ts +10 -0
- package/src/widgets/range/index.ts +16 -0
- package/src/widgets/range/range-ui.test.tsx +203 -0
- package/src/widgets/range/range-ui.tsx +11 -0
- package/src/widgets/range/serializer.test.ts +70 -0
- package/src/widgets/range/serializer.ts +27 -0
- package/src/widgets/range/skeleton.tsx +14 -0
- package/src/widgets/range/style.ts +37 -0
- package/src/widgets/range/types.ts +39 -0
- package/src/widgets/scatterplot/config.ts +138 -0
- package/src/widgets/scatterplot/index.ts +8 -0
- package/src/widgets/scatterplot/skeleton.tsx +59 -0
- package/src/widgets/scatterplot/style.ts +21 -0
- package/src/widgets/scatterplot/types.ts +17 -0
- package/src/widgets/selection-summary/index.ts +6 -0
- package/src/widgets/selection-summary/selection-summary.tsx +46 -0
- package/src/widgets/selection-summary/style.ts +10 -0
- package/src/widgets/selection-summary/types.ts +14 -0
- package/src/widgets/skeleton-loader/index.ts +2 -0
- package/src/widgets/skeleton-loader/skeleton-loader.test.tsx +139 -0
- package/src/widgets/skeleton-loader/skeleton-loader.tsx +28 -0
- package/src/widgets/skeleton-loader/types.ts +8 -0
- package/src/widgets/spread/components/max-value.tsx +29 -0
- package/src/widgets/spread/components/min-value.tsx +29 -0
- package/src/widgets/spread/components/separator.tsx +6 -0
- package/src/widgets/spread/config.ts +34 -0
- package/src/widgets/spread/index.ts +23 -0
- package/src/widgets/spread/skeleton.tsx +10 -0
- package/src/widgets/spread/spread-ui.test.tsx +368 -0
- package/src/widgets/spread/spread-ui.tsx +29 -0
- package/src/widgets/spread/style.ts +22 -0
- package/src/widgets/spread/types.ts +47 -0
- package/src/widgets/stores/index.ts +9 -0
- package/src/widgets/stores/types.ts +192 -0
- package/src/widgets/stores/widget-store.test.ts +601 -0
- package/src/widgets/stores/widget-store.ts +239 -0
- package/src/widgets/subheader/index.ts +3 -0
- package/src/widgets/subheader/style.ts +20 -0
- package/src/widgets/subheader/subheader.test.tsx +45 -0
- package/src/widgets/subheader/subheader.tsx +16 -0
- package/src/widgets/subheader/types.ts +11 -0
- package/src/widgets/table/components/cell-header.tsx +58 -0
- package/src/widgets/table/components/cell.tsx +80 -0
- package/src/widgets/table/components/index.ts +4 -0
- package/src/widgets/table/components/pagination-actions.tsx +67 -0
- package/src/widgets/table/components/pagination.tsx +41 -0
- package/src/widgets/table/components/row.tsx +60 -0
- package/src/widgets/table/config.ts +71 -0
- package/src/widgets/table/helpers.test.ts +244 -0
- package/src/widgets/table/helpers.ts +107 -0
- package/src/widgets/table/hooks/index.ts +7 -0
- package/src/widgets/table/hooks/use-pagination.test.ts +294 -0
- package/src/widgets/table/hooks/use-pagination.ts +155 -0
- package/src/widgets/table/hooks/use-selection.test.ts +504 -0
- package/src/widgets/table/hooks/use-selection.ts +189 -0
- package/src/widgets/table/hooks/use-sort.test.ts +296 -0
- package/src/widgets/table/hooks/use-sort.ts +138 -0
- package/src/widgets/table/index.ts +53 -0
- package/src/widgets/table/serializer.ts +54 -0
- package/src/widgets/table/skeleton.tsx +48 -0
- package/src/widgets/table/style.ts +34 -0
- package/src/widgets/table/table-ui.tsx +64 -0
- package/src/widgets/table/types.ts +223 -0
- package/src/widgets/timeseries/config.ts +135 -0
- package/src/widgets/timeseries/index.ts +8 -0
- package/src/widgets/timeseries/skeleton.tsx +55 -0
- package/src/widgets/timeseries/style.ts +36 -0
- package/src/widgets/timeseries/types.ts +17 -0
- package/src/widgets/toolbar-actions/index.ts +6 -0
- package/src/widgets/toolbar-actions/styles.ts +38 -0
- package/src/widgets/toolbar-actions/toolbar-actions.test.tsx +691 -0
- package/src/widgets/toolbar-actions/toolbar-actions.tsx +145 -0
- package/src/widgets/toolbar-actions/types.ts +60 -0
- package/src/widgets/wrapper/components/actions.test.tsx +101 -0
- package/src/widgets/wrapper/components/actions.tsx +30 -0
- package/src/widgets/wrapper/components/options.test.tsx +323 -0
- package/src/widgets/wrapper/components/options.tsx +73 -0
- package/src/widgets/wrapper/components/title.test.tsx +126 -0
- package/src/widgets/wrapper/components/title.tsx +32 -0
- package/src/widgets/wrapper/index.ts +16 -0
- package/src/widgets/wrapper/styles.ts +98 -0
- package/src/widgets/wrapper/types.ts +55 -0
- package/src/widgets/wrapper/wrapper-ui.test.tsx +232 -0
- package/src/widgets/wrapper/wrapper-ui.tsx +57 -0
- package/src/widgets/wrapper/wrapper.test.tsx +365 -0
- package/src/widgets/wrapper/wrapper.tsx +50 -0
- package/dist/lasso-tool-BwRzEW7k.js.map +0 -1
- package/dist/types/common/common.d.ts +0 -3
- package/dist/types/common/index.d.ts +0 -26
- package/dist/types/common/lasso-tools.d.ts +0 -36
- package/dist/types/common/measurement-tools.d.ts +0 -65
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { Paper, TooltipProps } from '@mui/material'
|
|
2
|
+
import type { ComponentProps } from 'react'
|
|
3
|
+
import type {
|
|
4
|
+
MeasurementMode,
|
|
5
|
+
MeasurementModes,
|
|
6
|
+
MeasurementOptionsMode,
|
|
7
|
+
MeasurementOptionsUnit,
|
|
8
|
+
MeasurementUnit,
|
|
9
|
+
MeasurementUnitImperialDistance,
|
|
10
|
+
MeasurementUnitMetricDistance,
|
|
11
|
+
MeasurementUnits,
|
|
12
|
+
MeasurementModesMapping,
|
|
13
|
+
MeasurementUnitsMapping,
|
|
14
|
+
} from '../types'
|
|
15
|
+
|
|
16
|
+
interface Labels {
|
|
17
|
+
action?: {
|
|
18
|
+
tooltip?: {
|
|
19
|
+
active?: string
|
|
20
|
+
inactive?: string
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
chip?: {
|
|
24
|
+
tooltip?: {
|
|
25
|
+
active?: string
|
|
26
|
+
inactive?: string
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
options?: {
|
|
30
|
+
mode?: {
|
|
31
|
+
title?: string
|
|
32
|
+
options?: MeasurementOptionsMode
|
|
33
|
+
}
|
|
34
|
+
units?: {
|
|
35
|
+
title?: string
|
|
36
|
+
modal?: {
|
|
37
|
+
title?: string
|
|
38
|
+
subtitle?: string
|
|
39
|
+
apply?: string
|
|
40
|
+
options?: {
|
|
41
|
+
metric: {
|
|
42
|
+
title: string
|
|
43
|
+
options: MeasurementOptionsUnit<MeasurementUnitMetricDistance>
|
|
44
|
+
}
|
|
45
|
+
imperial: {
|
|
46
|
+
title: string
|
|
47
|
+
options: MeasurementOptionsUnit<MeasurementUnitImperialDistance>
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
interface ActionProps {
|
|
56
|
+
TooltipProps?: Omit<TooltipProps, 'title'>
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface MeasurementToolsComponentProps<
|
|
60
|
+
T extends string = MeasurementMode,
|
|
61
|
+
U extends string = MeasurementUnit,
|
|
62
|
+
> {
|
|
63
|
+
enabled: boolean
|
|
64
|
+
value: string
|
|
65
|
+
labels?: Labels
|
|
66
|
+
modesMapping?: MeasurementModesMapping<T>
|
|
67
|
+
unitsMapping?: MeasurementUnitsMapping<U>
|
|
68
|
+
actionProps?: ActionProps
|
|
69
|
+
modeSelected?: T
|
|
70
|
+
modes: Partial<MeasurementModes<T>>
|
|
71
|
+
units: MeasurementUnits<T, U>
|
|
72
|
+
unitSelected?: string
|
|
73
|
+
PaperProps?: ComponentProps<typeof Paper>
|
|
74
|
+
onActionToggle: (data: boolean) => void
|
|
75
|
+
onChangeMode: (mode?: T) => void
|
|
76
|
+
onChangeUnit: (unit: string) => void
|
|
77
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest'
|
|
2
|
+
import { render, within } from '@testing-library/react'
|
|
3
|
+
import { NoDataAlert } from './no-data-alert'
|
|
4
|
+
|
|
5
|
+
describe('NoDataAlert', () => {
|
|
6
|
+
test('with default props', () => {
|
|
7
|
+
const { container } = render(<NoDataAlert />)
|
|
8
|
+
|
|
9
|
+
const title = within(container).queryByText('No data available')
|
|
10
|
+
const body = within(container).queryByText(
|
|
11
|
+
'There are no results for the combination of filters applied to your data. Try tweaking your filters, or zoom and pan the map to adjust the Map View.',
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
expect(title).toBeTruthy()
|
|
15
|
+
expect(body).toBeTruthy()
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
test('with custom title', () => {
|
|
19
|
+
const { container } = render(<NoDataAlert title='Custom title' />)
|
|
20
|
+
|
|
21
|
+
const title = within(container).queryByText('Custom title')
|
|
22
|
+
expect(title).toBeTruthy()
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
test('with custom body', () => {
|
|
26
|
+
const { container } = render(<NoDataAlert body='Custom body' />)
|
|
27
|
+
|
|
28
|
+
const body = within(container).queryByText('Custom body')
|
|
29
|
+
expect(body).toBeTruthy()
|
|
30
|
+
})
|
|
31
|
+
})
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Alert,
|
|
3
|
+
Box,
|
|
4
|
+
Typography,
|
|
5
|
+
type AlertProps,
|
|
6
|
+
type TypographyProps,
|
|
7
|
+
} from '@mui/material'
|
|
8
|
+
|
|
9
|
+
interface NoDataAlertProps {
|
|
10
|
+
title?: string
|
|
11
|
+
body?: string
|
|
12
|
+
severity?: AlertProps['severity']
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function NoDataAlert({
|
|
16
|
+
title = 'No data available',
|
|
17
|
+
body = 'There are no results for the combination of filters applied to your data. Try tweaking your filters, or zoom and pan the map to adjust the Map View.',
|
|
18
|
+
severity,
|
|
19
|
+
}: NoDataAlertProps) {
|
|
20
|
+
if (severity) {
|
|
21
|
+
return (
|
|
22
|
+
<Alert title={title} severity={severity}>
|
|
23
|
+
<AlertBody>{body}</AlertBody>
|
|
24
|
+
</Alert>
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<Box>
|
|
30
|
+
{title && <Typography variant='body2'>{title}</Typography>}
|
|
31
|
+
<AlertBody color='textSecondary'>{body}</AlertBody>
|
|
32
|
+
</Box>
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Aux
|
|
37
|
+
interface AlertBodyProps {
|
|
38
|
+
color?: TypographyProps['color']
|
|
39
|
+
children: React.ReactNode
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function AlertBody({ color, children }: AlertBodyProps) {
|
|
43
|
+
if (children) {
|
|
44
|
+
return (
|
|
45
|
+
<Box mt={0.5}>
|
|
46
|
+
<Typography
|
|
47
|
+
component='div'
|
|
48
|
+
variant='caption'
|
|
49
|
+
color={color ?? 'inherit'}
|
|
50
|
+
style={{ fontWeight: 'normal' }}
|
|
51
|
+
>
|
|
52
|
+
{children}
|
|
53
|
+
</Typography>
|
|
54
|
+
</Box>
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return <Box mt={-1} />
|
|
59
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { render, screen, fireEvent } from '@testing-library/react'
|
|
2
|
+
import { describe, test, expect, vi, beforeEach } from 'vitest'
|
|
3
|
+
import { ResponsiveDrawer } from './responsive-drawer'
|
|
4
|
+
import { ThemeProvider } from '@mui/material'
|
|
5
|
+
import { createTheme } from '@mui/material/styles'
|
|
6
|
+
|
|
7
|
+
// Create a basic theme for testing
|
|
8
|
+
const theme = createTheme()
|
|
9
|
+
|
|
10
|
+
describe('ResponsiveDrawer', () => {
|
|
11
|
+
const mockOnChangeCollapsed = vi.fn()
|
|
12
|
+
|
|
13
|
+
const defaultProps = {
|
|
14
|
+
collapsed: false,
|
|
15
|
+
onChangeCollapsed: mockOnChangeCollapsed,
|
|
16
|
+
position: 'top-left' as const,
|
|
17
|
+
isMobile: false,
|
|
18
|
+
children: <div data-testid='drawer-content'>Test Content</div>,
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
mockOnChangeCollapsed.mockReset()
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
test('renders in desktop mode when isMobile is false', () => {
|
|
26
|
+
const { container } = render(
|
|
27
|
+
<ThemeProvider theme={theme}>
|
|
28
|
+
<ResponsiveDrawer ref={null} {...defaultProps} />
|
|
29
|
+
</ThemeProvider>,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
// Check if content is rendered
|
|
33
|
+
const content = screen.getByTestId('drawer-content')
|
|
34
|
+
expect(content).toBeDefined()
|
|
35
|
+
|
|
36
|
+
// Make sure we're not using the mobile Drawer (no presentation role)
|
|
37
|
+
const presentationElements = container.querySelectorAll(
|
|
38
|
+
'[role="presentation"]',
|
|
39
|
+
)
|
|
40
|
+
expect(presentationElements.length).toBe(0)
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
test('renders in mobile mode when isMobile is true', () => {
|
|
44
|
+
render(
|
|
45
|
+
<ThemeProvider theme={theme}>
|
|
46
|
+
<ResponsiveDrawer ref={null} {...defaultProps} isMobile={true} />
|
|
47
|
+
</ThemeProvider>,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
// Check if content is rendered
|
|
51
|
+
const content = screen.getByTestId('drawer-content')
|
|
52
|
+
expect(content).toBeDefined()
|
|
53
|
+
|
|
54
|
+
// Mobile mode uses MUI Drawer which has a 'presentation' role
|
|
55
|
+
const presentationElements = document.querySelectorAll(
|
|
56
|
+
'[role="presentation"]',
|
|
57
|
+
)
|
|
58
|
+
expect(presentationElements.length).toBeGreaterThan(0)
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
test('hides content when collapsed is true in desktop mode', () => {
|
|
62
|
+
render(
|
|
63
|
+
<ThemeProvider theme={theme}>
|
|
64
|
+
<ResponsiveDrawer ref={null} {...defaultProps} collapsed={true} />
|
|
65
|
+
</ThemeProvider>,
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
// When collapsed, the Popover should be closed and content should not be in the document
|
|
69
|
+
const content = screen.queryByTestId('drawer-content')
|
|
70
|
+
expect(content).toBeNull()
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
test('closes drawer when clicking outside in mobile mode', () => {
|
|
74
|
+
const { container } = render(
|
|
75
|
+
<ThemeProvider theme={theme}>
|
|
76
|
+
<ResponsiveDrawer ref={null} {...defaultProps} isMobile={true} />
|
|
77
|
+
</ThemeProvider>,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
// Find and click the backdrop to close the drawer
|
|
81
|
+
const backdrop = container.querySelector('[role="presentation"] > div')
|
|
82
|
+
expect(backdrop).toBeDefined()
|
|
83
|
+
if (backdrop) {
|
|
84
|
+
fireEvent.click(backdrop)
|
|
85
|
+
|
|
86
|
+
// onChangeCollapsed should be called to close the drawer
|
|
87
|
+
expect(mockOnChangeCollapsed).toHaveBeenCalledTimes(1)
|
|
88
|
+
expect(mockOnChangeCollapsed).toHaveBeenCalledWith(true)
|
|
89
|
+
}
|
|
90
|
+
})
|
|
91
|
+
})
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { Drawer, Popover, type PopoverProps } from '@mui/material'
|
|
2
|
+
import type { ReactNode } from 'react'
|
|
3
|
+
|
|
4
|
+
export function ResponsiveDrawer<
|
|
5
|
+
T extends {
|
|
6
|
+
collapsed: boolean
|
|
7
|
+
onChangeCollapsed: (collapsed: boolean) => void
|
|
8
|
+
position: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'
|
|
9
|
+
slotProps?: PopoverProps['slotProps']
|
|
10
|
+
},
|
|
11
|
+
>({
|
|
12
|
+
ref,
|
|
13
|
+
children,
|
|
14
|
+
collapsed,
|
|
15
|
+
isMobile = false,
|
|
16
|
+
position,
|
|
17
|
+
sx,
|
|
18
|
+
slotProps,
|
|
19
|
+
onChangeCollapsed,
|
|
20
|
+
}: Required<Pick<T, 'collapsed' | 'onChangeCollapsed' | 'position'>> &
|
|
21
|
+
Pick<PopoverProps, 'slotProps' | 'sx'> & {
|
|
22
|
+
ref: HTMLElement | null
|
|
23
|
+
isMobile: boolean
|
|
24
|
+
children: ReactNode
|
|
25
|
+
}) {
|
|
26
|
+
if (isMobile) {
|
|
27
|
+
return (
|
|
28
|
+
<Drawer anchor='bottom' open={!collapsed} onClose={onChangeCollapsed}>
|
|
29
|
+
{children}
|
|
30
|
+
</Drawer>
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<Popover
|
|
36
|
+
sx={sx}
|
|
37
|
+
anchorEl={ref}
|
|
38
|
+
open={!collapsed}
|
|
39
|
+
onClose={() => onChangeCollapsed(true)}
|
|
40
|
+
anchorOrigin={{
|
|
41
|
+
vertical: position.startsWith('bottom') ? 'bottom' : 'top',
|
|
42
|
+
horizontal: position.endsWith('right') ? 'left' : 'right',
|
|
43
|
+
}}
|
|
44
|
+
transformOrigin={{
|
|
45
|
+
vertical: position.startsWith('bottom') ? 'bottom' : 'top',
|
|
46
|
+
horizontal: position.endsWith('right') ? 'right' : 'left',
|
|
47
|
+
}}
|
|
48
|
+
slotProps={slotProps}
|
|
49
|
+
>
|
|
50
|
+
{children}
|
|
51
|
+
</Popover>
|
|
52
|
+
)
|
|
53
|
+
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { describe, test, expect, vi, beforeEach, afterEach } from 'vitest'
|
|
2
|
+
import { render, screen } from '@testing-library/react'
|
|
3
|
+
import * as React from 'react'
|
|
4
|
+
import { SmartTooltip } from './smart-tooltip'
|
|
5
|
+
|
|
6
|
+
// Mock the useLayoutEffect hook for testing overflow scenarios
|
|
7
|
+
vi.mock('react', async () => {
|
|
8
|
+
const actual = await vi.importActual('react')
|
|
9
|
+
return {
|
|
10
|
+
...actual,
|
|
11
|
+
useLayoutEffect: (callback: () => void) => {
|
|
12
|
+
callback()
|
|
13
|
+
},
|
|
14
|
+
}
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
// Setup timers for useLayoutEffect timeout
|
|
18
|
+
beforeEach(() => {
|
|
19
|
+
vi.useFakeTimers()
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
afterEach(() => {
|
|
23
|
+
vi.restoreAllMocks()
|
|
24
|
+
vi.useRealTimers()
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
describe('SmartTooltip', () => {
|
|
28
|
+
const defaultProps = {
|
|
29
|
+
title: 'Test Label',
|
|
30
|
+
children: ({ ref }: { ref: React.Ref<HTMLElement> }) => (
|
|
31
|
+
<div ref={ref as React.Ref<HTMLDivElement>} data-testid='test-child'>
|
|
32
|
+
Content
|
|
33
|
+
</div>
|
|
34
|
+
),
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
test('renders correctly with child element', () => {
|
|
38
|
+
render(<SmartTooltip {...defaultProps} />)
|
|
39
|
+
const child = screen.getByTestId('test-child')
|
|
40
|
+
expect(child).toBeTruthy()
|
|
41
|
+
expect(child.textContent).toBe('Content')
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
test('passes ref to children function', () => {
|
|
45
|
+
const childrenSpy = vi
|
|
46
|
+
.fn()
|
|
47
|
+
.mockReturnValue(<div data-testid='test-child'>Content</div>)
|
|
48
|
+
render(<SmartTooltip title='Test Label'>{childrenSpy}</SmartTooltip>)
|
|
49
|
+
|
|
50
|
+
expect(childrenSpy).toHaveBeenCalledTimes(1)
|
|
51
|
+
// Just check that a ref was passed
|
|
52
|
+
expect(childrenSpy).toHaveBeenCalled()
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
test('handles undefined title', () => {
|
|
56
|
+
render(
|
|
57
|
+
<SmartTooltip title={undefined}>
|
|
58
|
+
{({ ref }) => (
|
|
59
|
+
<div ref={ref as React.Ref<HTMLDivElement>} data-testid='test-child'>
|
|
60
|
+
Content
|
|
61
|
+
</div>
|
|
62
|
+
)}
|
|
63
|
+
</SmartTooltip>,
|
|
64
|
+
)
|
|
65
|
+
const child = screen.getByTestId('test-child')
|
|
66
|
+
expect(child).toBeTruthy()
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
test('updates isOverflowing state when dependencies change', () => {
|
|
70
|
+
const { rerender } = render(
|
|
71
|
+
<SmartTooltip title='Test Label' dependencies={[1]}>
|
|
72
|
+
{({ ref }) => (
|
|
73
|
+
<div ref={ref as React.Ref<HTMLDivElement>} data-testid='test-child'>
|
|
74
|
+
Content
|
|
75
|
+
</div>
|
|
76
|
+
)}
|
|
77
|
+
</SmartTooltip>,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
// Re-render with different dependencies to trigger useLayoutEffect
|
|
81
|
+
rerender(
|
|
82
|
+
<SmartTooltip title='Test Label' dependencies={[2]}>
|
|
83
|
+
{({ ref }) => (
|
|
84
|
+
<div ref={ref as React.Ref<HTMLDivElement>} data-testid='test-child'>
|
|
85
|
+
Content
|
|
86
|
+
</div>
|
|
87
|
+
)}
|
|
88
|
+
</SmartTooltip>,
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
expect(screen.getByTestId('test-child')).toBeTruthy()
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
test('tooltip behavior with overflowing content', () => {
|
|
95
|
+
// Mock the ref.current properties to simulate overflow
|
|
96
|
+
vi.spyOn(React, 'useRef').mockReturnValue({
|
|
97
|
+
current: {
|
|
98
|
+
scrollWidth: 100,
|
|
99
|
+
clientWidth: 50,
|
|
100
|
+
scrollHeight: 100,
|
|
101
|
+
clientHeight: 50,
|
|
102
|
+
},
|
|
103
|
+
} as React.RefObject<HTMLDivElement>)
|
|
104
|
+
|
|
105
|
+
render(<SmartTooltip {...defaultProps} />)
|
|
106
|
+
|
|
107
|
+
// Force the timeout in useLayoutEffect to execute
|
|
108
|
+
vi.runAllTimers()
|
|
109
|
+
|
|
110
|
+
// Verify the tooltip has the correct title
|
|
111
|
+
const tooltipWrapper = screen.getByTestId('test-child')
|
|
112
|
+
expect(tooltipWrapper).toBeTruthy()
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
test('tooltip behavior with non-overflowing content', () => {
|
|
116
|
+
// Mock the ref.current properties to simulate no overflow
|
|
117
|
+
vi.spyOn(React, 'useRef').mockReturnValue({
|
|
118
|
+
current: {
|
|
119
|
+
scrollWidth: 50,
|
|
120
|
+
clientWidth: 100,
|
|
121
|
+
scrollHeight: 50,
|
|
122
|
+
clientHeight: 100,
|
|
123
|
+
},
|
|
124
|
+
} as React.RefObject<HTMLDivElement>)
|
|
125
|
+
|
|
126
|
+
render(<SmartTooltip {...defaultProps} />)
|
|
127
|
+
|
|
128
|
+
// Force the timeout in useLayoutEffect to execute
|
|
129
|
+
vi.runAllTimers()
|
|
130
|
+
|
|
131
|
+
// Verify the tooltip doesn't have a title (since there's no overflow)
|
|
132
|
+
const tooltipWrapper = screen.getByTestId('test-child')
|
|
133
|
+
expect(tooltipWrapper).toBeTruthy()
|
|
134
|
+
// Check that the title attribute is not set since content is not overflowing
|
|
135
|
+
expect(tooltipWrapper?.getAttribute('title')).toBeFalsy()
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
test('accepts custom timeout parameter', () => {
|
|
139
|
+
const customTimeout = 1000
|
|
140
|
+
|
|
141
|
+
// Spy on setTimeout to verify it's called with the custom timeout
|
|
142
|
+
const setTimeoutSpy = vi.spyOn(global, 'setTimeout')
|
|
143
|
+
|
|
144
|
+
render(<SmartTooltip {...defaultProps} timeout={customTimeout} />)
|
|
145
|
+
|
|
146
|
+
expect(setTimeoutSpy).toHaveBeenCalledWith(
|
|
147
|
+
expect.any(Function),
|
|
148
|
+
customTimeout,
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
setTimeoutSpy.mockRestore()
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
test('passes TooltipProps to the Tooltip component', () => {
|
|
155
|
+
render(
|
|
156
|
+
<SmartTooltip
|
|
157
|
+
{...defaultProps}
|
|
158
|
+
TooltipProps={{
|
|
159
|
+
placement: 'bottom',
|
|
160
|
+
arrow: true,
|
|
161
|
+
}}
|
|
162
|
+
/>,
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
const tooltipWrapper = screen.getByTestId('test-child')
|
|
166
|
+
expect(tooltipWrapper).toBeTruthy()
|
|
167
|
+
})
|
|
168
|
+
})
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { TooltipProps } from '@mui/material'
|
|
2
|
+
import { useLayoutEffect, useRef, useState, type JSX, type Ref } from 'react'
|
|
3
|
+
import { Tooltip } from '../tooltip/tooltip'
|
|
4
|
+
|
|
5
|
+
export function SmartTooltip<T extends HTMLElement>({
|
|
6
|
+
title,
|
|
7
|
+
dependencies = [],
|
|
8
|
+
timeout = 500,
|
|
9
|
+
TooltipProps,
|
|
10
|
+
children,
|
|
11
|
+
}: {
|
|
12
|
+
title: string | undefined
|
|
13
|
+
dependencies?: unknown[]
|
|
14
|
+
timeout?: number
|
|
15
|
+
children: (props: { ref: Ref<T> }) => JSX.Element
|
|
16
|
+
TooltipProps?: Partial<TooltipProps>
|
|
17
|
+
}) {
|
|
18
|
+
const ref = useRef<T>(null)
|
|
19
|
+
const [isOverflowing, setIsOverflowing] = useState(false)
|
|
20
|
+
|
|
21
|
+
useLayoutEffect(() => {
|
|
22
|
+
const timerId = setTimeout(() => {
|
|
23
|
+
if (ref.current) {
|
|
24
|
+
const isOverflowing =
|
|
25
|
+
ref.current.scrollWidth > ref.current.clientWidth ||
|
|
26
|
+
ref.current.scrollHeight > ref.current.clientHeight
|
|
27
|
+
|
|
28
|
+
setIsOverflowing(isOverflowing)
|
|
29
|
+
}
|
|
30
|
+
}, timeout)
|
|
31
|
+
|
|
32
|
+
return () => clearTimeout(timerId)
|
|
33
|
+
}, [dependencies, timeout])
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<Tooltip title={isOverflowing && title} {...TooltipProps}>
|
|
37
|
+
{children({ ref })}
|
|
38
|
+
</Tooltip>
|
|
39
|
+
)
|
|
40
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest'
|
|
2
|
+
import { render, screen } from '@testing-library/react'
|
|
3
|
+
import { Tooltip, setTooltipEnterDelay } from './tooltip'
|
|
4
|
+
|
|
5
|
+
describe('Tooltip', () => {
|
|
6
|
+
test('renders children correctly', () => {
|
|
7
|
+
render(
|
|
8
|
+
<Tooltip title='Test tooltip'>
|
|
9
|
+
<button>Hover me</button>
|
|
10
|
+
</Tooltip>,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
expect(screen.getByText('Hover me')).toBeTruthy()
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
test('uses default enterNextDelay of 1000ms', () => {
|
|
17
|
+
render(
|
|
18
|
+
<Tooltip title='Test tooltip'>
|
|
19
|
+
<button>Hover me</button>
|
|
20
|
+
</Tooltip>,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
// Since we're wrapping MUI Tooltip and not altering its behavior much,
|
|
24
|
+
// and MUI applies most props internally, we can't easily test the
|
|
25
|
+
// enterNextDelay prop directly. Instead, we verify the component renders.
|
|
26
|
+
expect(screen.getByText('Hover me')).toBeTruthy()
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
test('accepts custom enterNextDelay', () => {
|
|
30
|
+
render(
|
|
31
|
+
<Tooltip title='Test tooltip' enterNextDelay={500}>
|
|
32
|
+
<button>Hover me</button>
|
|
33
|
+
</Tooltip>,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
// Similar to above test, we mainly ensure the component renders correctly
|
|
37
|
+
expect(screen.getByText('Hover me')).toBeTruthy()
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
test('passes additional props to MUI Tooltip', () => {
|
|
41
|
+
render(
|
|
42
|
+
<Tooltip
|
|
43
|
+
title='Test tooltip'
|
|
44
|
+
placement='bottom'
|
|
45
|
+
arrow={true}
|
|
46
|
+
data-testid='custom-tooltip'
|
|
47
|
+
>
|
|
48
|
+
<button>Hover me</button>
|
|
49
|
+
</Tooltip>,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
// Verify that our wrapper properly passes through props
|
|
53
|
+
const tooltipWrapper = screen
|
|
54
|
+
.getByText('Hover me')
|
|
55
|
+
.closest('[data-testid="custom-tooltip"]')
|
|
56
|
+
expect(tooltipWrapper).toBeTruthy()
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
test('setTooltipEnterDelay function sets the delay', () => {
|
|
60
|
+
const delay = 700
|
|
61
|
+
setTooltipEnterDelay(delay)
|
|
62
|
+
|
|
63
|
+
// We can't test the internal implementation, but we can ensure that
|
|
64
|
+
// the function can be called without errors.
|
|
65
|
+
expect(() => setTooltipEnterDelay(delay)).not.toThrow()
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
test('setTooltipEnterDelay updates the default enter delay', () => {
|
|
69
|
+
const newDelay = 2000
|
|
70
|
+
setTooltipEnterDelay(newDelay)
|
|
71
|
+
|
|
72
|
+
render(
|
|
73
|
+
<Tooltip title='Test tooltip'>
|
|
74
|
+
<button>Hover me</button>
|
|
75
|
+
</Tooltip>,
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
// After setting a new delay, the component should use that as the default
|
|
79
|
+
// We can verify by checking the props passed to the rendered component
|
|
80
|
+
const tooltipElement = screen.getByText('Hover me').parentElement
|
|
81
|
+
expect(tooltipElement).toBeTruthy()
|
|
82
|
+
|
|
83
|
+
// Reset the delay for other tests
|
|
84
|
+
setTooltipEnterDelay(1000)
|
|
85
|
+
})
|
|
86
|
+
})
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Tooltip as MuiTooltip, type TooltipProps } from '@mui/material'
|
|
2
|
+
|
|
3
|
+
let tooltipEnterDelay = 500
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A wrapper around MUI's Tooltip component with enterNextDelay set to 1000ms by default.
|
|
7
|
+
*
|
|
8
|
+
* This component ensures consistent tooltip behavior across the application.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* <Tooltip title="This is a tooltip">
|
|
12
|
+
* <Button>Hover me</Button>
|
|
13
|
+
* </Tooltip>
|
|
14
|
+
*/
|
|
15
|
+
export function Tooltip({
|
|
16
|
+
children,
|
|
17
|
+
title,
|
|
18
|
+
enterNextDelay = tooltipEnterDelay,
|
|
19
|
+
...props
|
|
20
|
+
}: TooltipProps) {
|
|
21
|
+
return (
|
|
22
|
+
<MuiTooltip title={title} enterNextDelay={enterNextDelay} {...props}>
|
|
23
|
+
{children}
|
|
24
|
+
</MuiTooltip>
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function setTooltipEnterDelay(delay: number) {
|
|
29
|
+
tooltipEnterDelay = delay
|
|
30
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './common-types'
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { SxProps, Theme } from '@mui/material'
|
|
2
|
+
|
|
3
|
+
export const styles = {
|
|
4
|
+
zoom: {
|
|
5
|
+
position: 'relative',
|
|
6
|
+
height: ({ spacing }) => spacing(4),
|
|
7
|
+
aspectRatio: 1,
|
|
8
|
+
display: 'flex',
|
|
9
|
+
alignItems: 'center',
|
|
10
|
+
justifyContent: 'center',
|
|
11
|
+
},
|
|
12
|
+
paper: {
|
|
13
|
+
display: 'flex',
|
|
14
|
+
backgroundColor: ({ palette }) => palette.background.paper,
|
|
15
|
+
width: 'auto',
|
|
16
|
+
overflow: 'hidden',
|
|
17
|
+
boxShadow: ({ shadows }) => shadows[1],
|
|
18
|
+
borderRadius: ({ spacing }) => spacing(0.5),
|
|
19
|
+
|
|
20
|
+
button: {
|
|
21
|
+
borderRadius: 0,
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
circularProgress: {
|
|
25
|
+
position: 'absolute',
|
|
26
|
+
},
|
|
27
|
+
} satisfies Record<string, SxProps<Theme>>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Paper } from '@mui/material'
|
|
2
|
+
import type { ComponentProps, ElementType } from 'react'
|
|
3
|
+
|
|
4
|
+
export interface ZoomControlProps {
|
|
5
|
+
zoom: number
|
|
6
|
+
direction?: 'vertical' | 'horizontal'
|
|
7
|
+
reverse?: boolean
|
|
8
|
+
disabled?: boolean
|
|
9
|
+
isLoading?: boolean
|
|
10
|
+
maxZoom?: number
|
|
11
|
+
minZoom?: number
|
|
12
|
+
PaperProps?: ComponentProps<typeof Paper>
|
|
13
|
+
ResetViewProps?: {
|
|
14
|
+
Icon: ElementType
|
|
15
|
+
}
|
|
16
|
+
showZoom?: boolean
|
|
17
|
+
onChange: (zoom: number) => void
|
|
18
|
+
onReset?: () => void
|
|
19
|
+
}
|