@threadlabs/looma 0.10.2 → 0.10.3

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.
@@ -4109,23 +4109,28 @@ to {
4109
4109
  display: none;
4110
4110
  }
4111
4111
 
4112
- [data-component~="ui-tree"][data-ui-tree-state~="density=compact"][data-v-a2bb2dca] {
4112
+ /* Reaches the items the way density does, so the setting lives on the tree the way a reader
4113
+ thinks about it: this list scrolls its long names. */
4114
+ [data-component~="ui-tree"][data-ui-tree-state~="marquee"][data-v-5c1143dd] {
4115
+ --ui-tree-item-marquee: 1;
4116
+ }
4117
+ [data-component~="ui-tree"][data-ui-tree-state~="density=compact"][data-v-5c1143dd] {
4113
4118
  --ui-tree-item-min-block-size: var(--ui-control-size-sm);
4114
4119
  --ui-tree-item-font-size: var(--ui-font-size-sm);
4115
4120
  --ui-tree-item-label-padding-block: 0;
4116
4121
  }
4117
- [data-component~="ui-tree"][data-v-a2bb2dca] {
4122
+ [data-component~="ui-tree"][data-v-5c1143dd] {
4118
4123
  display: block;
4119
4124
  min-inline-size: 0;
4120
4125
  padding-inline-start: var(--ui-tree-gutter, 0px);
4121
4126
  }
4122
4127
 
4123
4128
  /* A component that sets its display still honours the hidden attribute on its root. */
4124
- [data-component~="ui-tree"][hidden][data-v-a2bb2dca] {
4129
+ [data-component~="ui-tree"][hidden][data-v-5c1143dd] {
4125
4130
  display: none;
4126
4131
  }
4127
4132
 
4128
- [data-component~="ui-tree-item"][data-v-48465a46] {
4133
+ [data-component~="ui-tree-item"][data-v-171d033f] {
4129
4134
  --_tree-row-min-height: 32px;
4130
4135
  --_tree-disclosure-size: 16px;
4131
4136
 
@@ -4134,7 +4139,7 @@ to {
4134
4139
  min-inline-size: 0;
4135
4140
  margin-inline-start: calc(var(--ui-tree-item-depth, 0) * var(--ui-tree-indent, 16px));
4136
4141
  }
4137
- .row[data-v-48465a46] {
4142
+ .row[data-v-171d033f] {
4138
4143
  position: relative;
4139
4144
  display: grid;
4140
4145
  grid-template-columns: var(--_tree-disclosure-size) auto minmax(0, 1fr);
@@ -4151,38 +4156,38 @@ to {
4151
4156
  box-shadow var(--ui-motion-fast) var(--ui-motion-ease),
4152
4157
  min-block-size var(--ui-motion-base) var(--ui-motion-ease);
4153
4158
  }
4154
- .row[data-v-48465a46]:hover,
4155
- [data-component~="ui-tree-item"][data-ui-tree-item-state~="selected"] .row[data-v-48465a46],
4156
- .row[data-v-48465a46]:focus-within {
4159
+ .row[data-v-171d033f]:hover,
4160
+ [data-component~="ui-tree-item"][data-ui-tree-item-state~="selected"] .row[data-v-171d033f],
4161
+ .row[data-v-171d033f]:focus-within {
4157
4162
  color: var(--ui-text-primary);
4158
4163
  background: var(--ui-surface-muted);
4159
4164
  }
4160
- [data-component~="ui-tree-item"][data-ui-tree-item-state~="disabled"] .row[data-v-48465a46] {
4165
+ [data-component~="ui-tree-item"][data-ui-tree-item-state~="disabled"] .row[data-v-171d033f] {
4161
4166
  opacity: 0.55;
4162
4167
  }
4163
- [data-component~="ui-tree-item"][data-dragging] .row[data-v-48465a46] {
4168
+ [data-component~="ui-tree-item"][data-dragging] .row[data-v-171d033f] {
4164
4169
  opacity: 0.42;
4165
4170
  }
4166
- [data-component~="ui-tree-item"][data-v-48465a46]:focus {
4171
+ [data-component~="ui-tree-item"][data-v-171d033f]:focus {
4167
4172
  outline: none;
4168
4173
  }
4169
- [data-component~="ui-tree-item"]:focus-visible .row[data-v-48465a46] {
4174
+ [data-component~="ui-tree-item"]:focus-visible .row[data-v-171d033f] {
4170
4175
  box-shadow: 0 0 0 2px var(--ui-focus-ring);
4171
4176
  }
4172
4177
 
4173
4178
  /* Child combinators: drop feedback belongs to this item's own row, not the rows nested in it. */
4174
- [data-component~="ui-tree-item"][data-drop-position="inside"] > .row[data-v-48465a46] {
4179
+ [data-component~="ui-tree-item"][data-drop-position="inside"] > .row[data-v-171d033f] {
4175
4180
  background: var(--ui-accent-subtle);
4176
4181
  box-shadow: inset 0 0 0 1px var(--ui-tree-drop-color, var(--ui-accent-solid));
4177
4182
  }
4178
- .disclosure[data-v-48465a46],
4179
- .disclosure-spacer[data-v-48465a46] {
4183
+ .disclosure[data-v-171d033f],
4184
+ .disclosure-spacer[data-v-171d033f] {
4180
4185
  grid-column: 1;
4181
4186
  grid-row: 1;
4182
4187
  inline-size: var(--_tree-disclosure-size);
4183
4188
  block-size: 28px;
4184
4189
  }
4185
- .disclosure[data-v-48465a46] {
4190
+ .disclosure[data-v-171d033f] {
4186
4191
  display: grid;
4187
4192
  /* Start-aligned: the chevron's ink, not its hit area, aligns with the content above it. */
4188
4193
  place-items: center start;
@@ -4193,14 +4198,14 @@ to {
4193
4198
  border-radius: var(--ui-radius-sm);
4194
4199
  cursor: pointer;
4195
4200
  }
4196
- .disclosure[hidden][data-v-48465a46] {
4201
+ .disclosure[hidden][data-v-171d033f] {
4197
4202
  display: none;
4198
4203
  }
4199
- .disclosure[data-v-48465a46]:hover {
4204
+ .disclosure[data-v-171d033f]:hover {
4200
4205
  color: var(--ui-text-primary);
4201
4206
  background: var(--ui-surface-elevated);
4202
4207
  }
4203
- .disclosure-icon[data-v-48465a46] {
4208
+ .disclosure-icon[data-v-171d033f] {
4204
4209
  display: grid;
4205
4210
  place-items: center;
4206
4211
  inline-size: 12px;
@@ -4208,7 +4213,7 @@ to {
4208
4213
  transform: rotate(-90deg);
4209
4214
  transition: transform var(--ui-motion-fast) var(--ui-motion-ease);
4210
4215
  }
4211
- .disclosure-icon[data-v-48465a46]::before {
4216
+ .disclosure-icon[data-v-171d033f]::before {
4212
4217
  display: block;
4213
4218
  inline-size: 0.375rem;
4214
4219
  block-size: 0.375rem;
@@ -4218,19 +4223,19 @@ to {
4218
4223
  /* A chevron's ink sits below its box centre; lift it so it centres optically (in either rotation). */
4219
4224
  transform: translateY(-20%) rotate(45deg);
4220
4225
  }
4221
- [data-component~="ui-tree-item"][aria-expanded="true"] .disclosure-icon[data-v-48465a46] {
4226
+ [data-component~="ui-tree-item"][aria-expanded="true"] .disclosure-icon[data-v-171d033f] {
4222
4227
  transform: rotate(0deg);
4223
4228
  }
4224
4229
 
4225
4230
  /* Lucide grip-vertical, filling the handle as in Looma 0.2. */
4226
- .drag-handle svg[data-v-48465a46] {
4231
+ .drag-handle svg[data-v-171d033f] {
4227
4232
  display: block;
4228
4233
  inline-size: 100%;
4229
4234
  block-size: 100%;
4230
4235
  }
4231
4236
 
4232
4237
  /* Slotted content is outside this scope, so :has() cannot see it; hide only a truly empty slot. */
4233
- .leading[data-v-48465a46] {
4238
+ .leading[data-v-171d033f] {
4234
4239
  display: inline-grid;
4235
4240
  place-items: center;
4236
4241
  grid-column: 2;
@@ -4240,12 +4245,12 @@ to {
4240
4245
  margin-inline-start: var(--ui-space-1);
4241
4246
  color: var(--ui-text-muted);
4242
4247
  }
4243
- .leading[data-v-48465a46]:empty {
4248
+ .leading[data-v-171d033f]:empty {
4244
4249
  display: none;
4245
4250
  }
4246
4251
 
4247
4252
  /* Icons match the label's size (as in Knit's tree): an unsized SVG would otherwise render 300×150. */
4248
- svg[data-v-48465a46-s],img[data-v-48465a46-s] {
4253
+ svg[data-v-171d033f-s],img[data-v-171d033f-s] {
4249
4254
  display: block;
4250
4255
  inline-size: 1em;
4251
4256
  block-size: 1em;
@@ -4254,28 +4259,87 @@ svg[data-v-48465a46-s],img[data-v-48465a46-s] {
4254
4259
 
4255
4260
  /* The label spans the row's height and centres its content, so slotted content (a link) can
4256
4261
  stretch to fill the row as its own hit area; the padding tokens remove the inset. */
4257
- .label[data-v-48465a46] {
4262
+ .label[data-v-171d033f] {
4258
4263
  grid-column: 3;
4259
4264
  grid-row: 1;
4260
4265
  align-self: stretch;
4261
4266
  display: flex;
4262
4267
  align-items: center;
4263
4268
  min-inline-size: 0;
4269
+ /* The cell clips: a name longer than the row slides inside it rather than over its icons. */
4270
+ overflow: hidden;
4264
4271
  padding: var(--ui-tree-item-label-padding-block, var(--ui-space-1))
4265
4272
  var(--ui-tree-item-label-padding-inline, var(--ui-space-2));
4266
4273
  }
4267
4274
 
4268
4275
  /* Slotted label content fills the cell, so a link is the row's hit area rather than sizing to
4269
4276
  its own text and reading as overflow. */
4270
- .label > [data-v-48465a46-s] {
4277
+ .label-text[data-v-171d033f] {
4278
+ display: flex;
4279
+ align-items: center;
4280
+ /* Stretches, so slotted content can still be the row's full-height hit area. */
4281
+ align-self: stretch;
4282
+ block-size: 100%;
4283
+ min-inline-size: 0;
4284
+ inline-size: 100%;
4285
+ white-space: nowrap;
4286
+ }
4287
+ .label-text > [data-v-171d033f-s] {
4271
4288
  flex: 1 1 auto;
4272
4289
  min-inline-size: 0;
4273
4290
  }
4274
4291
 
4292
+ /* A hovered row reads its whole name: the label slides far enough to show the end, waits
4293
+ there, and comes back. Only when it actually overflows — the controller measures by how
4294
+ much — after the controls have taken their place over its end — and hands over the distance
4295
+ and a duration from it, so a longer name travels no faster. */
4296
+ .row[data-ui-marquee] > .label > .label-text[data-v-171d033f] {
4297
+ /* Once, and it stays at the end while the pointer is there: a name that keeps sliding back
4298
+ and forth under the pointer is harder to read than one that arrives and holds. */
4299
+ animation: ui-tree-item-marquee-171d033f var(--_marquee-duration) linear 0.5s 1 normal forwards;
4300
+ will-change: transform;
4301
+ }
4302
+
4303
+ /* While it slides, the start fades too: the name is leaving the cell at both ends, and a hard
4304
+ edge beside the icon reads as a collision rather than as more text. */
4305
+ .row[data-ui-marquee] > .label[data-v-171d033f] {
4306
+ mask-image: linear-gradient(
4307
+ to right,
4308
+ transparent 0,
4309
+ #000 var(--ui-space-2),
4310
+ #000 calc(100% - var(--_tree-actions-width, 1.75rem) - var(--ui-space-3)),
4311
+ transparent calc(100% - var(--_tree-actions-width, 1.75rem))
4312
+ );
4313
+ }
4314
+ .row[data-ui-marquee] > .label[data-v-171d033f]:dir(rtl) {
4315
+ mask-image: linear-gradient(
4316
+ to left,
4317
+ transparent 0,
4318
+ #000 var(--ui-space-2),
4319
+ #000 calc(100% - var(--_tree-actions-width, 1.75rem) - var(--ui-space-3)),
4320
+ transparent calc(100% - var(--_tree-actions-width, 1.75rem))
4321
+ );
4322
+ }
4323
+ @keyframes ui-tree-item-marquee-171d033f {
4324
+ from {
4325
+ transform: translateX(0);
4326
+ }
4327
+ to {
4328
+ transform: translateX(var(--_marquee-distance));
4329
+ }
4330
+ }
4331
+
4332
+ /* Reduced motion keeps the fade, which already says the name continues. */
4333
+ @media (prefers-reduced-motion: reduce) {
4334
+ .row[data-ui-marquee] > .label > .label-text[data-v-171d033f] {
4335
+ animation: none;
4336
+ }
4337
+ }
4338
+
4275
4339
  /* The controls sit over the label's end, so the text fades out where they begin. The fade is
4276
4340
  the truncation mark while it shows: an ellipsis under it would read as a second one. */
4277
- .row:hover > .label[data-v-48465a46],
4278
- .row:focus-within > .label[data-v-48465a46] {
4341
+ .row:hover > .label[data-v-171d033f],
4342
+ .row:focus-within > .label[data-v-171d033f] {
4279
4343
  text-overflow: clip;
4280
4344
  mask-image: linear-gradient(
4281
4345
  to right,
@@ -4283,19 +4347,19 @@ svg[data-v-48465a46-s],img[data-v-48465a46-s] {
4283
4347
  transparent calc(100% - var(--_tree-actions-width, 1.75rem))
4284
4348
  );
4285
4349
  }
4286
- .row:hover > .label[data-v-48465a46]:dir(rtl),
4287
- .row:focus-within > .label[data-v-48465a46]:dir(rtl) {
4350
+ .row:hover > .label[data-v-171d033f]:dir(rtl),
4351
+ .row:focus-within > .label[data-v-171d033f]:dir(rtl) {
4288
4352
  mask-image: linear-gradient(
4289
4353
  to left,
4290
4354
  #000 calc(100% - var(--_tree-actions-width, 1.75rem) - var(--ui-space-3)),
4291
4355
  transparent calc(100% - var(--_tree-actions-width, 1.75rem))
4292
4356
  );
4293
4357
  }
4294
- .row:hover > .label > [data-v-48465a46-s],
4295
- .row:focus-within > .label > [data-v-48465a46-s] {
4358
+ .row:hover > .label > [data-v-171d033f-s],
4359
+ .row:focus-within > .label > [data-v-171d033f-s] {
4296
4360
  text-overflow: clip;
4297
4361
  }
4298
- .actions[data-v-48465a46] {
4362
+ .actions[data-v-171d033f] {
4299
4363
  position: absolute;
4300
4364
  z-index: 1;
4301
4365
  inset-block: 0;
@@ -4307,18 +4371,18 @@ svg[data-v-48465a46-s],img[data-v-48465a46-s] {
4307
4371
  pointer-events: none;
4308
4372
  transition: opacity var(--ui-motion-fast) var(--ui-motion-ease);
4309
4373
  }
4310
- .row:hover > .actions[data-v-48465a46],
4311
- .row:focus-within > .actions[data-v-48465a46] {
4374
+ .row:hover > .actions[data-v-171d033f],
4375
+ .row:focus-within > .actions[data-v-171d033f] {
4312
4376
  opacity: 1;
4313
4377
  pointer-events: auto;
4314
4378
  }
4315
4379
 
4316
4380
  /* Without hover there is no reveal, so the controls keep their own column. */
4317
4381
  @media (hover: none) {
4318
- .row[data-v-48465a46] {
4382
+ .row[data-v-171d033f] {
4319
4383
  grid-template-columns: var(--_tree-disclosure-size) auto minmax(0, 1fr) auto;
4320
4384
  }
4321
- .actions[data-v-48465a46] {
4385
+ .actions[data-v-171d033f] {
4322
4386
  position: static;
4323
4387
  grid-column: 4;
4324
4388
  grid-row: 1;
@@ -4328,7 +4392,7 @@ svg[data-v-48465a46-s],img[data-v-48465a46-s] {
4328
4392
  pointer-events: auto;
4329
4393
  }
4330
4394
  }
4331
- .drag-handle[data-v-48465a46] {
4395
+ .drag-handle[data-v-171d033f] {
4332
4396
  position: absolute;
4333
4397
  z-index: 2;
4334
4398
  inset-block-start: 50%;
@@ -4349,16 +4413,16 @@ svg[data-v-48465a46-s],img[data-v-48465a46-s] {
4349
4413
  transform: translateY(-50%);
4350
4414
  transition: opacity var(--ui-motion-fast) var(--ui-motion-ease);
4351
4415
  }
4352
- .row:hover .drag-handle[data-v-48465a46],
4353
- .drag-handle[data-v-48465a46]:hover,
4354
- .drag-handle[data-v-48465a46]:focus-visible,
4355
- [data-component~="ui-tree-item"][data-dragging] > .row > .drag-handle[data-v-48465a46] {
4416
+ .row:hover .drag-handle[data-v-171d033f],
4417
+ .drag-handle[data-v-171d033f]:hover,
4418
+ .drag-handle[data-v-171d033f]:focus-visible,
4419
+ [data-component~="ui-tree-item"][data-dragging] > .row > .drag-handle[data-v-171d033f] {
4356
4420
  opacity: 1;
4357
4421
  }
4358
- .drag-handle[data-v-48465a46]:active {
4422
+ .drag-handle[data-v-171d033f]:active {
4359
4423
  cursor: grabbing;
4360
4424
  }
4361
- .drop-indicator[data-v-48465a46] {
4425
+ .drop-indicator[data-v-171d033f] {
4362
4426
  position: absolute;
4363
4427
  z-index: 3;
4364
4428
  inset-inline: 1px;
@@ -4368,8 +4432,8 @@ svg[data-v-48465a46-s],img[data-v-48465a46-s] {
4368
4432
  background: var(--ui-tree-drop-color, var(--ui-accent-solid));
4369
4433
  pointer-events: none;
4370
4434
  }
4371
- .drop-indicator[data-v-48465a46]::before,
4372
- .drop-indicator[data-v-48465a46]::after {
4435
+ .drop-indicator[data-v-171d033f]::before,
4436
+ .drop-indicator[data-v-171d033f]::after {
4373
4437
  content: "";
4374
4438
  position: absolute;
4375
4439
  inset-block-start: 50%;
@@ -4380,39 +4444,39 @@ svg[data-v-48465a46-s],img[data-v-48465a46-s] {
4380
4444
  background: var(--ui-surface-elevated);
4381
4445
  transform: translateY(-50%);
4382
4446
  }
4383
- .drop-indicator[data-v-48465a46]::before {
4447
+ .drop-indicator[data-v-171d033f]::before {
4384
4448
  inset-inline-start: -1px;
4385
4449
  }
4386
- .drop-indicator[data-v-48465a46]::after {
4450
+ .drop-indicator[data-v-171d033f]::after {
4387
4451
  inset-inline-end: -1px;
4388
4452
  }
4389
- [data-component~="ui-tree-item"][data-drop-position="before"] > .row > .row-drop-indicator[data-v-48465a46] {
4453
+ [data-component~="ui-tree-item"][data-drop-position="before"] > .row > .row-drop-indicator[data-v-171d033f] {
4390
4454
  display: block;
4391
4455
  inset-block-start: -1px;
4392
4456
  }
4393
- [data-component~="ui-tree-item"][data-drop-position="after"] > .subtree-drop-indicator[data-v-48465a46] {
4457
+ [data-component~="ui-tree-item"][data-drop-position="after"] > .subtree-drop-indicator[data-v-171d033f] {
4394
4458
  display: block;
4395
4459
  inset-block-end: -1px;
4396
4460
  }
4397
- .children[hidden][data-v-48465a46] {
4461
+ .children[hidden][data-v-171d033f] {
4398
4462
  display: none;
4399
4463
  }
4400
- html[data-ui-input-modality="touch"] [data-component~="ui-tree-item"][data-v-48465a46] {
4464
+ html[data-ui-input-modality="touch"] [data-component~="ui-tree-item"][data-v-171d033f] {
4401
4465
  --_tree-row-min-height: 44px;
4402
4466
  }
4403
- html[data-ui-input-modality="touch"] [data-component~="ui-tree-item"] .drag-handle[data-v-48465a46] {
4467
+ html[data-ui-input-modality="touch"] [data-component~="ui-tree-item"] .drag-handle[data-v-171d033f] {
4404
4468
  display: none;
4405
4469
  }
4406
4470
  @media (prefers-reduced-motion: reduce) {
4407
- .row[data-v-48465a46],
4408
- .disclosure-icon[data-v-48465a46],
4409
- .drag-handle[data-v-48465a46] {
4471
+ .row[data-v-171d033f],
4472
+ .disclosure-icon[data-v-171d033f],
4473
+ .drag-handle[data-v-171d033f] {
4410
4474
  transition: none;
4411
4475
  }
4412
4476
  }
4413
4477
 
4414
4478
  /* A component that sets its display still honours the hidden attribute on its root. */
4415
- [data-component~="ui-tree-item"][hidden][data-v-48465a46] {
4479
+ [data-component~="ui-tree-item"][hidden][data-v-171d033f] {
4416
4480
  display: none;
4417
4481
  }
4418
4482
  /**