@threadlabs/looma 0.10.9 → 0.10.11
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/components/ui-dialog/ui-dialog.html +17 -0
- package/components/ui-editor-mention-menu/ui-editor-mention-menu.html +17 -0
- package/components/ui-editor-slash-menu/ui-editor-slash-menu.html +17 -0
- package/components/ui-editor-toolbar/ui-editor-toolbar.html +24 -43
- package/components/ui-reel/ui-reel.html +24 -0
- package/components/ui-scroll-area/ui-scroll-area.html +56 -0
- package/components/ui-search-shell/ui-search-shell.html +17 -0
- package/components/ui-sidebar/ui-sidebar.html +18 -0
- package/components/ui-tree-item/ui-tree-item.html +39 -29
- package/components/ui-tree-item/ui-tree-item.js +17 -11
- package/dist/index.js +19 -20
- package/package.json +1 -1
- package/styles/ui-dialog.css +17 -0
- package/styles/ui-editor-mention-menu.css +17 -0
- package/styles/ui-editor-slash-menu.css +17 -0
- package/styles/ui-editor-toolbar.css +25 -42
- package/styles/ui-reel.css +27 -1
- package/styles/ui-scroll-area.css +57 -0
- package/styles/ui-search-shell.css +17 -0
- package/styles/ui-sidebar.css +22 -1
- package/styles/ui-tree-item.css +44 -32
- package/tokens.css +44 -0
- package/vanilla/UiEditorToolbar.js +1 -3
- package/vanilla/UiScrollArea.d.ts +14 -0
- package/vanilla/UiScrollArea.js +28 -0
- package/vanilla/UiTreeItem.js +1 -1
- package/vanilla/index.js +1 -0
- package/vue/UiDialog.vue +21 -0
- package/vue/UiEditorMentionMenu.vue +21 -0
- package/vue/UiEditorSlashMenu.vue +21 -0
- package/vue/UiEditorToolbar.vue +26 -57
- package/vue/UiReel.vue +28 -0
- package/vue/UiScrollArea.d.ts +18 -0
- package/vue/UiScrollArea.js +2 -0
- package/vue/UiScrollArea.vue +85 -0
- package/vue/UiSearchShell.vue +21 -0
- package/vue/UiSidebar.vue +22 -0
- package/vue/UiTreeItem.vue +49 -29
- package/vue/chunks/UiDialog.js +1 -1
- package/vue/chunks/UiEditorMentionMenu.js +1 -1
- package/vue/chunks/UiEditorSlashMenu.js +1 -1
- package/vue/chunks/UiEditorToolbar.js +5 -29
- package/vue/chunks/UiReel.js +1 -1
- package/vue/chunks/UiScrollArea.js +21 -0
- package/vue/chunks/UiSearchShell.js +1 -1
- package/vue/chunks/UiSidebar.js +1 -1
- package/vue/chunks/UiTreeItem.js +15 -5
- package/vue/components.css +438 -248
- package/vue/index.d.ts +1 -0
- package/vue/index.js +2 -1
- package/components/ui-editor-toolbar/ui-editor-toolbar.js +0 -24
|
@@ -146,6 +146,23 @@
|
|
|
146
146
|
overflow: auto;
|
|
147
147
|
overscroll-behavior: contain;
|
|
148
148
|
padding: var(--ui-space-5);
|
|
149
|
+
/* Each edge that hides content fades: the scroll fade every Looma scroller uses (see ui-scroll-area). */
|
|
150
|
+
--_ui-scroll-fade-direction: to bottom;
|
|
151
|
+
--_ui-scroll-fade-size: var(--ui-scroll-fade-size, 24px);
|
|
152
|
+
mask-image: linear-gradient(
|
|
153
|
+
var(--_ui-scroll-fade-direction),
|
|
154
|
+
transparent,
|
|
155
|
+
#000 var(--_ui-scroll-fade-start),
|
|
156
|
+
#000 calc(100% - var(--_ui-scroll-fade-end)),
|
|
157
|
+
transparent
|
|
158
|
+
);
|
|
159
|
+
animation: ui-scroll-fade-start linear, ui-scroll-fade-start-hold linear, ui-scroll-fade-end-hold linear, ui-scroll-fade-end linear;
|
|
160
|
+
animation-timeline: scroll(self block);
|
|
161
|
+
animation-range:
|
|
162
|
+
0 var(--_ui-scroll-fade-size),
|
|
163
|
+
var(--_ui-scroll-fade-size) calc(100% + 1px),
|
|
164
|
+
-1px calc(100% - var(--_ui-scroll-fade-size)),
|
|
165
|
+
calc(100% - var(--_ui-scroll-fade-size)) 100%;
|
|
149
166
|
}
|
|
150
167
|
|
|
151
168
|
footer {
|
|
@@ -82,6 +82,23 @@
|
|
|
82
82
|
overflow-y: auto;
|
|
83
83
|
overscroll-behavior: contain;
|
|
84
84
|
list-style: none;
|
|
85
|
+
/* Each edge that hides content fades: the scroll fade every Looma scroller uses (see ui-scroll-area). */
|
|
86
|
+
--_ui-scroll-fade-direction: to bottom;
|
|
87
|
+
--_ui-scroll-fade-size: var(--ui-scroll-fade-size, 24px);
|
|
88
|
+
mask-image: linear-gradient(
|
|
89
|
+
var(--_ui-scroll-fade-direction),
|
|
90
|
+
transparent,
|
|
91
|
+
#000 var(--_ui-scroll-fade-start),
|
|
92
|
+
#000 calc(100% - var(--_ui-scroll-fade-end)),
|
|
93
|
+
transparent
|
|
94
|
+
);
|
|
95
|
+
animation: ui-scroll-fade-start linear, ui-scroll-fade-start-hold linear, ui-scroll-fade-end-hold linear, ui-scroll-fade-end linear;
|
|
96
|
+
animation-timeline: scroll(self block);
|
|
97
|
+
animation-range:
|
|
98
|
+
0 var(--_ui-scroll-fade-size),
|
|
99
|
+
var(--_ui-scroll-fade-size) calc(100% + 1px),
|
|
100
|
+
-1px calc(100% - var(--_ui-scroll-fade-size)),
|
|
101
|
+
calc(100% - var(--_ui-scroll-fade-size)) 100%;
|
|
85
102
|
}
|
|
86
103
|
|
|
87
104
|
.item {
|
|
@@ -90,6 +90,23 @@
|
|
|
90
90
|
overflow-y: auto;
|
|
91
91
|
max-height: 280px;
|
|
92
92
|
overscroll-behavior: contain;
|
|
93
|
+
/* Each edge that hides content fades: the scroll fade every Looma scroller uses (see ui-scroll-area). */
|
|
94
|
+
--_ui-scroll-fade-direction: to bottom;
|
|
95
|
+
--_ui-scroll-fade-size: var(--ui-scroll-fade-size, 24px);
|
|
96
|
+
mask-image: linear-gradient(
|
|
97
|
+
var(--_ui-scroll-fade-direction),
|
|
98
|
+
transparent,
|
|
99
|
+
#000 var(--_ui-scroll-fade-start),
|
|
100
|
+
#000 calc(100% - var(--_ui-scroll-fade-end)),
|
|
101
|
+
transparent
|
|
102
|
+
);
|
|
103
|
+
animation: ui-scroll-fade-start linear, ui-scroll-fade-start-hold linear, ui-scroll-fade-end-hold linear, ui-scroll-fade-end linear;
|
|
104
|
+
animation-timeline: scroll(self block);
|
|
105
|
+
animation-range:
|
|
106
|
+
0 var(--_ui-scroll-fade-size),
|
|
107
|
+
var(--_ui-scroll-fade-size) calc(100% + 1px),
|
|
108
|
+
-1px calc(100% - var(--_ui-scroll-fade-size)),
|
|
109
|
+
calc(100% - var(--_ui-scroll-fade-size)) 100%;
|
|
93
110
|
}
|
|
94
111
|
|
|
95
112
|
@media (max-width: 767px) {
|
|
@@ -1,15 +1,10 @@
|
|
|
1
|
-
<template component="ui-editor-toolbar"
|
|
1
|
+
<template component="ui-editor-toolbar">
|
|
2
2
|
<defs>
|
|
3
3
|
<prop name="floating" type="boolean" default="false">Shows the toolbar as a floating bar beside the selection rather than pinned to the editor.</prop>
|
|
4
|
-
<state name="overflowStart" :value="false"></state>
|
|
5
|
-
<state name="overflowEnd" :value="false"></state>
|
|
6
4
|
</defs>
|
|
7
5
|
<div role="toolbar" aria-label="Editor toolbar"><div class="strip" $ref="strip"><slot></slot></div></div>
|
|
8
6
|
<style>
|
|
9
7
|
:host {
|
|
10
|
-
/* The colour the edge fades blend into: whatever the toolbar is painted with. */
|
|
11
|
-
--_matte: var(--ui-editor-toolbar-surface, var(--ui-surface));
|
|
12
|
-
|
|
13
8
|
position: sticky;
|
|
14
9
|
top: 0;
|
|
15
10
|
z-index: var(--ui-editor-toolbar-z-index, 10);
|
|
@@ -44,41 +39,29 @@
|
|
|
44
39
|
flex: 0 0 auto;
|
|
45
40
|
}
|
|
46
41
|
|
|
47
|
-
/* The fades are
|
|
48
|
-
toolbar's border and shadow stay whole.
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
:host:dir(rtl)::before {
|
|
72
|
-
background: linear-gradient(to left, var(--_matte), transparent);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
:host:dir(rtl)::after {
|
|
76
|
-
background: linear-gradient(to right, var(--_matte), transparent);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
:host-state([overflowStart])::before,
|
|
80
|
-
:host-state([overflowEnd])::after {
|
|
81
|
-
opacity: 1;
|
|
42
|
+
/* The edge fades are the scroll fade every Looma scroller uses (see ui-scroll-area), a mask on the
|
|
43
|
+
strip, so a floating toolbar's border and shadow stay whole. */
|
|
44
|
+
.strip {
|
|
45
|
+
--_ui-scroll-fade-direction: to right;
|
|
46
|
+
--_ui-scroll-fade-size: var(--ui-editor-toolbar-fade-size, var(--ui-scroll-fade-size, 24px));
|
|
47
|
+
mask-image: linear-gradient(
|
|
48
|
+
var(--_ui-scroll-fade-direction),
|
|
49
|
+
transparent,
|
|
50
|
+
#000 var(--_ui-scroll-fade-start),
|
|
51
|
+
#000 calc(100% - var(--_ui-scroll-fade-end)),
|
|
52
|
+
transparent
|
|
53
|
+
);
|
|
54
|
+
animation: ui-scroll-fade-start linear, ui-scroll-fade-start-hold linear, ui-scroll-fade-end-hold linear, ui-scroll-fade-end linear;
|
|
55
|
+
animation-timeline: scroll(self inline);
|
|
56
|
+
animation-range:
|
|
57
|
+
0 var(--_ui-scroll-fade-size),
|
|
58
|
+
var(--_ui-scroll-fade-size) calc(100% + 1px),
|
|
59
|
+
-1px calc(100% - var(--_ui-scroll-fade-size)),
|
|
60
|
+
calc(100% - var(--_ui-scroll-fade-size)) 100%;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
:host:dir(rtl) .strip {
|
|
64
|
+
--_ui-scroll-fade-direction: to left;
|
|
82
65
|
}
|
|
83
66
|
|
|
84
67
|
:slotted(.divider) {
|
|
@@ -128,8 +111,6 @@
|
|
|
128
111
|
|
|
129
112
|
/* Inside LoomaEditor's sticky shell, the shell is the sticky surface. */
|
|
130
113
|
.looma-editor__sticky-toolbar-shell :host {
|
|
131
|
-
--_matte: var(--ui-editor-toolbar-surface, var(--ui-surface));
|
|
132
|
-
|
|
133
114
|
position: relative;
|
|
134
115
|
min-height: var(--ui-editor-toolbar-min-height, 48px);
|
|
135
116
|
background: transparent;
|
|
@@ -26,6 +26,30 @@
|
|
|
26
26
|
overscroll-behavior-inline: contain;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
/* Each end that hides items fades: the scroll fade every Looma scroller uses (see ui-scroll-area). */
|
|
30
|
+
:host {
|
|
31
|
+
--_ui-scroll-fade-direction: to right;
|
|
32
|
+
--_ui-scroll-fade-size: var(--ui-scroll-fade-size, 24px);
|
|
33
|
+
mask-image: linear-gradient(
|
|
34
|
+
var(--_ui-scroll-fade-direction),
|
|
35
|
+
transparent,
|
|
36
|
+
#000 var(--_ui-scroll-fade-start),
|
|
37
|
+
#000 calc(100% - var(--_ui-scroll-fade-end)),
|
|
38
|
+
transparent
|
|
39
|
+
);
|
|
40
|
+
animation: ui-scroll-fade-start linear, ui-scroll-fade-start-hold linear, ui-scroll-fade-end-hold linear, ui-scroll-fade-end linear;
|
|
41
|
+
animation-timeline: scroll(self inline);
|
|
42
|
+
animation-range:
|
|
43
|
+
0 var(--_ui-scroll-fade-size),
|
|
44
|
+
var(--_ui-scroll-fade-size) calc(100% + 1px),
|
|
45
|
+
-1px calc(100% - var(--_ui-scroll-fade-size)),
|
|
46
|
+
calc(100% - var(--_ui-scroll-fade-size)) 100%;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
:host:dir(rtl) {
|
|
50
|
+
--_ui-scroll-fade-direction: to left;
|
|
51
|
+
}
|
|
52
|
+
|
|
29
53
|
:host > :slotted(*) {
|
|
30
54
|
min-inline-size: 0;
|
|
31
55
|
flex: 0 0 var(--ui-reel-item-width, var(--_reel-item-width));
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<template component="ui-scroll-area">
|
|
2
|
+
<defs>
|
|
3
|
+
<prop name="orientation" type="vertical | horizontal" default="vertical"
|
|
4
|
+
>The direction the content scrolls. Vertical scrolls up and down and clips sideways overflow; horizontal scrolls sideways and clips vertical
|
|
5
|
+
overflow.</prop>
|
|
6
|
+
</defs>
|
|
7
|
+
<div><slot></slot></div>
|
|
8
|
+
<style>
|
|
9
|
+
/* A region that scrolls when its content outgrows it. Each edge that hides content fades, growing
|
|
10
|
+
in as the content leaves that edge (the scroll fade in tokens.css), so the reader can tell there
|
|
11
|
+
is more; an edge with nothing past it stays crisp, and content that fits shows no fade. The
|
|
12
|
+
fade is a mask, so it blends into whatever is behind the area without knowing its colour. */
|
|
13
|
+
:host {
|
|
14
|
+
display: block;
|
|
15
|
+
box-sizing: border-box;
|
|
16
|
+
min-block-size: 0;
|
|
17
|
+
min-inline-size: 0;
|
|
18
|
+
overflow-x: hidden;
|
|
19
|
+
overflow-y: auto;
|
|
20
|
+
overscroll-behavior: contain;
|
|
21
|
+
--_ui-scroll-fade-direction: to bottom;
|
|
22
|
+
--_ui-scroll-fade-inline: to right;
|
|
23
|
+
--_ui-scroll-fade-size: var(--ui-scroll-fade-size, 24px);
|
|
24
|
+
mask-image: linear-gradient(
|
|
25
|
+
var(--_ui-scroll-fade-direction),
|
|
26
|
+
transparent,
|
|
27
|
+
#000 var(--_ui-scroll-fade-start),
|
|
28
|
+
#000 calc(100% - var(--_ui-scroll-fade-end)),
|
|
29
|
+
transparent
|
|
30
|
+
);
|
|
31
|
+
animation: ui-scroll-fade-start linear, ui-scroll-fade-start-hold linear, ui-scroll-fade-end-hold linear, ui-scroll-fade-end linear;
|
|
32
|
+
animation-timeline: scroll(self block);
|
|
33
|
+
animation-range:
|
|
34
|
+
0 var(--_ui-scroll-fade-size),
|
|
35
|
+
var(--_ui-scroll-fade-size) calc(100% + 1px),
|
|
36
|
+
-1px calc(100% - var(--_ui-scroll-fade-size)),
|
|
37
|
+
calc(100% - var(--_ui-scroll-fade-size)) 100%;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
:host-state([orientation="horizontal"]) {
|
|
41
|
+
overflow-x: auto;
|
|
42
|
+
overflow-y: hidden;
|
|
43
|
+
--_ui-scroll-fade-direction: var(--_ui-scroll-fade-inline);
|
|
44
|
+
animation-timeline: scroll(self inline);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
:host:dir(rtl) {
|
|
48
|
+
--_ui-scroll-fade-inline: to left;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/* A component that sets its display still honours the hidden attribute on its root. */
|
|
52
|
+
:host[hidden] {
|
|
53
|
+
display: none;
|
|
54
|
+
}
|
|
55
|
+
</style>
|
|
56
|
+
</template>
|
|
@@ -125,6 +125,23 @@
|
|
|
125
125
|
min-block-size: 0;
|
|
126
126
|
overflow: auto;
|
|
127
127
|
padding: var(--ui-space-2);
|
|
128
|
+
/* Each edge that hides content fades: the scroll fade every Looma scroller uses (see ui-scroll-area). */
|
|
129
|
+
--_ui-scroll-fade-direction: to bottom;
|
|
130
|
+
--_ui-scroll-fade-size: var(--ui-scroll-fade-size, 24px);
|
|
131
|
+
mask-image: linear-gradient(
|
|
132
|
+
var(--_ui-scroll-fade-direction),
|
|
133
|
+
transparent,
|
|
134
|
+
#000 var(--_ui-scroll-fade-start),
|
|
135
|
+
#000 calc(100% - var(--_ui-scroll-fade-end)),
|
|
136
|
+
transparent
|
|
137
|
+
);
|
|
138
|
+
animation: ui-scroll-fade-start linear, ui-scroll-fade-start-hold linear, ui-scroll-fade-end-hold linear, ui-scroll-fade-end linear;
|
|
139
|
+
animation-timeline: scroll(self block);
|
|
140
|
+
animation-range:
|
|
141
|
+
0 var(--_ui-scroll-fade-size),
|
|
142
|
+
var(--_ui-scroll-fade-size) calc(100% + 1px),
|
|
143
|
+
-1px calc(100% - var(--_ui-scroll-fade-size)),
|
|
144
|
+
calc(100% - var(--_ui-scroll-fade-size)) 100%;
|
|
128
145
|
}
|
|
129
146
|
|
|
130
147
|
@media (max-width: 47.9375rem) {
|
|
@@ -49,10 +49,28 @@
|
|
|
49
49
|
border-inline-start: 1px solid var(--ui-sidebar-border, var(--ui-border-default));
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
/* The panel's content scrolls, and each edge that hides content fades: the scroll fade every
|
|
53
|
+
Looma scroller uses (see ui-scroll-area). */
|
|
52
54
|
.content {
|
|
53
55
|
flex: 1;
|
|
54
56
|
min-block-size: 0;
|
|
55
57
|
overflow: auto;
|
|
58
|
+
--_ui-scroll-fade-direction: to bottom;
|
|
59
|
+
--_ui-scroll-fade-size: var(--ui-scroll-fade-size, 24px);
|
|
60
|
+
mask-image: linear-gradient(
|
|
61
|
+
var(--_ui-scroll-fade-direction),
|
|
62
|
+
transparent,
|
|
63
|
+
#000 var(--_ui-scroll-fade-start),
|
|
64
|
+
#000 calc(100% - var(--_ui-scroll-fade-end)),
|
|
65
|
+
transparent
|
|
66
|
+
);
|
|
67
|
+
animation: ui-scroll-fade-start linear, ui-scroll-fade-start-hold linear, ui-scroll-fade-end-hold linear, ui-scroll-fade-end linear;
|
|
68
|
+
animation-timeline: scroll(self block);
|
|
69
|
+
animation-range:
|
|
70
|
+
0 var(--_ui-scroll-fade-size),
|
|
71
|
+
var(--_ui-scroll-fade-size) calc(100% + 1px),
|
|
72
|
+
-1px calc(100% - var(--_ui-scroll-fade-size)),
|
|
73
|
+
calc(100% - var(--_ui-scroll-fade-size)) 100%;
|
|
56
74
|
}
|
|
57
75
|
|
|
58
76
|
/* Collapsed while docked. */
|
|
@@ -85,8 +85,8 @@
|
|
|
85
85
|
<button class="disclosure" $ref="disclosure" type="button" :disabled="disabled" :hidden="not isContainer">
|
|
86
86
|
<span class="disclosure-icon" aria-hidden="true"></span>
|
|
87
87
|
</button>
|
|
88
|
-
<span class="leading"><slot name="leading"></slot></span>
|
|
89
|
-
<span class="label"><span class="label-text" $ref="labelText"><slot name="label"><template $value="label"></template></slot></span></span>
|
|
88
|
+
<span class="leading" $ref="leading"><slot name="leading"></slot></span>
|
|
89
|
+
<span class="label" $ref="label"><span class="label-text" $ref="labelText"><slot name="label"><template $value="label"></template></slot></span></span>
|
|
90
90
|
<span class="actions" $ref="actions"><slot name="actions"></slot></span>
|
|
91
91
|
<span class="drop-indicator row-drop-indicator" aria-hidden="true"></span>
|
|
92
92
|
</div>
|
|
@@ -221,6 +221,9 @@
|
|
|
221
221
|
block-size: 1em;
|
|
222
222
|
margin-inline-start: var(--ui-space-1);
|
|
223
223
|
color: var(--ui-text-muted);
|
|
224
|
+
/* Above the label, so a sliding name passes under the icon. */
|
|
225
|
+
position: relative;
|
|
226
|
+
z-index: 1;
|
|
224
227
|
}
|
|
225
228
|
|
|
226
229
|
.leading:empty {
|
|
@@ -248,6 +251,9 @@
|
|
|
248
251
|
/* The cell clips: a name longer than the row slides inside it rather than over its icons. */
|
|
249
252
|
overflow: hidden;
|
|
250
253
|
padding: var(--ui-tree-item-label-padding-block, var(--ui-space-1)) var(--ui-tree-item-label-padding-inline, var(--ui-space-2));
|
|
254
|
+
/* The length of the fade before the controls. The label's one flex child lays out no gap; this
|
|
255
|
+
is where the controller reads the length in pixels to stop a sliding name before the fade. */
|
|
256
|
+
column-gap: var(--ui-space-3);
|
|
251
257
|
}
|
|
252
258
|
|
|
253
259
|
/* Slotted label content fills the cell, so a link is the row's hit area rather than sizing to
|
|
@@ -268,6 +274,27 @@
|
|
|
268
274
|
min-inline-size: 0;
|
|
269
275
|
}
|
|
270
276
|
|
|
277
|
+
/* The controls sit over the label's end, so the text fades out where they begin. The fade is
|
|
278
|
+
the truncation mark while it shows: an ellipsis under it would read as a second one. */
|
|
279
|
+
.row:hover > .label,
|
|
280
|
+
.row:focus-within > .label {
|
|
281
|
+
text-overflow: clip;
|
|
282
|
+
mask-image: linear-gradient(
|
|
283
|
+
to right,
|
|
284
|
+
#000 calc(100% - var(--_tree-actions-width, 1.75rem) - var(--ui-space-3)),
|
|
285
|
+
transparent calc(100% - var(--_tree-actions-width, 1.75rem))
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
.row:hover > .label:dir(rtl),
|
|
290
|
+
.row:focus-within > .label:dir(rtl) {
|
|
291
|
+
mask-image: linear-gradient(
|
|
292
|
+
to left,
|
|
293
|
+
#000 calc(100% - var(--_tree-actions-width, 1.75rem) - var(--ui-space-3)),
|
|
294
|
+
transparent calc(100% - var(--_tree-actions-width, 1.75rem))
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
|
|
271
298
|
/* A hovered row reads its whole name: the label slides far enough to show the end, waits
|
|
272
299
|
there, and comes back. Only when it actually overflows — the controller measures by how
|
|
273
300
|
much — after the controls have taken their place over its end — and hands over the distance
|
|
@@ -279,13 +306,17 @@
|
|
|
279
306
|
will-change: transform;
|
|
280
307
|
}
|
|
281
308
|
|
|
282
|
-
/*
|
|
283
|
-
|
|
309
|
+
/* This comes after the hover fade, which it replaces at the same specificity. While the name
|
|
310
|
+
slides, the label reaches back under the icon (the controller measures how far) with its text
|
|
311
|
+
where it was, and fades out across that stretch, gone by the icon's middle: the name slips
|
|
312
|
+
under the icon rather than stopping at a hard edge beside it. */
|
|
284
313
|
.row[data-ui-marquee] > .label {
|
|
314
|
+
margin-inline-start: calc(-1 * var(--_marquee-lead, 0px));
|
|
315
|
+
padding-inline-start: calc(var(--_marquee-lead, 0px) + var(--ui-tree-item-label-padding-inline, var(--ui-space-2)));
|
|
285
316
|
mask-image: linear-gradient(
|
|
286
317
|
to right,
|
|
287
|
-
transparent
|
|
288
|
-
#000 var(--ui-space-2),
|
|
318
|
+
transparent calc(var(--_marquee-lead, 0px) / 2),
|
|
319
|
+
#000 calc(var(--_marquee-lead, 0px) + var(--ui-tree-item-label-padding-inline, var(--ui-space-2))),
|
|
289
320
|
#000 calc(100% - var(--_tree-actions-width, 1.75rem) - var(--ui-space-3)),
|
|
290
321
|
transparent calc(100% - var(--_tree-actions-width, 1.75rem))
|
|
291
322
|
);
|
|
@@ -294,8 +325,8 @@
|
|
|
294
325
|
.row[data-ui-marquee] > .label:dir(rtl) {
|
|
295
326
|
mask-image: linear-gradient(
|
|
296
327
|
to left,
|
|
297
|
-
transparent
|
|
298
|
-
#000 var(--ui-space-2),
|
|
328
|
+
transparent calc(var(--_marquee-lead, 0px) / 2),
|
|
329
|
+
#000 calc(var(--_marquee-lead, 0px) + var(--ui-tree-item-label-padding-inline, var(--ui-space-2))),
|
|
299
330
|
#000 calc(100% - var(--_tree-actions-width, 1.75rem) - var(--ui-space-3)),
|
|
300
331
|
transparent calc(100% - var(--_tree-actions-width, 1.75rem))
|
|
301
332
|
);
|
|
@@ -318,27 +349,6 @@
|
|
|
318
349
|
}
|
|
319
350
|
}
|
|
320
351
|
|
|
321
|
-
/* The controls sit over the label's end, so the text fades out where they begin. The fade is
|
|
322
|
-
the truncation mark while it shows: an ellipsis under it would read as a second one. */
|
|
323
|
-
.row:hover > .label,
|
|
324
|
-
.row:focus-within > .label {
|
|
325
|
-
text-overflow: clip;
|
|
326
|
-
mask-image: linear-gradient(
|
|
327
|
-
to right,
|
|
328
|
-
#000 calc(100% - var(--_tree-actions-width, 1.75rem) - var(--ui-space-3)),
|
|
329
|
-
transparent calc(100% - var(--_tree-actions-width, 1.75rem))
|
|
330
|
-
);
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
.row:hover > .label:dir(rtl),
|
|
334
|
-
.row:focus-within > .label:dir(rtl) {
|
|
335
|
-
mask-image: linear-gradient(
|
|
336
|
-
to left,
|
|
337
|
-
#000 calc(100% - var(--_tree-actions-width, 1.75rem) - var(--ui-space-3)),
|
|
338
|
-
transparent calc(100% - var(--_tree-actions-width, 1.75rem))
|
|
339
|
-
);
|
|
340
|
-
}
|
|
341
|
-
|
|
342
352
|
.row:hover > .label > :slotted(*),
|
|
343
353
|
.row:focus-within > .label > :slotted(*) {
|
|
344
354
|
text-overflow: clip;
|
|
@@ -19,7 +19,7 @@ const CONTROLS = [
|
|
|
19
19
|
|
|
20
20
|
export default function controller(host) {
|
|
21
21
|
const element = host.element;
|
|
22
|
-
const { row, disclosure, children, actions, labelText } = host.refs;
|
|
22
|
+
const { row, disclosure, children, leading, label, actions, labelText } = host.refs;
|
|
23
23
|
// Touch use enlarges rows and hides drag handles (see the template's styles).
|
|
24
24
|
trackInputModality(element.ownerDocument);
|
|
25
25
|
const childItems = () => Array.from(children?.children ?? [])
|
|
@@ -98,23 +98,28 @@ export default function controller(host) {
|
|
|
98
98
|
const stop = host.effect(apply);
|
|
99
99
|
apply();
|
|
100
100
|
/**
|
|
101
|
-
* A hovered row reads its whole name. The
|
|
102
|
-
* width
|
|
103
|
-
*
|
|
101
|
+
* A hovered row reads its whole name. The label box always fills the row, so the name is measured
|
|
102
|
+
* at its own width; it has to end where the fade before the controls begins, since the controls
|
|
103
|
+
* overlay the label's end rather than taking width from it.
|
|
104
104
|
*/
|
|
105
105
|
const MARQUEE_SPEED = 36; // CSS pixels per second.
|
|
106
|
-
const MARQUEE_SLACK = 4; // So the tail clears the edge rather than stopping on it.
|
|
107
106
|
// The tree sets this for its items; an item's own prop overrides it either way.
|
|
108
107
|
const marqueeWanted = () => host.state.marquee
|
|
109
108
|
|| getComputedStyle(element).getPropertyValue("--ui-tree-item-marquee").trim() === "1";
|
|
110
109
|
const startMarquee = () => {
|
|
111
|
-
if (!labelText || !marqueeWanted()) return;
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
const
|
|
110
|
+
if (!labelText || !label || !marqueeWanted()) return;
|
|
111
|
+
labelText.style.flex = "none";
|
|
112
|
+
labelText.style.inlineSize = "max-content";
|
|
113
|
+
const text = labelText.getBoundingClientRect();
|
|
114
|
+
labelText.style.flex = labelText.style.inlineSize = "";
|
|
115
|
+
const cell = label.getBoundingClientRect();
|
|
116
|
+
const icon = leading?.getBoundingClientRect();
|
|
117
|
+
const stop = (actions?.offsetWidth ?? 0) + parseFloat(getComputedStyle(label).columnGap);
|
|
117
118
|
const rightToLeft = getComputedStyle(element).direction === "rtl";
|
|
119
|
+
const distance = Math.ceil(rightToLeft ? cell.left + stop - text.left : text.right - (cell.right - stop));
|
|
120
|
+
if (distance <= 0) return;
|
|
121
|
+
const lead = icon?.width ? (rightToLeft ? icon.right - cell.right : cell.left - icon.left) : 0;
|
|
122
|
+
row.style.setProperty("--_marquee-lead", `${Math.max(0, lead)}px`);
|
|
118
123
|
row.style.setProperty("--_marquee-distance", `${rightToLeft ? distance : -distance}px`);
|
|
119
124
|
row.style.setProperty(
|
|
120
125
|
"--_marquee-duration",
|
|
@@ -124,6 +129,7 @@ export default function controller(host) {
|
|
|
124
129
|
};
|
|
125
130
|
const stopMarquee = () => {
|
|
126
131
|
delete row.dataset.uiMarquee;
|
|
132
|
+
row.style.removeProperty("--_marquee-lead");
|
|
127
133
|
row.style.removeProperty("--_marquee-distance");
|
|
128
134
|
row.style.removeProperty("--_marquee-duration");
|
|
129
135
|
};
|