@cfasim-ui/docs 0.7.2 → 0.7.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.
|
@@ -279,10 +279,10 @@ hide it.
|
|
|
279
279
|
full extent.
|
|
280
280
|
- **Touch:** a **double tap** expands the map to fill the window, zoomed
|
|
281
281
|
in on the tapped point; single taps select features inline. Inside the
|
|
282
|
-
expanded view, one finger pans, a pinch zooms, and a tap selects
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
still scrolls the page.
|
|
282
|
+
expanded view, one finger pans, a pinch zooms, and a tap selects — its
|
|
283
|
+
tooltip slides up as a bottom sheet; the +/−/reset controls sit top-left
|
|
284
|
+
and a close (✕) button top-right returns to the inline map at full
|
|
285
|
+
extent. A single finger over the inline map still scrolls the page.
|
|
286
286
|
|
|
287
287
|
Filling the window is always an activated state: whether entered via the
|
|
288
288
|
menu's **Fullscreen** item or a double tap, pan/zoom works immediately and
|
|
@@ -319,11 +319,16 @@ pans, and touch gestures work inline with no tap-to-expand step. The
|
|
|
319
319
|
|
|
320
320
|
Set `geoType="counties"` to render county-level data using 5-digit FIPS codes. State borders are drawn on top for context. Double-click (or double-tap on touch) to explore — useful for dense county data.
|
|
321
321
|
|
|
322
|
+
This demo also wires up an interactive tooltip (`tooltip-trigger="hover"`):
|
|
323
|
+
hover a county on desktop, or tap one on touch, and it works the same
|
|
324
|
+
before and after zooming in.
|
|
325
|
+
|
|
322
326
|
<ComponentDemo>
|
|
323
327
|
<ChoroplethMap
|
|
324
328
|
:topology="countiesTopo"
|
|
325
329
|
geo-type="counties"
|
|
326
330
|
zoom
|
|
331
|
+
tooltip-trigger="hover"
|
|
327
332
|
:data="[
|
|
328
333
|
{ id: '06037', value: 100 },
|
|
329
334
|
{ id: '06073', value: 80 },
|
|
@@ -348,6 +353,7 @@ Set `geoType="counties"` to render county-level data using 5-digit FIPS codes. S
|
|
|
348
353
|
:topology="countiesTopo"
|
|
349
354
|
geo-type="counties"
|
|
350
355
|
zoom
|
|
356
|
+
tooltip-trigger="hover"
|
|
351
357
|
:data="[
|
|
352
358
|
{ id: '06037', value: 100 },
|
|
353
359
|
{ id: '36061', value: 90 },
|
|
@@ -368,11 +374,15 @@ Set `geoType="counties"` to render county-level data using 5-digit FIPS codes. S
|
|
|
368
374
|
|
|
369
375
|
Set `geoType="hsas"` to render Health Service Area boundaries. HSAs are dissolved from county boundaries using a built-in FIPS-to-HSA mapping. Use 6-digit HSA codes as IDs. State borders are overlaid for context.
|
|
370
376
|
|
|
377
|
+
This demo pairs `tooltip-trigger="hover"` with a custom `#tooltip` slot —
|
|
378
|
+
hover an HSA on desktop, or tap one on touch, before or after zooming in.
|
|
379
|
+
|
|
371
380
|
<ComponentDemo>
|
|
372
381
|
<ChoroplethMap
|
|
373
382
|
:topology="countiesTopo"
|
|
374
383
|
geo-type="hsas"
|
|
375
384
|
zoom
|
|
385
|
+
tooltip-trigger="hover"
|
|
376
386
|
:data="[
|
|
377
387
|
{ id: '010259', value: 100 },
|
|
378
388
|
{ id: '060766', value: 90 },
|
|
@@ -388,7 +398,14 @@ Set `geoType="hsas"` to render Health Service Area boundaries. HSAs are dissolve
|
|
|
388
398
|
title="Cases by HSA"
|
|
389
399
|
:legend-title="'Cases'"
|
|
390
400
|
:height="400"
|
|
391
|
-
|
|
401
|
+
>
|
|
402
|
+
<template #tooltip="{ id, name, value }">
|
|
403
|
+
<div style="font-weight: 600">{{ name }}</div>
|
|
404
|
+
<div style="opacity: 0.7; font-size: 0.85em">HSA {{ id }}</div>
|
|
405
|
+
<div v-if="value != null">Cases: {{ value }}</div>
|
|
406
|
+
<div v-else style="opacity: 0.6">No data</div>
|
|
407
|
+
</template>
|
|
408
|
+
</ChoroplethMap>
|
|
392
409
|
|
|
393
410
|
<template #code>
|
|
394
411
|
|
|
@@ -397,6 +414,7 @@ Set `geoType="hsas"` to render Health Service Area boundaries. HSAs are dissolve
|
|
|
397
414
|
:topology="countiesTopo"
|
|
398
415
|
geo-type="hsas"
|
|
399
416
|
zoom
|
|
417
|
+
tooltip-trigger="hover"
|
|
400
418
|
:data="[
|
|
401
419
|
{ id: '010259', value: 100 },
|
|
402
420
|
{ id: '060766', value: 90 },
|
|
@@ -407,7 +425,14 @@ Set `geoType="hsas"` to render Health Service Area boundaries. HSAs are dissolve
|
|
|
407
425
|
title="Cases by HSA"
|
|
408
426
|
:legend-title="'Cases'"
|
|
409
427
|
:height="400"
|
|
410
|
-
|
|
428
|
+
>
|
|
429
|
+
<template #tooltip="{ id, name, value }">
|
|
430
|
+
<div style="font-weight: 600">{{ name }}</div>
|
|
431
|
+
<div style="opacity: 0.7; font-size: 0.85em">HSA {{ id }}</div>
|
|
432
|
+
<div v-if="value != null">Cases: {{ value }}</div>
|
|
433
|
+
<div v-else style="opacity: 0.6">No data</div>
|
|
434
|
+
</template>
|
|
435
|
+
</ChoroplethMap>
|
|
411
436
|
```
|
|
412
437
|
|
|
413
438
|
</template>
|
|
@@ -499,8 +524,9 @@ Selection works the same on touch: a single-finger **tap** on a feature
|
|
|
499
524
|
emits `stateClick` and toggles focus, inline or inside the expanded view.
|
|
500
525
|
(Inline with `zoom` on, the selection fires after the brief double-tap
|
|
501
526
|
window.) A tap also stands in for hover — it applies the hover highlight,
|
|
502
|
-
emits `stateHover`, and shows the feature's tooltip
|
|
503
|
-
|
|
527
|
+
emits `stateHover`, and shows the feature's tooltip (anchored to the
|
|
528
|
+
feature inline; sliding up as a bottom sheet in the expanded view); only
|
|
529
|
+
continuous hover _tracking_ is off on touch, for performance.
|
|
504
530
|
|
|
505
531
|
Click-to-focus interactions usually pair best with `:touch-expand="false"`,
|
|
506
532
|
as in the demos below — a double tap zooms in place while taps keep
|
|
@@ -474,6 +474,8 @@ function setupInteraction() {
|
|
|
474
474
|
// `touchend` is non-passive so a confirmed tap can preventDefault and
|
|
475
475
|
// suppress the compatibility click/hover the browser would otherwise
|
|
476
476
|
// synthesize (the double-fire and iOS first-tap-hover sources).
|
|
477
|
+
// Must run before setupZoom(): d3-zoom stopImmediatePropagation()s
|
|
478
|
+
// touch events once its filter passes, which would starve these.
|
|
477
479
|
svg.addEventListener("touchstart", onTouchStart, { passive: true });
|
|
478
480
|
svg.addEventListener("touchend", onTouchEnd);
|
|
479
481
|
svg.addEventListener("touchcancel", onTouchCancel, { passive: true });
|
|
@@ -515,8 +517,13 @@ function dismissOnViewportChange() {
|
|
|
515
517
|
let svgResizeObserver: ResizeObserver | null = null;
|
|
516
518
|
|
|
517
519
|
onMounted(() => {
|
|
518
|
-
|
|
520
|
+
// Order is load-bearing: once its filter passes (zoom activated /
|
|
521
|
+
// expanded), d3-zoom calls stopImmediatePropagation() on touchstart and
|
|
522
|
+
// touchend. Same-element listeners run in registration order, so our
|
|
523
|
+
// tap listeners must be registered BEFORE d3-zoom's or taps (selection,
|
|
524
|
+
// tooltips) go dead the moment the map owns touch gestures.
|
|
519
525
|
setupInteraction();
|
|
526
|
+
setupZoom();
|
|
520
527
|
rebuildPaths();
|
|
521
528
|
applyFocus();
|
|
522
529
|
attachTooltipObserver();
|
|
@@ -555,11 +562,20 @@ function setupZoom() {
|
|
|
555
562
|
const svg = select(svgRef.value);
|
|
556
563
|
zoomBehavior = d3Zoom<SVGSVGElement, unknown>()
|
|
557
564
|
.scaleExtent([1, maxScale.value])
|
|
565
|
+
// d3-zoom swallows the click after any mousedown→mouseup movement
|
|
566
|
+
// beyond this distance. The default of 0 makes clicks unreliable the
|
|
567
|
+
// moment drag-pan is live (a pixel of hand jitter reads as a drag),
|
|
568
|
+
// so allow a few pixels of slack.
|
|
569
|
+
.clickDistance(6)
|
|
558
570
|
.on("start", () => {
|
|
559
571
|
isZooming = true;
|
|
560
|
-
clearHover();
|
|
561
572
|
})
|
|
562
573
|
.on("zoom", (event) => {
|
|
574
|
+
// Cleared here, not on gesture start: a plain mousedown opens a
|
|
575
|
+
// gesture once drag-pan is live, and hiding the tooltip on every
|
|
576
|
+
// click press felt broken. The tooltip only needs to go once the
|
|
577
|
+
// map actually moves under the cursor.
|
|
578
|
+
clearHover();
|
|
563
579
|
if (mapGroupRef.value) {
|
|
564
580
|
mapGroupRef.value.setAttribute("transform", event.transform);
|
|
565
581
|
}
|
|
@@ -924,8 +940,12 @@ const svgStyle = computed(() => {
|
|
|
924
940
|
if (
|
|
925
941
|
hasZoomed.value ||
|
|
926
942
|
fullscreen.isFullscreen.value ||
|
|
927
|
-
(props.zoom && isScrollMode.value)
|
|
943
|
+
(props.zoom && (isScrollMode.value || isTouchDevice()))
|
|
928
944
|
) {
|
|
945
|
+
// Touch maps get the layer up front, not just once zoomed: a tap
|
|
946
|
+
// restyles a feature path, and without the layer WebKit repaints the
|
|
947
|
+
// surrounding page layer (~200ms per mutation on the HSA map — taps
|
|
948
|
+
// felt sluggish inline while fullscreen, already layered, was fast).
|
|
929
949
|
style["will-change"] = "transform";
|
|
930
950
|
}
|
|
931
951
|
return Object.keys(style).length ? style : undefined;
|
|
@@ -1511,23 +1531,53 @@ function applyTooltipPosition(clientX: number, clientY: number) {
|
|
|
1511
1531
|
chartRect,
|
|
1512
1532
|
);
|
|
1513
1533
|
el.style.transform = `translate3d(${left}px, ${top}px, 0) translateY(-50%)`;
|
|
1534
|
+
// Safari reports client coordinates (events AND element rects) in
|
|
1535
|
+
// visual-viewport space, while position: fixed resolves against the
|
|
1536
|
+
// layout viewport — under page pinch-zoom the tooltip lands offset from
|
|
1537
|
+
// its target (typically "too high" by the pan offset). Rather than
|
|
1538
|
+
// sniffing engines, self-calibrate: re-measure where the tooltip
|
|
1539
|
+
// actually landed — the rect comes back in the same client space as the
|
|
1540
|
+
// target coords — and shift by the residual. Chrome measures ~0.
|
|
1541
|
+
const vv = typeof window !== "undefined" ? window.visualViewport : null;
|
|
1542
|
+
if (!vv || (vv.scale <= 1.01 && vv.offsetTop < 1 && vv.offsetLeft < 1)) {
|
|
1543
|
+
return;
|
|
1544
|
+
}
|
|
1545
|
+
const actual = el.getBoundingClientRect();
|
|
1546
|
+
const dx = actual.left - left;
|
|
1547
|
+
const dy = actual.top + actual.height / 2 - top;
|
|
1548
|
+
if (Math.abs(dx) > 1 || Math.abs(dy) > 1) {
|
|
1549
|
+
el.style.transform = `translate3d(${left - dx}px, ${top - dy}px, 0) translateY(-50%)`;
|
|
1550
|
+
}
|
|
1514
1551
|
}
|
|
1515
1552
|
|
|
1553
|
+
// The expanded touch view swaps the pointer-anchored tooltip for a bottom
|
|
1554
|
+
// sheet: floating fixed positioning is unreliable there (Safari reports
|
|
1555
|
+
// touch/rect coordinates in visual-viewport space once the page is
|
|
1556
|
+
// pinch-zoomed), while a sheet pinned to the wrapper is always right.
|
|
1557
|
+
const tooltipMode = computed<"float" | "sheet">(() =>
|
|
1558
|
+
fullscreen.isFullscreen.value && isTouchDevice() ? "sheet" : "float",
|
|
1559
|
+
);
|
|
1560
|
+
|
|
1516
1561
|
function showTooltip(featId: string, clientX: number, clientY: number) {
|
|
1517
1562
|
const data = tooltipDataById.get(featId);
|
|
1518
1563
|
if (!data) return;
|
|
1519
1564
|
const child = tooltipChildRef.value;
|
|
1520
|
-
|
|
1521
|
-
if (!child || !el) return;
|
|
1565
|
+
if (!child) return;
|
|
1522
1566
|
child.setData(data);
|
|
1523
|
-
lastPointer = { x: clientX, y: clientY };
|
|
1524
1567
|
tooltipVisible = true;
|
|
1568
|
+
if (tooltipMode.value === "sheet") {
|
|
1569
|
+
child.setOpen(true);
|
|
1570
|
+
return;
|
|
1571
|
+
}
|
|
1572
|
+
const el = child.getEl();
|
|
1573
|
+
if (!el) return;
|
|
1574
|
+
lastPointer = { x: clientX, y: clientY };
|
|
1525
1575
|
applyTooltipPosition(clientX, clientY);
|
|
1526
1576
|
el.style.visibility = "visible";
|
|
1527
1577
|
}
|
|
1528
1578
|
|
|
1529
1579
|
function moveTooltip(clientX: number, clientY: number) {
|
|
1530
|
-
if (!tooltipVisible) return;
|
|
1580
|
+
if (!tooltipVisible || tooltipMode.value === "sheet") return;
|
|
1531
1581
|
pendingMoveX = clientX;
|
|
1532
1582
|
pendingMoveY = clientY;
|
|
1533
1583
|
if (pendingMoveFrame) return;
|
|
@@ -1545,6 +1595,7 @@ function hideTooltip() {
|
|
|
1545
1595
|
if (!tooltipVisible) return;
|
|
1546
1596
|
tooltipVisible = false;
|
|
1547
1597
|
lastPointer = null;
|
|
1598
|
+
tooltipChildRef.value?.setOpen(false);
|
|
1548
1599
|
const el = tooltipChildRef.value?.getEl();
|
|
1549
1600
|
if (el) el.style.visibility = "hidden";
|
|
1550
1601
|
}
|
|
@@ -1690,7 +1741,10 @@ function emitSelection(data: TooltipPayload) {
|
|
|
1690
1741
|
}
|
|
1691
1742
|
|
|
1692
1743
|
function onDelegatedEvent(event: Event) {
|
|
1693
|
-
|
|
1744
|
+
// Only hover is suppressed mid-gesture (stroke churn while the map
|
|
1745
|
+
// moves); clicks stay live — even during zoom animations — since d3
|
|
1746
|
+
// already swallows genuine post-drag clicks via clickDistance.
|
|
1747
|
+
if (event.type === "mouseover" && isZooming) return;
|
|
1694
1748
|
const me = event as MouseEvent;
|
|
1695
1749
|
const featId = eventToFeatureId(me.target);
|
|
1696
1750
|
if (!featId) return;
|
|
@@ -1821,14 +1875,29 @@ function onTouchEnd(event: TouchEvent) {
|
|
|
1821
1875
|
}
|
|
1822
1876
|
|
|
1823
1877
|
// A tap doubles as the touch replacement for hover: apply the hover-style
|
|
1824
|
-
// highlight, announce it, and show the tooltip
|
|
1825
|
-
//
|
|
1826
|
-
//
|
|
1878
|
+
// highlight, announce it, and show the tooltip. (Continuous hover
|
|
1879
|
+
// *tracking* stays off on touch — see setupInteraction — this is the
|
|
1880
|
+
// one-shot equivalent.)
|
|
1827
1881
|
function touchHover(data: TooltipPayload, clientX: number, clientY: number) {
|
|
1828
1882
|
const pathEl = pathsByFeatureId.get(data.id);
|
|
1829
1883
|
if (pathEl) setHover(pathEl);
|
|
1830
1884
|
emit("stateHover", { id: data.id, name: data.name, value: data.value });
|
|
1831
|
-
if (hasInteractiveTooltip.value)
|
|
1885
|
+
if (!hasInteractiveTooltip.value) return;
|
|
1886
|
+
if (pathEl) {
|
|
1887
|
+
// Anchor to the feature, not the finger: element rects and fixed
|
|
1888
|
+
// positioning share the layout-viewport coordinate space, so this
|
|
1889
|
+
// stays put when the page itself is pinch-zoomed — Safari reports
|
|
1890
|
+
// touch client coords in *visual*-viewport space, which would skew a
|
|
1891
|
+
// finger-anchored tooltip. Also keeps it out from under the finger.
|
|
1892
|
+
const rect = pathEl.getBoundingClientRect();
|
|
1893
|
+
showTooltip(
|
|
1894
|
+
data.id,
|
|
1895
|
+
rect.left + rect.width / 2,
|
|
1896
|
+
rect.top + rect.height / 2,
|
|
1897
|
+
);
|
|
1898
|
+
} else {
|
|
1899
|
+
showTooltip(data.id, clientX, clientY);
|
|
1900
|
+
}
|
|
1832
1901
|
}
|
|
1833
1902
|
|
|
1834
1903
|
function onTouchCancel() {
|
|
@@ -2099,10 +2168,12 @@ watch(
|
|
|
2099
2168
|
|
|
2100
2169
|
// Exiting the expanded touch view (✕, Escape) returns to the static inline
|
|
2101
2170
|
// map at full extent — the inline map has no pan gestures, so a preserved
|
|
2102
|
-
// transform would strand the user off-center.
|
|
2171
|
+
// transform would strand the user off-center. Any toggle also drops the
|
|
2172
|
+
// tooltip: the presentation mode (float vs sheet) may change with it.
|
|
2103
2173
|
watch(
|
|
2104
2174
|
() => fullscreen.isFullscreen.value,
|
|
2105
2175
|
(expanded) => {
|
|
2176
|
+
hideTooltip();
|
|
2106
2177
|
if (expanded || !isTouchDevice()) return;
|
|
2107
2178
|
if (!svgRef.value || !zoomBehavior) return;
|
|
2108
2179
|
const svg = select(svgRef.value);
|
|
@@ -2222,7 +2293,11 @@ watch(
|
|
|
2222
2293
|
@zoom-out="zoomBy(1 / ZOOM_STEP)"
|
|
2223
2294
|
@reset="resetZoom"
|
|
2224
2295
|
/>
|
|
2225
|
-
<ChoroplethTooltip
|
|
2296
|
+
<ChoroplethTooltip
|
|
2297
|
+
v-if="hasInteractiveTooltip"
|
|
2298
|
+
ref="tooltipChildRef"
|
|
2299
|
+
:mode="tooltipMode"
|
|
2300
|
+
>
|
|
2226
2301
|
<template #default="raw">
|
|
2227
2302
|
<slot name="tooltip" v-bind="narrowSlotProps(raw)">
|
|
2228
2303
|
<span v-if="tooltipFormat" v-html="tooltipFormat(raw)" />
|
|
@@ -8,20 +8,36 @@ export interface ChoroplethTooltipData {
|
|
|
8
8
|
feature: unknown;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
withDefaults(
|
|
12
|
+
defineProps<{
|
|
13
|
+
/**
|
|
14
|
+
* `"float"` (default) renders the classic pointer-anchored tooltip.
|
|
15
|
+
* `"sheet"` renders a bottom sheet that slides up inside the map
|
|
16
|
+
* wrapper instead — used in the expanded touch view, where it stays
|
|
17
|
+
* correctly positioned regardless of the page's pinch-zoom state
|
|
18
|
+
* (the wrapper is pinned to the visual viewport; floating fixed
|
|
19
|
+
* positioning is not).
|
|
20
|
+
*/
|
|
21
|
+
mode?: "float" | "sheet";
|
|
22
|
+
}>(),
|
|
23
|
+
{ mode: "float" },
|
|
24
|
+
);
|
|
14
25
|
|
|
15
26
|
// Local reactive state. Held inside the child so the parent's render scope
|
|
16
27
|
// never subscribes to it — hover updates re-render only this small tree,
|
|
17
28
|
// not the parent's 3,000+ paths.
|
|
18
29
|
const data = ref<ChoroplethTooltipData | null>(null);
|
|
30
|
+
const open = ref(false);
|
|
19
31
|
const rootRef = useTemplateRef<HTMLDivElement>("root");
|
|
20
32
|
|
|
21
33
|
defineExpose({
|
|
22
34
|
setData(next: ChoroplethTooltipData | null) {
|
|
23
35
|
data.value = next;
|
|
24
36
|
},
|
|
37
|
+
/** Sheet-mode visibility (float mode is driven imperatively via getEl). */
|
|
38
|
+
setOpen(next: boolean) {
|
|
39
|
+
open.value = next;
|
|
40
|
+
},
|
|
25
41
|
getEl(): HTMLDivElement | null {
|
|
26
42
|
return rootRef.value;
|
|
27
43
|
},
|
|
@@ -29,6 +45,10 @@ defineExpose({
|
|
|
29
45
|
</script>
|
|
30
46
|
|
|
31
47
|
<template>
|
|
48
|
+
<!-- Float: always mounted (the parent's ResizeObserver holds onto it);
|
|
49
|
+
its slot only renders in float mode. z-index sits one above the
|
|
50
|
+
fullscreen overlay so it stays visible while the map fills the window
|
|
51
|
+
(both live in body). -->
|
|
32
52
|
<Teleport to="body">
|
|
33
53
|
<div
|
|
34
54
|
ref="root"
|
|
@@ -37,13 +57,47 @@ defineExpose({
|
|
|
37
57
|
position: fixed;
|
|
38
58
|
left: 0;
|
|
39
59
|
top: 0;
|
|
60
|
+
z-index: calc(var(--cfasim-z-fullscreen, 1000) + 1);
|
|
40
61
|
visibility: hidden;
|
|
41
62
|
will-change: transform;
|
|
42
63
|
pointer-events: none;
|
|
43
64
|
transform: translateY(-50%);
|
|
44
65
|
"
|
|
45
66
|
>
|
|
46
|
-
<slot v-if="data" v-bind="data" />
|
|
67
|
+
<slot v-if="data && mode === 'float'" v-bind="data" />
|
|
47
68
|
</div>
|
|
48
69
|
</Teleport>
|
|
70
|
+
<!-- Sheet: rendered in place inside the map wrapper, so it anchors to
|
|
71
|
+
the (visual-viewport-pinned) expanded box. -->
|
|
72
|
+
<div
|
|
73
|
+
v-if="mode === 'sheet'"
|
|
74
|
+
class="chart-tooltip-sheet"
|
|
75
|
+
:class="{ 'is-open': open }"
|
|
76
|
+
>
|
|
77
|
+
<slot v-if="data" v-bind="data" />
|
|
78
|
+
</div>
|
|
49
79
|
</template>
|
|
80
|
+
|
|
81
|
+
<style scoped>
|
|
82
|
+
.chart-tooltip-sheet {
|
|
83
|
+
position: absolute;
|
|
84
|
+
left: 0;
|
|
85
|
+
right: 0;
|
|
86
|
+
bottom: 0;
|
|
87
|
+
z-index: 2;
|
|
88
|
+
background: var(--color-bg-0, #fff);
|
|
89
|
+
color: var(--color-text, inherit);
|
|
90
|
+
border-top: 1px solid var(--color-border, #e5e7eb);
|
|
91
|
+
box-shadow: 0 -4px 12px rgba(0, 0, 0, 0.12);
|
|
92
|
+
padding: 14px 16px calc(14px + env(safe-area-inset-bottom, 0px));
|
|
93
|
+
font-size: 14px;
|
|
94
|
+
line-height: 1.4;
|
|
95
|
+
pointer-events: none;
|
|
96
|
+
transform: translateY(100%);
|
|
97
|
+
transition: transform 0.25s ease;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.chart-tooltip-sheet.is-open {
|
|
101
|
+
transform: translateY(0);
|
|
102
|
+
}
|
|
103
|
+
</style>
|
package/index.json
CHANGED