@juspay/svelte-ui-components 2.80.2 → 2.80.3
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.
|
@@ -4,10 +4,20 @@
|
|
|
4
4
|
|
|
5
5
|
let {
|
|
6
6
|
text,
|
|
7
|
+
variant = 'primary',
|
|
8
|
+
size = 'md',
|
|
9
|
+
iconOnly = false,
|
|
10
|
+
fullWidth = false,
|
|
11
|
+
href,
|
|
12
|
+
target,
|
|
13
|
+
rel,
|
|
14
|
+
loading = false,
|
|
15
|
+
allowHtml = false,
|
|
7
16
|
enable = true,
|
|
8
17
|
disabled = false,
|
|
9
18
|
showLoader = false,
|
|
10
19
|
loaderType,
|
|
20
|
+
showProgressBar = $bindable(false),
|
|
11
21
|
type = 'button',
|
|
12
22
|
testId,
|
|
13
23
|
ariaLabel,
|
|
@@ -22,30 +32,46 @@
|
|
|
22
32
|
onmouseleave,
|
|
23
33
|
ontouchstart,
|
|
24
34
|
ontouchend,
|
|
25
|
-
showProgressBar = $bindable(false),
|
|
26
35
|
icon,
|
|
27
36
|
children,
|
|
28
37
|
classes
|
|
29
38
|
}: ButtonProperties = $props();
|
|
30
39
|
|
|
31
|
-
|
|
40
|
+
// `loading` and the legacy Circular loaderType both render the spinner and disable the button.
|
|
41
|
+
let showCircularLoader = $derived(loading || (showLoader && loaderType === 'Circular'));
|
|
42
|
+
// The legacy ProgressBar loader stays clickable until the first click starts the bar, then
|
|
43
|
+
// it disables (the documented flow). So it must NOT count toward "disabled" before it starts.
|
|
44
|
+
let isProgressBarLoader = $derived(showLoader && loaderType === 'ProgressBar');
|
|
45
|
+
let isBusy = $derived(showCircularLoader || showProgressBar);
|
|
46
|
+
let isDisabled = $derived(disabled || !enable || showCircularLoader || showProgressBar);
|
|
47
|
+
let resolvedRel = $derived(rel ?? (target === '_blank' ? 'noopener noreferrer' : null));
|
|
32
48
|
|
|
33
49
|
function handleButtonClick(event: MouseEvent): void {
|
|
34
|
-
if (
|
|
50
|
+
if (isDisabled) {
|
|
51
|
+
// Anchors have no native disabled state — block navigation/handler explicitly.
|
|
52
|
+
if (href) {
|
|
53
|
+
event.preventDefault();
|
|
54
|
+
}
|
|
35
55
|
return;
|
|
36
56
|
}
|
|
37
57
|
onclick?.(event);
|
|
38
|
-
if (
|
|
58
|
+
if (isProgressBarLoader) {
|
|
39
59
|
showProgressBar = true;
|
|
40
60
|
}
|
|
41
61
|
}
|
|
42
62
|
</script>
|
|
43
63
|
|
|
44
|
-
<div
|
|
64
|
+
<div
|
|
65
|
+
class="button-container variant-{variant} size-{size} {classes ?? ''}"
|
|
66
|
+
class:icon-only={iconOnly}
|
|
67
|
+
class:full-width={fullWidth}
|
|
68
|
+
>
|
|
45
69
|
{#if showProgressBar}
|
|
46
70
|
<div class="button-progress-bar"></div>
|
|
47
71
|
{/if}
|
|
48
|
-
<
|
|
72
|
+
<svelte:element
|
|
73
|
+
this={href ? 'a' : 'button'}
|
|
74
|
+
class="button-el"
|
|
49
75
|
class:disabled={isDisabled}
|
|
50
76
|
onclick={handleButtonClick}
|
|
51
77
|
{onkeydown}
|
|
@@ -55,28 +81,38 @@
|
|
|
55
81
|
{onmouseleave}
|
|
56
82
|
{ontouchstart}
|
|
57
83
|
{ontouchend}
|
|
58
|
-
disabled={isDisabled}
|
|
59
|
-
{type}
|
|
60
84
|
data-pw={testId}
|
|
61
|
-
|
|
62
|
-
aria-
|
|
63
|
-
aria-
|
|
64
|
-
{
|
|
85
|
+
role={role ?? null}
|
|
86
|
+
aria-label={ariaLabel ?? null}
|
|
87
|
+
aria-expanded={ariaExpanded ?? null}
|
|
88
|
+
aria-selected={ariaSelected ?? null}
|
|
89
|
+
aria-busy={isBusy || null}
|
|
90
|
+
type={href ? null : type}
|
|
91
|
+
disabled={href ? null : isDisabled}
|
|
92
|
+
href={href ? (isDisabled ? null : href) : null}
|
|
93
|
+
target={href ? target : null}
|
|
94
|
+
rel={href ? resolvedRel : null}
|
|
95
|
+
aria-disabled={href && isDisabled ? 'true' : null}
|
|
96
|
+
tabindex={href && isDisabled ? -1 : null}
|
|
65
97
|
>
|
|
66
|
-
{#if
|
|
98
|
+
{#if showCircularLoader}
|
|
67
99
|
<div class="button-loader"><Loader /></div>
|
|
68
100
|
{/if}
|
|
69
101
|
{#if typeof icon === 'function'}
|
|
70
102
|
<div class="button-icon">{@render icon()}</div>
|
|
71
103
|
{/if}
|
|
72
104
|
{#if typeof text === 'string' && text.length > 0}
|
|
73
|
-
|
|
74
|
-
|
|
105
|
+
{#if allowHtml}
|
|
106
|
+
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
|
107
|
+
<div class="button-text">{@html text}</div>
|
|
108
|
+
{:else}
|
|
109
|
+
<div class="button-text">{text}</div>
|
|
110
|
+
{/if}
|
|
75
111
|
{/if}
|
|
76
112
|
{#if typeof children === 'function'}
|
|
77
113
|
{@render children()}
|
|
78
114
|
{/if}
|
|
79
|
-
</
|
|
115
|
+
</svelte:element>
|
|
80
116
|
</div>
|
|
81
117
|
|
|
82
118
|
<style>
|
|
@@ -84,23 +120,92 @@
|
|
|
84
120
|
position: relative;
|
|
85
121
|
width: var(--button-width, fit-content);
|
|
86
122
|
}
|
|
87
|
-
|
|
123
|
+
|
|
124
|
+
/* ---- Variant defaults (set the internal --_btn-* layer; explicit --button-* always wins) ---- */
|
|
125
|
+
.variant-primary {
|
|
126
|
+
--_btn-color: #3a4550;
|
|
127
|
+
--_btn-text-color: #ffffff;
|
|
128
|
+
--_btn-border: none;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.variant-secondary {
|
|
132
|
+
--_btn-color: transparent;
|
|
133
|
+
--_btn-text-color: #3a4550;
|
|
134
|
+
--_btn-border: 1px solid #cbd5e1;
|
|
135
|
+
--_btn-hover-color: #f1f5f9;
|
|
136
|
+
--_btn-hover-text-color: #3a4550;
|
|
137
|
+
--_btn-hover-border: 1px solid #cbd5e1;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.variant-ghost {
|
|
141
|
+
--_btn-color: transparent;
|
|
142
|
+
--_btn-text-color: #3a4550;
|
|
143
|
+
--_btn-border: none;
|
|
144
|
+
--_btn-hover-color: #f1f5f9;
|
|
145
|
+
--_btn-hover-text-color: #3a4550;
|
|
146
|
+
--_btn-hover-border: none;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.variant-destructive {
|
|
150
|
+
--_btn-color: #e7000b;
|
|
151
|
+
--_btn-text-color: #ffffff;
|
|
152
|
+
--_btn-border: none;
|
|
153
|
+
--_btn-hover-color: #c10007;
|
|
154
|
+
--_btn-hover-text-color: #ffffff;
|
|
155
|
+
--_btn-hover-border: none;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/* ---- Size defaults (md reproduces the legacy 16px padding / 14px font) ---- */
|
|
159
|
+
.size-sm {
|
|
160
|
+
--_btn-padding: 8px 12px;
|
|
161
|
+
--_btn-font-size: 13px;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.size-md {
|
|
165
|
+
--_btn-padding: 16px;
|
|
166
|
+
--_btn-font-size: 14px;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.size-lg {
|
|
170
|
+
--_btn-padding: 20px 28px;
|
|
171
|
+
--_btn-font-size: 16px;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.icon-only {
|
|
175
|
+
--_btn-padding: 8px;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.icon-only.size-sm {
|
|
179
|
+
--_btn-padding: 6px;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
.icon-only.size-lg {
|
|
183
|
+
--_btn-padding: 12px;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.full-width {
|
|
187
|
+
--button-width: 100%;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.button-el {
|
|
88
191
|
max-height: var(--button-max-height);
|
|
89
192
|
max-width: var(--button-max-width);
|
|
90
193
|
min-width: var(--button-min-width);
|
|
91
194
|
font-family: var(--button-font-family);
|
|
92
195
|
font-weight: var(--button-font-weight, 500);
|
|
93
|
-
font-size: var(--button-font-size, 14px);
|
|
94
|
-
background-color: var(--button-color, #3a4550);
|
|
95
|
-
color: var(--button-text-color, white);
|
|
196
|
+
font-size: var(--button-font-size, var(--_btn-font-size, 14px));
|
|
197
|
+
background-color: var(--button-color, var(--_btn-color, #3a4550));
|
|
198
|
+
color: var(--button-text-color, var(--_btn-text-color, white));
|
|
96
199
|
height: var(--button-height, fit-content);
|
|
97
|
-
padding: var(--button-padding, 16px);
|
|
200
|
+
padding: var(--button-padding, var(--_btn-padding, 16px));
|
|
98
201
|
margin: var(--button-margin);
|
|
99
|
-
border-radius: var(--button-border-radius, var(--radius,
|
|
202
|
+
border-radius: var(--button-border-radius, var(--radius, 6px));
|
|
100
203
|
width: var(--button-width, fit-content);
|
|
101
204
|
cursor: var(--cursor, pointer);
|
|
102
205
|
opacity: var(--opacity, 1);
|
|
103
|
-
border: var(--button-border, none);
|
|
206
|
+
border: var(--button-border, var(--_btn-border, none));
|
|
207
|
+
box-sizing: border-box;
|
|
208
|
+
text-decoration: none;
|
|
104
209
|
display: flex;
|
|
105
210
|
justify-content: var(--button-justify-content, center);
|
|
106
211
|
align-items: center;
|
|
@@ -110,14 +215,16 @@
|
|
|
110
215
|
box-shadow: var(--button-box-shadow, none);
|
|
111
216
|
}
|
|
112
217
|
|
|
113
|
-
.disabled
|
|
218
|
+
.button-el.disabled,
|
|
219
|
+
.button-el:disabled {
|
|
114
220
|
cursor: var(--disabled-cursor, not-allowed);
|
|
115
221
|
opacity: var(--disabled-opacity, 0.4);
|
|
116
|
-
color: var(--disabled-text-color, var(--button-text-color, white));
|
|
222
|
+
color: var(--disabled-text-color, var(--button-text-color, var(--_btn-text-color, white)));
|
|
117
223
|
font-size: var(--disabled-font-size);
|
|
118
224
|
font-weight: var(--disabled-font-weight);
|
|
119
|
-
border
|
|
120
|
-
|
|
225
|
+
/* Preserve the variant border when disabled so secondary (bordered) stays distinct from ghost. */
|
|
226
|
+
border: var(--disabled-border, var(--button-border, var(--_btn-border, none)));
|
|
227
|
+
background: var(--disabled-background-color, var(--button-color, var(--_btn-color, #3a4550)));
|
|
121
228
|
box-shadow: var(
|
|
122
229
|
--button-disabled-box-shadow,
|
|
123
230
|
var(--disabled-box-shadow, var(--button-box-shadow, none))
|
|
@@ -138,21 +245,30 @@
|
|
|
138
245
|
display: var(--button-text-display);
|
|
139
246
|
}
|
|
140
247
|
|
|
141
|
-
button:hover {
|
|
142
|
-
background: var(
|
|
143
|
-
|
|
144
|
-
|
|
248
|
+
.button-el:hover:not(.disabled) {
|
|
249
|
+
background: var(
|
|
250
|
+
--button-hover-color,
|
|
251
|
+
var(--_btn-hover-color, var(--button-color, var(--_btn-color, #3a4550)))
|
|
252
|
+
);
|
|
253
|
+
color: var(
|
|
254
|
+
--button-hover-text-color,
|
|
255
|
+
var(--_btn-hover-text-color, var(--button-text-color, var(--_btn-text-color, white)))
|
|
256
|
+
);
|
|
257
|
+
border: var(
|
|
258
|
+
--button-hover-border,
|
|
259
|
+
var(--_btn-hover-border, var(--button-border, var(--_btn-border, none)))
|
|
260
|
+
);
|
|
145
261
|
transform: var(--button-hover-transform);
|
|
146
262
|
box-shadow: var(--button-hover-box-shadow, var(--button-box-shadow, none));
|
|
147
263
|
}
|
|
148
264
|
|
|
149
|
-
button:active {
|
|
265
|
+
.button-el:active:not(.disabled) {
|
|
150
266
|
transform: var(--button-active-transform);
|
|
151
|
-
background: var(--button-active-background, var(--button-color, #3a4550));
|
|
267
|
+
background: var(--button-active-background, var(--button-color, var(--_btn-color, #3a4550)));
|
|
152
268
|
box-shadow: var(--button-active-box-shadow, var(--button-box-shadow, none));
|
|
153
269
|
}
|
|
154
270
|
|
|
155
|
-
button:focus-visible {
|
|
271
|
+
.button-el:focus-visible {
|
|
156
272
|
box-shadow: var(--button-focus-visible-box-shadow, var(--button-box-shadow, none));
|
|
157
273
|
}
|
|
158
274
|
|
|
@@ -1,12 +1,51 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
2
|
export type LoaderType = 'Circular' | 'ProgressBar';
|
|
3
|
+
/** Visual style of the button. Maps to a built-in palette via `--button-*` variables. */
|
|
4
|
+
export type ButtonVariant = 'primary' | 'secondary' | 'ghost' | 'destructive';
|
|
5
|
+
/** Size preset controlling padding/height/font-size. */
|
|
6
|
+
export type ButtonSize = 'sm' | 'md' | 'lg';
|
|
3
7
|
export type ButtonProperties = OptionalButtonProperties & ButtonEventProperties;
|
|
4
8
|
export type OptionalButtonProperties = {
|
|
5
9
|
text?: string;
|
|
10
|
+
/**
|
|
11
|
+
* Visual style: `primary` (default, filled), `secondary` (outlined), `ghost`
|
|
12
|
+
* (transparent), `destructive` (danger). Each maps to the `--button-*` variables, so an
|
|
13
|
+
* explicit `--button-color` / `classes` override always wins over the variant default.
|
|
14
|
+
*/
|
|
15
|
+
variant?: ButtonVariant;
|
|
16
|
+
/** Size preset: `sm` / `md` (default) / `lg`. Controls padding, height, and font size. */
|
|
17
|
+
size?: ButtonSize;
|
|
18
|
+
/** Square padding for an icon-only button. Pair with `ariaLabel` for accessibility. */
|
|
19
|
+
iconOnly?: boolean;
|
|
20
|
+
/** Stretch the button to the full width of its container. */
|
|
21
|
+
fullWidth?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Render the button as an `<a>` styled identically. Use for button-styled links/navigation.
|
|
24
|
+
* When set, `type` is ignored; a disabled link is rendered inert via `aria-disabled`.
|
|
25
|
+
*/
|
|
26
|
+
href?: string;
|
|
27
|
+
/** Anchor target (only with `href`), e.g. `_blank`. */
|
|
28
|
+
target?: string;
|
|
29
|
+
/** Anchor rel (only with `href`). Defaults to `noopener noreferrer` when `target="_blank"`. */
|
|
30
|
+
rel?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Show a loading state: renders the circular loader, sets `aria-busy`, and disables the
|
|
33
|
+
* button. Preferred over the legacy `showLoader`/`loaderType` pair.
|
|
34
|
+
*/
|
|
35
|
+
loading?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Render the `text` as raw HTML. Defaults to `false` (safe plain-text rendering). Only enable
|
|
38
|
+
* for trusted, non-user-derived markup.
|
|
39
|
+
*/
|
|
40
|
+
allowHtml?: boolean;
|
|
41
|
+
/** @deprecated Use `disabled` instead. Retained for backward compatibility. */
|
|
6
42
|
enable?: boolean;
|
|
7
|
-
|
|
43
|
+
/** @deprecated Prefer `loading`. Shows a loader; pair with `loaderType`. */
|
|
8
44
|
showLoader?: boolean;
|
|
45
|
+
/** @deprecated Used with `showLoader`. `'Circular'` or `'ProgressBar'`. */
|
|
9
46
|
loaderType?: LoaderType;
|
|
47
|
+
/** @deprecated Drives the progress-bar animation when `loaderType='ProgressBar'`. */
|
|
48
|
+
showProgressBar?: boolean;
|
|
10
49
|
type?: 'submit' | 'reset' | 'button';
|
|
11
50
|
testId?: string;
|
|
12
51
|
icon?: Snippet;
|
|
@@ -30,6 +30,9 @@
|
|
|
30
30
|
barRadius = 3,
|
|
31
31
|
barPadding = 0.25,
|
|
32
32
|
aspectRatio = 16 / 9,
|
|
33
|
+
minBarHeight = 2,
|
|
34
|
+
margin,
|
|
35
|
+
tooltipPortal = false,
|
|
33
36
|
tooltipSnippet,
|
|
34
37
|
onbarclick,
|
|
35
38
|
testId,
|
|
@@ -44,6 +47,8 @@
|
|
|
44
47
|
let hoveredCategoryIndex = $state<number | null>(null);
|
|
45
48
|
let mouseX = $state(0);
|
|
46
49
|
let mouseY = $state(0);
|
|
50
|
+
let mouseClientX = $state(0);
|
|
51
|
+
let mouseClientY = $state(0);
|
|
47
52
|
|
|
48
53
|
// ── Formatters ─────────────────────────────────────────────────
|
|
49
54
|
|
|
@@ -53,7 +58,13 @@
|
|
|
53
58
|
// ── Layout — wider right margin to accommodate right-axis labels ─
|
|
54
59
|
|
|
55
60
|
const dims = $derived(
|
|
56
|
-
computeChartDimensions(chartWidth, chartHeight, {
|
|
61
|
+
computeChartDimensions(chartWidth, chartHeight, {
|
|
62
|
+
top: 24,
|
|
63
|
+
right: 56,
|
|
64
|
+
bottom: 40,
|
|
65
|
+
left: 56,
|
|
66
|
+
...margin
|
|
67
|
+
})
|
|
57
68
|
);
|
|
58
69
|
|
|
59
70
|
// ── Scales ─────────────────────────────────────────────────────
|
|
@@ -152,7 +163,7 @@
|
|
|
152
163
|
const barX = bandStart + subIndex * subBandWidth + barGap;
|
|
153
164
|
const valueY = scale(value);
|
|
154
165
|
const barY = value >= 0 ? valueY : zeroY;
|
|
155
|
-
const barHeight = Math.max(
|
|
166
|
+
const barHeight = Math.max(minBarHeight, Math.abs(valueY - zeroY));
|
|
156
167
|
|
|
157
168
|
const path = roundedRectPath(barX, barY, barW, barHeight, barRadius, barRadius, 0, 0);
|
|
158
169
|
|
|
@@ -278,6 +289,22 @@
|
|
|
278
289
|
const rect = containerEl.getBoundingClientRect();
|
|
279
290
|
mouseX = event.clientX - rect.left;
|
|
280
291
|
mouseY = event.clientY - rect.top;
|
|
292
|
+
mouseClientX = event.clientX;
|
|
293
|
+
mouseClientY = event.clientY;
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Svelte action: relocates the tooltip layer to `document.body` so a `position:fixed`
|
|
298
|
+
* tooltip is never clipped by an `overflow`/scroll ancestor. Used only when
|
|
299
|
+
* `tooltipPortal` is set; `use:` actions never run during SSR.
|
|
300
|
+
*/
|
|
301
|
+
const portalToBody = (node: HTMLElement) => {
|
|
302
|
+
document.body.appendChild(node);
|
|
303
|
+
return {
|
|
304
|
+
destroy: () => {
|
|
305
|
+
node.remove();
|
|
306
|
+
}
|
|
307
|
+
};
|
|
281
308
|
};
|
|
282
309
|
|
|
283
310
|
const handleCategoryEnter = (event: MouseEvent, catIdx: number) => {
|
|
@@ -439,12 +466,31 @@
|
|
|
439
466
|
</ChartContainer>
|
|
440
467
|
|
|
441
468
|
<!-- Tooltip -->
|
|
442
|
-
{#if
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
469
|
+
{#if hoveredCategoryIndex !== null}
|
|
470
|
+
{#if tooltipPortal}
|
|
471
|
+
<!-- Portaled to <body> with fixed viewport coords so the tooltip is never
|
|
472
|
+
clipped by an overflow/scroll ancestor (e.g. a scrollable report sheet).
|
|
473
|
+
The inner elements keep their own +12/-12 offset relative to this layer. -->
|
|
474
|
+
<div
|
|
475
|
+
class="chart-tooltip-portal"
|
|
476
|
+
style="left: {mouseClientX}px; top: {mouseClientY}px;"
|
|
477
|
+
use:portalToBody
|
|
478
|
+
>
|
|
479
|
+
{#if typeof tooltipSnippet === 'function'}
|
|
480
|
+
<div class="chart-tooltip-slot" style="left: 12px; top: -12px;">
|
|
481
|
+
{@render tooltipSnippet(buildTooltipContext(hoveredCategoryIndex))}
|
|
482
|
+
</div>
|
|
483
|
+
{:else}
|
|
484
|
+
<ChartTooltip data={tooltipData} mouseX={0} mouseY={0} />
|
|
485
|
+
{/if}
|
|
486
|
+
</div>
|
|
487
|
+
{:else if typeof tooltipSnippet === 'function'}
|
|
488
|
+
<div class="chart-tooltip-slot" style="left: {mouseX + 12}px; top: {mouseY - 12}px;">
|
|
489
|
+
{@render tooltipSnippet(buildTooltipContext(hoveredCategoryIndex))}
|
|
490
|
+
</div>
|
|
491
|
+
{:else}
|
|
492
|
+
<ChartTooltip data={tooltipData} {mouseX} {mouseY} />
|
|
493
|
+
{/if}
|
|
448
494
|
{/if}
|
|
449
495
|
{:else}
|
|
450
496
|
<div class="chart-empty">No data available.</div>
|
|
@@ -513,6 +559,12 @@
|
|
|
513
559
|
pointer-events: none;
|
|
514
560
|
}
|
|
515
561
|
|
|
562
|
+
.chart-tooltip-portal {
|
|
563
|
+
position: fixed;
|
|
564
|
+
z-index: var(--chart-tooltip-z-index, 10);
|
|
565
|
+
pointer-events: none;
|
|
566
|
+
}
|
|
567
|
+
|
|
516
568
|
.chart-empty {
|
|
517
569
|
padding: var(--chart-empty-padding, 32px 24px);
|
|
518
570
|
color: var(--chart-empty-color, #9ca3af);
|
|
@@ -95,6 +95,32 @@ export type OptionalDualAxisBarChartProperties = {
|
|
|
95
95
|
testId?: string;
|
|
96
96
|
/** Extra CSS class string on the root `<div>`. */
|
|
97
97
|
classes?: string;
|
|
98
|
+
/**
|
|
99
|
+
* Minimum rendered bar height in pixels. The default `2` keeps very small non-zero
|
|
100
|
+
* values visible, but it also paints a 2px stub for genuine zeros — set `0` so an
|
|
101
|
+
* all-zero/dormant series renders nothing (letting the consumer detect it and show
|
|
102
|
+
* an empty state instead of a row of indistinguishable baseline stubs). Default `2`.
|
|
103
|
+
*/
|
|
104
|
+
minBarHeight?: number;
|
|
105
|
+
/**
|
|
106
|
+
* Override the plot margins (px) reserved for axis titles and tick labels. Merged
|
|
107
|
+
* over the defaults `{ top: 24, right: 56, bottom: 40, left: 56 }`; widen `left`/`right`
|
|
108
|
+
* when long currency tick labels (e.g. `₹1,00,000`) would otherwise overlap the
|
|
109
|
+
* gridlines in a narrow container.
|
|
110
|
+
*/
|
|
111
|
+
margin?: {
|
|
112
|
+
top?: number;
|
|
113
|
+
right?: number;
|
|
114
|
+
bottom?: number;
|
|
115
|
+
left?: number;
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* Render the hover tooltip on `document.body` with `position: fixed` viewport
|
|
119
|
+
* coordinates instead of `position: absolute` inside the chart. Set `true` when the
|
|
120
|
+
* chart sits in an `overflow:auto`/scrollable container that would otherwise clip the
|
|
121
|
+
* tooltip. Default `false` (in-chart positioning, unchanged).
|
|
122
|
+
*/
|
|
123
|
+
tooltipPortal?: boolean;
|
|
98
124
|
};
|
|
99
125
|
export type DualAxisBarChartEventProperties = {
|
|
100
126
|
/**
|