@juspay/svelte-ui-components 4.52.1 → 4.53.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 +14 -0
- package/dist/AttachmentChipRow/AttachmentChipRow.svelte +3 -2
- package/dist/AttachmentChipRow/properties.d.ts +2 -0
- package/dist/Book/Book.svelte +2 -0
- package/dist/Book/properties.d.ts +2 -0
- package/dist/Chat/Chat.svelte +2 -0
- package/dist/Chat/properties.d.ts +2 -0
- package/dist/Chat/types.d.ts +2 -0
- package/dist/ChatMessage/ChatMessage.svelte +18 -3
- package/dist/ChatMessage/properties.d.ts +6 -0
- package/dist/ChatMessageList/ChatMessageList.svelte +31 -7
- package/dist/ChatMessageList/properties.d.ts +2 -0
- package/dist/Choicebox/Choicebox.svelte +33 -23
- package/dist/DateRangePicker/DateRangePicker.svelte +82 -33
- package/dist/DateRangePicker/properties.d.ts +18 -2
- package/dist/Draggable/Draggable.svelte +4 -2
- package/dist/MediaPlayer/MediaPlayer.svelte +28 -13
- package/dist/MediaPlayer/properties.d.ts +2 -0
- package/dist/Modal/Modal.svelte +30 -43
- package/dist/Modal/properties.d.ts +5 -4
- package/dist/Pagination/Pagination.svelte +2 -0
- package/dist/Pagination/properties.d.ts +2 -0
- package/dist/Pill/Pill.svelte +61 -4
- package/dist/Pill/properties.d.ts +8 -16
- package/dist/Radio/Radio.svelte +6 -2
- package/dist/RatingGroup/RatingGroup.svelte +38 -26
- package/dist/Select/Select.svelte +8 -0
- package/dist/StatCard/StatCard.svelte +68 -17
- package/dist/StatCard/properties.d.ts +1 -1
- package/dist/Stepper/Step.svelte +2 -2
- package/dist/Table/Table.svelte +32 -2
- package/dist/Table/properties.d.ts +11 -5
- package/dist/Tabs/Tabs.svelte +187 -12
- package/dist/ToolCallLog/ToolCallLog.svelte +4 -4
- package/dist/utils.js +20 -2
- package/dist-codemod/codemod/cli.js +4 -4
- package/dist-wc/index.js +3134 -2717
- package/package.json +3 -2
- package/scripts/postinstall.mjs +13 -15
|
@@ -183,7 +183,7 @@ export type OptionalStatCardProperties = {
|
|
|
183
183
|
classes?: string;
|
|
184
184
|
};
|
|
185
185
|
export type StatCardEventProperties = {
|
|
186
|
-
/** Makes the card interactive
|
|
186
|
+
/** Makes the card interactive with a native action button; child controls remain independent. */
|
|
187
187
|
onclick?: (event: MouseEvent) => void;
|
|
188
188
|
/** Fired when the header checkbox changes. */
|
|
189
189
|
oncheckboxchange?: (checked: boolean) => void;
|
package/dist/Stepper/Step.svelte
CHANGED
|
@@ -64,8 +64,8 @@
|
|
|
64
64
|
onkeydown={handleKeydown}
|
|
65
65
|
role={suppressRoleAndTabindex ? null : 'button'}
|
|
66
66
|
tabindex={suppressRoleAndTabindex ? null : 0}
|
|
67
|
-
aria-label={ariaLabel ?? null}
|
|
68
|
-
aria-labelledby={ariaLabel ? null : labelId}
|
|
67
|
+
aria-label={suppressRoleAndTabindex ? null : (ariaLabel ?? null)}
|
|
68
|
+
aria-labelledby={suppressRoleAndTabindex || ariaLabel ? null : labelId}
|
|
69
69
|
aria-current={status === 'active' ? 'step' : null}
|
|
70
70
|
>
|
|
71
71
|
{#if typeof icon === 'string' && icon.length > 0}
|
package/dist/Table/Table.svelte
CHANGED
|
@@ -225,11 +225,24 @@
|
|
|
225
225
|
// viewports, but a bare scroll container gives no visual hint that more
|
|
226
226
|
// columns exist. Track whether either edge has hidden content and surface
|
|
227
227
|
// it as edge scrims (see .table-scroll-shell styles).
|
|
228
|
+
// Caption identity must reach the actual keyboard scroll owner, not only its
|
|
229
|
+
// descendant table. Groups keep nested axes out of the landmark namespace and
|
|
230
|
+
// add no tab stop or keyboard handler; native overflow/fit focus stays intact.
|
|
231
|
+
let scrollCaption = $derived(
|
|
232
|
+
typeof caption === 'string' && caption.trim().length > 0 ? caption : null
|
|
233
|
+
);
|
|
234
|
+
let hasVerticalScrollOwner = $state(false);
|
|
228
235
|
let canScrollLeft = $state(false);
|
|
229
236
|
let canScrollRight = $state(false);
|
|
230
237
|
|
|
231
238
|
const trackHorizontalScroll = (scrollNode: HTMLElement) => {
|
|
239
|
+
const containerNode = scrollNode.closest<HTMLElement>('.table-container');
|
|
232
240
|
const updateScrollHints = () => {
|
|
241
|
+
const verticalOverflow = containerNode ? getComputedStyle(containerNode).overflowY : '';
|
|
242
|
+
hasVerticalScrollOwner =
|
|
243
|
+
containerNode !== null &&
|
|
244
|
+
(verticalOverflow === 'auto' || verticalOverflow === 'scroll') &&
|
|
245
|
+
containerNode.scrollHeight > containerNode.clientHeight;
|
|
233
246
|
canScrollLeft = scrollNode.scrollLeft > 2;
|
|
234
247
|
canScrollRight = scrollNode.scrollLeft + scrollNode.clientWidth < scrollNode.scrollWidth - 2;
|
|
235
248
|
};
|
|
@@ -239,6 +252,9 @@
|
|
|
239
252
|
// (async rows/columns arriving) change scrollWidth, so observe both.
|
|
240
253
|
const hintResizeObserver = new ResizeObserver(updateScrollHints);
|
|
241
254
|
hintResizeObserver.observe(scrollNode);
|
|
255
|
+
if (containerNode !== null) {
|
|
256
|
+
hintResizeObserver.observe(containerNode);
|
|
257
|
+
}
|
|
242
258
|
const tableElement = scrollNode.querySelector('table');
|
|
243
259
|
if (tableElement) {
|
|
244
260
|
hintResizeObserver.observe(tableElement);
|
|
@@ -836,6 +852,8 @@
|
|
|
836
852
|
<div
|
|
837
853
|
class="table-container {isTableScrollable ? 'scrollable-table' : ''} {classes ?? ''}"
|
|
838
854
|
class:table-mobile-cards={mobileCardLayout}
|
|
855
|
+
role={scrollCaption !== null && hasVerticalScrollOwner ? 'group' : null}
|
|
856
|
+
aria-label={hasVerticalScrollOwner ? scrollCaption : null}
|
|
839
857
|
data-pw={testId}
|
|
840
858
|
testID={testId}
|
|
841
859
|
>
|
|
@@ -844,7 +862,12 @@
|
|
|
844
862
|
class:scrollable-left={canScrollLeft}
|
|
845
863
|
class:scrollable-right={canScrollRight}
|
|
846
864
|
>
|
|
847
|
-
<div
|
|
865
|
+
<div
|
|
866
|
+
class="table-scroll"
|
|
867
|
+
role={scrollCaption !== null ? 'group' : null}
|
|
868
|
+
aria-label={scrollCaption}
|
|
869
|
+
use:trackHorizontalScroll
|
|
870
|
+
>
|
|
848
871
|
<table role={mobileRole('table')}>
|
|
849
872
|
{#if caption}
|
|
850
873
|
<caption class="sr-only">{caption}</caption>
|
|
@@ -878,8 +901,9 @@
|
|
|
878
901
|
/>
|
|
879
902
|
</th>
|
|
880
903
|
{:else if isCheckboxMode && isSingleSelect}
|
|
881
|
-
<!--
|
|
904
|
+
<!-- Selection is a real column even without a select-all action. -->
|
|
882
905
|
<th
|
|
906
|
+
aria-label={labels?.selectionColumn ?? 'Row selection'}
|
|
883
907
|
class="table-header table-checkbox-col"
|
|
884
908
|
class:table-header-sticky={isStickyHeader}
|
|
885
909
|
role={mobileRole('columnheader')}
|
|
@@ -1084,6 +1108,7 @@
|
|
|
1084
1108
|
{#each paginatedTableData as row, pageRowIndex (rowIdByRow.get(row) ?? pageRowIndex)}
|
|
1085
1109
|
{@const rowIndex = pageRowIndex + rowIndexOffset}
|
|
1086
1110
|
{@const originalIndex = originalIndexByRow.get(row) ?? rowIndex}
|
|
1111
|
+
{@const rowContext = rowLabels.get(row) ?? `row ${originalIndex + 1}`}
|
|
1087
1112
|
{@const rowId = rowIdByRow.get(row) ?? String(rowIndex)}
|
|
1088
1113
|
{@const rowDisabled = isCheckboxMode && isRowDisabled(rowId)}
|
|
1089
1114
|
{@const rowSelected = isCheckboxMode && isRowSelected(rowId)}
|
|
@@ -1094,6 +1119,9 @@
|
|
|
1094
1119
|
class:table-summary-row={summaryRowIndex !== null &&
|
|
1095
1120
|
originalIndex === summaryRowIndex}
|
|
1096
1121
|
role={mobileRole('row')}
|
|
1122
|
+
aria-label={isRowClickable
|
|
1123
|
+
? (labels?.rowAction?.(rowContext) ?? rowContext)
|
|
1124
|
+
: null}
|
|
1097
1125
|
data-pw={typeof getRowTestId === 'function' ? getRowTestId(row, rowIndex) : null}
|
|
1098
1126
|
testID={typeof getRowTestId === 'function' ? getRowTestId(row, rowIndex) : null}
|
|
1099
1127
|
onclick={isRowClickable
|
|
@@ -1280,6 +1308,8 @@
|
|
|
1280
1308
|
{/if}
|
|
1281
1309
|
{#if !hideSteppers}
|
|
1282
1310
|
<Pagination
|
|
1311
|
+
ariaLabel={labels?.pageNavigation ??
|
|
1312
|
+
(tableTitle ? `${tableTitle} pagination` : 'Pagination')}
|
|
1283
1313
|
totalPages={paginationTotalPages}
|
|
1284
1314
|
currentPage={effectivePage}
|
|
1285
1315
|
hasMore={pagination.hasMore ?? false}
|
|
@@ -524,12 +524,11 @@ export type TableProperties = OptionalTableProperties & TableEventProperties;
|
|
|
524
524
|
* Accessible names Table generates for its own controls, for callers who do
|
|
525
525
|
* not ship an English UI.
|
|
526
526
|
*
|
|
527
|
-
* Every member is optional
|
|
528
|
-
*
|
|
529
|
-
* two add a name to a control that previously had none.
|
|
527
|
+
* Every member is optional. Control labels use English defaults; rowAction
|
|
528
|
+
* uses the readable source-row caption.
|
|
530
529
|
*
|
|
531
|
-
*
|
|
532
|
-
*
|
|
530
|
+
* Members that depend on a column or row are functions rather than templates
|
|
531
|
+
* with a placeholder: a translator needs to
|
|
533
532
|
* put the header where their grammar wants it, not where an English sentence
|
|
534
533
|
* happens to leave a slot.
|
|
535
534
|
*
|
|
@@ -546,6 +545,8 @@ export type TableLabels = {
|
|
|
546
545
|
* naming an empty row. Default: `Select row ${rowId || 'non-selectable'}`. */
|
|
547
546
|
selectRow?: (rowId: string) => string;
|
|
548
547
|
/** Header checkbox that selects every row on the page. Default: `Select all rows`. */
|
|
548
|
+
/** Accessible header name for the row-selection column, including single-selection mode. */
|
|
549
|
+
selectionColumn?: string;
|
|
549
550
|
selectAllRows?: string;
|
|
550
551
|
/** Button that empties the search box. Default: `Clear search`. */
|
|
551
552
|
clearSearch?: string;
|
|
@@ -553,8 +554,12 @@ export type TableLabels = {
|
|
|
553
554
|
closeSearch?: string;
|
|
554
555
|
/** Built-in editor name. Default: `${columnLabel} for ${rowLabel}`. */
|
|
555
556
|
cellEditor?: (columnLabel: string, rowLabel: string) => string;
|
|
557
|
+
/** Clickable row name. Receives stable readable source-row context. Default: rowLabel. */
|
|
558
|
+
rowAction?: (rowLabel: string) => string;
|
|
556
559
|
/** Page-size selector in the built-in paginator footer. Default: `Rows per page`. */
|
|
557
560
|
rowsPerPage?: string;
|
|
561
|
+
/** Page-navigation landmark name. Default: `Pagination`. */
|
|
562
|
+
pageNavigation?: string;
|
|
558
563
|
};
|
|
559
564
|
export type OptionalTableProperties = {
|
|
560
565
|
labels?: TableLabels;
|
|
@@ -669,6 +674,7 @@ export type OptionalTableProperties = {
|
|
|
669
674
|
isTableScrollable?: boolean;
|
|
670
675
|
isContentScrollable?: boolean;
|
|
671
676
|
testId?: string;
|
|
677
|
+
/** Visually hidden native table caption; non-empty also names existing scroll groups. */
|
|
672
678
|
caption?: string;
|
|
673
679
|
sortAscIcon?: Snippet;
|
|
674
680
|
sortDescIcon?: Snippet;
|
package/dist/Tabs/Tabs.svelte
CHANGED
|
@@ -156,19 +156,137 @@
|
|
|
156
156
|
return getComputedStyle(scrollContainer).direction === 'rtl';
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
+
function availableWithoutArrows(node: HTMLElement, vertical: boolean): number {
|
|
160
|
+
const owner = node.parentElement;
|
|
161
|
+
const current = vertical ? node.clientHeight : node.clientWidth;
|
|
162
|
+
if (owner === null) {
|
|
163
|
+
return current;
|
|
164
|
+
}
|
|
165
|
+
const ownerStyle = getComputedStyle(owner);
|
|
166
|
+
const barStyle = getComputedStyle(node);
|
|
167
|
+
const flexLayout = ownerStyle.display === 'flex' || ownerStyle.display === 'inline-flex';
|
|
168
|
+
const matchingAxis = vertical
|
|
169
|
+
? ownerStyle.flexDirection === 'column' || ownerStyle.flexDirection === 'column-reverse'
|
|
170
|
+
: ownerStyle.flexDirection === 'row' || ownerStyle.flexDirection === 'row-reverse';
|
|
171
|
+
if (!flexLayout || !matchingAxis || Number.parseFloat(barStyle.flexGrow) <= 0) {
|
|
172
|
+
return current;
|
|
173
|
+
}
|
|
174
|
+
const pixels = (value: string): number => Number.parseFloat(value) || 0;
|
|
175
|
+
const padding = vertical
|
|
176
|
+
? pixels(ownerStyle.paddingTop) + pixels(ownerStyle.paddingBottom)
|
|
177
|
+
: pixels(ownerStyle.paddingLeft) + pixels(ownerStyle.paddingRight);
|
|
178
|
+
const budget = (vertical ? owner.clientHeight : owner.clientWidth) - padding;
|
|
179
|
+
const arrows = Array.from(owner.querySelectorAll<HTMLElement>(':scope > .tabs-arrow'));
|
|
180
|
+
const gap = pixels(vertical ? ownerStyle.rowGap : ownerStyle.columnGap);
|
|
181
|
+
const gutter = arrows.reduce(
|
|
182
|
+
(total, arrow) => total + (vertical ? arrow.offsetHeight : arrow.offsetWidth),
|
|
183
|
+
gap * arrows.length
|
|
184
|
+
);
|
|
185
|
+
const border = vertical
|
|
186
|
+
? pixels(barStyle.borderTopWidth) + pixels(barStyle.borderBottomWidth)
|
|
187
|
+
: pixels(barStyle.borderLeftWidth) + pixels(barStyle.borderRightWidth);
|
|
188
|
+
let available = Math.min(current + gutter, Math.max(0, budget - border));
|
|
189
|
+
const maximum = vertical ? barStyle.maxHeight : barStyle.maxWidth;
|
|
190
|
+
if (maximum !== 'none') {
|
|
191
|
+
const limit = maximum.endsWith('%')
|
|
192
|
+
? (pixels(maximum) * budget) / 100
|
|
193
|
+
: maximum.endsWith('px')
|
|
194
|
+
? pixels(maximum)
|
|
195
|
+
: Number.NaN;
|
|
196
|
+
if (!Number.isFinite(limit)) {
|
|
197
|
+
// Keep the measured constraint when an authored CSS expression cannot
|
|
198
|
+
// be resolved here without changing that layout.
|
|
199
|
+
return current;
|
|
200
|
+
}
|
|
201
|
+
const barPadding = vertical
|
|
202
|
+
? pixels(barStyle.paddingTop) + pixels(barStyle.paddingBottom)
|
|
203
|
+
: pixels(barStyle.paddingLeft) + pixels(barStyle.paddingRight);
|
|
204
|
+
available = Math.min(
|
|
205
|
+
available,
|
|
206
|
+
barStyle.boxSizing === 'border-box' ? Math.max(0, limit - border) : limit + barPadding
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
return available;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function inFlowContentExtent(node: HTMLElement, vertical: boolean): number {
|
|
213
|
+
let minimum = Number.POSITIVE_INFINITY;
|
|
214
|
+
let maximum = Number.NEGATIVE_INFINITY;
|
|
215
|
+
const pixels = (value: string): number => Number.parseFloat(value) || 0;
|
|
216
|
+
for (const child of Array.from(node.children)) {
|
|
217
|
+
if (
|
|
218
|
+
!(child instanceof HTMLElement) ||
|
|
219
|
+
child.classList.contains('tabs-indicator') ||
|
|
220
|
+
child.getClientRects().length === 0
|
|
221
|
+
) {
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
if (child.offsetParent !== node) {
|
|
225
|
+
// An authored offset parent uses another coordinate system.
|
|
226
|
+
return vertical ? node.scrollHeight : node.scrollWidth;
|
|
227
|
+
}
|
|
228
|
+
const childStyle = getComputedStyle(child);
|
|
229
|
+
const start = vertical ? child.offsetTop : child.offsetLeft;
|
|
230
|
+
const end = start + (vertical ? child.offsetHeight : child.offsetWidth);
|
|
231
|
+
const before = pixels(vertical ? childStyle.marginTop : childStyle.marginLeft);
|
|
232
|
+
const after = pixels(vertical ? childStyle.marginBottom : childStyle.marginRight);
|
|
233
|
+
minimum = Math.min(minimum, start, start - before);
|
|
234
|
+
maximum = Math.max(maximum, end, end + after);
|
|
235
|
+
}
|
|
236
|
+
const style = getComputedStyle(node);
|
|
237
|
+
const padding = vertical
|
|
238
|
+
? pixels(style.paddingTop) + pixels(style.paddingBottom)
|
|
239
|
+
: pixels(style.paddingLeft) + pixels(style.paddingRight);
|
|
240
|
+
// The absolute indicator can temporarily extend during its transition;
|
|
241
|
+
// it is decoration rather than additional tab content.
|
|
242
|
+
return (Number.isFinite(minimum) ? Math.max(0, maximum - minimum) : 0) + padding;
|
|
243
|
+
}
|
|
244
|
+
|
|
159
245
|
function updateOverflow(): void {
|
|
160
246
|
if (scrollContainer === null) {
|
|
161
247
|
return;
|
|
162
248
|
}
|
|
163
249
|
if (isVertical) {
|
|
164
250
|
const { scrollTop, scrollHeight, clientHeight } = scrollContainer;
|
|
251
|
+
if (clientHeight <= 0) {
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
if (
|
|
255
|
+
inFlowContentExtent(scrollContainer, true) <=
|
|
256
|
+
availableWithoutArrows(scrollContainer, true) + 1
|
|
257
|
+
) {
|
|
258
|
+
canScrollUp = false;
|
|
259
|
+
canScrollDown = false;
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
165
262
|
canScrollUp = scrollTop > 1;
|
|
166
263
|
canScrollDown = scrollTop + clientHeight < scrollHeight - 1;
|
|
167
264
|
return;
|
|
168
265
|
}
|
|
169
266
|
const { scrollLeft, scrollWidth, clientWidth } = scrollContainer;
|
|
170
|
-
|
|
171
|
-
|
|
267
|
+
if (clientWidth <= 0) {
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
if (
|
|
271
|
+
inFlowContentExtent(scrollContainer, false) <=
|
|
272
|
+
availableWithoutArrows(scrollContainer, false) + 1
|
|
273
|
+
) {
|
|
274
|
+
canScrollLeft = false;
|
|
275
|
+
canScrollRight = false;
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
const maxScroll = Math.max(0, scrollWidth - clientWidth);
|
|
279
|
+
// RTL starts at zero at the physical right edge and moves negatively to
|
|
280
|
+
// the left. Express both directions as distance from the physical left.
|
|
281
|
+
const physicalLeft = Math.min(
|
|
282
|
+
maxScroll,
|
|
283
|
+
Math.max(
|
|
284
|
+
0,
|
|
285
|
+
getComputedStyle(scrollContainer).direction === 'rtl' ? maxScroll + scrollLeft : scrollLeft
|
|
286
|
+
)
|
|
287
|
+
);
|
|
288
|
+
canScrollLeft = physicalLeft > 1;
|
|
289
|
+
canScrollRight = physicalLeft < maxScroll - 1;
|
|
172
290
|
}
|
|
173
291
|
|
|
174
292
|
function updateIndicator(): void {
|
|
@@ -176,6 +294,11 @@
|
|
|
176
294
|
indicatorReady = false;
|
|
177
295
|
return;
|
|
178
296
|
}
|
|
297
|
+
// A hidden or temporarily zero-sized viewport cannot provide label offsets.
|
|
298
|
+
// Keep the last measured indicator until this axis can be laid out again.
|
|
299
|
+
if ((isVertical ? scrollContainer.clientHeight : scrollContainer.clientWidth) <= 0) {
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
179
302
|
const activeEl = scrollContainer.querySelector<HTMLElement>('.tabs-item.active');
|
|
180
303
|
if (activeEl === null) {
|
|
181
304
|
indicatorReady = false;
|
|
@@ -359,6 +482,21 @@
|
|
|
359
482
|
if (next instanceof HTMLElement && tabElements().includes(next)) {
|
|
360
483
|
return;
|
|
361
484
|
}
|
|
485
|
+
if (next === null && event.target instanceof HTMLElement) {
|
|
486
|
+
const target = event.target;
|
|
487
|
+
const previousKey = focusedKey;
|
|
488
|
+
focusedKey = null;
|
|
489
|
+
// Chromium fires focusout before removing the focused node. Let that
|
|
490
|
+
// mutation finish before restoring removal focus. An intentional blur
|
|
491
|
+
// releases ownership immediately, including during a selection update.
|
|
492
|
+
queueMicrotask(() => {
|
|
493
|
+
if (!target.isConnected && focusedKey === null && previousKey !== null) {
|
|
494
|
+
focusedKey = previousKey;
|
|
495
|
+
reconcileFocus();
|
|
496
|
+
}
|
|
497
|
+
});
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
362
500
|
focusedKey = null;
|
|
363
501
|
}
|
|
364
502
|
|
|
@@ -387,8 +525,20 @@
|
|
|
387
525
|
focusedKey = null;
|
|
388
526
|
return;
|
|
389
527
|
}
|
|
390
|
-
if (!isInside
|
|
391
|
-
|
|
528
|
+
if (!isInside) {
|
|
529
|
+
// A removed tab leaves focus on the body; restore that lost focus. An
|
|
530
|
+
// external control (including this strip's arrow) owns its own focus.
|
|
531
|
+
const root = scrollContainer?.getRootNode();
|
|
532
|
+
const hostActive = root instanceof ShadowRoot ? getActiveElement(root.host) : null;
|
|
533
|
+
const lostToBody =
|
|
534
|
+
active === scrollContainer?.ownerDocument.body ||
|
|
535
|
+
(root instanceof ShadowRoot &&
|
|
536
|
+
active === null &&
|
|
537
|
+
(hostActive === root.host || hostActive === scrollContainer?.ownerDocument.body));
|
|
538
|
+
if (focusedKey === null || !lostToBody) {
|
|
539
|
+
focusedKey = null;
|
|
540
|
+
return;
|
|
541
|
+
}
|
|
392
542
|
}
|
|
393
543
|
// Focus follows a selection made elsewhere, so a parent switching tabs does not
|
|
394
544
|
// strand the user on a tab that is no longer the selected one.
|
|
@@ -414,7 +564,32 @@
|
|
|
414
564
|
updateOverflow();
|
|
415
565
|
updateIndicator();
|
|
416
566
|
reconcileFocus();
|
|
567
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
568
|
+
updateOverflow();
|
|
569
|
+
updateIndicator();
|
|
570
|
+
});
|
|
571
|
+
let resizeTargets: Element[] = [];
|
|
572
|
+
const syncResizeTargets = (): void => {
|
|
573
|
+
const targets: Element[] = [
|
|
574
|
+
node,
|
|
575
|
+
...node.querySelectorAll('.tabs-item, .tabs-section-label')
|
|
576
|
+
];
|
|
577
|
+
for (const previous of resizeTargets) {
|
|
578
|
+
if (!targets.includes(previous)) {
|
|
579
|
+
resizeObserver.unobserve(previous);
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
for (const target of targets) {
|
|
583
|
+
if (!resizeTargets.includes(target)) {
|
|
584
|
+
resizeObserver.observe(target, {
|
|
585
|
+
box: target === node ? 'content-box' : 'border-box'
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
resizeTargets = targets;
|
|
590
|
+
};
|
|
417
591
|
const observer = new MutationObserver(() => {
|
|
592
|
+
syncResizeTargets();
|
|
418
593
|
updateOverflow();
|
|
419
594
|
updateIndicator();
|
|
420
595
|
reconcileFocus();
|
|
@@ -425,11 +600,7 @@
|
|
|
425
600
|
attributes: true,
|
|
426
601
|
attributeFilter: ['class', 'tabindex', 'aria-selected', 'aria-disabled']
|
|
427
602
|
});
|
|
428
|
-
|
|
429
|
-
updateOverflow();
|
|
430
|
-
updateIndicator();
|
|
431
|
-
});
|
|
432
|
-
resizeObserver.observe(node);
|
|
603
|
+
syncResizeTargets();
|
|
433
604
|
return () => {
|
|
434
605
|
observer.disconnect();
|
|
435
606
|
resizeObserver.disconnect();
|
|
@@ -521,7 +692,11 @@
|
|
|
521
692
|
{#if typeof tabItem?.icon === 'string' && tabItem.icon.length > 0}
|
|
522
693
|
<Img inlineSvg src={tabItem.icon} alt="" fallback="" classes="tabs-item-icon" />
|
|
523
694
|
{/if}
|
|
524
|
-
|
|
695
|
+
<!-- Refresh only the label node: WebKit can retain the old attr() ghost
|
|
696
|
+
after a reused label changes, while the tab and its focus stay stable. -->
|
|
697
|
+
{#key label}
|
|
698
|
+
<span class="tabs-item-label" data-text={label}>{label}</span>
|
|
699
|
+
{/key}
|
|
525
700
|
{#if tabItem?.status && tabItem.status !== 'none'}
|
|
526
701
|
<span class="tabs-item-status status-{tabItem.status}" aria-hidden="true"></span>
|
|
527
702
|
{/if}
|
|
@@ -735,12 +910,12 @@
|
|
|
735
910
|
with height:0/visibility:hidden -- invisible, but its width still sets
|
|
736
911
|
the shrink-to-fit width of the inline-block label, so the box is already
|
|
737
912
|
as wide as the active state needs even while showing the lighter weight. */
|
|
738
|
-
.tabs-item-label {
|
|
913
|
+
.tabs-item :global(.tabs-item-label) {
|
|
739
914
|
position: relative;
|
|
740
915
|
display: inline-block;
|
|
741
916
|
}
|
|
742
917
|
|
|
743
|
-
.tabs-item-label::after {
|
|
918
|
+
.tabs-item :global(.tabs-item-label)::after {
|
|
744
919
|
content: attr(data-text);
|
|
745
920
|
display: block;
|
|
746
921
|
height: 0;
|
|
@@ -289,10 +289,10 @@
|
|
|
289
289
|
gap: var(--tool-call-log-gap, 8px);
|
|
290
290
|
}
|
|
291
291
|
|
|
292
|
-
/* Bespoke <button> markup (
|
|
293
|
-
|
|
294
|
-
pulled from Pill's own tokens (line-height, cursor) so it reads as
|
|
295
|
-
of control as the diffstat Pill badges nested inside it. */
|
|
292
|
+
/* Bespoke <button> markup (the chip holds mixed content -- spinner, label, meta and nested
|
|
293
|
+
diffstat Pill badges -- where Pill renders one `text` string; see docs), but its sizing
|
|
294
|
+
recipe is deliberately pulled from Pill's own tokens (line-height, cursor) so it reads as
|
|
295
|
+
the same family of control as the diffstat Pill badges nested inside it. */
|
|
296
296
|
.chip {
|
|
297
297
|
display: inline-flex;
|
|
298
298
|
align-items: center;
|
package/dist/utils.js
CHANGED
|
@@ -372,8 +372,24 @@ export function createDebouncer(delay) {
|
|
|
372
372
|
}
|
|
373
373
|
};
|
|
374
374
|
}
|
|
375
|
-
|
|
376
|
-
const
|
|
375
|
+
const scrollLocksKey = Symbol.for('@juspay/svelte-ui-components/scroll-locks/v1');
|
|
376
|
+
const activeScrollLocksKey = Symbol.for('@juspay/svelte-ui-components/active-scroll-locks/v1');
|
|
377
|
+
/** Independent package and custom-element bundles share the actual owner's holds. */
|
|
378
|
+
function scrollLocksFor(container) {
|
|
379
|
+
const activeOwner = container;
|
|
380
|
+
if (activeOwner[activeScrollLocksKey]) {
|
|
381
|
+
return activeOwner[activeScrollLocksKey];
|
|
382
|
+
}
|
|
383
|
+
const owner = container.ownerDocument;
|
|
384
|
+
let locks = owner[scrollLocksKey];
|
|
385
|
+
if (!locks) {
|
|
386
|
+
locks = new WeakMap();
|
|
387
|
+
Object.defineProperty(owner, scrollLocksKey, { value: locks });
|
|
388
|
+
}
|
|
389
|
+
// The same real owner can be adopted into another document while held.
|
|
390
|
+
Object.defineProperty(activeOwner, activeScrollLocksKey, { value: locks, configurable: true });
|
|
391
|
+
return locks;
|
|
392
|
+
}
|
|
377
393
|
const bodyScrollReleases = [];
|
|
378
394
|
/**
|
|
379
395
|
* Acquire one hold and return its idempotent release function. Only overflow
|
|
@@ -385,6 +401,7 @@ export function acquireScrollLock(container = typeof document === 'undefined' ?
|
|
|
385
401
|
if (container === null) {
|
|
386
402
|
return () => { };
|
|
387
403
|
}
|
|
404
|
+
const scrollLocks = scrollLocksFor(container);
|
|
388
405
|
let lock = scrollLocks.get(container);
|
|
389
406
|
if (!lock) {
|
|
390
407
|
const overflow = [];
|
|
@@ -419,6 +436,7 @@ export function acquireScrollLock(container = typeof document === 'undefined' ?
|
|
|
419
436
|
container.style.setProperty(name, value, priority);
|
|
420
437
|
}
|
|
421
438
|
scrollLocks.delete(container);
|
|
439
|
+
Reflect.deleteProperty(container, activeScrollLocksKey);
|
|
422
440
|
}
|
|
423
441
|
};
|
|
424
442
|
}
|
|
@@ -9,10 +9,10 @@ const USAGE = [
|
|
|
9
9
|
' npx sui-codemod migrate [--dry-run] <path>',
|
|
10
10
|
' (inside this repository: node scripts/codemod/cli.ts ...)',
|
|
11
11
|
'',
|
|
12
|
-
'
|
|
13
|
-
'
|
|
14
|
-
'
|
|
15
|
-
'
|
|
12
|
+
'Migrates older @juspay/svelte-ui-components usage to the current API:',
|
|
13
|
+
'renames removed event-prop spellings on library component tags to their',
|
|
14
|
+
'lowercase replacements (see legacy-pairs.ts) and reports unsupported',
|
|
15
|
+
'`children` assignments on affected custom elements.',
|
|
16
16
|
'',
|
|
17
17
|
' --dry-run print every change as a diff without writing any file',
|
|
18
18
|
' --help show this help',
|