@svgrid/grid 2.1.5 → 2.1.7
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/SvCarousel.svelte +35 -6
- package/dist/SvCarousel.svelte.d.ts +3 -0
- package/dist/SvColorInput.svelte +0 -1
- package/dist/SvContextMenu.svelte +26 -6
- package/dist/SvDrawer.svelte +5 -3
- package/dist/SvGrid.controller.svelte.d.ts +85 -2
- package/dist/SvGrid.controller.svelte.js +494 -1
- package/dist/SvGrid.css +142 -0
- package/dist/SvGrid.svelte +49 -27
- package/dist/SvGrid.types.d.ts +78 -0
- package/dist/SvGridBoard.svelte +71 -13
- package/dist/SvGridChart.svelte +41 -7
- package/dist/SvGridChart.svelte.d.ts +4 -0
- package/dist/SvGridChartPanel.svelte +485 -0
- package/dist/SvGridChartPanel.svelte.d.ts +28 -0
- package/dist/SvGridDropdown.svelte +18 -2
- package/dist/SvGroupCell.svelte +5 -5
- package/dist/SvMenu.svelte +25 -2
- package/dist/SvMenu.svelte.d.ts +3 -0
- package/dist/SvMenuList.svelte +31 -9
- package/dist/SvMenuList.svelte.d.ts +9 -1
- package/dist/SvNumberInput.svelte +1 -1
- package/dist/SvOtpInput.svelte +3 -2
- package/dist/SvPopover.svelte +13 -1
- package/dist/SvRowGroupPanel.svelte +23 -0
- package/dist/SvScrollArea.svelte +13 -2
- package/dist/SvScrollArea.svelte.d.ts +2 -0
- package/dist/SvTooltip.svelte +27 -2
- package/dist/SvTooltip.svelte.d.ts +3 -2
- package/dist/SvTour.svelte +30 -5
- package/dist/SvTour.svelte.d.ts +3 -0
- package/dist/SvTree.svelte +7 -3
- package/dist/SvTreeSelect.svelte +16 -9
- package/dist/build-api.js +51 -0
- package/dist/cdn/svgrid.js +17394 -16052
- package/dist/cdn/svgrid.svelte-external.js +16784 -15644
- package/dist/chart-export.d.ts +21 -0
- package/dist/chart-export.js +52 -11
- package/dist/chart.d.ts +30 -0
- package/dist/chart.js +53 -13
- package/dist/createAutocomplete.svelte.d.ts +6 -0
- package/dist/createAutocomplete.svelte.js +10 -0
- package/dist/createCombobox.svelte.d.ts +1 -0
- package/dist/createCombobox.svelte.js +1 -0
- package/dist/createCountryInput.svelte.d.ts +5 -0
- package/dist/createCountryInput.svelte.js +11 -0
- package/dist/createDropdownList.svelte.d.ts +4 -0
- package/dist/createDropdownList.svelte.js +7 -0
- package/dist/createPopoverSelect.svelte.d.ts +5 -3
- package/dist/createPopoverSelect.svelte.js +5 -3
- package/dist/createTree.svelte.d.ts +1 -0
- package/dist/createTree.svelte.js +15 -2
- package/dist/index.d.ts +4 -2
- package/dist/index.js +3 -2
- package/dist/svgrid-wrapper.types.d.ts +58 -0
- package/package.json +1 -1
- package/src/SvCarousel.svelte +35 -6
- package/src/SvColorInput.svelte +0 -1
- package/src/SvContextMenu.svelte +26 -6
- package/src/SvDrawer.svelte +5 -3
- package/src/SvGrid.controller.svelte.ts +481 -0
- package/src/SvGrid.css +142 -0
- package/src/SvGrid.svelte +49 -27
- package/src/SvGrid.types.ts +83 -0
- package/src/SvGridBoard.svelte +71 -13
- package/src/SvGridChart.svelte +41 -7
- package/src/SvGridChartPanel.svelte +485 -0
- package/src/SvGridDropdown.svelte +18 -2
- package/src/SvGroupCell.svelte +5 -5
- package/src/SvMenu.svelte +25 -2
- package/src/SvMenuList.svelte +31 -9
- package/src/SvNumberInput.svelte +1 -1
- package/src/SvOtpInput.svelte +3 -2
- package/src/SvPopover.svelte +13 -1
- package/src/SvRowGroupPanel.svelte +23 -0
- package/src/SvScrollArea.svelte +13 -2
- package/src/SvTooltip.svelte +27 -2
- package/src/SvTour.svelte +30 -5
- package/src/SvTree.svelte +7 -3
- package/src/SvTreeSelect.svelte +16 -9
- package/src/build-api.ts +49 -0
- package/src/chart-export.ts +57 -0
- package/src/chart.ts +70 -13
- package/src/createAutocomplete.svelte.ts +11 -0
- package/src/createCombobox.svelte.ts +1 -0
- package/src/createCountryInput.svelte.ts +12 -0
- package/src/createDropdownList.svelte.ts +8 -0
- package/src/createPopoverSelect.svelte.ts +5 -3
- package/src/createTree.svelte.ts +15 -2
- package/src/index.ts +6 -0
- package/src/overlays.test.ts +5 -0
- package/src/svgrid-wrapper.types.ts +62 -0
- package/src/svgrid.charting.test.ts +527 -0
- package/src/test-setup.ts +22 -0
package/dist/index.js
CHANGED
|
@@ -150,8 +150,9 @@ export { isDisabledDay, isOutOfRange, isRestricted, isImportant, } from './datet
|
|
|
150
150
|
export { default as FlexRender } from './FlexRender.svelte';
|
|
151
151
|
export { renderComponent, renderSnippet } from './render-component';
|
|
152
152
|
export { default as SvGridChart } from './SvGridChart.svelte';
|
|
153
|
-
export {
|
|
154
|
-
export {
|
|
153
|
+
export { default as SvGridChartPanel } from './SvGridChartPanel.svelte';
|
|
154
|
+
export { buildChart, formatChartValue, rowsToChartSpec, niceScale, niceLogScale, linearTrend, simpleMovingAverage, exponentialMovingAverage, computeOverlay, buildLinePath, sampleGradient, pickContrastText, DEFAULT_PALETTE, } from './chart';
|
|
155
|
+
export { chartToSvgString, downloadChartSvg, chartToPngBlob, downloadChartPng, chartSpecToCsv, downloadChartCsv, } from './chart-export';
|
|
155
156
|
export { buildSparkline, toSparklineValues, } from './sparkline';
|
|
156
157
|
export { spreadsheetLayout, spansToMerges, } from './spreadsheet';
|
|
157
158
|
export { rowResize } from './row-resize';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { CellFormatConfig, ColumnDef, RowData, SvGridOptions, TableFeatures } from './core';
|
|
2
2
|
import type { GridExportOptions, GridClipboardOptions } from './export-format';
|
|
3
|
+
import type { ChartSpec, ChartType } from './chart';
|
|
3
4
|
export type SvGridFilterOperator = 'contains' | 'equals' | 'startsWith' | 'greaterThan' | 'lessThan' | 'between' | 'isBlank';
|
|
4
5
|
/**
|
|
5
6
|
* A serializable snapshot of everything that makes up the current "view":
|
|
@@ -34,6 +35,32 @@ export type SvGridViewState = {
|
|
|
34
35
|
}>;
|
|
35
36
|
/** Facet (Excel-style value checklist) selections, keyed by column id. */
|
|
36
37
|
facetFilters: Record<string, string[]>;
|
|
38
|
+
/** Built-in chart panel state (present only when `charting` is on): the
|
|
39
|
+
* ACTIVE chart, for back-compat + spread-and-tweak. */
|
|
40
|
+
chart?: {
|
|
41
|
+
open: boolean;
|
|
42
|
+
type: ChartType;
|
|
43
|
+
dimension: string | null;
|
|
44
|
+
series: string | null;
|
|
45
|
+
measure: string | null;
|
|
46
|
+
reduce: 'sum' | 'avg' | 'count';
|
|
47
|
+
stacked: boolean;
|
|
48
|
+
};
|
|
49
|
+
/** All charts in the tab strip (multi-chart), plus the active index. */
|
|
50
|
+
charts?: Array<{
|
|
51
|
+
title: string;
|
|
52
|
+
type: ChartType;
|
|
53
|
+
dimension: string | null;
|
|
54
|
+
series: string | null;
|
|
55
|
+
measure: string | null;
|
|
56
|
+
reduce: 'sum' | 'avg' | 'count';
|
|
57
|
+
stacked: boolean | null;
|
|
58
|
+
dataLabels: boolean | null;
|
|
59
|
+
logScale: boolean | null;
|
|
60
|
+
timeAxis: boolean | null;
|
|
61
|
+
valueFormat: 'number' | 'currency' | 'percent' | 'compact' | null;
|
|
62
|
+
}>;
|
|
63
|
+
chartActive?: number;
|
|
37
64
|
};
|
|
38
65
|
/**
|
|
39
66
|
* A batch of row mutations for `api.applyTransaction`. `update` / `remove`
|
|
@@ -85,6 +112,37 @@ export type SvGridApi<TFeatures extends TableFeatures, TData extends RowData> =
|
|
|
85
112
|
* `selectCells` accepts. Empty array when no range is active.
|
|
86
113
|
*/
|
|
87
114
|
getSelected(): Array<[number, number, number, number]>;
|
|
115
|
+
/** Open the built-in chart panel. */
|
|
116
|
+
openChart(): void;
|
|
117
|
+
/** Close the built-in chart panel. */
|
|
118
|
+
closeChart(): void;
|
|
119
|
+
/** The live chart spec the panel is rendering, or `null`. */
|
|
120
|
+
getChartSpec(): ChartSpec | null;
|
|
121
|
+
/** Select cell rectangles + open the chart panel (scopes to the range). */
|
|
122
|
+
chartRange(ranges?: ReadonlyArray<readonly [number, number, number, number]>): void;
|
|
123
|
+
/**
|
|
124
|
+
* Configure the built-in chart panel's ACTIVE chart. Column references
|
|
125
|
+
* accept a column id OR field name. Opens the panel unless `open === false`.
|
|
126
|
+
*/
|
|
127
|
+
configureChart(config: {
|
|
128
|
+
open?: boolean;
|
|
129
|
+
type?: ChartType;
|
|
130
|
+
dimension?: string | null;
|
|
131
|
+
series?: string | null;
|
|
132
|
+
measure?: string | null;
|
|
133
|
+
reduce?: 'sum' | 'avg' | 'count';
|
|
134
|
+
stacked?: boolean;
|
|
135
|
+
dataLabels?: boolean;
|
|
136
|
+
logScale?: boolean;
|
|
137
|
+
timeAxis?: boolean;
|
|
138
|
+
valueFormat?: 'number' | 'currency' | 'percent' | 'compact';
|
|
139
|
+
}): void;
|
|
140
|
+
/**
|
|
141
|
+
* Register a natural-language "chart this" handler. When set, the chart
|
|
142
|
+
* panel shows an AI button. `@svgrid/enterprise`'s `enableAiCharting(api)`
|
|
143
|
+
* fills this. Pass `null` to remove it.
|
|
144
|
+
*/
|
|
145
|
+
setChartAiHandler(handler: ((prompt: string) => Promise<Record<string, unknown> | null>) | null): void;
|
|
88
146
|
/** Add one row. `position` defaults to `'bottom'`. */
|
|
89
147
|
addRow(row: TData, position?: 'top' | 'bottom' | number): void;
|
|
90
148
|
addRows(rows: ReadonlyArray<TData>, position?: 'top' | 'bottom' | number): void;
|
package/package.json
CHANGED
package/src/SvCarousel.svelte
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* ```
|
|
13
13
|
*/
|
|
14
14
|
import type { Snippet } from 'svelte'
|
|
15
|
+
import { type EditorDir } from './editor-contract'
|
|
15
16
|
|
|
16
17
|
type Props = {
|
|
17
18
|
count: number
|
|
@@ -24,6 +25,8 @@
|
|
|
24
25
|
arrows?: boolean
|
|
25
26
|
dots?: boolean
|
|
26
27
|
ariaLabel?: string
|
|
28
|
+
/** Text direction (rtl mirrors the prev/next arrows + slide direction). */
|
|
29
|
+
dir?: EditorDir
|
|
27
30
|
}
|
|
28
31
|
|
|
29
32
|
let {
|
|
@@ -35,8 +38,12 @@
|
|
|
35
38
|
arrows = true,
|
|
36
39
|
dots = true,
|
|
37
40
|
ariaLabel = 'Carousel',
|
|
41
|
+
dir,
|
|
38
42
|
}: Props = $props()
|
|
39
43
|
|
|
44
|
+
const resolvedDir = $derived(dir === 'ltr' || dir === 'rtl' ? dir : undefined)
|
|
45
|
+
const rtl = $derived(resolvedDir === 'rtl')
|
|
46
|
+
|
|
40
47
|
function go(i: number) {
|
|
41
48
|
if (count === 0) return
|
|
42
49
|
current = loop ? (i + count) % count : Math.max(0, Math.min(i, count - 1))
|
|
@@ -44,10 +51,13 @@
|
|
|
44
51
|
const next = () => go(current + 1)
|
|
45
52
|
const prev = () => go(current - 1)
|
|
46
53
|
|
|
47
|
-
// Autoplay, paused while hovered/focused
|
|
54
|
+
// Autoplay, paused while hovered/focused, or stopped via the persistent
|
|
55
|
+
// play/pause toggle (WCAG 2.2.2: auto-advancing content needs a way to stop
|
|
56
|
+
// it that doesn't depend on hover/focus).
|
|
48
57
|
let paused = $state(false)
|
|
58
|
+
let userPaused = $state(false)
|
|
49
59
|
$effect(() => {
|
|
50
|
-
if (!autoplay || paused || count < 2) return
|
|
60
|
+
if (!autoplay || paused || userPaused || count < 2) return
|
|
51
61
|
const t = setInterval(next, autoplay)
|
|
52
62
|
return () => clearInterval(t)
|
|
53
63
|
})
|
|
@@ -82,9 +92,9 @@
|
|
|
82
92
|
>
|
|
83
93
|
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
84
94
|
<div class="sv-carousel__viewport" onpointerdown={down} onpointermove={move} onpointerup={up} onpointercancel={up}>
|
|
85
|
-
<div class="sv-carousel__track" class:is-dragging={dragging} style:transform={`translateX(calc(${-current * 100}% + ${dx}px))`}>
|
|
95
|
+
<div class="sv-carousel__track" class:is-dragging={dragging} style:transform={`translateX(calc(${(rtl ? current : -current) * 100}% + ${dx}px))`}>
|
|
86
96
|
{#each Array(count) as _, i (i)}
|
|
87
|
-
<div class="sv-carousel__slide" role="group" aria-roledescription="slide" aria-label={`${i + 1} of ${count}`} aria-hidden={i !== current}>
|
|
97
|
+
<div class="sv-carousel__slide" role="group" aria-roledescription="slide" aria-label={`${i + 1} of ${count}`} aria-hidden={i !== current} inert={i !== current}>
|
|
88
98
|
{@render slide?.(i)}
|
|
89
99
|
</div>
|
|
90
100
|
{/each}
|
|
@@ -92,8 +102,8 @@
|
|
|
92
102
|
</div>
|
|
93
103
|
|
|
94
104
|
{#if arrows && count > 1}
|
|
95
|
-
<button type="button" class="sv-carousel__arrow is-prev" aria-label=
|
|
96
|
-
<button type="button" class="sv-carousel__arrow is-next" aria-label=
|
|
105
|
+
<button type="button" class="sv-carousel__arrow is-prev" aria-label={rtl ? 'Next slide' : 'Previous slide'} onclick={rtl ? next : prev} disabled={rtl ? (!loop && current === count - 1) : (!loop && current === 0)}>{rtl ? '›' : '‹'}</button>
|
|
106
|
+
<button type="button" class="sv-carousel__arrow is-next" aria-label={rtl ? 'Previous slide' : 'Next slide'} onclick={rtl ? prev : next} disabled={rtl ? (!loop && current === 0) : (!loop && current === count - 1)}>{rtl ? '‹' : '›'}</button>
|
|
97
107
|
{/if}
|
|
98
108
|
|
|
99
109
|
{#if dots && count > 1}
|
|
@@ -103,6 +113,16 @@
|
|
|
103
113
|
{/each}
|
|
104
114
|
</div>
|
|
105
115
|
{/if}
|
|
116
|
+
|
|
117
|
+
{#if autoplay > 0}
|
|
118
|
+
<button
|
|
119
|
+
type="button"
|
|
120
|
+
class="sv-carousel__playpause"
|
|
121
|
+
aria-label={userPaused ? 'Play autoplay' : 'Pause autoplay'}
|
|
122
|
+
aria-pressed={userPaused}
|
|
123
|
+
onclick={() => (userPaused = !userPaused)}
|
|
124
|
+
>{userPaused ? '▶' : '⏸'}</button>
|
|
125
|
+
{/if}
|
|
106
126
|
</div>
|
|
107
127
|
|
|
108
128
|
<style>
|
|
@@ -131,4 +151,13 @@
|
|
|
131
151
|
background: color-mix(in srgb, var(--sg-fg, #0f172a) 30%, var(--sg-bg, #fff)); transition: background 0.15s, width 0.15s;
|
|
132
152
|
}
|
|
133
153
|
.sv-carousel__dot.is-active { width: 20px; border-radius: 4px; background: var(--sg-accent, #2563eb); }
|
|
154
|
+
|
|
155
|
+
.sv-carousel__playpause {
|
|
156
|
+
position: absolute; top: 10px; inset-inline-end: 10px; z-index: 2;
|
|
157
|
+
width: 28px; height: 28px; display: grid; place-items: center; border-radius: 50%;
|
|
158
|
+
background: color-mix(in srgb, var(--sg-bg, #fff) 82%, transparent); color: var(--sg-fg, #0f172a);
|
|
159
|
+
border: 1px solid var(--sg-border, #e2e8f0); cursor: pointer; font-size: 12px; line-height: 1;
|
|
160
|
+
box-shadow: 0 4px 12px -4px rgba(15, 23, 42, 0.3);
|
|
161
|
+
}
|
|
162
|
+
.sv-carousel__playpause:hover { background: var(--sg-bg, #fff); }
|
|
134
163
|
</style>
|
package/src/SvColorInput.svelte
CHANGED
package/src/SvContextMenu.svelte
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
import type { Snippet } from 'svelte'
|
|
19
19
|
import { portalToBody, popIn } from './popover'
|
|
20
20
|
import { createDismissableLayer } from './a11y/dismissable'
|
|
21
|
+
import { createFocusTrap } from './a11y/focus-trap'
|
|
21
22
|
import SvMenuList, { type MenuItem } from './SvMenuList.svelte'
|
|
22
23
|
|
|
23
24
|
type Props = {
|
|
@@ -33,6 +34,7 @@
|
|
|
33
34
|
let open = $state(false)
|
|
34
35
|
let pos = $state({ x: 0, y: 0 })
|
|
35
36
|
let panelEl = $state<HTMLDivElement | null>(null)
|
|
37
|
+
let zoneEl = $state<HTMLDivElement | null>(null)
|
|
36
38
|
|
|
37
39
|
const MENU_W = 200
|
|
38
40
|
function openAt(clientX: number, clientY: number) {
|
|
@@ -50,9 +52,24 @@
|
|
|
50
52
|
openAt(e.clientX, e.clientY)
|
|
51
53
|
}
|
|
52
54
|
|
|
55
|
+
// Keyboard equivalent of a right-click: the ContextMenu key, or Shift+F10.
|
|
56
|
+
// Anchors at the focused zone's own position instead of the (nonexistent)
|
|
57
|
+
// pointer coordinates.
|
|
58
|
+
function onZoneKeydown(e: KeyboardEvent) {
|
|
59
|
+
if (disabled) return
|
|
60
|
+
const isMenuKey = e.key === 'ContextMenu' || (e.key === 'F10' && e.shiftKey)
|
|
61
|
+
if (!isMenuKey) return
|
|
62
|
+
e.preventDefault()
|
|
63
|
+
const rect = zoneEl?.getBoundingClientRect()
|
|
64
|
+
openAt(rect ? rect.left : 0, rect ? rect.bottom : 0)
|
|
65
|
+
}
|
|
66
|
+
|
|
53
67
|
$effect(() => {
|
|
54
|
-
if (!open) return
|
|
55
|
-
|
|
68
|
+
if (!open || !panelEl) return
|
|
69
|
+
const trap = createFocusTrap(panelEl, {
|
|
70
|
+
initialFocus: () => panelEl?.querySelector<HTMLElement>('[role="menuitem"]:not([disabled])') ?? null,
|
|
71
|
+
})
|
|
72
|
+
trap.activate()
|
|
56
73
|
const layer = createDismissableLayer({
|
|
57
74
|
element: () => panelEl,
|
|
58
75
|
onDismiss: () => (open = false),
|
|
@@ -61,12 +78,12 @@
|
|
|
61
78
|
// Reposition-close on scroll (a moved anchor would leave the menu stranded).
|
|
62
79
|
const onScroll = () => (open = false)
|
|
63
80
|
window.addEventListener('scroll', onScroll, true)
|
|
64
|
-
return () => { layer.release(); window.removeEventListener('scroll', onScroll, true) }
|
|
81
|
+
return () => { layer.release(); trap.release(); window.removeEventListener('scroll', onScroll, true) }
|
|
65
82
|
})
|
|
66
83
|
</script>
|
|
67
84
|
|
|
68
|
-
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
69
|
-
<div class="sv-ctx__zone" oncontextmenu={onContextMenu}>
|
|
85
|
+
<!-- svelte-ignore a11y_no_static_element_interactions, a11y_no_noninteractive_tabindex -->
|
|
86
|
+
<div class="sv-ctx__zone" bind:this={zoneEl} tabindex={disabled ? -1 : 0} oncontextmenu={onContextMenu} onkeydown={onZoneKeydown}>
|
|
70
87
|
{@render children?.()}
|
|
71
88
|
</div>
|
|
72
89
|
|
|
@@ -86,7 +103,10 @@
|
|
|
86
103
|
{/if}
|
|
87
104
|
|
|
88
105
|
<style>
|
|
89
|
-
|
|
106
|
+
/* display:contents generates no box and per spec cannot receive focus - it
|
|
107
|
+
must be a real box for the keyboard-open path (tabindex) to work at all. */
|
|
108
|
+
.sv-ctx__zone { display: block; }
|
|
109
|
+
.sv-ctx__zone:focus-visible { outline: 2px solid var(--sg-accent, #6366f1); outline-offset: 1px; }
|
|
90
110
|
:global(.sv-ctx) {
|
|
91
111
|
z-index: 2147483646; min-width: 200px;
|
|
92
112
|
background: var(--sg-bg, #fff); color: var(--sg-fg, #0f172a);
|
package/src/SvDrawer.svelte
CHANGED
|
@@ -171,12 +171,14 @@
|
|
|
171
171
|
box-shadow: 0 24px 64px -16px rgba(15, 23, 42, 0.5);
|
|
172
172
|
overflow: hidden;
|
|
173
173
|
}
|
|
174
|
-
/* Left / right: full height, fixed width, slide along X.
|
|
174
|
+
/* Left / right: full height, fixed width, slide along X. `side` is a stated
|
|
175
|
+
physical edge (like SvToaster's position prop), not a text-flow-relative
|
|
176
|
+
"start/end" - so it stays physical left/right regardless of page dir. */
|
|
175
177
|
:global(.sv-drawer--right), :global(.sv-drawer--left) {
|
|
176
178
|
top: 0; bottom: 0; width: var(--sv-drawer-size); max-width: 100vw;
|
|
177
179
|
}
|
|
178
|
-
:global(.sv-drawer--right) {
|
|
179
|
-
:global(.sv-drawer--left) {
|
|
180
|
+
:global(.sv-drawer--right) { right: 0; border-left: 1px solid var(--sg-border, #e2e8f0); animation: sv-drawer-in-right 0.22s cubic-bezier(0.16, 1, 0.3, 1) both; }
|
|
181
|
+
:global(.sv-drawer--left) { left: 0; border-right: 1px solid var(--sg-border, #e2e8f0); animation: sv-drawer-in-left 0.22s cubic-bezier(0.16, 1, 0.3, 1) both; }
|
|
180
182
|
/* Top / bottom: full width, fixed height, slide along Y. */
|
|
181
183
|
:global(.sv-drawer--top), :global(.sv-drawer--bottom) {
|
|
182
184
|
left: 0; right: 0; height: var(--sv-drawer-size); max-height: 100vh;
|