@lavalogic/scoria 0.37.16 → 0.37.18
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/Components/Table/Body/QuickSearchCell.svelte +2 -0
- package/dist/Components/Table/Body/Rows/ColumnListRow.svelte +95 -56
- package/dist/Components/Table/Body/Rows/Columns/BubbleCell.svelte +1 -0
- package/dist/Components/Table/ColumnFactory.svelte.js +19 -5
- package/dist/Components/Table/Misc/ColumnPanel.svelte +2 -0
- package/dist/Components/Table/Table.svelte +16 -1
- package/dist/scss/_mixins.scss +11 -0
- package/package.json +1 -1
|
@@ -368,56 +368,71 @@
|
|
|
368
368
|
ondragleave={disableDragVisual}
|
|
369
369
|
ondrop={disableDragVisual}
|
|
370
370
|
>
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
Tri-state pin selector rendered via `ThreeStateRadio`,
|
|
384
|
-
matching the visual segmented-control used elsewhere in
|
|
385
|
-
the table (filter Active state, etc.). The three
|
|
386
|
-
`Ternary` slots map to:
|
|
387
|
-
False → pinned LEFT (pin-left icon, leftmost)
|
|
388
|
-
Neutral → unpinned (circle-cross icon, middle)
|
|
389
|
-
True → pinned RIGHT (pin-right icon, rightmost)
|
|
390
|
-
Expand columns can never be pinned, so the group goes
|
|
391
|
-
fully disabled for them.
|
|
392
|
-
-->
|
|
393
|
-
<div
|
|
394
|
-
class="pin-selector"
|
|
395
|
-
class:disabled={isExpandColumn}
|
|
371
|
+
<!--
|
|
372
|
+
`.row-main` stacks the column label on top and the
|
|
373
|
+
visibility / pin controls underneath, so the label gets
|
|
374
|
+
the full card width to wrap into (instead of competing
|
|
375
|
+
horizontally with the controls). `.reorder-buttons` stays
|
|
376
|
+
as a sibling outside `.row-main` so the up / down arrows
|
|
377
|
+
remain vertically centred on the right edge of the card.
|
|
378
|
+
-->
|
|
379
|
+
<div class="row-main">
|
|
380
|
+
<span
|
|
381
|
+
class="column-label"
|
|
382
|
+
title={typeof columnDef.header === 'string' ? columnDef.header : columnDef.id}
|
|
396
383
|
>
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
384
|
+
{#if typeof columnDef.header === 'function'}
|
|
385
|
+
<!-- FIXME this needs testing -->
|
|
386
|
+
{@render columnDef.header()}
|
|
387
|
+
{:else}
|
|
388
|
+
{columnDef.header}
|
|
389
|
+
{/if}
|
|
390
|
+
</span>
|
|
391
|
+
|
|
392
|
+
<div class="row-controls">
|
|
393
|
+
<div class="visibility-wrapper">
|
|
394
|
+
<Checkbox
|
|
395
|
+
icon={{ name: 'assessment', size: Size.MediumSmall }}
|
|
396
|
+
size={Size.FillWidth}
|
|
397
|
+
id={`is-visible-${tableContext.tableName}-${columnDef.id}`}
|
|
398
|
+
value={tableContext.columnVisibility[columnDef.id] !== false}
|
|
399
|
+
onchange={onVisibilityChange}
|
|
400
|
+
/>
|
|
401
|
+
</div>
|
|
402
|
+
|
|
403
|
+
{#if tableContext.allowColumnReordering}
|
|
404
|
+
<!--
|
|
405
|
+
Tri-state pin selector rendered via `ThreeStateRadio`,
|
|
406
|
+
matching the visual segmented-control used elsewhere in
|
|
407
|
+
the table (filter Active state, etc.). The three
|
|
408
|
+
`Ternary` slots map to:
|
|
409
|
+
False → pinned LEFT (pin-left icon, leftmost)
|
|
410
|
+
Neutral → unpinned (circle-cross icon, middle)
|
|
411
|
+
True → pinned RIGHT (pin-right icon, rightmost)
|
|
412
|
+
Expand columns can never be pinned, so the group goes
|
|
413
|
+
fully disabled for them.
|
|
414
|
+
-->
|
|
415
|
+
<div
|
|
416
|
+
class="pin-selector"
|
|
417
|
+
class:disabled={isExpandColumn}
|
|
418
|
+
>
|
|
419
|
+
<ThreeStateRadio
|
|
420
|
+
value={pinSide}
|
|
421
|
+
disabled={isExpandColumn}
|
|
422
|
+
noLabel="Pin to left"
|
|
423
|
+
neutralLabel="Unpinned"
|
|
424
|
+
yesLabel="Pin to right"
|
|
425
|
+
noIcon={{ name: 'pin-left', size: Size.MediumSmall }}
|
|
426
|
+
neutralIcon={{ name: 'circle-cross', size: Size.MediumSmall }}
|
|
427
|
+
yesIcon={{ name: 'pin-right', size: Size.MediumSmall }}
|
|
428
|
+
onchange={(next: Ternary) => {
|
|
429
|
+
setPin(next);
|
|
430
|
+
}}
|
|
431
|
+
/>
|
|
432
|
+
</div>
|
|
433
|
+
{/if}
|
|
410
434
|
</div>
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
<span class="column-label">
|
|
414
|
-
{#if typeof columnDef.header === 'function'}
|
|
415
|
-
<!-- FIXME this needs testing -->
|
|
416
|
-
{@render columnDef.header()}
|
|
417
|
-
{:else}
|
|
418
|
-
{columnDef.header}
|
|
419
|
-
{/if}
|
|
420
|
-
</span>
|
|
435
|
+
</div>
|
|
421
436
|
|
|
422
437
|
{#if tableContext.allowColumnReordering}
|
|
423
438
|
<!--
|
|
@@ -478,10 +493,11 @@ li.targeted {
|
|
|
478
493
|
|
|
479
494
|
li.single-column:not(.anchor) {
|
|
480
495
|
display: flex;
|
|
481
|
-
|
|
482
|
-
padding: 0.5rem 0.75rem;
|
|
483
|
-
margin-bottom: 0.5rem;
|
|
496
|
+
flex-flow: row nowrap;
|
|
484
497
|
align-items: center;
|
|
498
|
+
gap: 0.5rem;
|
|
499
|
+
padding: 0.5rem 0.625rem;
|
|
500
|
+
margin-bottom: 0.375rem;
|
|
485
501
|
background-color: #ffffff;
|
|
486
502
|
border: solid 1px #cbd4da;
|
|
487
503
|
border-radius: 4px;
|
|
@@ -499,15 +515,30 @@ li.single-column:not(.anchor):last-of-type {
|
|
|
499
515
|
margin-bottom: 0;
|
|
500
516
|
}
|
|
501
517
|
|
|
518
|
+
.row-main {
|
|
519
|
+
flex: 1 1 auto;
|
|
520
|
+
min-width: 0;
|
|
521
|
+
display: flex;
|
|
522
|
+
flex-flow: column nowrap;
|
|
523
|
+
gap: 0.375rem;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
.row-controls {
|
|
527
|
+
display: flex;
|
|
528
|
+
flex-flow: row nowrap;
|
|
529
|
+
align-items: center;
|
|
530
|
+
gap: 0.5rem;
|
|
531
|
+
}
|
|
532
|
+
|
|
502
533
|
.visibility-wrapper {
|
|
503
|
-
width:
|
|
504
|
-
height:
|
|
534
|
+
width: 2.25rem;
|
|
535
|
+
height: 2.25rem;
|
|
505
536
|
display: flex;
|
|
506
537
|
flex-shrink: 0;
|
|
507
538
|
}
|
|
508
539
|
|
|
509
540
|
.pin-selector {
|
|
510
|
-
--input-height:
|
|
541
|
+
--input-height: 2.25rem;
|
|
511
542
|
--input-width: auto;
|
|
512
543
|
flex-shrink: 0;
|
|
513
544
|
display: flex;
|
|
@@ -519,11 +550,19 @@ li.single-column:not(.anchor):last-of-type {
|
|
|
519
550
|
}
|
|
520
551
|
|
|
521
552
|
.column-label {
|
|
522
|
-
|
|
553
|
+
width: 100%;
|
|
523
554
|
min-width: 0;
|
|
555
|
+
font-size: 1.125rem;
|
|
556
|
+
font-weight: 500;
|
|
557
|
+
line-height: 1.25;
|
|
558
|
+
color: #3a4952;
|
|
559
|
+
display: -webkit-box;
|
|
560
|
+
-webkit-line-clamp: 2;
|
|
561
|
+
-webkit-box-orient: vertical;
|
|
524
562
|
overflow: hidden;
|
|
525
563
|
text-overflow: ellipsis;
|
|
526
|
-
|
|
564
|
+
word-break: normal;
|
|
565
|
+
overflow-wrap: anywhere;
|
|
527
566
|
}
|
|
528
567
|
|
|
529
568
|
.reorder-buttons {
|
|
@@ -127,12 +127,26 @@ function commonProps(opts, kind) {
|
|
|
127
127
|
filterGroup: opts.filterGroup,
|
|
128
128
|
};
|
|
129
129
|
}
|
|
130
|
-
/** Generate a
|
|
131
|
-
* from the caller.
|
|
132
|
-
*
|
|
130
|
+
/** Generate a column id for a kind whose option type does not require
|
|
131
|
+
* an `id` from the caller.
|
|
132
|
+
*
|
|
133
|
+
* - When `hint` is provided, use it as the id verbatim. This is the
|
|
134
|
+
* server-side-filtering contract: callers who pass an `idHint` are
|
|
135
|
+
* indicating that the column maps to a real backend field (so the
|
|
136
|
+
* filter row's `id` flows through `createRemoteRowSource` as the
|
|
137
|
+
* query-string key the server expects). Adding a synthetic prefix
|
|
138
|
+
* here would mean every `col.display({ idHint: 'outboundType_id' })`
|
|
139
|
+
* serialised as `display-outboundType_id` and the server rejected
|
|
140
|
+
* the request with "field does not exist".
|
|
141
|
+
* - When no `hint` is provided, fall back to `${prefix}-${UUID}` so
|
|
142
|
+
* the id is still unique within the table. Such columns cannot
|
|
143
|
+
* participate in server-driven filtering anyway (the server would
|
|
144
|
+
* not know the random suffix). */
|
|
133
145
|
function mintSyntheticId(prefix, hint) {
|
|
134
|
-
|
|
135
|
-
|
|
146
|
+
if (hint != null) {
|
|
147
|
+
return syntheticColumnId(hint);
|
|
148
|
+
}
|
|
149
|
+
return syntheticColumnId(`${prefix}-${generateUUID()}`);
|
|
136
150
|
}
|
|
137
151
|
/** Resolve an `options` field that may be a static array or an async
|
|
138
152
|
* loader into the always-loader form the Def expects. Mutable arrays are
|
|
@@ -156,10 +156,25 @@
|
|
|
156
156
|
`#${tableContext.tableName}-cell-${row}-${def.id}`
|
|
157
157
|
) as HTMLElement | undefined;
|
|
158
158
|
|
|
159
|
+
// Skip horizontal scroll-into-view for pinned (sticky)
|
|
160
|
+
// cells. Sticky positioning makes the cell visually
|
|
161
|
+
// "always on screen", but its true layout position is at
|
|
162
|
+
// its real column track - which for a right-pinned column
|
|
163
|
+
// in a wider-than-viewport table is offscreen. Asking the
|
|
164
|
+
// browser to `scrollIntoView({inline: 'nearest'})` then
|
|
165
|
+
// scrolls the table horizontally to bring the cell's
|
|
166
|
+
// underlying position into view, which is the user-facing
|
|
167
|
+
// "table jumps right when I click the Actions button"
|
|
168
|
+
// bug. The vertical block axis still scrolls because the
|
|
169
|
+
// row's vertical position is the user's actual scroll
|
|
170
|
+
// target.
|
|
171
|
+
const isPinned =
|
|
172
|
+
cell?.classList.contains('pinned-left') ||
|
|
173
|
+
cell?.classList.contains('pinned-right');
|
|
159
174
|
cell?.scrollIntoView({
|
|
160
175
|
behavior: 'instant',
|
|
161
176
|
block: 'nearest',
|
|
162
|
-
inline: 'nearest',
|
|
177
|
+
inline: isPinned ? undefined : 'nearest',
|
|
163
178
|
});
|
|
164
179
|
}
|
|
165
180
|
});
|
package/dist/scss/_mixins.scss
CHANGED
|
@@ -1869,6 +1869,17 @@
|
|
|
1869
1869
|
overflow: visible;
|
|
1870
1870
|
padding-left: 0;
|
|
1871
1871
|
padding-right: 0;
|
|
1872
|
+
// Reassert the column-separator border-right here so it survives
|
|
1873
|
+
// even when a narrow select-filter cell's internal widget (the
|
|
1874
|
+
// SingleSelect / MultiSelect dropdown trigger) paints flush to
|
|
1875
|
+
// the right edge. Without this rule, two adjacent select filters
|
|
1876
|
+
// visually merge because the inner widget's background covers
|
|
1877
|
+
// the cell's table-cell-basic border. `!important` is here to
|
|
1878
|
+
// override the more-specific .focusable rule from
|
|
1879
|
+
// table-cell-basic that occasionally re-paints the right edge
|
|
1880
|
+
// transparent during focus.
|
|
1881
|
+
border-right: solid 1px colours.$ui-blue-4 !important;
|
|
1882
|
+
box-sizing: border-box;
|
|
1872
1883
|
|
|
1873
1884
|
div.stick-right {
|
|
1874
1885
|
position: absolute;
|