@juspay/svelte-ui-components 4.27.6 → 4.28.1
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
|
@@ -143,7 +143,12 @@
|
|
|
143
143
|
display: flex;
|
|
144
144
|
align-items: baseline;
|
|
145
145
|
gap: var(--task-list-row-inline-gap, 10px);
|
|
146
|
-
|
|
146
|
+
/* --task-list-ease was an easing-only token (DESIGN_PRINCIPLES.md motion
|
|
147
|
+
convention) — kept working unchanged, now paired with a duration token
|
|
148
|
+
and both fall back through the library-wide --motion-* tokens. */
|
|
149
|
+
animation: task-list-fade-up
|
|
150
|
+
var(--task-list-row-animation-duration, var(--motion-duration, 320ms))
|
|
151
|
+
var(--task-list-ease, var(--motion-easing, cubic-bezier(0.23, 1, 0.32, 1))) both;
|
|
147
152
|
}
|
|
148
153
|
|
|
149
154
|
.row-glyph {
|
|
@@ -160,7 +165,9 @@
|
|
|
160
165
|
display: inline-flex;
|
|
161
166
|
align-items: center;
|
|
162
167
|
justify-content: center;
|
|
163
|
-
animation: task-list-glyph-fade
|
|
168
|
+
animation: task-list-glyph-fade
|
|
169
|
+
var(--task-list-glyph-animation-duration, var(--motion-duration, 150ms))
|
|
170
|
+
var(--task-list-glyph-animation-easing, var(--motion-easing, ease)) both;
|
|
164
171
|
}
|
|
165
172
|
|
|
166
173
|
.glyph-dot {
|
|
@@ -197,7 +204,9 @@
|
|
|
197
204
|
}
|
|
198
205
|
.glyph-check {
|
|
199
206
|
color: var(--task-list-done-color, #6b6b6b);
|
|
200
|
-
animation: task-list-check-pop
|
|
207
|
+
animation: task-list-check-pop
|
|
208
|
+
var(--task-list-check-pop-animation-duration, var(--motion-duration, 200ms))
|
|
209
|
+
var(--task-list-ease, var(--motion-easing, cubic-bezier(0.23, 1, 0.32, 1))) both;
|
|
201
210
|
}
|
|
202
211
|
.glyph-x {
|
|
203
212
|
color: var(--task-list-error-color, #c93f38);
|
|
@@ -211,7 +220,7 @@
|
|
|
211
220
|
gap: var(--task-list-text-gap, 8px);
|
|
212
221
|
}
|
|
213
222
|
.task-row.pending .row-text {
|
|
214
|
-
opacity: var(--task-list-pending-opacity, 0.
|
|
223
|
+
opacity: var(--task-list-pending-opacity, 0.85);
|
|
215
224
|
}
|
|
216
225
|
|
|
217
226
|
.row-label {
|
|
@@ -225,7 +234,7 @@
|
|
|
225
234
|
|
|
226
235
|
.row-secondary {
|
|
227
236
|
font-size: var(--task-list-secondary-font-size, 0.75rem);
|
|
228
|
-
color: var(--task-list-secondary-color, #
|
|
237
|
+
color: var(--task-list-secondary-color, #555b65);
|
|
229
238
|
white-space: nowrap;
|
|
230
239
|
}
|
|
231
240
|
.row-secondary.mono {
|
|
@@ -143,6 +143,7 @@
|
|
|
143
143
|
class:selected={currentValue === option.value}
|
|
144
144
|
onclick={() => applyValue(option.value)}
|
|
145
145
|
aria-label={option.label ?? option.value}
|
|
146
|
+
aria-pressed={currentValue === option.value}
|
|
146
147
|
>
|
|
147
148
|
<span class="icon">
|
|
148
149
|
{#if typeof option.icon === 'function'}
|
|
@@ -255,4 +256,26 @@
|
|
|
255
256
|
.segment-button.selected {
|
|
256
257
|
color: var(--theme-switcher-icon-color-active, #1f2937);
|
|
257
258
|
}
|
|
259
|
+
|
|
260
|
+
/* Unlike the two progress-bar loaders elsewhere in this library, every
|
|
261
|
+
transition here moves between two states that are each fully meaningful
|
|
262
|
+
on their own (a background tint, an icon's shown/hidden pose, the
|
|
263
|
+
indicator's resting position, a label's active color) -- there is no
|
|
264
|
+
in-between frame that could be misread as a different state. Dropping the
|
|
265
|
+
transition just makes the swap instant instead of animated; nothing is
|
|
266
|
+
stranded mid-motion the way a freeze mid-fill would be. Four separate
|
|
267
|
+
rules declare `transition` in this file (toggle background, icon
|
|
268
|
+
opacity/transform, segment indicator left/width, segment label color) --
|
|
269
|
+
all four are covered here, not just the two the icon/indicator case calls
|
|
270
|
+
out, so no motion in this component is left unguarded. Lives in the
|
|
271
|
+
component's own <style> because that is the only stylesheet that reaches
|
|
272
|
+
inside the shadow root a custom-element consumer gets. */
|
|
273
|
+
@media (prefers-reduced-motion: reduce) {
|
|
274
|
+
.toggle-button,
|
|
275
|
+
.icon,
|
|
276
|
+
.segment-indicator,
|
|
277
|
+
.segment-button {
|
|
278
|
+
transition: none;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
258
281
|
</style>
|
|
@@ -666,14 +666,18 @@
|
|
|
666
666
|
padding-top: var(--thinking-indicator-detail-padding-top, 0.5rem);
|
|
667
667
|
font-size: var(--thinking-indicator-detail-font-size, 0.875rem);
|
|
668
668
|
line-height: var(--thinking-indicator-detail-line-height, 1.5);
|
|
669
|
-
|
|
669
|
+
/* Resting text, not the shimmer highlight — needs its own readable default
|
|
670
|
+
rather than reusing the shimmer's light sweep color. Matches
|
|
671
|
+
--thinking-indicator-trace-prose-color, the same prose-at-rest ink used
|
|
672
|
+
for the reasoning trace's paragraph rows. */
|
|
673
|
+
color: var(--thinking-indicator-detail-color, #6b6b6b);
|
|
670
674
|
text-align: left;
|
|
671
675
|
}
|
|
672
676
|
|
|
673
677
|
.elapsed {
|
|
674
678
|
flex-shrink: 0;
|
|
675
679
|
font-variant-numeric: tabular-nums;
|
|
676
|
-
color: var(--thinking-indicator-elapsed-color, #
|
|
680
|
+
color: var(--thinking-indicator-elapsed-color, #4b5563);
|
|
677
681
|
font-size: var(--thinking-indicator-elapsed-font-size, 0.75rem);
|
|
678
682
|
}
|
|
679
683
|
|
|
@@ -753,7 +757,9 @@
|
|
|
753
757
|
margin: -3px -6px;
|
|
754
758
|
border-radius: var(--thinking-indicator-trace-row-radius, 6px);
|
|
755
759
|
cursor: pointer;
|
|
756
|
-
transition: background
|
|
760
|
+
transition: background
|
|
761
|
+
var(--thinking-indicator-trace-row-transition-duration, var(--motion-duration, 150ms))
|
|
762
|
+
var(--thinking-indicator-trace-row-transition-easing, var(--motion-easing, ease));
|
|
757
763
|
width: calc(100% + 12px);
|
|
758
764
|
}
|
|
759
765
|
|
|
@@ -777,7 +783,7 @@
|
|
|
777
783
|
}
|
|
778
784
|
|
|
779
785
|
.row-secondary {
|
|
780
|
-
color: var(--thinking-indicator-trace-secondary-color, #
|
|
786
|
+
color: var(--thinking-indicator-trace-secondary-color, #4b5563);
|
|
781
787
|
font-size: var(--thinking-indicator-trace-secondary-font-size, 0.75rem);
|
|
782
788
|
white-space: nowrap;
|
|
783
789
|
}
|
|
@@ -861,7 +867,9 @@
|
|
|
861
867
|
font-size: var(--thinking-indicator-trace-more-font-size, 0.75rem);
|
|
862
868
|
color: var(--thinking-indicator-trace-more-color, #9a9a9a);
|
|
863
869
|
padding: 6px 0 0 22px;
|
|
864
|
-
animation: thinking-indicator-fade-in
|
|
870
|
+
animation: thinking-indicator-fade-in
|
|
871
|
+
var(--thinking-indicator-trace-more-animation-duration, var(--motion-duration, 300ms))
|
|
872
|
+
var(--thinking-indicator-trace-more-animation-easing, var(--motion-easing, ease)) both;
|
|
865
873
|
}
|
|
866
874
|
|
|
867
875
|
@media (prefers-reduced-motion: reduce) {
|
package/dist/Toast/Toast.svelte
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { untrack } from 'svelte';
|
|
3
3
|
import { fly } from 'svelte/transition';
|
|
4
|
+
import { prefersReducedMotion } from '../utils';
|
|
4
5
|
import type { ToastDirection, ToastProperties } from './properties';
|
|
5
6
|
import type { FlyAnimationConfig } from '../types';
|
|
6
7
|
import Img from '../Img/Img.svelte';
|
|
@@ -72,6 +73,20 @@
|
|
|
72
73
|
break;
|
|
73
74
|
}
|
|
74
75
|
|
|
76
|
+
// Reduced motion zeroes the OFFSETS as well as the durations, and the offsets
|
|
77
|
+
// are the part that matters. `fly` interpolates from x/y to 0, so a duration of
|
|
78
|
+
// 0 with x still at 500 paints the toast 500px away on its first frame and then
|
|
79
|
+
// snaps -- a stranded frame that reads as a glitch rather than as no animation.
|
|
80
|
+
// Zeroing both makes it simply appear in place, which is what the preference
|
|
81
|
+
// asks for. A `@media` block cannot reach any of this: these values are consumed
|
|
82
|
+
// by `in:fly={...}` / `out:fly={...}`, so the guard has to live here.
|
|
83
|
+
if (prefersReducedMotion()) {
|
|
84
|
+
return {
|
|
85
|
+
in: { x: 0, y: 0, duration: 0 },
|
|
86
|
+
out: { x: 0, y: 0, duration: 0 }
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
75
90
|
return {
|
|
76
91
|
in: {
|
|
77
92
|
x: inX,
|
|
@@ -108,12 +123,22 @@
|
|
|
108
123
|
</script>
|
|
109
124
|
|
|
110
125
|
{#if showToast}
|
|
126
|
+
<!-- `showToast` starts `true` (see the `$state(true)` above), so this
|
|
127
|
+
`{#if}` is already satisfied on the component's own first render -- a
|
|
128
|
+
*local* transition only plays when its enclosing block flips true as a
|
|
129
|
+
later reactive update, not when the block is created already-true,
|
|
130
|
+
which is what happens every time a caller mounts Toast fresh (e.g.
|
|
131
|
+
`{#if visible}<Toast .../>{/if}` in the caller). `in:fly|global` plays
|
|
132
|
+
the intro on creation regardless, matching Sheet's panel transition
|
|
133
|
+
(Sheet.svelte). `out:fly` needs no such modifier: `hideToast()` always
|
|
134
|
+
flips an already-mounted block from true to false, a genuine local
|
|
135
|
+
transition that already fires correctly. -->
|
|
111
136
|
<div
|
|
112
137
|
class={rootClass}
|
|
113
138
|
class:no-page-overlap={!overlapPage}
|
|
114
139
|
role="alert"
|
|
115
140
|
aria-live="assertive"
|
|
116
|
-
in:fly={animationConfig.in}
|
|
141
|
+
in:fly|global={animationConfig.in}
|
|
117
142
|
out:fly={animationConfig.out}
|
|
118
143
|
onoutroend={handleAnimationEnd}
|
|
119
144
|
data-pw={testId}
|
|
@@ -162,7 +187,7 @@
|
|
|
162
187
|
padding: var(--toast-padding, 10px);
|
|
163
188
|
font-size: var(--toast-font-size, 14px);
|
|
164
189
|
font-family: var(--toast-font-family, inherit);
|
|
165
|
-
font-weight: var(--toast-font-weight);
|
|
190
|
+
font-weight: var(--toast-font-weight, inherit);
|
|
166
191
|
height: var(--toast-height, fit-content);
|
|
167
192
|
border-radius: var(--toast-border-radius, var(--radius, 4px));
|
|
168
193
|
border: var(--toast-border, none);
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { describeField } from '../_field/description';
|
|
2
3
|
import type { ToggleProperties } from './properties';
|
|
3
4
|
|
|
4
5
|
let {
|
|
5
|
-
checked = false,
|
|
6
|
+
checked = $bindable(false),
|
|
6
7
|
text = '',
|
|
7
8
|
disabled = false,
|
|
8
9
|
testId,
|
|
@@ -12,11 +13,26 @@
|
|
|
12
13
|
ariaLabelledby,
|
|
13
14
|
onclick,
|
|
14
15
|
name,
|
|
15
|
-
value
|
|
16
|
+
value,
|
|
17
|
+
required = false,
|
|
18
|
+
form,
|
|
19
|
+
errorMessage,
|
|
20
|
+
infoMessage,
|
|
21
|
+
invalid = false
|
|
16
22
|
}: ToggleProperties = $props();
|
|
17
23
|
|
|
18
24
|
// Stable across hydration so the hidden input stays named and text remains clickable.
|
|
19
25
|
const generatedId = $props.id();
|
|
26
|
+
|
|
27
|
+
/* The control and the text that explains it were never linked: a screen-reader
|
|
28
|
+
user reaching this control heard its name and nothing about why it was
|
|
29
|
+
rejected. `describeField` composes the reference from the messages that are
|
|
30
|
+
actually rendered, so aria-describedby never points at an id that is not in
|
|
31
|
+
the DOM -- which passes an attribute assertion and resolves to nothing in a
|
|
32
|
+
real reader. */
|
|
33
|
+
const field = $derived(
|
|
34
|
+
describeField(generatedId, { error: errorMessage, info: infoMessage, invalid })
|
|
35
|
+
);
|
|
20
36
|
const inputId = $derived(id?.trim() || `toggle-${generatedId}`);
|
|
21
37
|
|
|
22
38
|
const handleCheckboxClick = (e: MouseEvent): void => {
|
|
@@ -40,10 +56,16 @@
|
|
|
40
56
|
id={inputId}
|
|
41
57
|
class="input-checkbox"
|
|
42
58
|
type="checkbox"
|
|
59
|
+
aria-describedby={field.describedBy}
|
|
60
|
+
aria-invalid={field.ariaInvalid}
|
|
43
61
|
{checked}
|
|
44
62
|
{disabled}
|
|
45
|
-
name={name ?? null}
|
|
46
63
|
value={value ?? null}
|
|
64
|
+
{required}
|
|
65
|
+
name={typeof name === 'string' ? name : null}
|
|
66
|
+
form={typeof form === 'string' ? form : null}
|
|
67
|
+
data-state={checked ? 'checked' : 'unchecked'}
|
|
68
|
+
data-disabled={disabled ? '' : null}
|
|
47
69
|
aria-label={ariaLabel?.trim() || null}
|
|
48
70
|
aria-labelledby={ariaLabelledby?.trim() || null}
|
|
49
71
|
onclick={handleCheckboxClick}
|
|
@@ -52,6 +74,28 @@
|
|
|
52
74
|
</label>
|
|
53
75
|
</div>
|
|
54
76
|
|
|
77
|
+
{#if field.showsError}
|
|
78
|
+
<div
|
|
79
|
+
id={field.errorId}
|
|
80
|
+
role="alert"
|
|
81
|
+
class="field-error"
|
|
82
|
+
data-pw={typeof testId === 'string' ? `${testId}-error-message` : null}
|
|
83
|
+
testID={typeof testId === 'string' ? `${testId}-error-message` : null}
|
|
84
|
+
>
|
|
85
|
+
{errorMessage}
|
|
86
|
+
</div>
|
|
87
|
+
{/if}
|
|
88
|
+
{#if field.showsInfo}
|
|
89
|
+
<div
|
|
90
|
+
id={field.infoId}
|
|
91
|
+
class="field-info"
|
|
92
|
+
data-pw={typeof testId === 'string' ? `${testId}-info-message` : null}
|
|
93
|
+
testID={typeof testId === 'string' ? `${testId}-info-message` : null}
|
|
94
|
+
>
|
|
95
|
+
{infoMessage}
|
|
96
|
+
</div>
|
|
97
|
+
{/if}
|
|
98
|
+
|
|
55
99
|
<style>
|
|
56
100
|
.container {
|
|
57
101
|
display: var(--toggle-container-display, flex);
|
|
@@ -94,8 +138,16 @@
|
|
|
94
138
|
right: var(--toggle-slider-right, 0);
|
|
95
139
|
bottom: var(--toggle-slider-bottom, 0);
|
|
96
140
|
background-color: var(--slider-unchecked-color, #ccc);
|
|
97
|
-
-webkit-transition: var(
|
|
98
|
-
|
|
141
|
+
-webkit-transition: var(
|
|
142
|
+
--toggle-slider-transition,
|
|
143
|
+
all var(--toggle-slider-transition-duration, var(--motion-duration, 0.4s))
|
|
144
|
+
var(--toggle-slider-transition-easing, var(--motion-easing, ease))
|
|
145
|
+
);
|
|
146
|
+
transition: var(
|
|
147
|
+
--toggle-slider-transition,
|
|
148
|
+
all var(--toggle-slider-transition-duration, var(--motion-duration, 0.4s))
|
|
149
|
+
var(--toggle-slider-transition-easing, var(--motion-easing, ease))
|
|
150
|
+
);
|
|
99
151
|
}
|
|
100
152
|
|
|
101
153
|
.slider:before {
|
|
@@ -107,8 +159,16 @@
|
|
|
107
159
|
bottom: var(--toggle-slider-before-bottom, 1px);
|
|
108
160
|
top: var(--toggle-slider-before-top, 1px);
|
|
109
161
|
background-color: var(--toggle-slider-before-background-color, white);
|
|
110
|
-
-webkit-transition: var(
|
|
111
|
-
|
|
162
|
+
-webkit-transition: var(
|
|
163
|
+
--toggle-slider-transition,
|
|
164
|
+
all var(--toggle-slider-transition-duration, var(--motion-duration, 0.4s))
|
|
165
|
+
var(--toggle-slider-transition-easing, var(--motion-easing, ease))
|
|
166
|
+
);
|
|
167
|
+
transition: var(
|
|
168
|
+
--toggle-slider-transition,
|
|
169
|
+
all var(--toggle-slider-transition-duration, var(--motion-duration, 0.4s))
|
|
170
|
+
var(--toggle-slider-transition-easing, var(--motion-easing, ease))
|
|
171
|
+
);
|
|
112
172
|
}
|
|
113
173
|
|
|
114
174
|
.input-checkbox:checked + .slider {
|
|
@@ -132,4 +192,16 @@
|
|
|
132
192
|
.slider.round:before {
|
|
133
193
|
border-radius: var(--slider-border-radius-before, 50%);
|
|
134
194
|
}
|
|
195
|
+
|
|
196
|
+
.field-error {
|
|
197
|
+
color: var(--field-error-color, #c5120a);
|
|
198
|
+
font-size: var(--field-error-font-size, 12px);
|
|
199
|
+
margin: var(--field-error-margin, 4px 0 0 0);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.field-info {
|
|
203
|
+
color: var(--field-info-color, #6b7280);
|
|
204
|
+
font-size: var(--field-info-font-size, 12px);
|
|
205
|
+
margin: var(--field-info-margin, 4px 0 0 0);
|
|
206
|
+
}
|
|
135
207
|
</style>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { ToggleProperties } from './properties';
|
|
2
|
-
declare const Toggle: import("svelte").Component<ToggleProperties, {}, "">;
|
|
2
|
+
declare const Toggle: import("svelte").Component<ToggleProperties, {}, "checked">;
|
|
3
3
|
type Toggle = ReturnType<typeof Toggle>;
|
|
4
4
|
export default Toggle;
|
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
export type ToggleProperties = OptionalToggleProperties & ToggleEventProperties;
|
|
2
2
|
export type OptionalToggleProperties = {
|
|
3
|
+
/**
|
|
4
|
+
* Text shown, and announced, when the control is in error. Linked to the
|
|
5
|
+
* control through `aria-describedby`, and sets `aria-invalid` while present.
|
|
6
|
+
*/
|
|
7
|
+
errorMessage?: string | null;
|
|
8
|
+
/**
|
|
9
|
+
* Persistent helper text describing the control. Linked through
|
|
10
|
+
* `aria-describedby` too, so it is read before the user trips an error rather
|
|
11
|
+
* than only after.
|
|
12
|
+
*/
|
|
13
|
+
infoMessage?: string | null;
|
|
14
|
+
/**
|
|
15
|
+
* Marks the control invalid without supplying a message, for a consumer
|
|
16
|
+
* driving validity from a server or its own rules.
|
|
17
|
+
*/
|
|
18
|
+
invalid?: boolean;
|
|
3
19
|
text?: string;
|
|
20
|
+
/** Whether the switch is on. Bindable, like `Checkbox.checked` and `Slider.value`. */
|
|
4
21
|
checked?: boolean;
|
|
5
22
|
disabled?: boolean;
|
|
6
23
|
testId?: string;
|
|
@@ -19,15 +36,21 @@ export type OptionalToggleProperties = {
|
|
|
19
36
|
* `text` or `inputAriaLabel` for labels outside the shadow root.
|
|
20
37
|
*/
|
|
21
38
|
ariaLabelledby?: string;
|
|
22
|
-
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
39
|
+
/** Submits the switch under this name, so it participates in a surrounding
|
|
40
|
+
* `<form>`'s submission. Omitted by default: with no `name` the input stays
|
|
41
|
+
* nameless and outside `FormData`, exactly as before this prop existed. Omitted
|
|
42
|
+
* from submission too when off or disabled, matching the native checkbox the
|
|
43
|
+
* switch is built from. */
|
|
26
44
|
name?: string;
|
|
27
|
-
/**
|
|
28
|
-
* checkbox default
|
|
29
|
-
*
|
|
45
|
+
/** Value submitted while on. Left unset, the attribute is omitted and the native
|
|
46
|
+
* checkbox's own `"on"` default is what submits, so setting `name` alone is enough and
|
|
47
|
+
* an existing consumer's DOM is unchanged. An off switch never appears in `FormData`. */
|
|
30
48
|
value?: string;
|
|
49
|
+
/** Blocks submission while the switch is off. */
|
|
50
|
+
required?: boolean;
|
|
51
|
+
/** `id` of a form elsewhere in the same document. Unavailable through
|
|
52
|
+
* `<sui-toggle>`, whose control sits in a shadow root. */
|
|
53
|
+
form?: string;
|
|
31
54
|
};
|
|
32
55
|
export type ToggleEventProperties = {
|
|
33
56
|
onclick?: (checked: boolean) => void;
|
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
import Loader from '../Loader/Loader.svelte';
|
|
5
5
|
import Pill from '../Pill/Pill.svelte';
|
|
6
6
|
import { computeMenuDropdownPosition } from '../Menu/dropdownPosition';
|
|
7
|
+
import { eventHitsInside } from '../_interaction/dismissal';
|
|
7
8
|
import type { ToolCallChip, ToolCallLogProperties } from './properties';
|
|
8
9
|
|
|
9
|
-
let { chips, onchipclick, testId, classes }: ToolCallLogProperties = $props();
|
|
10
|
+
let { chips, onchipclick, testId, classes, usePortal = true }: ToolCallLogProperties = $props();
|
|
10
11
|
|
|
11
12
|
// Exactly one popover open at a time, component-local.
|
|
12
13
|
let openIndex = $state<number | null>(null);
|
|
@@ -97,16 +98,37 @@
|
|
|
97
98
|
});
|
|
98
99
|
|
|
99
100
|
/**
|
|
100
|
-
*
|
|
101
|
+
* Where a portalled node is allowed to land. Svelte scopes a custom element's
|
|
102
|
+
* CSS to its shadow root, so `document.body` is the one place the popover must
|
|
103
|
+
* never go from inside `<sui-tool-call-log>`: it keeps its `svelte-*` scoping
|
|
104
|
+
* class and loses every rule behind it, plus the host's custom properties.
|
|
105
|
+
* Measured in Chromium -- position fell back to `static`, background to
|
|
106
|
+
* transparent, border and shadow to none, so the detail text landed as a bare
|
|
107
|
+
* paragraph at the end of the page. Its own root holds that stylesheet and
|
|
108
|
+
* still sits above every overflow/scroll ancestor between the two.
|
|
109
|
+
*/
|
|
110
|
+
const portalTarget = (node: Node): Node => {
|
|
111
|
+
const root = node.getRootNode();
|
|
112
|
+
return root instanceof ShadowRoot ? root : document.body;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Svelte action for the popover element: relocates it out to its root
|
|
101
117
|
* (mirroring Menu's `usePortal`) so an `overflow: hidden` or scrolling
|
|
102
118
|
* ancestor — a chat bubble, a card — can never clip it, and keeps
|
|
103
119
|
* `popoverTick` bumping (rAF-coalesced) while it is mounted so `popoverStyle`
|
|
104
120
|
* re-derives on scroll/resize. The popover only exists in the DOM while open
|
|
105
121
|
* (see the `{#if}` below), so the listeners live exactly as long as it does;
|
|
106
122
|
* `use:` actions never run during SSR.
|
|
123
|
+
*
|
|
124
|
+
* The listeners are wired even when `usePortal` is false: the popover is
|
|
125
|
+
* `position: fixed` in both modes, so its coordinates go stale on scroll
|
|
126
|
+
* whether or not it was moved.
|
|
107
127
|
*/
|
|
108
128
|
const popoverPortal: Action<HTMLElement> = (node) => {
|
|
109
|
-
|
|
129
|
+
if (usePortal) {
|
|
130
|
+
portalTarget(node).appendChild(node);
|
|
131
|
+
}
|
|
110
132
|
let frame: number | null = null;
|
|
111
133
|
const bump = (): void => {
|
|
112
134
|
if (frame !== null) {
|
|
@@ -126,7 +148,11 @@
|
|
|
126
148
|
if (frame !== null) {
|
|
127
149
|
cancelAnimationFrame(frame);
|
|
128
150
|
}
|
|
129
|
-
node
|
|
151
|
+
// Only a node this action moved is this action's to take back out; an
|
|
152
|
+
// un-portalled one is still Svelte's, and it removes it on its own.
|
|
153
|
+
if (usePortal) {
|
|
154
|
+
node.remove();
|
|
155
|
+
}
|
|
130
156
|
}
|
|
131
157
|
};
|
|
132
158
|
};
|
|
@@ -138,14 +164,21 @@
|
|
|
138
164
|
* `openIndex`, and closing here too would race it: this listener runs after
|
|
139
165
|
* the chip's own `onclick` on the same bubbling click event, so without the
|
|
140
166
|
* guard it would immediately re-close a popover a click just opened.
|
|
167
|
+
*
|
|
168
|
+
* "Inside" is asked of the composed path, not of `contains(event.target)`.
|
|
169
|
+
* This listener is on the document, which sees the target retargeted to the
|
|
170
|
+
* shadow host, so `chipEl.contains(target)` was false for a click on the chip
|
|
171
|
+
* itself and the guard above never held: through `<sui-tool-call-log>` the
|
|
172
|
+
* popover opened and closed on the same click, every time. Observed under
|
|
173
|
+
* a MutationObserver — one insert, one removal, `aria-expanded` back to
|
|
174
|
+
* "false" — while chasing the portal fix this file also carries.
|
|
141
175
|
*/
|
|
142
176
|
const handleDocumentClick = (event: MouseEvent): void => {
|
|
143
|
-
|
|
144
|
-
if (openIndex === null || !(target instanceof Node)) {
|
|
177
|
+
if (openIndex === null) {
|
|
145
178
|
return;
|
|
146
179
|
}
|
|
147
|
-
const clickedInsideChip = chipEls.some((chipEl) => chipEl
|
|
148
|
-
const clickedInsidePopover = popoverEl
|
|
180
|
+
const clickedInsideChip = chipEls.some((chipEl) => eventHitsInside(chipEl, event));
|
|
181
|
+
const clickedInsidePopover = eventHitsInside(popoverEl, event);
|
|
149
182
|
if (!clickedInsideChip && !clickedInsidePopover) {
|
|
150
183
|
openIndex = null;
|
|
151
184
|
}
|
|
@@ -274,11 +307,14 @@
|
|
|
274
307
|
color: var(--tool-call-log-label-color, #2b2b2b);
|
|
275
308
|
cursor: var(--tool-call-log-chip-cursor, pointer);
|
|
276
309
|
max-width: 100%;
|
|
277
|
-
animation: tool-call-log-fade-up
|
|
278
|
-
|
|
310
|
+
animation: tool-call-log-fade-up
|
|
311
|
+
var(--tool-call-log-chip-animation-duration, var(--motion-duration, 320ms))
|
|
312
|
+
var(--tool-call-log-ease, var(--motion-easing, cubic-bezier(0.23, 1, 0.32, 1))) both;
|
|
279
313
|
transition:
|
|
280
|
-
background
|
|
281
|
-
|
|
314
|
+
background var(--tool-call-log-chip-transition-duration, var(--motion-duration, 150ms))
|
|
315
|
+
var(--tool-call-log-chip-transition-easing, var(--motion-easing, ease)),
|
|
316
|
+
border-color var(--tool-call-log-chip-transition-duration, var(--motion-duration, 150ms))
|
|
317
|
+
var(--tool-call-log-chip-transition-easing, var(--motion-easing, ease));
|
|
282
318
|
}
|
|
283
319
|
.chip:hover {
|
|
284
320
|
background: var(--tool-call-log-chip-hover-background, #f1f1f1);
|
|
@@ -288,7 +324,7 @@
|
|
|
288
324
|
}
|
|
289
325
|
|
|
290
326
|
.chip.error {
|
|
291
|
-
color: var(--tool-call-log-error-color, #
|
|
327
|
+
color: var(--tool-call-log-error-color, #9f2d27);
|
|
292
328
|
border-color: var(--tool-call-log-error-border-color, #f2b8b5);
|
|
293
329
|
background: var(--tool-call-log-error-background, #fdf1f0);
|
|
294
330
|
}
|
|
@@ -304,7 +340,7 @@
|
|
|
304
340
|
}
|
|
305
341
|
|
|
306
342
|
.chip-meta {
|
|
307
|
-
color: var(--tool-call-log-meta-color, #
|
|
343
|
+
color: var(--tool-call-log-meta-color, #666666);
|
|
308
344
|
font-size: var(--tool-call-log-meta-font-size, 0.75rem);
|
|
309
345
|
white-space: nowrap;
|
|
310
346
|
overflow: hidden;
|
|
@@ -366,13 +402,14 @@
|
|
|
366
402
|
}
|
|
367
403
|
.diffstat-removed {
|
|
368
404
|
--pill-background: var(--tool-call-log-removed-background, #fbeceb);
|
|
369
|
-
--pill-color: var(--tool-call-log-removed-color, #
|
|
405
|
+
--pill-color: var(--tool-call-log-removed-color, #a8302a);
|
|
370
406
|
}
|
|
371
407
|
|
|
372
|
-
/*
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
408
|
+
/* `position: fixed` is the baseline rather than a portal-only override —
|
|
409
|
+
left/top/z-index come from the inline `popoverStyle`, computed against the
|
|
410
|
+
live anchor rect, and that is viewport-relative in both portal modes. So
|
|
411
|
+
`usePortal={false}` (see `popoverPortal`) changes only which ancestors can
|
|
412
|
+
clip the popover, never how it is placed. */
|
|
376
413
|
.chip-popover {
|
|
377
414
|
position: fixed;
|
|
378
415
|
z-index: var(--tool-call-log-popover-z-index, 1000);
|
|
@@ -386,8 +423,9 @@
|
|
|
386
423
|
border: var(--tool-call-log-popover-border, 1px solid #e4e4e7);
|
|
387
424
|
border-radius: var(--tool-call-log-popover-radius, 10px);
|
|
388
425
|
box-shadow: var(--tool-call-log-popover-shadow, 0 10px 30px rgba(0, 0, 0, 0.12));
|
|
389
|
-
animation: tool-call-log-fade-up
|
|
390
|
-
|
|
426
|
+
animation: tool-call-log-fade-up
|
|
427
|
+
var(--tool-call-log-popover-animation-duration, var(--motion-duration, 200ms))
|
|
428
|
+
var(--tool-call-log-ease, var(--motion-easing, cubic-bezier(0.23, 1, 0.32, 1))) both;
|
|
391
429
|
}
|
|
392
430
|
|
|
393
431
|
.popover-detail {
|
|
@@ -24,4 +24,14 @@ export type OptionalToolCallLogProperties = {
|
|
|
24
24
|
onchipclick?: (index: number, chip: ToolCallChip) => void;
|
|
25
25
|
testId?: string;
|
|
26
26
|
classes?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Move the open detail popover out to the root of the tree it lives in, so an
|
|
29
|
+
* `overflow: hidden` or scrolling ancestor between the two — a chat bubble, a
|
|
30
|
+
* card — cannot clip it. Defaults to true, which is what this component did
|
|
31
|
+
* unconditionally before the prop existed. Placement is identical either way
|
|
32
|
+
* (the popover is `position: fixed` in both modes), so turning it off costs
|
|
33
|
+
* only the clipping escape — worth it when the popover must stay inside a
|
|
34
|
+
* container that is itself being transformed or scrolled as a unit.
|
|
35
|
+
*/
|
|
36
|
+
usePortal?: boolean;
|
|
27
37
|
};
|
|
@@ -211,7 +211,7 @@
|
|
|
211
211
|
font-weight: var(--toolbar-text-font-weight, normal);
|
|
212
212
|
padding: var(--toolbar-text-padding, 0px);
|
|
213
213
|
margin: var(--toolbar-text-margin, 0px);
|
|
214
|
-
color: var(--toolbar-text-color);
|
|
214
|
+
color: var(--toolbar-text-color, inherit);
|
|
215
215
|
flex: var(--toolbar-text-flex, 1);
|
|
216
216
|
}
|
|
217
217
|
</style>
|
|
@@ -93,6 +93,24 @@
|
|
|
93
93
|
/** Reference to the trigger wrapper element, used for `getBoundingClientRect` in portal mode. */
|
|
94
94
|
let containerEl: HTMLDivElement | null = $state(null);
|
|
95
95
|
|
|
96
|
+
/**
|
|
97
|
+
* Where the portalled bubble is allowed to land, asked of the TRIGGER rather
|
|
98
|
+
* than the bubble: a freshly created, still-detached element is its own root,
|
|
99
|
+
* so it can answer nothing useful about where the component lives.
|
|
100
|
+
*
|
|
101
|
+
* The bubble's own box survives `document.body` -- every rule of it is inline
|
|
102
|
+
* (see `createPortalBubble`) -- but two things it carries do not. The
|
|
103
|
+
* `--tooltip-*` custom properties those inline rules read inherit from the
|
|
104
|
+
* shadow host, not from `<body>`, so a themed `<sui-tooltip>` reverts to the
|
|
105
|
+
* literal fallbacks; and a `content` snippet is mounted into the bubble with
|
|
106
|
+
* the consumer's own `svelte-*` scoping classes, whose stylesheet is in the
|
|
107
|
+
* shadow root the bubble just left. Its own root keeps both.
|
|
108
|
+
*/
|
|
109
|
+
const portalTarget = (node: Node): Node => {
|
|
110
|
+
const root = node.getRootNode();
|
|
111
|
+
return root instanceof ShadowRoot ? root : document.body;
|
|
112
|
+
};
|
|
113
|
+
|
|
96
114
|
/**
|
|
97
115
|
* Imperatively managed portal bubble element.
|
|
98
116
|
* Created in `showTooltip` and removed in `hideTooltip` when `usePortal=true`.
|
|
@@ -303,7 +321,7 @@
|
|
|
303
321
|
}
|
|
304
322
|
portalBubbleEl = createPortalBubble(rect, pos);
|
|
305
323
|
if (portalBubbleEl !== null) {
|
|
306
|
-
|
|
324
|
+
portalTarget(containerEl).appendChild(portalBubbleEl);
|
|
307
325
|
const effectivePos = flipPortalBubbleIfNeeded(portalBubbleEl, rect, pos);
|
|
308
326
|
clampPortalBubble(portalBubbleEl, effectivePos);
|
|
309
327
|
}
|
|
@@ -405,7 +423,7 @@
|
|
|
405
423
|
color: var(--tooltip-color, #ffffff);
|
|
406
424
|
font-size: var(--tooltip-font-size, 12px);
|
|
407
425
|
font-weight: var(--tooltip-font-weight, 400);
|
|
408
|
-
font-family: var(--tooltip-font-family);
|
|
426
|
+
font-family: var(--tooltip-font-family, inherit);
|
|
409
427
|
padding: var(--tooltip-padding, 6px 10px);
|
|
410
428
|
border-radius: var(--tooltip-border-radius, var(--radius, 4px));
|
|
411
429
|
border: var(--tooltip-border, none);
|