@streamscloud/kit 0.40.0 → 0.40.2
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/styles/_semantic.scss +1 -0
- package/dist/ui/page-layout/cmp.page-layout.svelte +3 -1
- package/dist/ui/page-layout/cmp.page-layout.svelte.d.ts +1 -0
- package/dist/ui/page-layout/cmp.page-panel.svelte +120 -12
- package/dist/ui/page-layout/page-layout-localization.d.ts +2 -0
- package/dist/ui/page-layout/page-layout-localization.js +14 -0
- package/dist/ui/table/table-cells/table-image-cell.svelte +12 -0
- package/dist/ui/table/table-cells/table-image-cell.svelte.d.ts +8 -0
- package/package.json +1 -1
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
--sc-kit--color--bg--active: light-dark(#eef2f8, #{$color-dark-600});
|
|
17
17
|
--sc-kit--color--bg--menu-active: light-dark(#{$color-blue-50}, #{$color-dark-500});
|
|
18
18
|
--sc-kit--color--bg--images: light-dark(#{$color-neutral-300}, #{$color-dark-50});
|
|
19
|
+
--sc-kit--color--bg--images-subtle: light-dark(#{$color-neutral-100}, #{$color-dark-50});
|
|
19
20
|
|
|
20
21
|
// ============================================================
|
|
21
22
|
// COLOR — TEXT
|
|
@@ -71,6 +71,7 @@ sticky panel headers.
|
|
|
71
71
|
| `--sc-kit--page-layout--color` | Page text color | `--sc-kit--color--text--primary` |
|
|
72
72
|
| `--sc-kit--page-layout--border-color` | Header divider color | `--sc-kit--color--border` |
|
|
73
73
|
| `--sc-kit--page-layout--title--font-size` | Title font size | `18px` |
|
|
74
|
+
| `--sc-kit--page-layout--header--padding-inline` | Header inline padding | `24px` |
|
|
74
75
|
-->
|
|
75
76
|
<style>.page-layout {
|
|
76
77
|
--_page-layout--background: var(--sc-kit--page-layout--background, var(--sc-kit--color--bg--panel));
|
|
@@ -78,6 +79,7 @@ sticky panel headers.
|
|
|
78
79
|
--_page-layout--color: var(--sc-kit--page-layout--color, var(--sc-kit--color--text--primary));
|
|
79
80
|
--_page-layout--border-color: var(--sc-kit--page-layout--border-color, var(--sc-kit--color--border));
|
|
80
81
|
--_page-layout--title-font-size: var(--sc-kit--page-layout--title--font-size, 1.125rem);
|
|
82
|
+
--_page-layout--header-padding-inline: var(--sc-kit--page-layout--header--padding-inline, 1.5rem);
|
|
81
83
|
display: flex;
|
|
82
84
|
flex-direction: column;
|
|
83
85
|
height: 100%;
|
|
@@ -90,7 +92,7 @@ sticky panel headers.
|
|
|
90
92
|
align-items: center;
|
|
91
93
|
justify-content: space-between;
|
|
92
94
|
height: 4.1875rem;
|
|
93
|
-
padding: 1.25rem
|
|
95
|
+
padding: 1.25rem var(--_page-layout--header-padding-inline) 0.875rem;
|
|
94
96
|
background: var(--_page-layout--header-background);
|
|
95
97
|
border-bottom: 1px solid var(--_page-layout--border-color);
|
|
96
98
|
flex-shrink: 0;
|
|
@@ -28,6 +28,7 @@ type Props = {
|
|
|
28
28
|
* | `--sc-kit--page-layout--color` | Page text color | `--sc-kit--color--text--primary` |
|
|
29
29
|
* | `--sc-kit--page-layout--border-color` | Header divider color | `--sc-kit--color--border` |
|
|
30
30
|
* | `--sc-kit--page-layout--title--font-size` | Title font size | `18px` |
|
|
31
|
+
* | `--sc-kit--page-layout--header--padding-inline` | Header inline padding | `24px` |
|
|
31
32
|
*/
|
|
32
33
|
declare const Cmp: import("svelte").Component<Props, {}, "">;
|
|
33
34
|
type Cmp = ReturnType<typeof Cmp>;
|
|
@@ -1,11 +1,19 @@
|
|
|
1
|
-
<script lang="ts">import {
|
|
1
|
+
<script lang="ts">import { horizontalWheelScroll } from '../../core/actions';
|
|
2
|
+
import { slideHorizontally, transitionDuration } from '../../core/transitions';
|
|
3
|
+
import { Icon } from '../icon';
|
|
2
4
|
import PanelCollapseButton from './cmp.panel-collapse-button.svelte';
|
|
3
5
|
import { PageLayoutLocalization } from './page-layout-localization';
|
|
6
|
+
import IconChevronLeft from '@fluentui/svg-icons/icons/chevron_left_20_regular.svg?raw';
|
|
7
|
+
import IconChevronRight from '@fluentui/svg-icons/icons/chevron_right_20_regular.svg?raw';
|
|
4
8
|
import { untrack } from 'svelte';
|
|
5
9
|
const { panelState, children, id, header, footer, title, actionsLeft, actionsCenter, actionsRight, collapseButtons, hideHeader = false, balanceHeaderCenter = false, resizing = null, borders = [], on } = $props();
|
|
6
10
|
const localization = new PageLayoutLocalization();
|
|
7
11
|
const isFlex = untrack(() => !resizing);
|
|
12
|
+
const HEADER_SCROLL_STEP = 160;
|
|
8
13
|
let panelRef = $state(undefined);
|
|
14
|
+
let headerLeftTrack = $state(undefined);
|
|
15
|
+
let canScrollHeaderLeftBack = $state(false);
|
|
16
|
+
let canScrollHeaderLeftForward = $state(false);
|
|
9
17
|
const { id: panelId, entry } = untrack(() => panelState.register({
|
|
10
18
|
id,
|
|
11
19
|
initialWidth: resizing?.initialWidth ?? null,
|
|
@@ -15,6 +23,26 @@ const canResize = $derived(resizing && [resizing.initialWidth, resizing.minWidth
|
|
|
15
23
|
const widthCss = $derived(entry.width !== null ? `${entry.width}px` : undefined);
|
|
16
24
|
const leftCollapseIds = $derived((collapseButtons ?? []).filter((cid) => panelState.get(cid)?.collapseDirection === 'left'));
|
|
17
25
|
const rightCollapseIds = $derived((collapseButtons ?? []).filter((cid) => panelState.get(cid)?.collapseDirection === 'right'));
|
|
26
|
+
const updateHeaderLeftScrollState = (node) => {
|
|
27
|
+
const { scrollLeft, scrollWidth, clientWidth } = node;
|
|
28
|
+
canScrollHeaderLeftBack = scrollLeft > 0;
|
|
29
|
+
canScrollHeaderLeftForward = scrollLeft < scrollWidth - clientWidth - 1;
|
|
30
|
+
};
|
|
31
|
+
const headerLeftTrackMounted = (node) => {
|
|
32
|
+
headerLeftTrack = node;
|
|
33
|
+
const observer = new ResizeObserver(() => updateHeaderLeftScrollState(node));
|
|
34
|
+
observer.observe(node);
|
|
35
|
+
updateHeaderLeftScrollState(node);
|
|
36
|
+
return {
|
|
37
|
+
destroy: () => observer.disconnect()
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
const scrollHeaderLeftBack = () => {
|
|
41
|
+
headerLeftTrack?.scrollBy({ left: -HEADER_SCROLL_STEP, behavior: 'smooth' });
|
|
42
|
+
};
|
|
43
|
+
const scrollHeaderLeftForward = () => {
|
|
44
|
+
headerLeftTrack?.scrollBy({ left: HEADER_SCROLL_STEP, behavior: 'smooth' });
|
|
45
|
+
};
|
|
18
46
|
$effect(() => {
|
|
19
47
|
const collapsed = entry.collapsed;
|
|
20
48
|
untrack(() => {
|
|
@@ -117,16 +145,43 @@ $effect(() => {
|
|
|
117
145
|
{:else}
|
|
118
146
|
{#if balanceHeaderCenter || leftCollapseIds.length > 0 || title || actionsLeft}
|
|
119
147
|
<div class="page-panel__header-left" class:page-panel__header-left--balanced={balanceHeaderCenter}>
|
|
120
|
-
{#
|
|
121
|
-
<
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
148
|
+
{#if canScrollHeaderLeftBack}
|
|
149
|
+
<button
|
|
150
|
+
type="button"
|
|
151
|
+
class="page-panel__header-scroll-btn page-panel__header-scroll-btn--back"
|
|
152
|
+
onclick={scrollHeaderLeftBack}
|
|
153
|
+
aria-label={localization.scrollBack}>
|
|
154
|
+
<Icon src={IconChevronLeft} size="sm" />
|
|
155
|
+
</button>
|
|
127
156
|
{/if}
|
|
128
|
-
|
|
129
|
-
|
|
157
|
+
<div
|
|
158
|
+
class="page-panel__header-left-track"
|
|
159
|
+
class:page-panel__header-left-track--mask-back={canScrollHeaderLeftBack && !canScrollHeaderLeftForward}
|
|
160
|
+
class:page-panel__header-left-track--mask-forward={canScrollHeaderLeftForward && !canScrollHeaderLeftBack}
|
|
161
|
+
class:page-panel__header-left-track--mask-both={canScrollHeaderLeftBack && canScrollHeaderLeftForward}
|
|
162
|
+
use:headerLeftTrackMounted
|
|
163
|
+
use:horizontalWheelScroll
|
|
164
|
+
onscroll={(e) => updateHeaderLeftScrollState(e.currentTarget)}>
|
|
165
|
+
{#each leftCollapseIds as cid (cid)}
|
|
166
|
+
<PanelCollapseButton panelState={panelState} panelId={cid} />
|
|
167
|
+
{/each}
|
|
168
|
+
{#if typeof title === 'function'}
|
|
169
|
+
{@render title()}
|
|
170
|
+
{:else if title}
|
|
171
|
+
<span class="page-panel__title">{title}</span>
|
|
172
|
+
{/if}
|
|
173
|
+
{#if actionsLeft}
|
|
174
|
+
{@render actionsLeft()}
|
|
175
|
+
{/if}
|
|
176
|
+
</div>
|
|
177
|
+
{#if canScrollHeaderLeftForward}
|
|
178
|
+
<button
|
|
179
|
+
type="button"
|
|
180
|
+
class="page-panel__header-scroll-btn page-panel__header-scroll-btn--forward"
|
|
181
|
+
onclick={scrollHeaderLeftForward}
|
|
182
|
+
aria-label={localization.scrollForward}>
|
|
183
|
+
<Icon src={IconChevronRight} size="sm" />
|
|
184
|
+
</button>
|
|
130
185
|
{/if}
|
|
131
186
|
</div>
|
|
132
187
|
{/if}
|
|
@@ -282,13 +337,66 @@ to min / max; Enter / Space toggle collapsed.
|
|
|
282
337
|
display: flex;
|
|
283
338
|
align-self: stretch;
|
|
284
339
|
align-items: center;
|
|
285
|
-
gap: 1rem;
|
|
286
340
|
min-width: 0;
|
|
287
|
-
|
|
341
|
+
position: relative;
|
|
288
342
|
}
|
|
289
343
|
.page-panel__header-left--balanced {
|
|
290
344
|
justify-self: start;
|
|
291
345
|
}
|
|
346
|
+
.page-panel__header-left:hover {
|
|
347
|
+
--_scroll-btn-opacity: 1;
|
|
348
|
+
}
|
|
349
|
+
.page-panel__header-left-track {
|
|
350
|
+
--_mask-size: 1.5rem;
|
|
351
|
+
display: flex;
|
|
352
|
+
align-items: center;
|
|
353
|
+
gap: 1rem;
|
|
354
|
+
min-width: 0;
|
|
355
|
+
overflow-x: auto;
|
|
356
|
+
scrollbar-width: none;
|
|
357
|
+
}
|
|
358
|
+
.page-panel__header-left-track::-webkit-scrollbar {
|
|
359
|
+
display: none;
|
|
360
|
+
}
|
|
361
|
+
.page-panel__header-left-track--mask-back {
|
|
362
|
+
mask-image: linear-gradient(to right, transparent 0%, black var(--_mask-size), black 100%);
|
|
363
|
+
}
|
|
364
|
+
.page-panel__header-left-track--mask-forward {
|
|
365
|
+
mask-image: linear-gradient(to right, black 0%, black calc(100% - var(--_mask-size)), transparent 100%);
|
|
366
|
+
}
|
|
367
|
+
.page-panel__header-left-track--mask-both {
|
|
368
|
+
mask-image: linear-gradient(to right, transparent 0%, black var(--_mask-size), black calc(100% - var(--_mask-size)), transparent 100%);
|
|
369
|
+
}
|
|
370
|
+
.page-panel__header-scroll-btn {
|
|
371
|
+
position: absolute;
|
|
372
|
+
top: 0;
|
|
373
|
+
bottom: 0;
|
|
374
|
+
z-index: 1;
|
|
375
|
+
display: flex;
|
|
376
|
+
align-items: center;
|
|
377
|
+
justify-content: center;
|
|
378
|
+
padding: 0 0.25rem;
|
|
379
|
+
background: transparent;
|
|
380
|
+
backdrop-filter: blur(2px);
|
|
381
|
+
border: none;
|
|
382
|
+
cursor: pointer;
|
|
383
|
+
color: var(--sc-kit--color--text--secondary);
|
|
384
|
+
opacity: var(--_scroll-btn-opacity, 0);
|
|
385
|
+
transition: opacity var(--sc-kit--duration--base) var(--sc-kit--ease--default);
|
|
386
|
+
}
|
|
387
|
+
.page-panel__header-scroll-btn:hover {
|
|
388
|
+
color: var(--sc-kit--color--text--primary);
|
|
389
|
+
}
|
|
390
|
+
.page-panel__header-scroll-btn--back {
|
|
391
|
+
left: 0;
|
|
392
|
+
padding-right: 0.625rem;
|
|
393
|
+
background: linear-gradient(to right, var(--_page-panel--header-background) 60%, transparent);
|
|
394
|
+
}
|
|
395
|
+
.page-panel__header-scroll-btn--forward {
|
|
396
|
+
right: 0;
|
|
397
|
+
padding-left: 0.625rem;
|
|
398
|
+
background: linear-gradient(to left, var(--_page-panel--header-background) 60%, transparent);
|
|
399
|
+
}
|
|
292
400
|
.page-panel__header-center {
|
|
293
401
|
display: flex;
|
|
294
402
|
align-items: center;
|
|
@@ -19,6 +19,14 @@ const loc = {
|
|
|
19
19
|
close: {
|
|
20
20
|
en: 'Close',
|
|
21
21
|
no: 'Lukk'
|
|
22
|
+
},
|
|
23
|
+
scrollBack: {
|
|
24
|
+
en: 'Scroll back',
|
|
25
|
+
no: 'Rull tilbake'
|
|
26
|
+
},
|
|
27
|
+
scrollForward: {
|
|
28
|
+
en: 'Scroll forward',
|
|
29
|
+
no: 'Rull fremover'
|
|
22
30
|
}
|
|
23
31
|
};
|
|
24
32
|
export class PageLayoutLocalization {
|
|
@@ -37,4 +45,10 @@ export class PageLayoutLocalization {
|
|
|
37
45
|
get close() {
|
|
38
46
|
return loc.close[AppLocale.current];
|
|
39
47
|
}
|
|
48
|
+
get scrollBack() {
|
|
49
|
+
return loc.scrollBack[AppLocale.current];
|
|
50
|
+
}
|
|
51
|
+
get scrollForward() {
|
|
52
|
+
return loc.scrollForward[AppLocale.current];
|
|
53
|
+
}
|
|
40
54
|
}
|
|
@@ -32,7 +32,18 @@ const getValueForColumn = (column, item) => (column.valueFactory ? column.valueF
|
|
|
32
32
|
{/if}
|
|
33
33
|
</div>
|
|
34
34
|
|
|
35
|
+
<!--
|
|
36
|
+
@component
|
|
37
|
+
Image cell for table rows. Renders one of several image layouts depending on `column.format`.
|
|
38
|
+
|
|
39
|
+
### CSS Custom Properties
|
|
40
|
+
| Property | Description | Default |
|
|
41
|
+
|---|---|---|
|
|
42
|
+
| `--sc-kit--table-image-cell--image--background` | Background behind a `square-contain` image (letterboxing) | `var(--sc-kit--color--bg--images-subtle)` |
|
|
43
|
+
-->
|
|
44
|
+
|
|
35
45
|
<style>.table-image-cell {
|
|
46
|
+
--_table-image-cell--image--background: var(--sc-kit--table-image-cell--image--background, var(--sc-kit--color--bg--images-subtle));
|
|
36
47
|
display: flex;
|
|
37
48
|
height: 3.125em;
|
|
38
49
|
min-height: 3.125em;
|
|
@@ -60,6 +71,7 @@ const getValueForColumn = (column, item) => (column.valueFactory ? column.valueF
|
|
|
60
71
|
}
|
|
61
72
|
.table-image-cell__image--contain {
|
|
62
73
|
--sc-kit--image--object-fit: contain;
|
|
74
|
+
--sc-kit--image--background: var(--_table-image-cell--image--background);
|
|
63
75
|
height: var(--_table-image-cell--cover-height);
|
|
64
76
|
}
|
|
65
77
|
.table-image-cell__image--cover {
|
|
@@ -32,6 +32,14 @@ interface $$IsomorphicComponent {
|
|
|
32
32
|
}>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
|
|
33
33
|
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
34
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Image cell for table rows. Renders one of several image layouts depending on `column.format`.
|
|
37
|
+
*
|
|
38
|
+
* ### CSS Custom Properties
|
|
39
|
+
* | Property | Description | Default |
|
|
40
|
+
* |---|---|---|
|
|
41
|
+
* | `--sc-kit--table-image-cell--image--background` | Background behind a `square-contain` image (letterboxing) | `var(--sc-kit--color--bg--images-subtle)` |
|
|
42
|
+
*/
|
|
35
43
|
declare const TableImageCell: $$IsomorphicComponent;
|
|
36
44
|
type TableImageCell<T extends {
|
|
37
45
|
id: string;
|