@streamscloud/kit 0.54.1 → 0.55.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/dist/ui/player/buttons/cmp.mobile-player-buttons.svelte +30 -6
- package/dist/ui/player/buttons/cmp.mobile-player-buttons.svelte.d.ts +13 -4
- package/dist/ui/player/buttons/cmp.player-buttons.svelte +71 -20
- package/dist/ui/player/buttons/cmp.player-buttons.svelte.d.ts +12 -2
- package/dist/ui/player/buttons/cmp.responsive-player-buttons.svelte +12 -8
- package/dist/ui/player/buttons/cmp.responsive-player-buttons.svelte.d.ts +16 -6
- package/dist/ui/player/buttons/index.d.ts +1 -1
- package/dist/ui/player/buttons/player-buttons-localization.d.ts +3 -0
- package/dist/ui/player/buttons/player-buttons-localization.js +12 -0
- package/dist/ui/player/buttons/player-context-menu.svelte +20 -0
- package/dist/ui/player/buttons/player-context-menu.svelte.d.ts +9 -0
- package/dist/ui/player/buttons/types.d.ts +6 -0
- package/dist/ui/spinner/cmp.spinner.svelte +14 -7
- package/dist/ui/spinner/cmp.spinner.svelte.d.ts +6 -4
- package/package.json +1 -1
|
@@ -1,28 +1,42 @@
|
|
|
1
1
|
<script lang="ts">import { IconSlot } from '../../icon';
|
|
2
|
-
|
|
2
|
+
import PlayerContextMenu from './player-context-menu.svelte';
|
|
3
|
+
let { actions, contextActions = [], contextPosition = 'left-end' } = $props();
|
|
3
4
|
</script>
|
|
4
5
|
|
|
5
6
|
<div class="mobile-player-buttons">
|
|
6
|
-
{#each actions as action (
|
|
7
|
+
{#each actions as action, index (index)}
|
|
7
8
|
<button type="button" class="mobile-player-buttons__action" disabled={action.disabled} onclick={action.callback}>
|
|
8
9
|
<span class="mobile-player-buttons__action-icon">
|
|
9
10
|
<IconSlot icon={action.icon} />
|
|
10
11
|
</span>
|
|
11
12
|
</button>
|
|
12
13
|
{/each}
|
|
14
|
+
{#if contextActions.length}
|
|
15
|
+
<div class="mobile-player-buttons__action mobile-player-buttons__action--menu">
|
|
16
|
+
<PlayerContextMenu actions={contextActions} position={contextPosition} />
|
|
17
|
+
</div>
|
|
18
|
+
{/if}
|
|
13
19
|
</div>
|
|
14
20
|
|
|
15
21
|
<!--
|
|
16
22
|
@component
|
|
17
23
|
A vertically stacked column of player action buttons optimized for mobile touch targets.
|
|
24
|
+
`contextActions` appends an overflow-menu cell below the buttons.
|
|
18
25
|
|
|
19
|
-
###
|
|
20
|
-
|
|
|
26
|
+
### CSS Custom Properties
|
|
27
|
+
| Property | Description | Default |
|
|
21
28
|
|---|---|---|
|
|
22
|
-
| `
|
|
29
|
+
| `--sc-kit--player-button--color--inactive` | Overflow menu panel background | 60% opacity of `black` |
|
|
30
|
+
| `--sc-kit--player-button--menu--border-color` | Overflow menu panel border | `white` at 15% |
|
|
31
|
+
| `--sc-kit--player-button--menu--item--color` | Overflow menu row text / icon color | `--sc-kit--color--text--on-accent` |
|
|
32
|
+
| `--sc-kit--player-button--menu--item--background--hover` | Overflow menu row hover background | `white` at 12% |
|
|
23
33
|
-->
|
|
24
34
|
|
|
25
35
|
<style>.mobile-player-buttons {
|
|
36
|
+
--_player-button--color--inactive: var(--sc-kit--player-button--color--inactive, rgb(0 0 0 / 60%));
|
|
37
|
+
--_player-button--menu--border-color: var(--sc-kit--player-button--menu--border-color, rgb(255 255 255 / 15%));
|
|
38
|
+
--_player-button--menu--item-color: var(--sc-kit--player-button--menu--item--color, var(--sc-kit--color--text--on-accent));
|
|
39
|
+
--_player-button--menu--item-background-hover: var(--sc-kit--player-button--menu--item--background--hover, rgb(255 255 255 / 12%));
|
|
26
40
|
cursor: pointer;
|
|
27
41
|
display: flex;
|
|
28
42
|
flex-direction: column;
|
|
@@ -30,10 +44,11 @@ A vertically stacked column of player action buttons optimized for mobile touch
|
|
|
30
44
|
pointer-events: auto;
|
|
31
45
|
}
|
|
32
46
|
.mobile-player-buttons__action {
|
|
47
|
+
--_player-button--cell-padding: var(--sc-kit--space--4);
|
|
33
48
|
display: flex;
|
|
34
49
|
justify-content: center;
|
|
35
50
|
align-items: center;
|
|
36
|
-
padding: var(--
|
|
51
|
+
padding: var(--_player-button--cell-padding);
|
|
37
52
|
--sc-kit--icon--color: var(--sc-kit--color--text--on-accent);
|
|
38
53
|
--sc-kit--icon--size: 2rem;
|
|
39
54
|
--sc-kit--icon--filter: drop-shadow(1px 1px 0 rgba(0, 0, 0, 0.2));
|
|
@@ -42,6 +57,15 @@ A vertically stacked column of player action buttons optimized for mobile touch
|
|
|
42
57
|
opacity: 0.5;
|
|
43
58
|
cursor: default;
|
|
44
59
|
}
|
|
60
|
+
.mobile-player-buttons__action--menu {
|
|
61
|
+
padding: 0;
|
|
62
|
+
min-block-size: calc(var(--sc-kit--icon--size) + 2 * var(--_player-button--cell-padding));
|
|
63
|
+
min-inline-size: calc(var(--sc-kit--icon--size) + 2 * var(--_player-button--cell-padding));
|
|
64
|
+
--sc-kit--popover--content--background: var(--_player-button--color--inactive);
|
|
65
|
+
--sc-kit--popover--content--border-color: var(--_player-button--menu--border-color);
|
|
66
|
+
--sc-kit--popover-item--color: var(--_player-button--menu--item-color);
|
|
67
|
+
--sc-kit--popover-item--background--hover: var(--_player-button--menu--item-background-hover);
|
|
68
|
+
}
|
|
45
69
|
.mobile-player-buttons__action-icon {
|
|
46
70
|
display: block;
|
|
47
71
|
}</style>
|
|
@@ -1,14 +1,23 @@
|
|
|
1
|
-
import type { PlayerButtonDef } from './types';
|
|
1
|
+
import type { PlayerButtonDef, PlayerContextActionDef } from './types';
|
|
2
|
+
import type { Placement } from '@floating-ui/dom';
|
|
2
3
|
type Props = {
|
|
3
4
|
actions: PlayerButtonDef[];
|
|
5
|
+
/** Rows of an overflow menu rendered as the final cell — an ellipsis trigger opening a popover. Empty ⇒ no menu cell. @default [] */
|
|
6
|
+
contextActions?: PlayerContextActionDef[];
|
|
7
|
+
/** Floating UI placement of the overflow menu panel @default 'left-end' */
|
|
8
|
+
contextPosition?: Placement;
|
|
4
9
|
};
|
|
5
10
|
/**
|
|
6
11
|
* A vertically stacked column of player action buttons optimized for mobile touch targets.
|
|
12
|
+
* `contextActions` appends an overflow-menu cell below the buttons.
|
|
7
13
|
*
|
|
8
|
-
* ###
|
|
9
|
-
* |
|
|
14
|
+
* ### CSS Custom Properties
|
|
15
|
+
* | Property | Description | Default |
|
|
10
16
|
* |---|---|---|
|
|
11
|
-
* | `
|
|
17
|
+
* | `--sc-kit--player-button--color--inactive` | Overflow menu panel background | 60% opacity of `black` |
|
|
18
|
+
* | `--sc-kit--player-button--menu--border-color` | Overflow menu panel border | `white` at 15% |
|
|
19
|
+
* | `--sc-kit--player-button--menu--item--color` | Overflow menu row text / icon color | `--sc-kit--color--text--on-accent` |
|
|
20
|
+
* | `--sc-kit--player-button--menu--item--background--hover` | Overflow menu row hover background | `white` at 12% |
|
|
12
21
|
*/
|
|
13
22
|
declare const Cmp: import("svelte").Component<Props, {}, "">;
|
|
14
23
|
type Cmp = ReturnType<typeof Cmp>;
|
|
@@ -1,23 +1,32 @@
|
|
|
1
1
|
<script lang="ts">import { IconSlot } from '../../icon';
|
|
2
|
-
|
|
2
|
+
import PlayerContextMenu from './player-context-menu.svelte';
|
|
3
|
+
let { actions, contextActions = [], contextPosition = 'left-end', scaleEffect = false, zoom = 1 } = $props();
|
|
4
|
+
const hasMenu = $derived(contextActions.length > 0);
|
|
5
|
+
const cellCount = $derived(actions.length + (hasMenu ? 1 : 0));
|
|
3
6
|
</script>
|
|
4
7
|
|
|
5
|
-
{#if
|
|
6
|
-
{
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
{
|
|
8
|
+
{#if cellCount === 1}
|
|
9
|
+
{#if hasMenu}
|
|
10
|
+
<div class="player-button player-button--menu" style:zoom={zoom}>
|
|
11
|
+
<PlayerContextMenu actions={contextActions} position={contextPosition} />
|
|
12
|
+
</div>
|
|
13
|
+
{:else}
|
|
14
|
+
{@const action = actions[0]}
|
|
15
|
+
<button
|
|
16
|
+
type="button"
|
|
17
|
+
class="player-button"
|
|
18
|
+
style:zoom={zoom}
|
|
19
|
+
class:player-button--scale-effect={scaleEffect}
|
|
20
|
+
disabled={action.disabled}
|
|
21
|
+
onclick={action.callback}>
|
|
22
|
+
<span class="player-button__icon">
|
|
23
|
+
<IconSlot icon={action.icon} />
|
|
24
|
+
</span>
|
|
25
|
+
</button>
|
|
26
|
+
{/if}
|
|
27
|
+
{:else if cellCount > 1}
|
|
19
28
|
<div class="player-buttons" style:zoom={zoom}>
|
|
20
|
-
{#each actions as action (
|
|
29
|
+
{#each actions as action, index (index)}
|
|
21
30
|
<button
|
|
22
31
|
type="button"
|
|
23
32
|
class="player-buttons__action"
|
|
@@ -29,26 +38,40 @@ let { actions, scaleEffect = false, zoom = 1 } = $props();
|
|
|
29
38
|
</span>
|
|
30
39
|
</button>
|
|
31
40
|
{/each}
|
|
41
|
+
{#if hasMenu}
|
|
42
|
+
<div class="player-buttons__action player-buttons__action--menu">
|
|
43
|
+
<PlayerContextMenu actions={contextActions} position={contextPosition} />
|
|
44
|
+
</div>
|
|
45
|
+
{/if}
|
|
32
46
|
</div>
|
|
33
47
|
{/if}
|
|
34
48
|
|
|
35
49
|
<!--
|
|
36
50
|
@component
|
|
37
51
|
Desktop player action buttons — renders a single circular button or a vertically stacked pill for multiple actions.
|
|
52
|
+
`contextActions` adds an overflow-menu cell as the last item; it counts towards the single / pill split, so one
|
|
53
|
+
action plus a menu renders as a two-cell pill.
|
|
38
54
|
|
|
39
55
|
### CSS Custom Properties
|
|
40
56
|
| Property | Description | Default |
|
|
41
57
|
|---|---|---|
|
|
42
58
|
| `--sc-kit--player-button--color` | Button background at full opacity | `dark-500` / `black` at 95% |
|
|
43
|
-
| `--sc-kit--player-button--color--inactive` | Button background at rest | 60% opacity of `--color` |
|
|
59
|
+
| `--sc-kit--player-button--color--inactive` | Button background at rest — the overflow menu panel takes the same value | 60% opacity of `--color` |
|
|
60
|
+
| `--sc-kit--player-button--menu--border-color` | Overflow menu panel border | `white` at 15% |
|
|
61
|
+
| `--sc-kit--player-button--menu--item--color` | Overflow menu row text / icon color | `--sc-kit--color--text--on-accent` |
|
|
62
|
+
| `--sc-kit--player-button--menu--item--background--hover` | Overflow menu row hover background | `white` at 12% |
|
|
44
63
|
-->
|
|
45
64
|
|
|
46
65
|
<style>.player-button {
|
|
47
66
|
--_player-button--color: var(--sc-kit--player-button--color, rgb(0 0 0 / 95%));
|
|
48
67
|
--_player-button--color--inactive: var(--sc-kit--player-button--color--inactive, rgb(0 0 0 / 60%));
|
|
68
|
+
--_player-button--menu--border-color: var(--sc-kit--player-button--menu--border-color, rgb(255 255 255 / 15%));
|
|
69
|
+
--_player-button--menu--item-color: var(--sc-kit--player-button--menu--item--color, var(--sc-kit--color--text--on-accent));
|
|
70
|
+
--_player-button--menu--item-background-hover: var(--sc-kit--player-button--menu--item--background--hover, rgb(255 255 255 / 12%));
|
|
49
71
|
--_player-button--icon-scale: 1;
|
|
72
|
+
--_player-button--cell-padding: 0.625rem;
|
|
50
73
|
pointer-events: auto;
|
|
51
|
-
padding:
|
|
74
|
+
padding: var(--_player-button--cell-padding);
|
|
52
75
|
display: flex;
|
|
53
76
|
justify-content: center;
|
|
54
77
|
align-items: center;
|
|
@@ -69,6 +92,18 @@ Desktop player action buttons — renders a single circular button or a vertical
|
|
|
69
92
|
.player-button--scale-effect:hover:not(:disabled) {
|
|
70
93
|
--_player-button--icon-scale: 1.2;
|
|
71
94
|
}
|
|
95
|
+
.player-button--menu {
|
|
96
|
+
padding: 0;
|
|
97
|
+
min-block-size: calc(var(--sc-kit--icon--size) + 2 * var(--_player-button--cell-padding));
|
|
98
|
+
min-inline-size: calc(var(--sc-kit--icon--size) + 2 * var(--_player-button--cell-padding));
|
|
99
|
+
--sc-kit--popover--content--background: var(--_player-button--color--inactive);
|
|
100
|
+
--sc-kit--popover--content--border-color: var(--_player-button--menu--border-color);
|
|
101
|
+
--sc-kit--popover-item--color: var(--_player-button--menu--item-color);
|
|
102
|
+
--sc-kit--popover-item--background--hover: var(--_player-button--menu--item-background-hover);
|
|
103
|
+
}
|
|
104
|
+
.player-button--menu:hover:not(:disabled) {
|
|
105
|
+
background-color: var(--_player-button--color--inactive);
|
|
106
|
+
}
|
|
72
107
|
.player-button__icon {
|
|
73
108
|
display: block;
|
|
74
109
|
transform: scale(var(--_player-button--icon-scale));
|
|
@@ -79,7 +114,7 @@ Desktop player action buttons — renders a single circular button or a vertical
|
|
|
79
114
|
}
|
|
80
115
|
@container (width < 576px) {
|
|
81
116
|
.player-button {
|
|
82
|
-
padding: 0.5rem;
|
|
117
|
+
--_player-button--cell-padding: 0.5rem;
|
|
83
118
|
--sc-kit--icon--size: 1.5rem;
|
|
84
119
|
}
|
|
85
120
|
}
|
|
@@ -87,6 +122,9 @@ Desktop player action buttons — renders a single circular button or a vertical
|
|
|
87
122
|
.player-buttons {
|
|
88
123
|
--_player-button--color: var(--sc-kit--player-button--color, rgb(0 0 0 / 95%));
|
|
89
124
|
--_player-button--color--inactive: var(--sc-kit--player-button--color--inactive, rgb(0 0 0 / 60%));
|
|
125
|
+
--_player-button--menu--border-color: var(--sc-kit--player-button--menu--border-color, rgb(255 255 255 / 15%));
|
|
126
|
+
--_player-button--menu--item-color: var(--sc-kit--player-button--menu--item--color, var(--sc-kit--color--text--on-accent));
|
|
127
|
+
--_player-button--menu--item-background-hover: var(--sc-kit--player-button--menu--item--background--hover, rgb(255 255 255 / 12%));
|
|
90
128
|
cursor: pointer;
|
|
91
129
|
display: flex;
|
|
92
130
|
flex-direction: column;
|
|
@@ -98,10 +136,11 @@ Desktop player action buttons — renders a single circular button or a vertical
|
|
|
98
136
|
}
|
|
99
137
|
.player-buttons__action {
|
|
100
138
|
--_player-button--icon-scale: 1;
|
|
139
|
+
--_player-button--cell-padding: 0.5625rem;
|
|
101
140
|
display: flex;
|
|
102
141
|
justify-content: center;
|
|
103
142
|
align-items: center;
|
|
104
|
-
padding:
|
|
143
|
+
padding: var(--_player-button--cell-padding);
|
|
105
144
|
border-radius: 1.25rem;
|
|
106
145
|
color: var(--sc-kit--color--text--on-accent);
|
|
107
146
|
--sc-kit--icon--color: var(--sc-kit--color--text--on-accent);
|
|
@@ -119,6 +158,18 @@ Desktop player action buttons — renders a single circular button or a vertical
|
|
|
119
158
|
--_player-button--icon-scale: 1.2;
|
|
120
159
|
background-color: transparent;
|
|
121
160
|
}
|
|
161
|
+
.player-buttons__action--menu {
|
|
162
|
+
padding: 0;
|
|
163
|
+
min-block-size: calc(var(--sc-kit--icon--size) + 2 * var(--_player-button--cell-padding));
|
|
164
|
+
min-inline-size: calc(var(--sc-kit--icon--size) + 2 * var(--_player-button--cell-padding));
|
|
165
|
+
--sc-kit--popover--content--background: var(--_player-button--color--inactive);
|
|
166
|
+
--sc-kit--popover--content--border-color: var(--_player-button--menu--border-color);
|
|
167
|
+
--sc-kit--popover-item--color: var(--_player-button--menu--item-color);
|
|
168
|
+
--sc-kit--popover-item--background--hover: var(--_player-button--menu--item-background-hover);
|
|
169
|
+
}
|
|
170
|
+
.player-buttons__action--menu:hover:not(:disabled) {
|
|
171
|
+
background-color: transparent;
|
|
172
|
+
}
|
|
122
173
|
.player-buttons__action-icon {
|
|
123
174
|
display: block;
|
|
124
175
|
transform: scale(var(--_player-button--icon-scale));
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
import type { PlayerButtonDef } from './types';
|
|
1
|
+
import type { PlayerButtonDef, PlayerContextActionDef } from './types';
|
|
2
|
+
import type { Placement } from '@floating-ui/dom';
|
|
2
3
|
type Props = {
|
|
3
4
|
/** Array of button definitions (icon, callback, disabled state) */
|
|
4
5
|
actions: PlayerButtonDef[];
|
|
6
|
+
/** Rows of an overflow menu rendered as the final cell — an ellipsis trigger opening a popover. Empty ⇒ no menu cell. @default [] */
|
|
7
|
+
contextActions?: PlayerContextActionDef[];
|
|
8
|
+
/** Floating UI placement of the overflow menu panel @default 'left-end' */
|
|
9
|
+
contextPosition?: Placement;
|
|
5
10
|
/** Scale the icon on hover */
|
|
6
11
|
scaleEffect?: boolean;
|
|
7
12
|
/** CSS zoom level applied to the button container @default 1 */
|
|
@@ -9,12 +14,17 @@ type Props = {
|
|
|
9
14
|
};
|
|
10
15
|
/**
|
|
11
16
|
* Desktop player action buttons — renders a single circular button or a vertically stacked pill for multiple actions.
|
|
17
|
+
* `contextActions` adds an overflow-menu cell as the last item; it counts towards the single / pill split, so one
|
|
18
|
+
* action plus a menu renders as a two-cell pill.
|
|
12
19
|
*
|
|
13
20
|
* ### CSS Custom Properties
|
|
14
21
|
* | Property | Description | Default |
|
|
15
22
|
* |---|---|---|
|
|
16
23
|
* | `--sc-kit--player-button--color` | Button background at full opacity | `dark-500` / `black` at 95% |
|
|
17
|
-
* | `--sc-kit--player-button--color--inactive` | Button background at rest | 60% opacity of `--color` |
|
|
24
|
+
* | `--sc-kit--player-button--color--inactive` | Button background at rest — the overflow menu panel takes the same value | 60% opacity of `--color` |
|
|
25
|
+
* | `--sc-kit--player-button--menu--border-color` | Overflow menu panel border | `white` at 15% |
|
|
26
|
+
* | `--sc-kit--player-button--menu--item--color` | Overflow menu row text / icon color | `--sc-kit--color--text--on-accent` |
|
|
27
|
+
* | `--sc-kit--player-button--menu--item--background--hover` | Overflow menu row hover background | `white` at 12% |
|
|
18
28
|
*/
|
|
19
29
|
declare const Cmp: import("svelte").Component<Props, {}, "">;
|
|
20
30
|
type Cmp = ReturnType<typeof Cmp>;
|
|
@@ -1,25 +1,29 @@
|
|
|
1
1
|
<script lang="ts">import { default as MobilePlayerButtons } from './cmp.mobile-player-buttons.svelte';
|
|
2
2
|
import { default as PlayerButtons } from './cmp.player-buttons.svelte';
|
|
3
|
-
let { scaleEffect = false, actions } = $props();
|
|
3
|
+
let { scaleEffect = false, actions, contextActions = [], contextPosition = 'left-end' } = $props();
|
|
4
4
|
</script>
|
|
5
5
|
|
|
6
6
|
<div class="desktop-controls">
|
|
7
|
-
<PlayerButtons actions={actions} scaleEffect={scaleEffect} />
|
|
7
|
+
<PlayerButtons actions={actions} contextActions={contextActions} contextPosition={contextPosition} scaleEffect={scaleEffect} />
|
|
8
8
|
</div>
|
|
9
9
|
|
|
10
10
|
<div class="mobile-controls">
|
|
11
|
-
<MobilePlayerButtons actions={actions} />
|
|
11
|
+
<MobilePlayerButtons actions={actions} contextActions={contextActions} contextPosition={contextPosition} />
|
|
12
12
|
</div>
|
|
13
13
|
|
|
14
14
|
<!--
|
|
15
15
|
@component
|
|
16
16
|
Renders `PlayerButtons` on desktop and `MobilePlayerButtons` on mobile, switching via container query.
|
|
17
|
+
Both branches stay mounted, so `contextActions` builds a menu in each; only the visible one is reachable.
|
|
17
18
|
|
|
18
|
-
###
|
|
19
|
-
|
|
|
20
|
-
|
|
21
|
-
| `
|
|
22
|
-
| `
|
|
19
|
+
### CSS Custom Properties
|
|
20
|
+
| Property | Description | Default |
|
|
21
|
+
|---|---|---|
|
|
22
|
+
| `--sc-kit--player-button--color` | Button background at full opacity (desktop only — the mobile column paints no button background) | `black` at 95% |
|
|
23
|
+
| `--sc-kit--player-button--color--inactive` | Button background at rest — the overflow menu panel takes the same value | 60% opacity of `--color` |
|
|
24
|
+
| `--sc-kit--player-button--menu--border-color` | Overflow menu panel border | `white` at 15% |
|
|
25
|
+
| `--sc-kit--player-button--menu--item--color` | Overflow menu row text / icon color | `--sc-kit--color--text--on-accent` |
|
|
26
|
+
| `--sc-kit--player-button--menu--item--background--hover` | Overflow menu row hover background | `white` at 12% |
|
|
23
27
|
-->
|
|
24
28
|
|
|
25
29
|
<style>.desktop-controls {
|
|
@@ -1,16 +1,26 @@
|
|
|
1
|
-
import type { PlayerButtonDef } from './types';
|
|
1
|
+
import type { PlayerButtonDef, PlayerContextActionDef } from './types';
|
|
2
|
+
import type { Placement } from '@floating-ui/dom';
|
|
2
3
|
type Props = {
|
|
3
4
|
actions: PlayerButtonDef[];
|
|
5
|
+
/** Rows of an overflow menu rendered as the final cell — an ellipsis trigger opening a popover. Empty ⇒ no menu cell. @default [] */
|
|
6
|
+
contextActions?: PlayerContextActionDef[];
|
|
7
|
+
/** Floating UI placement of the overflow menu panel @default 'left-end' */
|
|
8
|
+
contextPosition?: Placement;
|
|
9
|
+
/** Scale the icon on hover (desktop only) */
|
|
4
10
|
scaleEffect?: boolean;
|
|
5
11
|
};
|
|
6
12
|
/**
|
|
7
13
|
* Renders `PlayerButtons` on desktop and `MobilePlayerButtons` on mobile, switching via container query.
|
|
14
|
+
* Both branches stay mounted, so `contextActions` builds a menu in each; only the visible one is reachable.
|
|
8
15
|
*
|
|
9
|
-
* ###
|
|
10
|
-
* |
|
|
11
|
-
*
|
|
12
|
-
* | `
|
|
13
|
-
* | `
|
|
16
|
+
* ### CSS Custom Properties
|
|
17
|
+
* | Property | Description | Default |
|
|
18
|
+
* |---|---|---|
|
|
19
|
+
* | `--sc-kit--player-button--color` | Button background at full opacity (desktop only — the mobile column paints no button background) | `black` at 95% |
|
|
20
|
+
* | `--sc-kit--player-button--color--inactive` | Button background at rest — the overflow menu panel takes the same value | 60% opacity of `--color` |
|
|
21
|
+
* | `--sc-kit--player-button--menu--border-color` | Overflow menu panel border | `white` at 15% |
|
|
22
|
+
* | `--sc-kit--player-button--menu--item--color` | Overflow menu row text / icon color | `--sc-kit--color--text--on-accent` |
|
|
23
|
+
* | `--sc-kit--player-button--menu--item--background--hover` | Overflow menu row hover background | `white` at 12% |
|
|
14
24
|
*/
|
|
15
25
|
declare const Cmp: import("svelte").Component<Props, {}, "">;
|
|
16
26
|
type Cmp = ReturnType<typeof Cmp>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { default as MobilePlayerButtons } from './cmp.mobile-player-buttons.svelte';
|
|
2
2
|
export { default as PlayerButtons } from './cmp.player-buttons.svelte';
|
|
3
3
|
export { default as ResponsivePlayerButtons } from './cmp.responsive-player-buttons.svelte';
|
|
4
|
-
export type { PlayerButtonDef } from './types';
|
|
4
|
+
export type { PlayerButtonDef, PlayerContextActionDef } from './types';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { AppLocale } from '../../../core/locale';
|
|
2
|
+
const loc = {
|
|
3
|
+
moreActions: {
|
|
4
|
+
en: 'More actions',
|
|
5
|
+
no: 'Flere handlinger'
|
|
6
|
+
}
|
|
7
|
+
};
|
|
8
|
+
export class PlayerButtonsLocalization {
|
|
9
|
+
get moreActions() {
|
|
10
|
+
return loc.moreActions[AppLocale.current];
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<script lang="ts">import { IconSlot } from '../../icon';
|
|
2
|
+
import { IconText } from '../../icon-text';
|
|
3
|
+
import { Popover, PopoverItem } from '../../popover';
|
|
4
|
+
import { PlayerButtonsLocalization } from './player-buttons-localization';
|
|
5
|
+
import IconMoreVertical from '@fluentui/svg-icons/icons/more_vertical_28_regular.svg?raw';
|
|
6
|
+
let { actions, position = 'left-end' } = $props();
|
|
7
|
+
const localization = new PlayerButtonsLocalization();
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<Popover position={position} fixedPosition fillContainer aria-label={localization.moreActions}>
|
|
11
|
+
{#snippet trigger()}
|
|
12
|
+
<IconSlot icon={IconMoreVertical} />
|
|
13
|
+
{/snippet}
|
|
14
|
+
|
|
15
|
+
{#each actions as action (action.label)}
|
|
16
|
+
<PopoverItem disabled={action.disabled} on={{ click: action.callback }}>
|
|
17
|
+
<IconText icon={action.icon} size="sm">{action.label}</IconText>
|
|
18
|
+
</PopoverItem>
|
|
19
|
+
{/each}
|
|
20
|
+
</Popover>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { PlayerContextActionDef } from './types';
|
|
2
|
+
import type { Placement } from '@floating-ui/dom';
|
|
3
|
+
type Props = {
|
|
4
|
+
actions: PlayerContextActionDef[];
|
|
5
|
+
position?: Placement;
|
|
6
|
+
};
|
|
7
|
+
declare const PlayerContextMenu: import("svelte").Component<Props, {}, "">;
|
|
8
|
+
type PlayerContextMenu = ReturnType<typeof PlayerContextMenu>;
|
|
9
|
+
export default PlayerContextMenu;
|
|
@@ -12,11 +12,11 @@ $effect(() => {
|
|
|
12
12
|
});
|
|
13
13
|
</script>
|
|
14
14
|
|
|
15
|
-
{#if
|
|
16
|
-
{
|
|
17
|
-
|
|
18
|
-
{/if}
|
|
15
|
+
{#if blocking}
|
|
16
|
+
<div class="spinner-overlay" class:spinner-overlay--fixed={position === 'fixed-center'} class:spinner-overlay--dimmed={visible}></div>
|
|
17
|
+
{/if}
|
|
19
18
|
|
|
19
|
+
{#if visible}
|
|
20
20
|
<span
|
|
21
21
|
class="spinner spinner--{size}"
|
|
22
22
|
class:spinner--accent={color === 'accent'}
|
|
@@ -41,7 +41,9 @@ $effect(() => {
|
|
|
41
41
|
@component
|
|
42
42
|
Spinner — indeterminate loading indicator. Single-arc circle rotating at a constant rate. Color preset (`accent` default) resolves to a semantic token; override the public CSS vars on any ancestor for global theming. Pass `label` to expose it to screen readers as a live status region.
|
|
43
43
|
|
|
44
|
-
Convenience props for the common "load happens, show a centered spinner with optional dimmer" pattern: `position` centers it within the nearest positioned ancestor (`absolute-center`) or the viewport (`fixed-center`); `blocking` adds
|
|
44
|
+
Convenience props for the common "load happens, show a centered spinner with optional dimmer" pattern: `position` centers it within the nearest positioned ancestor (`absolute-center`) or the viewport (`fixed-center`); `blocking` adds an overlay; `timeout` delays visibility to avoid flicker for fast operations.
|
|
45
|
+
|
|
46
|
+
`blocking` and `timeout` are orthogonal. The overlay mounts with the component and swallows pointer input from the first millisecond regardless of `timeout`; once `timeout` elapses the spinner appears and the overlay fades to its dim background. Pointer input only — a focused control underneath still reacts to the keyboard; wrap the region in `inert` if that matters.
|
|
45
47
|
|
|
46
48
|
For tight inline glyphs inside other kit cmps (Button loading state, async Select), use the internal `_internal/spinner` instead — that one fills its inline box and inherits `currentColor` for stroke.
|
|
47
49
|
|
|
@@ -58,7 +60,7 @@ For tight inline glyphs inside other kit cmps (Button loading state, async Selec
|
|
|
58
60
|
| `--sc-kit--spinner--color-text` | Color for `text` preset | `--sc-kit--color--text--primary` |
|
|
59
61
|
| `--sc-kit--spinner--color-on-accent` | Color for `on-accent` preset | `--sc-kit--color--text--on-accent` |
|
|
60
62
|
| `--sc-kit--spinner--duration` | Rotation duration | `1.6s` |
|
|
61
|
-
| `--sc-kit--spinner--overlay--background` | Backdrop color
|
|
63
|
+
| `--sc-kit--spinner--overlay--background` | Backdrop color the `blocking` overlay fades to once the spinner shows | `rgba(0, 0, 0, 0.3)` |
|
|
62
64
|
| `--sc-kit--spinner--overlay--z-index` | Backdrop stacking | `--sc-kit--z-index--popover` minus 1 |
|
|
63
65
|
|
|
64
66
|
### Size presets
|
|
@@ -74,12 +76,17 @@ For tight inline glyphs inside other kit cmps (Button loading state, async Selec
|
|
|
74
76
|
--_overlay--z-index: var(--sc-kit--spinner--overlay--z-index, calc(var(--sc-kit--z-index--popover) - 1));
|
|
75
77
|
position: absolute;
|
|
76
78
|
inset: 0;
|
|
77
|
-
background: var(--_overlay--background);
|
|
79
|
+
background-color: var(--_overlay--background);
|
|
80
|
+
opacity: 0;
|
|
78
81
|
z-index: var(--_overlay--z-index);
|
|
82
|
+
transition: opacity var(--sc-kit--duration--base) var(--sc-kit--ease--default);
|
|
79
83
|
}
|
|
80
84
|
.spinner-overlay--fixed {
|
|
81
85
|
position: fixed;
|
|
82
86
|
}
|
|
87
|
+
.spinner-overlay--dimmed {
|
|
88
|
+
opacity: 1;
|
|
89
|
+
}
|
|
83
90
|
|
|
84
91
|
.spinner {
|
|
85
92
|
--_spinner--size: var(--sc-kit--spinner--size, 1.25rem);
|
|
@@ -7,15 +7,17 @@ type Props = {
|
|
|
7
7
|
label?: string;
|
|
8
8
|
/** Centering mode. `absolute-center` centers within the closest positioned ancestor; `fixed-center` centers in the viewport. Omit for an inline-flex glyph at the current position. */
|
|
9
9
|
position?: 'absolute-center' | 'fixed-center';
|
|
10
|
-
/** Renders
|
|
10
|
+
/** Renders an overlay that swallows pointer input immediately, independent of `timeout`; it stays invisible until `timeout` elapses, then fades to its dim background. Pair with `position` for a full-area dimmer. */
|
|
11
11
|
blocking?: boolean;
|
|
12
|
-
/** Delay in ms before the spinner becomes visible (and
|
|
12
|
+
/** Delay in ms before the spinner becomes visible (and a `blocking` overlay dims). Prevents flicker for fast operations. @default 0 */
|
|
13
13
|
timeout?: number;
|
|
14
14
|
};
|
|
15
15
|
/**
|
|
16
16
|
* Spinner — indeterminate loading indicator. Single-arc circle rotating at a constant rate. Color preset (`accent` default) resolves to a semantic token; override the public CSS vars on any ancestor for global theming. Pass `label` to expose it to screen readers as a live status region.
|
|
17
17
|
*
|
|
18
|
-
* Convenience props for the common "load happens, show a centered spinner with optional dimmer" pattern: `position` centers it within the nearest positioned ancestor (`absolute-center`) or the viewport (`fixed-center`); `blocking` adds
|
|
18
|
+
* Convenience props for the common "load happens, show a centered spinner with optional dimmer" pattern: `position` centers it within the nearest positioned ancestor (`absolute-center`) or the viewport (`fixed-center`); `blocking` adds an overlay; `timeout` delays visibility to avoid flicker for fast operations.
|
|
19
|
+
*
|
|
20
|
+
* `blocking` and `timeout` are orthogonal. The overlay mounts with the component and swallows pointer input from the first millisecond regardless of `timeout`; once `timeout` elapses the spinner appears and the overlay fades to its dim background. Pointer input only — a focused control underneath still reacts to the keyboard; wrap the region in `inert` if that matters.
|
|
19
21
|
*
|
|
20
22
|
* For tight inline glyphs inside other kit cmps (Button loading state, async Select), use the internal `_internal/spinner` instead — that one fills its inline box and inherits `currentColor` for stroke.
|
|
21
23
|
*
|
|
@@ -32,7 +34,7 @@ type Props = {
|
|
|
32
34
|
* | `--sc-kit--spinner--color-text` | Color for `text` preset | `--sc-kit--color--text--primary` |
|
|
33
35
|
* | `--sc-kit--spinner--color-on-accent` | Color for `on-accent` preset | `--sc-kit--color--text--on-accent` |
|
|
34
36
|
* | `--sc-kit--spinner--duration` | Rotation duration | `1.6s` |
|
|
35
|
-
* | `--sc-kit--spinner--overlay--background` | Backdrop color
|
|
37
|
+
* | `--sc-kit--spinner--overlay--background` | Backdrop color the `blocking` overlay fades to once the spinner shows | `rgba(0, 0, 0, 0.3)` |
|
|
36
38
|
* | `--sc-kit--spinner--overlay--z-index` | Backdrop stacking | `--sc-kit--z-index--popover` minus 1 |
|
|
37
39
|
*
|
|
38
40
|
* ### Size presets
|