@juspay/svelte-ui-components 4.27.5 → 4.28.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/README.md +140 -36
- package/dist/Animations/ModalAnimation.svelte +15 -1
- package/dist/Animations/OverlayAnimation.svelte +7 -1
- package/dist/AreaChart/AreaChart.svelte +366 -85
- package/dist/AspectRatio/AspectRatio.svelte +51 -0
- package/dist/AspectRatio/AspectRatio.svelte.d.ts +3 -0
- package/dist/AspectRatio/properties.d.ts +27 -0
- package/dist/AspectRatio/properties.js +1 -0
- package/dist/Banner/Banner.svelte +10 -4
- package/dist/Banner/properties.d.ts +8 -0
- package/dist/BarChart/BarChart.svelte +156 -49
- package/dist/Book/Book.svelte +14 -1
- package/dist/BrandLoader/BrandLoader.svelte +76 -12
- package/dist/Button/Button.svelte +56 -11
- package/dist/Calendar/Calendar.svelte +88 -61
- package/dist/Card/Card.svelte +1 -1
- package/dist/Carousel/Carousel.svelte +6 -3
- package/dist/ChatComposer/ChatComposer.svelte +54 -4
- package/dist/ChatComposer/dictationState.d.ts +15 -0
- package/dist/ChatComposer/dictationState.js +9 -0
- package/dist/ChatComposer/properties.d.ts +28 -1
- package/dist/ChatMessage/ChatMessage.svelte +27 -1
- package/dist/CheckListItem/CheckListItem.svelte +3 -3
- package/dist/Checkbox/Checkbox.svelte +84 -3
- package/dist/Checkbox/properties.d.ts +45 -13
- package/dist/ChipInput/ChipInput.svelte +70 -3
- package/dist/ChipInput/properties.d.ts +16 -0
- package/dist/Choicebox/Choicebox.svelte +156 -1
- package/dist/Choicebox/group.d.ts +63 -0
- package/dist/Choicebox/group.js +127 -0
- package/dist/Choicebox/properties.d.ts +46 -0
- package/dist/ColorPicker/ColorPicker.svelte +169 -20
- package/dist/ColorPicker/properties.d.ts +16 -0
- package/dist/Combobox/Combobox.svelte +87 -25
- package/dist/Combobox/properties.d.ts +23 -0
- package/dist/CommandMenu/CommandMenu.svelte +27 -11
- package/dist/ContextMenu/ContextMenu.svelte +31 -37
- package/dist/DateRangePicker/DateRangePicker.svelte +171 -73
- package/dist/DeltaIndicator/DeltaIndicator.svelte +3 -3
- package/dist/Draggable/Draggable.svelte +12 -7
- package/dist/DualAxisBarChart/DualAxisBarChart.svelte +11 -4
- package/dist/EmptyState/EmptyState.svelte +1 -1
- package/dist/FileDropzoneTrigger/FileDropzoneTrigger.svelte +1 -1
- package/dist/FileInput/FileInput.svelte +50 -1
- package/dist/FileInput/properties.d.ts +7 -0
- package/dist/FunnelChart/FunnelChart.svelte +40 -12
- package/dist/FunnelChart/properties.d.ts +7 -1
- package/dist/Gallery/Gallery.svelte +20 -13
- package/dist/Gallery/properties.d.ts +8 -0
- package/dist/GridItem/GridItem.svelte +31 -1
- package/dist/HITL/HITL.svelte +35 -9
- package/dist/Icon/Icon.svelte +19 -3
- package/dist/Input/Input.svelte +24 -10
- package/dist/Input/properties.d.ts +37 -1
- package/dist/InputButton/InputButton.svelte +86 -11
- package/dist/InputButton/properties.d.ts +10 -1
- package/dist/Label/Label.svelte +54 -0
- package/dist/Label/Label.svelte.d.ts +3 -0
- package/dist/Label/properties.d.ts +26 -0
- package/dist/Label/properties.js +1 -0
- package/dist/LineChart/LineChart.svelte +385 -94
- package/dist/ListItem/ListItem.svelte +121 -15
- package/dist/Loader/Loader.svelte +22 -2
- package/dist/LoadingDots/LoadingDots.svelte +21 -0
- package/dist/MediaUpload/MediaUpload.svelte +13 -3
- package/dist/Menu/Menu.svelte +56 -28
- package/dist/Modal/Modal.svelte +77 -42
- package/dist/Pagination/Pagination.svelte +9 -2
- package/dist/Phone/Phone.svelte +4 -0
- package/dist/PieChart/PieChart.svelte +282 -38
- package/dist/PieChart/properties.d.ts +9 -0
- package/dist/Pill/Pill.svelte +14 -5
- package/dist/Progress/Progress.svelte +20 -0
- package/dist/Radio/Radio.svelte +58 -1
- package/dist/Radio/properties.d.ts +23 -0
- package/dist/RatingGroup/RatingGroup.svelte +283 -0
- package/dist/RatingGroup/RatingGroup.svelte.d.ts +4 -0
- package/dist/RatingGroup/properties.d.ts +73 -0
- package/dist/RatingGroup/properties.js +1 -0
- package/dist/RelativeTime/RelativeTime.svelte +1 -1
- package/dist/SankeyChart/SankeyChart.svelte +272 -50
- package/dist/SankeyChart/properties.d.ts +9 -0
- package/dist/Scroller/Scroller.svelte +37 -2
- package/dist/Select/Select.svelte +166 -46
- package/dist/Select/properties.d.ts +7 -0
- package/dist/Separator/Separator.svelte +48 -0
- package/dist/Separator/Separator.svelte.d.ts +3 -0
- package/dist/Separator/properties.d.ts +22 -0
- package/dist/Separator/properties.js +1 -0
- package/dist/Sheet/Sheet.svelte +60 -21
- package/dist/Shimmer/Shimmer.svelte +15 -0
- package/dist/Slider/Slider.svelte +87 -6
- package/dist/Slider/properties.d.ts +26 -0
- package/dist/Snippet/Snippet.svelte +4 -0
- package/dist/Snippet/copyState.svelte.d.ts +13 -1
- package/dist/Snippet/copyState.svelte.js +27 -1
- package/dist/Snippet/properties.d.ts +7 -0
- package/dist/SoundKit/SoundKit.js +9 -8
- package/dist/SplitInput/SplitInput.svelte +68 -2
- package/dist/SplitInput/properties.d.ts +23 -0
- package/dist/StatCard/StatCard.svelte +6 -6
- package/dist/Status/Status.svelte +2 -2
- package/dist/Stepper/Step.svelte +19 -6
- package/dist/Stepper/Stepper.svelte +108 -35
- package/dist/Table/BuiltinCell.svelte +2 -2
- package/dist/Table/Table.svelte +373 -55
- package/dist/Table/properties.d.ts +134 -3
- package/dist/Tabs/Tabs.svelte +263 -65
- package/dist/Tabs/properties.d.ts +23 -0
- package/dist/TaskList/TaskList.svelte +14 -5
- package/dist/ThemeSwitcher/ThemeSwitcher.svelte +23 -0
- package/dist/ThinkingIndicator/ThinkingIndicator.svelte +13 -5
- package/dist/Toast/Toast.svelte +27 -2
- package/dist/Toggle/Toggle.svelte +79 -7
- package/dist/Toggle/Toggle.svelte.d.ts +1 -1
- package/dist/Toggle/properties.d.ts +30 -7
- package/dist/ToolCallLog/ToolCallLog.svelte +59 -21
- package/dist/ToolCallLog/properties.d.ts +10 -0
- package/dist/Toolbar/Toolbar.svelte +1 -1
- package/dist/Tooltip/Tooltip.svelte +20 -2
- package/dist/Tooltip/tooltip-action.js +39 -4
- package/dist/TypewriterText/TypewriterText.svelte +34 -2
- package/dist/TypewriterText/properties.d.ts +18 -5
- package/dist/_chart/ChartContainer.svelte +12 -0
- package/dist/_chart/ChartTooltip.svelte +18 -4
- package/dist/_chart/Legend.svelte +21 -0
- package/dist/_chart/Legend.svelte.d.ts +15 -0
- package/dist/_chart/geometry.d.ts +54 -1
- package/dist/_chart/geometry.js +122 -14
- package/dist/_chart/interactions.d.ts +5 -1
- package/dist/_chart/interactions.js +9 -5
- package/dist/_chart/scales.js +16 -0
- package/dist/_chart/temporal.d.ts +45 -0
- package/dist/_chart/temporal.js +116 -0
- package/dist/_field/description.d.ts +50 -0
- package/dist/_field/description.js +51 -0
- package/dist/_interaction/dismissal.d.ts +67 -0
- package/dist/_interaction/dismissal.js +137 -0
- package/dist/_interaction/focus.d.ts +73 -0
- package/dist/_interaction/focus.js +143 -0
- package/dist/assets/star.svg +5 -0
- package/dist/index.d.ts +13 -1
- package/dist/index.js +21 -1
- package/dist/reduced-motion.svelte.d.ts +37 -0
- package/dist/reduced-motion.svelte.js +44 -0
- package/dist/styles/theme-dark.css +778 -0
- package/dist/types.d.ts +4 -2
- package/dist/utils.d.ts +62 -1
- package/dist/utils.js +80 -21
- package/dist-codemod/{bin.js → codemod/bin.js} +13 -2
- package/dist-codemod/{cli.js → codemod/cli.js} +48 -3
- package/dist-codemod/codemod/migrate-audit.js +395 -0
- package/dist-codemod/codemod/migration-assets/legacy-display.css +120 -0
- package/dist-codemod/codemod/migration-assets/legacy-palette.css +106 -0
- package/dist-codemod/codemod/migration-assets/wc-display.json +492 -0
- package/dist-codemod/migrate/analyze.js +804 -0
- package/dist-codemod/migrate/chart-tooltip-selector.js +301 -0
- package/dist-wc/index.js +13992 -4323
- package/package.json +13 -6
- package/dist/Modal/focus-trap.d.ts +0 -42
- package/dist/Modal/focus-trap.js +0 -57
- /package/dist-codemod/{legacy-pairs.js → codemod/legacy-pairs.js} +0 -0
- /package/dist-codemod/{transform.js → codemod/transform.js} +0 -0
- /package/dist-codemod/{wc-children.js → codemod/wc-children.js} +0 -0
|
@@ -4,11 +4,34 @@ export type MandatoryRadioProperties = {
|
|
|
4
4
|
value: string;
|
|
5
5
|
};
|
|
6
6
|
export type OptionalRadioProperties = {
|
|
7
|
+
/**
|
|
8
|
+
* Text shown, and announced, when the control is in error. Linked to the
|
|
9
|
+
* control through `aria-describedby`, and sets `aria-invalid` while present.
|
|
10
|
+
*/
|
|
11
|
+
errorMessage?: string | null;
|
|
12
|
+
/**
|
|
13
|
+
* Persistent helper text describing the control. Linked through
|
|
14
|
+
* `aria-describedby` too, so it is read before the user trips an error rather
|
|
15
|
+
* than only after.
|
|
16
|
+
*/
|
|
17
|
+
infoMessage?: string | null;
|
|
18
|
+
/**
|
|
19
|
+
* Marks the control invalid without supplying a message, for a consumer
|
|
20
|
+
* driving validity from a server or its own rules.
|
|
21
|
+
*/
|
|
22
|
+
invalid?: boolean;
|
|
7
23
|
selectedValue?: string;
|
|
8
24
|
text?: string;
|
|
9
25
|
disabled?: boolean;
|
|
10
26
|
testId?: string;
|
|
11
27
|
classes?: string;
|
|
28
|
+
/** Blocks submission until one radio in the group is selected. Set it on every
|
|
29
|
+
* member, the way the native control expects. */
|
|
30
|
+
required?: boolean;
|
|
31
|
+
/** `id` of a form elsewhere in the same document, for a radio rendered outside it.
|
|
32
|
+
* Not available through `<sui-radio>`: a shadow-root control cannot join a form
|
|
33
|
+
* in the host document. */
|
|
34
|
+
form?: string;
|
|
12
35
|
};
|
|
13
36
|
export type RadioEventProperties = {
|
|
14
37
|
onchange?: (value: string) => void;
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { RatingGroupProperties, RatingGroupStarState } from './properties';
|
|
3
|
+
import starSvg from '../assets/star.svg?raw';
|
|
4
|
+
|
|
5
|
+
let {
|
|
6
|
+
value = $bindable(0),
|
|
7
|
+
max = 5,
|
|
8
|
+
disabled = false,
|
|
9
|
+
readonly = false,
|
|
10
|
+
allowHalf = false,
|
|
11
|
+
ariaLabel,
|
|
12
|
+
testId,
|
|
13
|
+
classes,
|
|
14
|
+
star,
|
|
15
|
+
name,
|
|
16
|
+
required = false,
|
|
17
|
+
form,
|
|
18
|
+
onchange
|
|
19
|
+
}: RatingGroupProperties = $props();
|
|
20
|
+
|
|
21
|
+
// `max` has to be a finite positive number for a star count to mean anything -- a
|
|
22
|
+
// zero, negative, or non-finite max renders no stars at all instead of a broken or
|
|
23
|
+
// infinite row, mirroring Progress's guard against an unusable range.
|
|
24
|
+
const hasValidMax = $derived(Number.isFinite(max) && max > 0);
|
|
25
|
+
const effectiveMax = $derived(hasValidMax ? max : 0);
|
|
26
|
+
const starCount = $derived(hasValidMax ? Math.max(0, Math.floor(max)) : 0);
|
|
27
|
+
const starIndices = $derived(Array.from({ length: starCount }, (_, index) => index));
|
|
28
|
+
|
|
29
|
+
const step = $derived(allowHalf ? 0.5 : 1);
|
|
30
|
+
|
|
31
|
+
// Clamps AND steps a raw number into a value this component can actually paint and
|
|
32
|
+
// report: finite, within [0, effectiveMax], and aligned to the configured precision.
|
|
33
|
+
// A non-finite input (NaN, +/-Infinity) becomes 0 rather than propagating into
|
|
34
|
+
// aria-valuenow, and an out-of-range input is clamped rather than wrapped -- pressing
|
|
35
|
+
// ArrowRight past the last star stays on the last star, it does not jump to 0.
|
|
36
|
+
function sanitize(raw: number): number {
|
|
37
|
+
// NaN has no direction to clamp toward, so it collapses to 0. +/-Infinity does have
|
|
38
|
+
// a direction and needs no special case: Math.max/Math.min below already clamp it
|
|
39
|
+
// to the corresponding bound, the same as any other out-of-range finite number.
|
|
40
|
+
if (Number.isNaN(raw)) {
|
|
41
|
+
return 0;
|
|
42
|
+
}
|
|
43
|
+
const clamped = Math.min(effectiveMax, Math.max(0, raw));
|
|
44
|
+
const stepped = allowHalf ? Math.round(clamped * 2) / 2 : Math.round(clamped);
|
|
45
|
+
// Guards against -0, which is finite, in range, and would otherwise render as the
|
|
46
|
+
// (visually identical but semantically wrong) "-0 out of N stars".
|
|
47
|
+
return stepped === 0 ? 0 : stepped;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const sanitizedValue = $derived(sanitize(value));
|
|
51
|
+
|
|
52
|
+
function formatNumber(n: number): string {
|
|
53
|
+
return Number.isInteger(n) ? String(n) : n.toFixed(1);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const valueText = $derived(
|
|
57
|
+
`${formatNumber(sanitizedValue)} out of ${formatNumber(effectiveMax)} star${effectiveMax === 1 ? '' : 's'}`
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
function starState(index: number): RatingGroupStarState {
|
|
61
|
+
const filled = sanitizedValue - index;
|
|
62
|
+
if (filled >= 1) {
|
|
63
|
+
return 'full';
|
|
64
|
+
}
|
|
65
|
+
if (filled >= 0.5) {
|
|
66
|
+
return 'half';
|
|
67
|
+
}
|
|
68
|
+
return 'empty';
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Only interaction produces a value, so the result of sanitize() here is always
|
|
72
|
+
// already finite and in range -- the guard is against a no-op (e.g. ArrowRight
|
|
73
|
+
// already at max), not against an invalid result.
|
|
74
|
+
function commit(newValue: number): void {
|
|
75
|
+
const sanitizedNew = sanitize(newValue);
|
|
76
|
+
if (sanitizedNew === sanitizedValue) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
value = sanitizedNew;
|
|
80
|
+
onchange?.(sanitizedNew);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function handleStarClick(event: MouseEvent, index: number): void {
|
|
84
|
+
if (disabled) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
// Clicking anywhere in the group focuses it even while readonly -- readonly stays
|
|
88
|
+
// focusable, only the value stops being settable, so focus is unconditional here
|
|
89
|
+
// and the value change below is the part readonly guards.
|
|
90
|
+
root?.focus();
|
|
91
|
+
if (readonly) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const target = event.currentTarget;
|
|
95
|
+
const ratio =
|
|
96
|
+
target instanceof HTMLElement
|
|
97
|
+
? (() => {
|
|
98
|
+
const rect = target.getBoundingClientRect();
|
|
99
|
+
return rect.width > 0 ? (event.clientX - rect.left) / rect.width : 1;
|
|
100
|
+
})()
|
|
101
|
+
: 1;
|
|
102
|
+
const isHalfClick = allowHalf && ratio < 0.5;
|
|
103
|
+
commit(isHalfClick ? index + 0.5 : index + 1);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// A tablist-style guard against hijacking browser/OS shortcuts built on the same
|
|
107
|
+
// keys (Ctrl+Home, Shift+ArrowRight) -- mirrors Tabs.svelte's handleKeydown.
|
|
108
|
+
function handleKeydown(event: KeyboardEvent): void {
|
|
109
|
+
if (disabled || readonly) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
let next: number;
|
|
116
|
+
if (event.key === 'ArrowRight' || event.key === 'ArrowUp') {
|
|
117
|
+
next = sanitizedValue + step;
|
|
118
|
+
} else if (event.key === 'ArrowLeft' || event.key === 'ArrowDown') {
|
|
119
|
+
next = sanitizedValue - step;
|
|
120
|
+
} else if (event.key === 'Home') {
|
|
121
|
+
next = 0;
|
|
122
|
+
} else if (event.key === 'End') {
|
|
123
|
+
next = effectiveMax;
|
|
124
|
+
} else {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
event.preventDefault();
|
|
128
|
+
commit(next);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
let root: HTMLDivElement | null = $state(null);
|
|
132
|
+
|
|
133
|
+
// The hidden native input is tabindex="-1", so the browser's own "focus the invalid
|
|
134
|
+
// field" step would land on an element the user cannot see or reach. Focus the
|
|
135
|
+
// role="slider" element that carries the group's single tab stop instead -- the same
|
|
136
|
+
// pattern Checkbox.svelte uses for its own hidden control.
|
|
137
|
+
function handleInvalid(e: Event): void {
|
|
138
|
+
e.preventDefault();
|
|
139
|
+
root?.focus();
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// A native number input can't distinguish "explicitly rated 0" from "never touched",
|
|
143
|
+
// so 0 is submitted as empty -- required then blocks submission until a real rating
|
|
144
|
+
// is made, the same reading Checkbox gives an unchecked required box.
|
|
145
|
+
const submittedValue = $derived(sanitizedValue > 0 ? sanitizedValue : null);
|
|
146
|
+
</script>
|
|
147
|
+
|
|
148
|
+
<div
|
|
149
|
+
bind:this={root}
|
|
150
|
+
class="rating-group {classes ?? ''}"
|
|
151
|
+
class:disabled
|
|
152
|
+
class:readonly
|
|
153
|
+
data-pw={typeof testId === 'string' ? testId : null}
|
|
154
|
+
testID={typeof testId === 'string' ? testId : null}
|
|
155
|
+
role="slider"
|
|
156
|
+
tabindex={disabled ? -1 : 0}
|
|
157
|
+
aria-valuemin={0}
|
|
158
|
+
aria-valuemax={effectiveMax}
|
|
159
|
+
aria-valuenow={sanitizedValue}
|
|
160
|
+
aria-valuetext={valueText}
|
|
161
|
+
aria-label={ariaLabel ?? 'Rating'}
|
|
162
|
+
aria-disabled={disabled}
|
|
163
|
+
aria-readonly={readonly}
|
|
164
|
+
data-disabled={disabled ? '' : null}
|
|
165
|
+
data-readonly={readonly ? '' : null}
|
|
166
|
+
onkeydown={handleKeydown}
|
|
167
|
+
>
|
|
168
|
+
{#each starIndices as index (index)}
|
|
169
|
+
{@const state = starState(index)}
|
|
170
|
+
<span
|
|
171
|
+
class="star"
|
|
172
|
+
aria-hidden="true"
|
|
173
|
+
data-state={state}
|
|
174
|
+
data-pw={typeof testId === 'string' ? `${testId}-star-${index + 1}` : null}
|
|
175
|
+
testID={typeof testId === 'string' ? `${testId}-star-${index + 1}` : null}
|
|
176
|
+
onclick={(event) => handleStarClick(event, index)}
|
|
177
|
+
>
|
|
178
|
+
{#if typeof star === 'function'}
|
|
179
|
+
{@render star({ index, state })}
|
|
180
|
+
{:else}
|
|
181
|
+
<span class="star-empty">
|
|
182
|
+
<!-- eslint-disable svelte/no-at-html-tags -->
|
|
183
|
+
{@html starSvg}
|
|
184
|
+
</span>
|
|
185
|
+
{#if state !== 'empty'}
|
|
186
|
+
<span class="star-fill" style:width={state === 'half' ? '50%' : '100%'}>
|
|
187
|
+
<!-- eslint-disable svelte/no-at-html-tags -->
|
|
188
|
+
{@html starSvg}
|
|
189
|
+
</span>
|
|
190
|
+
{/if}
|
|
191
|
+
{/if}
|
|
192
|
+
</span>
|
|
193
|
+
{/each}
|
|
194
|
+
<input
|
|
195
|
+
type="number"
|
|
196
|
+
class="native-input"
|
|
197
|
+
tabindex={-1}
|
|
198
|
+
aria-hidden="true"
|
|
199
|
+
min={0}
|
|
200
|
+
max={hasValidMax ? max : null}
|
|
201
|
+
step={allowHalf ? 0.5 : 1}
|
|
202
|
+
value={submittedValue === null ? '' : submittedValue}
|
|
203
|
+
{disabled}
|
|
204
|
+
{required}
|
|
205
|
+
name={typeof name === 'string' && submittedValue !== null ? name : null}
|
|
206
|
+
form={typeof form === 'string' ? form : null}
|
|
207
|
+
oninvalid={handleInvalid}
|
|
208
|
+
data-pw={typeof testId === 'string' ? `${testId}-native-input` : null}
|
|
209
|
+
testID={typeof testId === 'string' ? `${testId}-native-input` : null}
|
|
210
|
+
/>
|
|
211
|
+
</div>
|
|
212
|
+
|
|
213
|
+
<style>
|
|
214
|
+
.rating-group {
|
|
215
|
+
display: var(--rating-group-display, inline-flex);
|
|
216
|
+
align-items: center;
|
|
217
|
+
gap: var(--rating-group-gap, 2px);
|
|
218
|
+
cursor: var(--rating-group-cursor, pointer);
|
|
219
|
+
outline: none;
|
|
220
|
+
border-radius: var(--rating-group-border-radius, var(--radius, 4px));
|
|
221
|
+
width: fit-content;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.rating-group:focus-visible {
|
|
225
|
+
box-shadow: var(--rating-group-focus-ring, 0 0 0 3px rgba(33, 150, 243, 0.3));
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
.rating-group.disabled {
|
|
229
|
+
opacity: var(--rating-group-disabled-opacity, 0.4);
|
|
230
|
+
cursor: var(--rating-group-disabled-cursor, not-allowed);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
.rating-group.readonly {
|
|
234
|
+
cursor: var(--rating-group-readonly-cursor, default);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.star {
|
|
238
|
+
position: relative;
|
|
239
|
+
display: inline-flex;
|
|
240
|
+
width: var(--rating-group-star-size, 24px);
|
|
241
|
+
height: var(--rating-group-star-size, 24px);
|
|
242
|
+
flex-shrink: 0;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
.rating-group:not(.disabled):not(.readonly) .star:hover {
|
|
246
|
+
transform: var(--rating-group-star-hover-transform, scale(1.1));
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
.star-empty,
|
|
250
|
+
.star-fill {
|
|
251
|
+
position: absolute;
|
|
252
|
+
inset: 0;
|
|
253
|
+
display: flex;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
.star-empty {
|
|
257
|
+
color: var(--rating-group-star-empty-color, #d1d5db);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
.star-empty :global(svg) {
|
|
261
|
+
width: 100%;
|
|
262
|
+
height: 100%;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
.star-fill {
|
|
266
|
+
color: var(--rating-group-star-filled-color, #f5a623);
|
|
267
|
+
overflow: hidden;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
.star-fill :global(svg) {
|
|
271
|
+
width: var(--rating-group-star-size, 24px);
|
|
272
|
+
height: var(--rating-group-star-size, 24px);
|
|
273
|
+
flex-shrink: 0;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
.native-input {
|
|
277
|
+
position: absolute;
|
|
278
|
+
opacity: 0;
|
|
279
|
+
width: 0;
|
|
280
|
+
height: 0;
|
|
281
|
+
pointer-events: none;
|
|
282
|
+
}
|
|
283
|
+
</style>
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
/** Fill state of a single star, passed to the `star` snippet. `'half'` is only ever
|
|
3
|
+
* produced while `allowHalf` is on -- with it off every star is `'empty'` or `'full'`. */
|
|
4
|
+
export type RatingGroupStarState = 'empty' | 'half' | 'full';
|
|
5
|
+
export type RatingGroupStarContext = {
|
|
6
|
+
/** 0-based position of this star in the row. */
|
|
7
|
+
index: number;
|
|
8
|
+
state: RatingGroupStarState;
|
|
9
|
+
};
|
|
10
|
+
export type RatingGroupProperties = OptionalRatingGroupProperties & RatingGroupEventProperties;
|
|
11
|
+
export type OptionalRatingGroupProperties = {
|
|
12
|
+
/**
|
|
13
|
+
* Current rating. Bindable, like `Checkbox.checked` and `Slider.value`. Defaults to
|
|
14
|
+
* `0` (unrated). Clamped to `[0, max]` and, unless `allowHalf` is set, rounded to the
|
|
15
|
+
* nearest whole star before it is ever painted or read back through `aria-valuenow` --
|
|
16
|
+
* a non-finite or out-of-range value never reaches the DOM as `NaN` or an overflowed
|
|
17
|
+
* star count, it renders as the nearest in-range value instead (mirrors `Progress`'s
|
|
18
|
+
* guard against an unusable `value`/`max`).
|
|
19
|
+
*/
|
|
20
|
+
value?: number;
|
|
21
|
+
/**
|
|
22
|
+
* Number of stars in the group. Must be a finite, positive number; a zero, negative,
|
|
23
|
+
* or non-finite `max` is an invalid range and renders no stars at all, the same way
|
|
24
|
+
* `Progress` renders an invalid range as an empty bar rather than a broken one.
|
|
25
|
+
*/
|
|
26
|
+
max?: number;
|
|
27
|
+
disabled?: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Read but not settable: the group stays a single tab stop and its ARIA value keeps
|
|
30
|
+
* following `value` from outside, but clicking a star or pressing an arrow key no
|
|
31
|
+
* longer changes it. Distinct from `disabled`, which removes it from the tab order
|
|
32
|
+
* entirely.
|
|
33
|
+
*/
|
|
34
|
+
readonly?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Allows landing on the half star between two whole ones -- clicking the left half of
|
|
37
|
+
* a star sets it, and the right half sets the whole star. Arrow keys move in 0.5 steps
|
|
38
|
+
* instead of 1 while this is on.
|
|
39
|
+
*/
|
|
40
|
+
allowHalf?: boolean;
|
|
41
|
+
/** Accessible name for the `role="slider"` element. Falls back to `"Rating"`; the
|
|
42
|
+
* current value is announced separately through `aria-valuetext`. */
|
|
43
|
+
ariaLabel?: string;
|
|
44
|
+
testId?: string;
|
|
45
|
+
classes?: string;
|
|
46
|
+
/**
|
|
47
|
+
* Custom rendering for a single star, given its 0-based `index` and fill `state`.
|
|
48
|
+
* Falls back to a themeable default star built from `--rating-group-star-*` custom
|
|
49
|
+
* properties.
|
|
50
|
+
*/
|
|
51
|
+
star?: Snippet<[RatingGroupStarContext]>;
|
|
52
|
+
/**
|
|
53
|
+
* Submits the current rating under this name via a hidden native `<input
|
|
54
|
+
* type="number">`, the way `Checkbox` submits through a visually hidden native input.
|
|
55
|
+
* Omitted entirely while disabled, and while unrated (`0`) -- a native number input
|
|
56
|
+
* cannot itself express "explicitly zero" vs. "never touched", so `0` is treated as
|
|
57
|
+
* the empty state for submission purposes, matching `required`'s reading of it below.
|
|
58
|
+
*/
|
|
59
|
+
name?: string;
|
|
60
|
+
/**
|
|
61
|
+
* Blocks submission while the rating is unset (`0`), the same way an unchecked
|
|
62
|
+
* required `Checkbox` does. Invalid focus lands on the group itself, since the
|
|
63
|
+
* hidden native input is deliberately not a tab stop.
|
|
64
|
+
*/
|
|
65
|
+
required?: boolean;
|
|
66
|
+
/** `id` of a form elsewhere in the same document, for a group rendered outside it.
|
|
67
|
+
* Unavailable through `<sui-rating-group>`, whose hidden input sits in a shadow
|
|
68
|
+
* root and cannot reach a form in the host document. */
|
|
69
|
+
form?: string;
|
|
70
|
+
};
|
|
71
|
+
export type RatingGroupEventProperties = {
|
|
72
|
+
onchange?: (value: number) => void;
|
|
73
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -112,7 +112,7 @@
|
|
|
112
112
|
.relative-time {
|
|
113
113
|
font-size: var(--relative-time-font-size, 14px);
|
|
114
114
|
font-weight: var(--relative-time-font-weight, 400);
|
|
115
|
-
font-family: var(--relative-time-font-family);
|
|
115
|
+
font-family: var(--relative-time-font-family, inherit);
|
|
116
116
|
color: var(--relative-time-color, inherit);
|
|
117
117
|
cursor: var(--relative-time-cursor, default);
|
|
118
118
|
}
|