@juspay/svelte-ui-components 2.97.1 → 2.98.0
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/Accordion/Accordion.svelte +12 -2
- package/dist/Accordion/properties.d.ts +8 -0
- package/dist/Button/Button.svelte +3 -1
- package/dist/Button/properties.d.ts +7 -0
- package/dist/Choicebox/Choicebox.svelte +5 -1
- package/dist/Select/Select.svelte +14 -0
- package/dist/Select/properties.d.ts +8 -0
- package/dist/Tabs/Tabs.svelte +48 -1
- package/dist/Tabs/properties.d.ts +22 -6
- package/package.json +1 -1
|
@@ -8,10 +8,14 @@
|
|
|
8
8
|
ontoggle,
|
|
9
9
|
triggerClasses,
|
|
10
10
|
classes,
|
|
11
|
-
testId
|
|
11
|
+
testId,
|
|
12
|
+
disabled = false
|
|
12
13
|
}: AccordionProperties = $props();
|
|
13
14
|
|
|
14
15
|
function handleTriggerClick(): void {
|
|
16
|
+
if (disabled) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
15
19
|
expand = !expand;
|
|
16
20
|
ontoggle?.(expand);
|
|
17
21
|
}
|
|
@@ -20,9 +24,11 @@
|
|
|
20
24
|
{#if trigger}
|
|
21
25
|
<div
|
|
22
26
|
class="accordion-trigger {triggerClasses ?? ''}"
|
|
27
|
+
class:disabled
|
|
23
28
|
role="button"
|
|
24
|
-
tabindex=
|
|
29
|
+
tabindex={disabled ? -1 : 0}
|
|
25
30
|
aria-expanded={expand}
|
|
31
|
+
aria-disabled={disabled}
|
|
26
32
|
onclick={handleTriggerClick}
|
|
27
33
|
onkeydown={(event) => {
|
|
28
34
|
if (event.key === 'Enter' || event.key === ' ') {
|
|
@@ -50,6 +56,10 @@
|
|
|
50
56
|
cursor: var(--accordion-trigger-cursor, pointer);
|
|
51
57
|
}
|
|
52
58
|
|
|
59
|
+
.accordion-trigger.disabled {
|
|
60
|
+
cursor: var(--accordion-trigger-disabled-cursor, not-allowed);
|
|
61
|
+
}
|
|
62
|
+
|
|
53
63
|
.accordion {
|
|
54
64
|
display: grid;
|
|
55
65
|
grid-template-rows: 0fr;
|
|
@@ -9,6 +9,14 @@ export type OptionalAccordionProperties = {
|
|
|
9
9
|
triggerClasses?: string;
|
|
10
10
|
classes?: string;
|
|
11
11
|
testId?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Disables the built-in trigger: clicks and Enter/Space no longer toggle,
|
|
14
|
+
* the trigger is removed from the tab order, and `aria-disabled="true"` is
|
|
15
|
+
* emitted. The trigger element also gets a `disabled` class so consumers can
|
|
16
|
+
* style the locked state. `expand` is still honoured, so a disabled accordion
|
|
17
|
+
* can be shown open or closed under external (controlled) state.
|
|
18
|
+
*/
|
|
19
|
+
disabled?: boolean;
|
|
12
20
|
};
|
|
13
21
|
export type AccordionEventProperties = {
|
|
14
22
|
ontoggle?: (expanded: boolean) => void;
|
|
@@ -34,7 +34,8 @@
|
|
|
34
34
|
ontouchend,
|
|
35
35
|
icon,
|
|
36
36
|
children,
|
|
37
|
-
classes
|
|
37
|
+
classes,
|
|
38
|
+
style
|
|
38
39
|
}: ButtonProperties = $props();
|
|
39
40
|
|
|
40
41
|
// `loading` and the legacy Circular loaderType both render the spinner and disable the button.
|
|
@@ -65,6 +66,7 @@
|
|
|
65
66
|
class="button-container variant-{variant} size-{size} {classes ?? ''}"
|
|
66
67
|
class:icon-only={iconOnly}
|
|
67
68
|
class:full-width={fullWidth}
|
|
69
|
+
style={style ?? null}
|
|
68
70
|
>
|
|
69
71
|
{#if showProgressBar}
|
|
70
72
|
<div class="button-progress-bar"></div>
|
|
@@ -56,6 +56,13 @@ export type OptionalButtonProperties = {
|
|
|
56
56
|
role?: string;
|
|
57
57
|
disabled?: boolean;
|
|
58
58
|
classes?: string;
|
|
59
|
+
/**
|
|
60
|
+
* Inline style applied to the outer `.button-container`. Use for per-instance
|
|
61
|
+
* dynamic values a static class can't express — e.g. a CSS custom property
|
|
62
|
+
* driven by runtime state (`--offset: {n}px`). Prefer `classes` / `--button-*`
|
|
63
|
+
* tokens for anything static.
|
|
64
|
+
*/
|
|
65
|
+
style?: string;
|
|
59
66
|
};
|
|
60
67
|
export type ButtonEventProperties = {
|
|
61
68
|
onclick?: (event: MouseEvent) => void;
|
|
@@ -68,7 +68,11 @@
|
|
|
68
68
|
box-shadow: var(--choicebox-focus-ring, 0 0 0 3px rgba(33, 150, 243, 0.3));
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
/* Exclude the selected state from hover: without :not(.selected) this rule
|
|
72
|
+
(specificity 0,3,0) outranks .choicebox.selected (0,2,0), so hovering a
|
|
73
|
+
selected card repaints it with the neutral hover border/fill until the
|
|
74
|
+
cursor leaves. Excluding selected lets .choicebox.selected show through. */
|
|
75
|
+
.choicebox:not(.disabled):not(.selected):hover {
|
|
72
76
|
border-color: var(--choicebox-hover-border-color, #9e9e9e);
|
|
73
77
|
background: var(--choicebox-hover-background, var(--choicebox-background, #ffffff));
|
|
74
78
|
}
|
|
@@ -587,6 +587,9 @@
|
|
|
587
587
|
</span>
|
|
588
588
|
{/if}
|
|
589
589
|
{/if}
|
|
590
|
+
{#if typeof row.item.icon === 'string' && row.item.icon.length > 0}
|
|
591
|
+
<Img src={row.item.icon} alt="" fallback="" classes="select-option-icon" />
|
|
592
|
+
{/if}
|
|
590
593
|
<span class="select-option-label">{row.item.label}</span>
|
|
591
594
|
{#if showSelectedTick && !multiple && value.includes(row.item.id)}
|
|
592
595
|
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
|
@@ -754,6 +757,17 @@
|
|
|
754
757
|
transition: background 0.1s;
|
|
755
758
|
}
|
|
756
759
|
|
|
760
|
+
/* Per-option leading icon (SelectItem.icon). Kept inline + vertically centred so
|
|
761
|
+
it needs no change to the option's display and can't regress icon-less lists. */
|
|
762
|
+
.select-option :global(.select-option-icon) {
|
|
763
|
+
--image-width: var(--select-option-icon-size, 16px);
|
|
764
|
+
--image-height: var(--select-option-icon-size, 16px);
|
|
765
|
+
--image-object-fit: contain;
|
|
766
|
+
|
|
767
|
+
vertical-align: middle;
|
|
768
|
+
margin-right: var(--select-option-icon-gap, 8px);
|
|
769
|
+
}
|
|
770
|
+
|
|
757
771
|
.select-option.multi {
|
|
758
772
|
display: flex;
|
|
759
773
|
align-items: center;
|
|
@@ -5,6 +5,14 @@ export type SelectItem = {
|
|
|
5
5
|
label: string;
|
|
6
6
|
/** Optional per-option test id, emitted as `data-pw` on the option element. */
|
|
7
7
|
testId?: string;
|
|
8
|
+
/**
|
|
9
|
+
* Optional image src (URL or data URI) rendered at the left of the option row,
|
|
10
|
+
* before the label — for icon pickers and any list whose options carry a glyph.
|
|
11
|
+
* Size is controlled by the `--select-option-icon-size` CSS variable (default 16px).
|
|
12
|
+
* Pair with the trigger's `leftIcon` (driven by the selected option's icon) to show
|
|
13
|
+
* the current selection in the closed trigger.
|
|
14
|
+
*/
|
|
15
|
+
icon?: string;
|
|
8
16
|
};
|
|
9
17
|
export type MandatorySelectProperties = {
|
|
10
18
|
items: SelectItem[] | string[];
|
package/dist/Tabs/Tabs.svelte
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { TabItem, TabsProperties } from './properties';
|
|
3
|
+
import Img from '../Img/Img.svelte';
|
|
3
4
|
import chevronLeftSvg from '../assets/chevron-left.svg?raw';
|
|
4
5
|
import chevronRightSvg from '../assets/chevron-right.svg?raw';
|
|
5
6
|
|
|
@@ -191,9 +192,22 @@
|
|
|
191
192
|
onkeydown={(event) => handleKeydown(event, index)}
|
|
192
193
|
>
|
|
193
194
|
{#if typeof tab === 'function'}
|
|
194
|
-
{@render tab({
|
|
195
|
+
{@render tab({
|
|
196
|
+
label,
|
|
197
|
+
index,
|
|
198
|
+
active: isActiveItem(index),
|
|
199
|
+
subtitle: tabItem?.subtitle,
|
|
200
|
+
icon: tabItem?.icon,
|
|
201
|
+
status: tabItem?.status
|
|
202
|
+
})}
|
|
195
203
|
{:else}
|
|
204
|
+
{#if typeof tabItem?.icon === 'string' && tabItem.icon.length > 0}
|
|
205
|
+
<Img src={tabItem.icon} alt="" fallback="" classes="tabs-item-icon" />
|
|
206
|
+
{/if}
|
|
196
207
|
{label}
|
|
208
|
+
{#if tabItem?.status && tabItem.status !== 'none'}
|
|
209
|
+
<span class="tabs-item-status status-{tabItem.status}" aria-hidden="true"></span>
|
|
210
|
+
{/if}
|
|
197
211
|
{/if}
|
|
198
212
|
</div>
|
|
199
213
|
{/each}
|
|
@@ -327,6 +341,7 @@
|
|
|
327
341
|
.tabs-item {
|
|
328
342
|
display: flex;
|
|
329
343
|
align-items: center;
|
|
344
|
+
gap: var(--tabs-item-gap, 8px);
|
|
330
345
|
position: relative;
|
|
331
346
|
padding: var(--tabs-item-padding, 12px 16px);
|
|
332
347
|
font-size: var(--tabs-item-font-size, 14px);
|
|
@@ -344,6 +359,38 @@
|
|
|
344
359
|
transition: var(--tabs-transition, color 0.2s ease, background 0.2s ease);
|
|
345
360
|
}
|
|
346
361
|
|
|
362
|
+
.tabs-item :global(.tabs-item-icon) {
|
|
363
|
+
--image-width: var(--tabs-item-icon-size, 16px);
|
|
364
|
+
--image-height: var(--tabs-item-icon-size, 16px);
|
|
365
|
+
--image-object-fit: contain;
|
|
366
|
+
|
|
367
|
+
flex-shrink: 0;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/* Trailing status dot for nav/menu tabs. margin-left:auto pushes it to the row's
|
|
371
|
+
end (e.g. a settings menu); harmless on a normal tab bar where the item shrinks
|
|
372
|
+
to content. */
|
|
373
|
+
.tabs-item-status {
|
|
374
|
+
width: var(--tabs-item-status-size, 8px);
|
|
375
|
+
height: var(--tabs-item-status-size, 8px);
|
|
376
|
+
margin-left: auto;
|
|
377
|
+
border-radius: 50%;
|
|
378
|
+
flex-shrink: 0;
|
|
379
|
+
background: var(--tabs-item-status-default-color, transparent);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
.tabs-item-status.status-pending {
|
|
383
|
+
background: var(--tabs-item-status-pending-color, #f59e0b);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
.tabs-item-status.status-error {
|
|
387
|
+
background: var(--tabs-item-status-error-color, #e7000b);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
.tabs-item-status.status-success {
|
|
391
|
+
background: var(--tabs-item-status-success-color, #16a34a);
|
|
392
|
+
}
|
|
393
|
+
|
|
347
394
|
.tabs-item:hover:not(.active):not([aria-disabled]) {
|
|
348
395
|
color: var(--tabs-hover-color, #333333);
|
|
349
396
|
background: var(--tabs-hover-background, #f5f5f5);
|
|
@@ -4,6 +4,18 @@ export type TabItem = {
|
|
|
4
4
|
label: string;
|
|
5
5
|
testId?: string;
|
|
6
6
|
subtitle?: string;
|
|
7
|
+
/**
|
|
8
|
+
* Optional image src (URL or data URI) rendered before the label in the default
|
|
9
|
+
* tab layout. Size is controlled by the `--tabs-item-icon-size` CSS variable
|
|
10
|
+
* (default 16px). Also forwarded to the `tab` snippet for custom layouts.
|
|
11
|
+
*/
|
|
12
|
+
icon?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Optional status dot rendered after the label — for nav/menu tabs that flag
|
|
15
|
+
* per-item state. `'none'` (default) renders nothing. Colours are themeable via
|
|
16
|
+
* `--tabs-item-status-{pending,error,success}-color`.
|
|
17
|
+
*/
|
|
18
|
+
status?: 'none' | 'pending' | 'error' | 'success';
|
|
7
19
|
};
|
|
8
20
|
export type TabsProperties = MandatoryTabsProperties & OptionalTabsProperties & TabsEventProperties;
|
|
9
21
|
export type MandatoryTabsProperties = {
|
|
@@ -16,12 +28,16 @@ export type OptionalTabsProperties = {
|
|
|
16
28
|
testId?: string;
|
|
17
29
|
scrollLeftIcon?: Snippet;
|
|
18
30
|
scrollRightIcon?: Snippet;
|
|
19
|
-
tab?: Snippet<[
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
31
|
+
tab?: Snippet<[
|
|
32
|
+
{
|
|
33
|
+
label: string;
|
|
34
|
+
index: number;
|
|
35
|
+
active: boolean;
|
|
36
|
+
subtitle?: string;
|
|
37
|
+
icon?: string;
|
|
38
|
+
status?: TabItem['status'];
|
|
39
|
+
}
|
|
40
|
+
]>;
|
|
25
41
|
classes?: string;
|
|
26
42
|
};
|
|
27
43
|
export type TabsEventProperties = {
|