@threadlabs/looma 0.6.3 → 0.6.4

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.
@@ -63,7 +63,7 @@
63
63
  </button>
64
64
  <span class="leading"><slot name="leading"></slot></span>
65
65
  <span class="label"><slot name="label"><template $value="label"></template></slot></span>
66
- <span class="actions"><slot name="actions"></slot></span>
66
+ <span class="actions" $ref="actions"><slot name="actions"></slot></span>
67
67
  <span class="drop-indicator row-drop-indicator" aria-hidden="true"></span>
68
68
  </div>
69
69
  <div class="children" $ref="children" role="group" :hidden="not (isContainer and internalExpanded)"><slot></slot></div>
@@ -72,6 +72,7 @@
72
72
  <style>
73
73
  :host {
74
74
  --_tree-row-min-height: 32px;
75
+ --_tree-disclosure-size: 16px;
75
76
 
76
77
  position: relative;
77
78
  display: block;
@@ -82,7 +83,7 @@
82
83
  .row {
83
84
  position: relative;
84
85
  display: grid;
85
- grid-template-columns: 20px auto minmax(0, 1fr) auto;
86
+ grid-template-columns: var(--_tree-disclosure-size) auto minmax(0, 1fr);
86
87
  align-items: center;
87
88
  min-block-size: var(--ui-tree-item-min-block-size, var(--_tree-row-min-height));
88
89
  min-inline-size: 0;
@@ -130,13 +131,14 @@
130
131
  .disclosure-spacer {
131
132
  grid-column: 1;
132
133
  grid-row: 1;
133
- inline-size: 20px;
134
+ inline-size: var(--_tree-disclosure-size);
134
135
  block-size: 28px;
135
136
  }
136
137
 
137
138
  .disclosure {
138
139
  display: grid;
139
- place-items: center;
140
+ /* Start-aligned: the chevron's ink, not its hit area, aligns with the content above it. */
141
+ place-items: center start;
140
142
  padding: 0;
141
143
  color: var(--ui-text-muted);
142
144
  background: transparent;
@@ -157,18 +159,18 @@
157
159
  .disclosure-icon {
158
160
  display: grid;
159
161
  place-items: center;
160
- inline-size: 14px;
161
- block-size: 14px;
162
+ inline-size: 12px;
163
+ block-size: 12px;
162
164
  transform: rotate(-90deg);
163
165
  transition: transform var(--ui-motion-fast) var(--ui-motion-ease);
164
166
  }
165
167
 
166
168
  .disclosure-icon::before {
167
169
  display: block;
168
- inline-size: 0.45rem;
169
- block-size: 0.45rem;
170
- border-inline-end: 2px solid currentColor;
171
- border-block-end: 2px solid currentColor;
170
+ inline-size: 0.375rem;
171
+ block-size: 0.375rem;
172
+ border-inline-end: 1.5px solid currentColor;
173
+ border-block-end: 1.5px solid currentColor;
172
174
  content: "";
173
175
  /* A chevron's ink sits below its box centre; lift it so it centres optically (in either rotation). */
174
176
  transform: translateY(-20%) rotate(45deg);
@@ -229,12 +231,66 @@
229
231
  min-inline-size: 0;
230
232
  }
231
233
 
234
+ /* The controls sit over the label's end, so the text fades out where they begin. The fade is
235
+ the truncation mark while it shows: an ellipsis under it would read as a second one. */
236
+ .row:hover > .label,
237
+ .row:focus-within > .label {
238
+ text-overflow: clip;
239
+ mask-image: linear-gradient(
240
+ to right,
241
+ #000 calc(100% - var(--_tree-actions-width, 1.75rem) - var(--ui-space-3)),
242
+ transparent calc(100% - var(--_tree-actions-width, 1.75rem))
243
+ );
244
+ }
245
+
246
+ .row:hover > .label:dir(rtl),
247
+ .row:focus-within > .label:dir(rtl) {
248
+ mask-image: linear-gradient(
249
+ to left,
250
+ #000 calc(100% - var(--_tree-actions-width, 1.75rem) - var(--ui-space-3)),
251
+ transparent calc(100% - var(--_tree-actions-width, 1.75rem))
252
+ );
253
+ }
254
+
255
+ .row:hover > .label > :slotted(*),
256
+ .row:focus-within > .label > :slotted(*) {
257
+ text-overflow: clip;
258
+ }
259
+
232
260
  .actions {
233
- grid-column: 4;
234
- grid-row: 1;
261
+ position: absolute;
262
+ z-index: 1;
263
+ inset-block: 0;
264
+ inset-inline-end: 0;
235
265
  display: inline-flex;
236
266
  align-items: center;
237
267
  min-inline-size: 0;
268
+ opacity: 0;
269
+ pointer-events: none;
270
+ transition: opacity var(--ui-motion-fast) var(--ui-motion-ease);
271
+ }
272
+
273
+ .row:hover > .actions,
274
+ .row:focus-within > .actions {
275
+ opacity: 1;
276
+ pointer-events: auto;
277
+ }
278
+
279
+ /* Without hover there is no reveal, so the controls keep their own column. */
280
+ @media (hover: none) {
281
+ .row {
282
+ grid-template-columns: var(--_tree-disclosure-size) auto minmax(0, 1fr) auto;
283
+ }
284
+
285
+ .actions {
286
+ position: static;
287
+ grid-column: 4;
288
+ grid-row: 1;
289
+ padding-inline-start: 0;
290
+ background: none;
291
+ opacity: 1;
292
+ pointer-events: auto;
293
+ }
238
294
  }
239
295
 
240
296
  .drag-handle {
@@ -11,7 +11,7 @@ function parentItem(element) {
11
11
  /** Synchronizes an inferred tree hierarchy after nested component lowering. */
12
12
  export default function controller(host) {
13
13
  const element = host.element;
14
- const { row, disclosure, children } = host.refs;
14
+ const { row, disclosure, children, actions } = host.refs;
15
15
  // Touch use enlarges rows and hides drag handles (see the template's styles).
16
16
  trackInputModality(element.ownerDocument);
17
17
  const childItems = () => Array.from(children?.children ?? [])
@@ -81,9 +81,17 @@ export default function controller(host) {
81
81
  updateLevel();
82
82
  const stop = host.effect(apply);
83
83
  apply();
84
+ // The label's fade has to end where the controls begin, and only the controls know their width.
85
+ const actionsSize = new ResizeObserver(([entry]) => {
86
+ const width = entry.borderBoxSize?.[0]?.inlineSize ?? entry.contentRect.width;
87
+ element.style.setProperty("--_tree-actions-width", `${width}px`);
88
+ });
89
+ if (actions) actionsSize.observe(actions);
90
+
84
91
  return () => {
85
92
  stop?.();
86
93
  observer.disconnect();
94
+ actionsSize.disconnect();
87
95
  element.removeEventListener("ui-tree-auto-expand", onAutoExpand);
88
96
  element.removeEventListener("ui-tree-structure-sync", onStructure);
89
97
  element.removeEventListener("ui-tree-roving-tab-stop", onRoving);