@sybilion/uilib 1.3.19 → 1.3.21
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/esm/components/ui/Chart/Chart.styl.js +2 -2
- package/dist/esm/components/ui/Chart/components/ChartTooltipItem.js +1 -1
- package/dist/esm/components/ui/Dialog/Dialog.js +10 -2
- package/dist/esm/constants/appMount.js +5 -0
- package/dist/esm/types/src/constants/appMount.d.ts +4 -0
- package/package.json +1 -1
- package/src/components/ui/Chart/Chart.styl +23 -4
- package/src/components/ui/Chart/Chart.styl.d.ts +1 -0
- package/src/components/ui/Chart/components/ChartTooltipItem.tsx +1 -1
- package/src/components/ui/Dialog/Dialog.tsx +19 -2
- package/src/constants/appMount.ts +5 -0
- package/src/docs/index.tsx +2 -1
- package/src/docs/pages/ChartAreaInteractivePage.tsx +4 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import styleInject from 'style-inject';
|
|
2
2
|
|
|
3
|
-
var css_248z = ".Chart_chartContainer__--q1l{aspect-ratio:16/9;display:flex;font-size:.75rem;justify-content:center;line-height:1rem;max-width:100%;touch-action:none;width:100%}.Chart_chartContainer__--q1l .recharts-cartesian-axis-tick text{fill:var(--muted-foreground)}.Chart_chartContainer__--q1l .recharts-cartesian-grid line[stroke=\"#ccc\"]{stroke:var(--border)}.dark .Chart_chartContainer__--q1l .recharts-cartesian-grid line[stroke=\"#ccc\"]{stroke:var(--sb-slate-900)}.Chart_chartContainer__--q1l .recharts-curve.recharts-tooltip-cursor,.Chart_chartContainer__--q1l .recharts-polar-grid [stroke=\"#ccc\"]{stroke:var(--border)}.Chart_chartContainer__--q1l .recharts-radial-bar-background-sector,.Chart_chartContainer__--q1l .recharts-rectangle.recharts-tooltip-cursor{fill:var(--muted)}.Chart_chartContainer__--q1l .recharts-reference-line [stroke=\"#ccc\"]{stroke:var(--border)}.Chart_chartContainer__--q1l .recharts-dot[stroke=\"#fff\"]{stroke:transparent}.Chart_chartContainer__--q1l .recharts-layer,.Chart_chartContainer__--q1l .recharts-sector{outline:none}.Chart_chartContainer__--q1l .recharts-sector[stroke=\"#fff\"]{stroke:transparent}.Chart_chartContainer__--q1l .recharts-surface{outline:none}.Chart_chartContainer__--q1l .recharts-wrapper{position:relative}.Chart_chartContainer__--q1l .recharts-surface{position:relative;z-index:1}.Chart_chartContainer__--q1l .recharts-tooltip-wrapper{z-index:3!important}.Chart_chartContainer__--q1l .recharts-active-dot{z-index:3}.Chart_chartGrid__t52WF{stroke-width:.6}.Chart_tooltipContainer__6tc0q{align-items:start;box-sizing:border-box;display:grid;max-width:
|
|
4
|
-
var S = {"chartContainer":"Chart_chartContainer__--q1l","chartGrid":"Chart_chartGrid__t52WF","tooltipContainer":"Chart_tooltipContainer__6tc0q","tooltipItem":"Chart_tooltipItem__j8I9T","tooltipIndicator":"Chart_tooltipIndicator__Z-JWp","indicator-dot":"Chart_indicator-dot__MWcmW","indicator-line":"Chart_indicator-line__MO3ul","indicator-dashed":"Chart_indicator-dashed__2LqIN","nested":"Chart_nested__7EWWk","tooltipContent":"Chart_tooltipContent__M3R-W","tooltipLabel":"Chart_tooltipLabel__zMpjZ","tooltipValue":"Chart_tooltipValue__vTQxU","legendContainer":"Chart_legendContainer__u1J3U","legendItem":"Chart_legendItem__0CSyC","legendIndicator":"Chart_legendIndicator__erzzP","chart-line-blink":"Chart_chart-line-blink__4EI-g"};
|
|
3
|
+
var css_248z = "@media (max-width:768px){:root{--page-x-padding:var(--p-6);--page-y-padding:var(--p-6)}}.Chart_chartContainer__--q1l{aspect-ratio:16/9;display:flex;font-size:.75rem;justify-content:center;line-height:1rem;max-width:100%;touch-action:none;width:100%}.Chart_chartContainer__--q1l .recharts-cartesian-axis-tick text{fill:var(--muted-foreground)}.Chart_chartContainer__--q1l .recharts-cartesian-grid line[stroke=\"#ccc\"]{stroke:var(--border)}.dark .Chart_chartContainer__--q1l .recharts-cartesian-grid line[stroke=\"#ccc\"]{stroke:var(--sb-slate-900)}.Chart_chartContainer__--q1l .recharts-curve.recharts-tooltip-cursor,.Chart_chartContainer__--q1l .recharts-polar-grid [stroke=\"#ccc\"]{stroke:var(--border)}.Chart_chartContainer__--q1l .recharts-radial-bar-background-sector,.Chart_chartContainer__--q1l .recharts-rectangle.recharts-tooltip-cursor{fill:var(--muted)}.Chart_chartContainer__--q1l .recharts-reference-line [stroke=\"#ccc\"]{stroke:var(--border)}.Chart_chartContainer__--q1l .recharts-dot[stroke=\"#fff\"]{stroke:transparent}.Chart_chartContainer__--q1l .recharts-layer,.Chart_chartContainer__--q1l .recharts-sector{outline:none}.Chart_chartContainer__--q1l .recharts-sector[stroke=\"#fff\"]{stroke:transparent}.Chart_chartContainer__--q1l .recharts-surface{outline:none}.Chart_chartContainer__--q1l .recharts-wrapper{position:relative}.Chart_chartContainer__--q1l .recharts-surface{position:relative;z-index:1}.Chart_chartContainer__--q1l .recharts-tooltip-wrapper{box-sizing:border-box;max-width:90%;z-index:3!important}.Chart_chartContainer__--q1l .recharts-active-dot{z-index:3}.Chart_chartGrid__t52WF{stroke-width:.6}.Chart_tooltipContainer__6tc0q{align-items:start;box-sizing:border-box;display:grid;max-width:min(500px,90vw);min-width:0;overflow-wrap:break-word;width:100%;word-break:break-word;grid-gap:.375rem;backdrop-filter:blur(10px);background-color:color-mix(in srgb,var(--background) 50%,transparent);border:1px solid var(--border)/.5;border-radius:.5rem;box-shadow:0 10px 10px -5px rgba(0,0,0,.2),0 0 1px 0 var(--muted-foreground);font-size:.75rem;gap:.375rem;line-height:1rem;opacity:0;padding:.375rem .625rem;transition:opacity .5s ease-out}.dark .Chart_tooltipContainer__6tc0q{box-shadow:0 0 1px 0 var(--sb-slate-700),0 10px 10px -5px rgba(0,0,0,.7)}.Chart_chartContainer__--q1l:hover .Chart_tooltipContainer__6tc0q{opacity:1;transition-duration:.5s}.Chart_tooltipItem__j8I9T{align-items:stretch;display:flex;flex-wrap:wrap;gap:.5rem;width:100%}.Chart_tooltipItem__j8I9T>svg{color:var(--muted-foreground);height:.625rem;width:.625rem}.Chart_tooltipIndicator__Z-JWp{background-color:var(--color-bg);border-color:var(--color-border);border-radius:2px;border-width:1px;flex-shrink:0}.Chart_tooltipIndicator__Z-JWp.Chart_indicator-dot__MWcmW{height:.625rem;width:.625rem}.Chart_tooltipIndicator__Z-JWp.Chart_indicator-line__MO3ul{width:.25rem}.Chart_tooltipIndicator__Z-JWp.Chart_indicator-dashed__2LqIN{background-color:transparent;border-style:dashed;border-width:1.5px;width:0}.Chart_tooltipIndicator__Z-JWp.Chart_indicator-dashed__2LqIN.Chart_nested__7EWWk{margin-bottom:.125rem;margin-top:.125rem}.Chart_tooltipContent__M3R-W{display:flex;flex:1 1 0%;justify-content:space-between;line-height:1;min-width:0}.Chart_tooltipLabel__zMpjZ{display:grid;min-width:0;grid-gap:.375rem;gap:.375rem}.Chart_tooltipLabelText__45osJ{display:-webkit-box;-webkit-line-clamp:3;max-width:100%;min-width:0;overflow:hidden;word-break:break-word;-webkit-box-orient:vertical}.Chart_tooltipValue__vTQxU{color:var(--foreground);font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:\"tnum\";font-variant-numeric:tabular-nums;font-weight:500;margin-left:var(--p-3);white-space:nowrap}.Chart_legendContainer__u1J3U{align-items:center;display:flex;gap:1rem;justify-content:center}.Chart_legendItem__0CSyC{align-items:center;display:flex;gap:.375rem}.Chart_legendItem__0CSyC>svg{color:var(--muted-foreground);height:.75rem;width:.75rem}.Chart_legendIndicator__erzzP{border-radius:2px;flex-shrink:0;height:.5rem;width:.5rem}.chart-line-blinking path{animation:chart-line-blink 1s ease-in-out infinite;animation-direction:alternate}@keyframes Chart_chart-line-blink__4EI-g{0%{opacity:.5}to{opacity:1}}";
|
|
4
|
+
var S = {"chartContainer":"Chart_chartContainer__--q1l","chartGrid":"Chart_chartGrid__t52WF","tooltipContainer":"Chart_tooltipContainer__6tc0q","tooltipItem":"Chart_tooltipItem__j8I9T","tooltipIndicator":"Chart_tooltipIndicator__Z-JWp","indicator-dot":"Chart_indicator-dot__MWcmW","indicator-line":"Chart_indicator-line__MO3ul","indicator-dashed":"Chart_indicator-dashed__2LqIN","nested":"Chart_nested__7EWWk","tooltipContent":"Chart_tooltipContent__M3R-W","tooltipLabel":"Chart_tooltipLabel__zMpjZ","tooltipLabelText":"Chart_tooltipLabelText__45osJ","tooltipValue":"Chart_tooltipValue__vTQxU","legendContainer":"Chart_legendContainer__u1J3U","legendItem":"Chart_legendItem__0CSyC","legendIndicator":"Chart_legendIndicator__erzzP","chart-line-blink":"Chart_chart-line-blink__4EI-g"};
|
|
5
5
|
styleInject(css_248z);
|
|
6
6
|
|
|
7
7
|
export { S as default };
|
|
@@ -16,7 +16,7 @@ function ChartTooltipItem({ item, index, config, indicator, hideIndicator, nestL
|
|
|
16
16
|
return (jsx("div", { className: cn(S.tooltipItem, indicator === 'dot' && 'items-center'), children: formatter && item?.value !== undefined && item.name ? (formatter(item.value, item.name, item, index, item.payload)) : (jsxs(Fragment, { children: [itemConfig?.icon ? (jsx(itemConfig.icon, {})) : (!hideIndicator && (jsx("div", { className: cn(S.tooltipIndicator, S[`indicator-${indicator}`], nestLabel && S.nested), style: {
|
|
17
17
|
'--color-bg': indicatorColor,
|
|
18
18
|
'--color-border': indicatorColor,
|
|
19
|
-
} }))), jsxs("div", { className: cn(S.tooltipContent, nestLabel ? 'items-end' : 'items-center'), children: [jsxs("div", { className: S.tooltipLabel, children: [nestLabel ? tooltipLabel : null, jsx("span", { className:
|
|
19
|
+
} }))), jsxs("div", { className: cn(S.tooltipContent, nestLabel ? 'items-end' : 'items-center'), children: [jsxs("div", { className: S.tooltipLabel, children: [nestLabel ? tooltipLabel : null, jsx("span", { className: cn('text-muted-foreground', S.tooltipLabelText), children: itemConfig?.label || item.name })] }), item.value && (jsx("span", { className: S.tooltipValue, children: Array.isArray(item.value)
|
|
20
20
|
? `${item.value[0].toLocaleString(undefined, { maximumFractionDigits: 20 })} – ${item.value[1].toLocaleString(undefined, { maximumFractionDigits: 20 })}`
|
|
21
21
|
: item.value.toLocaleString(undefined, {
|
|
22
22
|
maximumFractionDigits: 20,
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
2
2
|
import cn from 'classnames';
|
|
3
|
-
import React__default, { useState, useRef, useId, useEffect } from 'react';
|
|
3
|
+
import React__default, { useState, useRef, useId, useEffect, useLayoutEffect } from 'react';
|
|
4
4
|
import { createPortal } from 'react-dom';
|
|
5
5
|
import { Card, CardHeader, CardContent, CardFooter } from '../Card/Card.js';
|
|
6
|
+
import { APP_MODAL_ID } from '../../../constants/appMount.js';
|
|
6
7
|
import { XIcon } from '@phosphor-icons/react';
|
|
7
8
|
import S from './Dialog.styl.js';
|
|
8
9
|
|
|
9
10
|
function Dialog({ open, onOpenChange, disabled, trigger, title, subtitle, disableCloseButton, icon, content, contentClassName, footer, footerClassName, footerAlignment = 'center', size = 'default', className, noScroll, maxHeight, autoScrollBottom, width, }) {
|
|
10
11
|
const [isMounted, setIsMounted] = useState(false);
|
|
12
|
+
const [modalContainer, setModalContainer] = useState(null);
|
|
11
13
|
const [isAnimating, setIsAnimating] = useState(false);
|
|
12
14
|
const dialogRef = useRef(null);
|
|
13
15
|
const triggerRef = useRef(null);
|
|
@@ -19,6 +21,9 @@ function Dialog({ open, onOpenChange, disabled, trigger, title, subtitle, disabl
|
|
|
19
21
|
setIsMounted(true);
|
|
20
22
|
return () => setIsMounted(false);
|
|
21
23
|
}, []);
|
|
24
|
+
useLayoutEffect(() => {
|
|
25
|
+
setModalContainer(document.getElementById(APP_MODAL_ID));
|
|
26
|
+
}, []);
|
|
22
27
|
// Handle open/close animations
|
|
23
28
|
useEffect(() => {
|
|
24
29
|
if (open) {
|
|
@@ -120,7 +125,10 @@ function Dialog({ open, onOpenChange, disabled, trigger, title, subtitle, disabl
|
|
|
120
125
|
: null,
|
|
121
126
|
}, children: [(title || subtitle || icon) && (jsx(CardHeader, { icon: icon, title: title, description: subtitle })), !disableCloseButton && (jsx("button", { className: S.dialogClose, onClick: handleCloseClick, "aria-label": "Close dialog", type: "button", children: jsx(XIcon, { size: 16 }) })), content && (jsx(CardContent, { className: contentClassName, noScroll: noScroll, autoScrollBottom: autoScrollBottom, children: content })), footer && (jsx(CardFooter, { className: cn(S.footer, S[`align-${footerAlignment}`], footerClassName), children: footer }))] })] }));
|
|
122
127
|
const onTriggerClick = !disabled ? () => onOpenChange(true) : undefined;
|
|
123
|
-
return (jsxs(Fragment, { children: [trigger && jsx("div", { onClick: onTriggerClick, children: trigger }), open &&
|
|
128
|
+
return (jsxs(Fragment, { children: [trigger && jsx("div", { onClick: onTriggerClick, children: trigger }), open &&
|
|
129
|
+
!disabled &&
|
|
130
|
+
modalContainer &&
|
|
131
|
+
createPortal(dialogContent, modalContainer)] }));
|
|
124
132
|
}
|
|
125
133
|
|
|
126
134
|
export { Dialog, S as DialogStyles };
|
package/package.json
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
@import 'lib/theme.styl'
|
|
2
|
+
|
|
1
3
|
// Chart container
|
|
2
4
|
.chartContainer
|
|
3
5
|
display flex
|
|
@@ -60,6 +62,8 @@
|
|
|
60
62
|
// Tooltip portal positions with absolute + transform; do not override with relative.
|
|
61
63
|
.recharts-tooltip-wrapper
|
|
62
64
|
z-index 3 !important
|
|
65
|
+
max-width 90%
|
|
66
|
+
box-sizing border-box
|
|
63
67
|
|
|
64
68
|
// Active dots and cursor
|
|
65
69
|
.recharts-active-dot
|
|
@@ -75,8 +79,8 @@
|
|
|
75
79
|
.tooltipContainer
|
|
76
80
|
display grid
|
|
77
81
|
box-sizing border-box
|
|
78
|
-
width
|
|
79
|
-
max-width
|
|
82
|
+
width 100%
|
|
83
|
+
max-width unquote('min(500px, 90vw)')
|
|
80
84
|
min-width 0
|
|
81
85
|
overflow-wrap break-word
|
|
82
86
|
word-break break-word
|
|
@@ -85,13 +89,18 @@
|
|
|
85
89
|
padding 0.375rem 0.625rem /* py-1.5 px-2.5 */
|
|
86
90
|
border-radius 0.5rem /* rounded-lg */
|
|
87
91
|
border 1px solid var(--border) / 0.5
|
|
88
|
-
background-color var(--background)
|
|
92
|
+
// background-color var(--background)
|
|
93
|
+
backdrop-filter blur(10px)
|
|
94
|
+
background-color unquote('color-mix(in srgb, var(--background) 50%, transparent)')
|
|
89
95
|
font-size 0.75rem /* text-xs */
|
|
90
96
|
line-height 1rem
|
|
91
|
-
box-shadow 0 10px 10px -5px rgba(0 0 0 0.
|
|
97
|
+
box-shadow 0 10px 10px -5px rgba(0 0 0 0.2), 0 0 1px 0 var(--muted-foreground)
|
|
92
98
|
opacity 0
|
|
93
99
|
transition opacity 0.5s ease-out
|
|
94
100
|
|
|
101
|
+
:global(.dark) &
|
|
102
|
+
box-shadow 0 0 1px 0 var(--sb-slate-700), 0 10px 10px -5px rgba(0 0 0 0.7)
|
|
103
|
+
|
|
95
104
|
.chartContainer:hover &
|
|
96
105
|
opacity 1
|
|
97
106
|
transition-duration 0.5s
|
|
@@ -135,19 +144,29 @@
|
|
|
135
144
|
.tooltipContent
|
|
136
145
|
display flex
|
|
137
146
|
flex 1 1 0%
|
|
147
|
+
min-width 0
|
|
138
148
|
justify-content space-between
|
|
139
149
|
line-height 1
|
|
140
150
|
|
|
141
151
|
.tooltipLabel
|
|
142
152
|
display grid
|
|
153
|
+
min-width 0
|
|
143
154
|
gap 0.375rem /* gap-1.5 */
|
|
144
155
|
|
|
156
|
+
.tooltipLabelText
|
|
157
|
+
min-width 0
|
|
158
|
+
max-width 100%
|
|
159
|
+
overflow hidden
|
|
160
|
+
word-break break-word
|
|
161
|
+
line-clamp(3)
|
|
162
|
+
|
|
145
163
|
.tooltipValue
|
|
146
164
|
font-family ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace
|
|
147
165
|
font-weight 500
|
|
148
166
|
font-variant-numeric tabular-nums
|
|
149
167
|
color var(--foreground)
|
|
150
168
|
margin-left var(--p-3)
|
|
169
|
+
white-space nowrap
|
|
151
170
|
|
|
152
171
|
// Legend styles
|
|
153
172
|
.legendContainer
|
|
@@ -92,7 +92,7 @@ export function ChartTooltipItem({
|
|
|
92
92
|
>
|
|
93
93
|
<div className={S.tooltipLabel}>
|
|
94
94
|
{nestLabel ? tooltipLabel : null}
|
|
95
|
-
<span className=
|
|
95
|
+
<span className={cn('text-muted-foreground', S.tooltipLabelText)}>
|
|
96
96
|
{itemConfig?.label || item.name}
|
|
97
97
|
</span>
|
|
98
98
|
</div>
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import cn from 'classnames';
|
|
2
|
-
import React, {
|
|
2
|
+
import React, {
|
|
3
|
+
useEffect,
|
|
4
|
+
useId,
|
|
5
|
+
useLayoutEffect,
|
|
6
|
+
useRef,
|
|
7
|
+
useState,
|
|
8
|
+
} from 'react';
|
|
3
9
|
import { createPortal } from 'react-dom';
|
|
4
10
|
|
|
5
11
|
import {
|
|
@@ -8,6 +14,7 @@ import {
|
|
|
8
14
|
CardFooter,
|
|
9
15
|
CardHeader,
|
|
10
16
|
} from '#uilib/components/ui/Card/Card';
|
|
17
|
+
import { APP_MODAL_ID } from '#uilib/constants/appMount';
|
|
11
18
|
import { XIcon } from '@phosphor-icons/react';
|
|
12
19
|
|
|
13
20
|
import S from './Dialog.styl';
|
|
@@ -35,6 +42,9 @@ export function Dialog({
|
|
|
35
42
|
width,
|
|
36
43
|
}: DialogProps) {
|
|
37
44
|
const [isMounted, setIsMounted] = useState(false);
|
|
45
|
+
const [modalContainer, setModalContainer] = useState<HTMLElement | null>(
|
|
46
|
+
null,
|
|
47
|
+
);
|
|
38
48
|
const [isAnimating, setIsAnimating] = useState(false);
|
|
39
49
|
const dialogRef = useRef<HTMLDivElement>(null);
|
|
40
50
|
const triggerRef = useRef<HTMLElement | null>(null);
|
|
@@ -48,6 +58,10 @@ export function Dialog({
|
|
|
48
58
|
return () => setIsMounted(false);
|
|
49
59
|
}, []);
|
|
50
60
|
|
|
61
|
+
useLayoutEffect(() => {
|
|
62
|
+
setModalContainer(document.getElementById(APP_MODAL_ID));
|
|
63
|
+
}, []);
|
|
64
|
+
|
|
51
65
|
// Handle open/close animations
|
|
52
66
|
useEffect(() => {
|
|
53
67
|
if (open) {
|
|
@@ -228,7 +242,10 @@ export function Dialog({
|
|
|
228
242
|
return (
|
|
229
243
|
<>
|
|
230
244
|
{trigger && <div onClick={onTriggerClick}>{trigger}</div>}
|
|
231
|
-
{open &&
|
|
245
|
+
{open &&
|
|
246
|
+
!disabled &&
|
|
247
|
+
modalContainer &&
|
|
248
|
+
createPortal(dialogContent, modalContainer)}
|
|
232
249
|
</>
|
|
233
250
|
);
|
|
234
251
|
}
|
package/src/docs/index.tsx
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { createRoot } from 'react-dom/client';
|
|
2
2
|
import { BrowserRouter } from 'react-router-dom';
|
|
3
3
|
|
|
4
|
+
import { APP_ROOT_ID } from '#uilib/constants/appMount';
|
|
4
5
|
import { DEFAULT_THEME_ACTIVE_COLOR } from '#uilib/docs/lib/theme';
|
|
5
6
|
|
|
6
7
|
import App from './App/App';
|
|
7
8
|
import { ThemeProvider } from './contexts/theme-context';
|
|
8
9
|
|
|
9
|
-
const elem = document.getElementById(
|
|
10
|
+
const elem = document.getElementById(APP_ROOT_ID) as HTMLElement;
|
|
10
11
|
const root = createRoot(elem);
|
|
11
12
|
|
|
12
13
|
root.render(
|
|
@@ -85,7 +85,10 @@ const INITIAL_CHART: ChartDataPoint[] = [
|
|
|
85
85
|
];
|
|
86
86
|
|
|
87
87
|
const DEMO_FORECAST_ITEMS: ForecastItemData[] = [
|
|
88
|
-
{
|
|
88
|
+
{
|
|
89
|
+
id: DEMO_FORECAST_ID,
|
|
90
|
+
name: 'My custom forecast with an extremely long descriptive name that should wrap and clamp inside the chart tooltip after three lines',
|
|
91
|
+
},
|
|
89
92
|
];
|
|
90
93
|
|
|
91
94
|
type DemoMode = 'none' | OverlayMode;
|