@quillmark/svelte 0.7.2 → 0.8.0
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/core/codec/prose.css +6 -12
- package/dist/core/theme.css +16 -16
- package/dist/visual/ArrayField.svelte +14 -22
- package/dist/visual/BooleanField.svelte +6 -1
- package/dist/visual/Card.svelte +114 -61
- package/dist/visual/CardControls.svelte +31 -26
- package/dist/visual/EnumField.svelte +17 -2
- package/dist/visual/ObjectField.svelte +1 -1
- package/dist/visual/controls.css +63 -28
- package/dist/visual/ext.d.ts +7 -0
- package/dist/visual/ext.js +13 -2
- package/dist/visual/icons/Icon.svelte +2 -3
- package/dist/visual/icons/Icon.svelte.d.ts +2 -3
- package/dist/visual/strings.d.ts +1 -1
- package/package.json +2 -2
|
@@ -76,7 +76,7 @@ li.ProseMirror-selectednode::after {
|
|
|
76
76
|
reads as set apart without a fill or a second box. */
|
|
77
77
|
.ProseMirror blockquote {
|
|
78
78
|
padding-left: var(--_qm-space-3);
|
|
79
|
-
border-left: var(--_qm-
|
|
79
|
+
border-left: var(--_qm-vertical-width) solid var(--_qm-border);
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
/* ── The positive half ───────────────────────────────────────────────────────
|
|
@@ -425,11 +425,11 @@ li.ProseMirror-selectednode::after {
|
|
|
425
425
|
top: 100%;
|
|
426
426
|
height: var(--_qm-tap-min);
|
|
427
427
|
}
|
|
428
|
-
/* The reveal
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
428
|
+
/* The reveal is the control's own (CODEC §"The table island"): one comes up while the
|
|
429
|
+
pointer is on that control, while it holds the focus, or while it is what a gesture is
|
|
430
|
+
about — the selected line's grip, and the lifted one, which is drawn through a drag the
|
|
431
|
+
pointer has travelled off. The controls' boxes meet at no point, so what is drawn is
|
|
432
|
+
the one line the pointer has picked out.
|
|
433
433
|
|
|
434
434
|
Opacity rather than absence, so every control keeps its box and is hit-tested wherever
|
|
435
435
|
it sits. A grip's reach is the pointer's alone and it holds no focus, so it carries no
|
|
@@ -441,12 +441,6 @@ li.ProseMirror-selectednode::after {
|
|
|
441
441
|
opacity: 0;
|
|
442
442
|
transition: opacity var(--_qm-duration-fast) var(--_qm-ease-reverse);
|
|
443
443
|
}
|
|
444
|
-
/* `:where` on the island, so the first rung carries the specificity of the control alone
|
|
445
|
-
and the second one outranks it. Unwrapped, the descendant selector is the heavier of
|
|
446
|
-
the two and a hovered grip stays muted under the pointer that is on it. */
|
|
447
|
-
:where(.qm-table-island:hover) :is(.qm-table-grip, .qm-table-add) {
|
|
448
|
-
opacity: var(--_qm-opacity-muted);
|
|
449
|
-
}
|
|
450
444
|
.qm-table-add:is(:hover, :focus-visible),
|
|
451
445
|
.qm-table-grip:is(:hover, [aria-pressed='true'], .qm-table-lifted) {
|
|
452
446
|
opacity: 1;
|
package/dist/core/theme.css
CHANGED
|
@@ -280,14 +280,19 @@
|
|
|
280
280
|
--_qm-reveal: 500ms cubic-bezier(0.4, 0, 0.2, 1);
|
|
281
281
|
|
|
282
282
|
/* ── Geometry ──────────────────────────────────────────────────────────*/
|
|
283
|
-
/* One stroke width for every edge the chrome draws
|
|
284
|
-
|
|
285
|
-
rhythm choice, like the tap floor: a hairline is a hairline at
|
|
286
|
-
`--qm-space`, so
|
|
287
|
-
|
|
288
|
-
and a subform's are one stroke at three depths, and `check:style`'s
|
|
289
|
-
border-width axis can only hold that against a token. */
|
|
283
|
+
/* One stroke width for every edge the chrome draws and every rule it ranks
|
|
284
|
+
with: a card's, a control's, the two closing a card's payload. A threshold
|
|
285
|
+
rather than a rhythm choice, like the tap floor: a hairline is a hairline at
|
|
286
|
+
any `--qm-space`, so neither derives from a dial. Both exist as rungs because
|
|
287
|
+
`check:style`'s border-width axis can only hold a stroke against a token. */
|
|
290
288
|
--_qm-border-width: 1px;
|
|
289
|
+
/* Half a step over it, for the verticals alone — a section's, a subform's, a
|
|
290
|
+
blockquote's. What a vertical states is depth, and depth is the one thing a
|
|
291
|
+
reader has to find in a dense card; the strokes that close a block or rank two
|
|
292
|
+
stay at the hairline, so the ladder is what carries the extra weight. Half,
|
|
293
|
+
because a whole step reads as a different kind of line rather than the same
|
|
294
|
+
one doing more work. */
|
|
295
|
+
--_qm-vertical-width: 1.5px;
|
|
291
296
|
--_qm-radius: var(--qm-radius, 8px);
|
|
292
297
|
/* The interior corner, and half is the relationship rather than the number: a
|
|
293
298
|
corner inside a corner reads as nested only while it is visibly tighter, and
|
|
@@ -324,17 +329,12 @@
|
|
|
324
329
|
--_qm-tail: 40vh;
|
|
325
330
|
/* WCAG 2.5.8's 24x24 pointer-target floor. A rung rather than a sixth step on
|
|
326
331
|
the space scale: it is a threshold the spec fixes, not a rhythm choice, so
|
|
327
|
-
it does not move when `--qm-space` does.
|
|
332
|
+
it does not move when `--qm-space` does. Every button family reads it, so the
|
|
328
333
|
floor is one number instead of one expression per control. */
|
|
329
334
|
--_qm-tap-min: 24px;
|
|
330
|
-
/* The
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
card's gutter is an arithmetic of the two, and a literal on either side is a
|
|
334
|
-
balance that silently breaks when the glyph moves. Sized in CSS rather than
|
|
335
|
-
through the icon's `size`, so the hang and the glyph read one number. Scoped to
|
|
336
|
-
the control pair: the hint and the format marks take their own sizes, and a
|
|
337
|
-
rung claiming to be every glyph would be false at three of them. */
|
|
335
|
+
/* The chrome glyph: a chip's, and the in-well remove's. Sized in CSS rather than
|
|
336
|
+
through the icon's `size`, so a stylesheet beats the SVG presentation attribute
|
|
337
|
+
and one rung is the whole of what a control draws. */
|
|
338
338
|
--_qm-glyph-control: 14px;
|
|
339
339
|
|
|
340
340
|
/* ── Type ────────────────────────────────────────────────────────────────
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
by `items.type`: `richtext` / `plaintext` → a prose element
|
|
6
6
|
({@link ProseValue}), `object` → a summary row that opens onto a subform,
|
|
7
7
|
everything else → a text input. The
|
|
8
|
-
add
|
|
8
|
+
add chip sits in the label header row (space-between with the field label);
|
|
9
9
|
{@link Field} skips its own label for array controls and hands this component the
|
|
10
10
|
label track with it.
|
|
11
11
|
|
|
@@ -352,7 +352,7 @@
|
|
|
352
352
|
{/if}
|
|
353
353
|
<button
|
|
354
354
|
type="button"
|
|
355
|
-
class="qm-add-el qm-
|
|
355
|
+
class="qm-add-el qm-chip qm-focus-ring qm-tap-floor"
|
|
356
356
|
bind:this={addEl}
|
|
357
357
|
onclick={add}>{t.strings.arrayAdd}</button
|
|
358
358
|
>
|
|
@@ -442,10 +442,9 @@
|
|
|
442
442
|
gap: var(--_qm-space);
|
|
443
443
|
}
|
|
444
444
|
/* The array's first line is the row's label line: this component owns the label
|
|
445
|
-
track (Field.svelte), so the
|
|
446
|
-
|
|
447
|
-
label
|
|
448
|
-
below. */
|
|
445
|
+
track (Field.svelte). Arrays never pack (`packable`), so the chip's tap floor is
|
|
446
|
+
free to size the header; a caption on this line would have had to match
|
|
447
|
+
`.qm-field-label-row`. */
|
|
449
448
|
.qm-array-header {
|
|
450
449
|
display: flex;
|
|
451
450
|
align-items: center;
|
|
@@ -584,29 +583,22 @@
|
|
|
584
583
|
color: var(--_qm-ink-label);
|
|
585
584
|
font-style: italic;
|
|
586
585
|
}
|
|
587
|
-
/*
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
target-sized box would stand the header 8px taller than the `.qm-field-label-row`
|
|
593
|
-
beside it in a shared row and put the two labels on different lines.
|
|
594
|
-
|
|
595
|
-
The label rung in place of the family's body rung, which the family invites: it reads
|
|
596
|
-
as one more thing on the label line rather than as a control from the row below. */
|
|
586
|
+
/* The label line's own type: size, weight and leading are `.qm-field-label`'s, so
|
|
587
|
+
the two read as one register. Inner radius: the chip family is the card's, and this
|
|
588
|
+
box is a line of type. The chip's tap floor is given back (`.qm-tap-floor`),
|
|
589
|
+
and the padding with it, so the drawn box is the line and the target is the floor.
|
|
590
|
+
It rests dim and comes up under the pointer; empty, it is the way in. */
|
|
597
591
|
.qm-add-el {
|
|
598
592
|
padding: 0 var(--_qm-space);
|
|
599
|
-
font-
|
|
593
|
+
font-weight: var(--_qm-weight-mid);
|
|
594
|
+
line-height: var(--_qm-leading-tight);
|
|
595
|
+
border-radius: var(--_qm-radius-inner);
|
|
600
596
|
opacity: var(--_qm-opacity-idle);
|
|
601
597
|
}
|
|
602
|
-
.qm-
|
|
598
|
+
.qm-add-el:hover,
|
|
603
599
|
.qm-add-el:focus-visible {
|
|
604
600
|
opacity: 1;
|
|
605
601
|
}
|
|
606
|
-
/* Empty, the rows box is `display: none` and the field is a label and this trigger:
|
|
607
|
-
nothing left for it to compete with, and nothing else in the field to act on. So
|
|
608
|
-
it rests full-strength there and takes the recede back once it heads a list. A
|
|
609
|
-
receded trigger beside no content reads as a caption rather than as a way in. */
|
|
610
602
|
.qm-array.empty .qm-add-el {
|
|
611
603
|
opacity: 1;
|
|
612
604
|
}
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
|
|
39
39
|
<span class="qm-switch-wrap">
|
|
40
40
|
<Switch.Root
|
|
41
|
-
class="qm-switch qm-focus-ring"
|
|
41
|
+
class="qm-switch qm-focus-ring qm-tap-floor"
|
|
42
42
|
checked={local.value}
|
|
43
43
|
{id}
|
|
44
44
|
aria-label={id ? undefined : label}
|
|
@@ -55,6 +55,11 @@
|
|
|
55
55
|
<style>
|
|
56
56
|
/* A primitive renders its own element, which a scoped selector cannot reach:
|
|
57
57
|
styled through the wrapper with `:global`. */
|
|
58
|
+
/* The track is the drawn box and the target is `.qm-tap-floor`'s (controls.css): a
|
|
59
|
+
switch is a mark standing in a field's row, so its height is the track's, where WCAG
|
|
60
|
+
2.5.8's floor is half again that. The `<label for>` beside it forwards a press but
|
|
61
|
+
stands at the label rung, so it is no taller: without the floor no region on the
|
|
62
|
+
surface reaches this control at the size every other control on it holds. */
|
|
58
63
|
.qm-switch-wrap :global(.qm-switch) {
|
|
59
64
|
display: inline-flex;
|
|
60
65
|
align-items: center;
|
package/dist/visual/Card.svelte
CHANGED
|
@@ -408,33 +408,54 @@
|
|
|
408
408
|
|
|
409
409
|
<style>
|
|
410
410
|
/* An island: the card is the base plane, the column behind it the sunken one, and the
|
|
411
|
-
hairline closes it (ARCHITECTURE §Styling). The
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
411
|
+
hairline closes it (ARCHITECTURE §Styling). The block half is the same rung as the
|
|
412
|
+
gap: the payload stands that far off the card's edge and off the body below it. The
|
|
413
|
+
header insets itself to the section-heading column (`.qm-card-header`). The inline
|
|
414
|
+
half stands a step tighter than the nesting rung the verticals inside keep: this
|
|
415
|
+
edge closes the block rather than nesting one, and the rules it holds run that much
|
|
416
|
+
further for it. */
|
|
415
417
|
.qm-card {
|
|
416
418
|
border: var(--_qm-border-width) solid var(--_qm-border);
|
|
417
419
|
border-radius: var(--_qm-radius);
|
|
418
|
-
padding: var(--_qm-space-3) var(--_qm-
|
|
420
|
+
padding: var(--_qm-space-3) var(--_qm-space-2);
|
|
419
421
|
background: var(--_qm-surface);
|
|
420
422
|
display: flex;
|
|
421
423
|
flex-direction: column;
|
|
422
424
|
gap: var(--_qm-space-3);
|
|
423
425
|
}
|
|
426
|
+
/* Headerless, the payload faces that edge with nothing between. A field row
|
|
427
|
+
leading it stands the edge's own inset off the top, as it does off the side:
|
|
428
|
+
this rung plus the section's block padding is the inline inset. A card that
|
|
429
|
+
opens on its body keeps the full inset — prose is neither a heading nor a
|
|
430
|
+
field row. */
|
|
431
|
+
.qm-card.qm-main:has(> .qm-card-body > .qm-card-meta:first-child) {
|
|
432
|
+
padding-top: var(--_qm-space);
|
|
433
|
+
}
|
|
434
|
+
/* A section heading leading it: the vertical starts at the content's
|
|
435
|
+
top-left, so the top inset is the inline one and the tip is a square
|
|
436
|
+
corner of the card. */
|
|
437
|
+
.qm-card.qm-main:has(> .qm-card-body > .qm-card-meta:first-child > .qm-groups:first-child) {
|
|
438
|
+
padding-top: var(--_qm-space-2);
|
|
439
|
+
}
|
|
424
440
|
.qm-card-header {
|
|
425
441
|
display: flex;
|
|
426
442
|
align-items: center;
|
|
427
443
|
justify-content: space-between;
|
|
428
444
|
gap: var(--_qm-space-2);
|
|
445
|
+
/* The group's vertical plus the rung the chevron stands off it: the title
|
|
446
|
+
shares that column. Inline only. The block pull is half the card's block
|
|
447
|
+
inset, so the header sits that far off the hairline and the rule. */
|
|
448
|
+
padding-inline: calc(var(--_qm-space) + var(--_qm-vertical-width));
|
|
449
|
+
margin-block: calc(-1 * var(--_qm-space-3) / 2);
|
|
429
450
|
}
|
|
430
|
-
/* The overhang is the tap target's own centring given back, so the glyphs sit on the
|
|
431
|
-
card's gutter rather than the targets around them. It is the fill that crosses the
|
|
432
|
-
line, not a box: an icon button rests unboxed and fills only under the pointer. */
|
|
433
451
|
.qm-card-header-right {
|
|
434
452
|
display: flex;
|
|
435
453
|
align-items: center;
|
|
436
454
|
gap: var(--_qm-space-2);
|
|
437
|
-
|
|
455
|
+
/* The overhang is the tap target's own centring given back, so the delete
|
|
456
|
+
glyph sits on the header's inset rather than the pad around it. The fill is
|
|
457
|
+
what crosses the line. */
|
|
458
|
+
margin-inline-end: calc(-1 * (var(--_qm-tap-min) - var(--_qm-glyph-control)) / 2);
|
|
438
459
|
}
|
|
439
460
|
/* Focus as well as hover, so a caret in any leaf, the title, or a chevron holds the
|
|
440
461
|
reveal: hover alone would strand the pair on keyboard and touch. */
|
|
@@ -445,7 +466,7 @@
|
|
|
445
466
|
/* The rename hit region is the header's free width at full height, so a press
|
|
446
467
|
anywhere left of the controls enters the title edit. `align-self: stretch` beats the
|
|
447
468
|
header's centring, which is also what keeps the target legal with no padding: WCAG
|
|
448
|
-
2.5.8's floor is the row's, which the
|
|
469
|
+
2.5.8's floor is the row's, which the chips hold at `--_qm-tap-min`. */
|
|
449
470
|
.qm-card-rename {
|
|
450
471
|
flex: 1;
|
|
451
472
|
min-width: 0;
|
|
@@ -504,24 +525,21 @@
|
|
|
504
525
|
flex-direction: column;
|
|
505
526
|
gap: var(--_qm-space-3);
|
|
506
527
|
}
|
|
507
|
-
/* Where two sections meet the distance is three of one rung — the cap closing the one
|
|
508
|
-
above, this gap, the cap opening the one below — the same whether either side is a
|
|
509
|
-
group or the ungrouped block. That total is what the fields inside a section keep
|
|
510
|
-
between their rows (`.qm-fields` row-gap), so a section boundary stands no further
|
|
511
|
-
apart than a field boundary: what ranks them is the stroke, not the air. */
|
|
512
528
|
.qm-card-meta,
|
|
513
529
|
.qm-groups {
|
|
514
530
|
display: flex;
|
|
515
531
|
flex-direction: column;
|
|
516
|
-
gap: var(--_qm-space);
|
|
517
532
|
}
|
|
518
|
-
/* One rung
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
533
|
+
/* One rung between the payload's two kinds of section, and none inside the accordion:
|
|
534
|
+
what stands one disclosure row off the next is the two headers' own block padding and
|
|
535
|
+
nothing else, so the rows tile and their targets with them. A run of one-line rows
|
|
536
|
+
wants the tighter rhythm — the `--_qm-space-3` the fields keep between their own rows
|
|
537
|
+
is calibrated for a label over a well, and reads as a float between two lines of text.
|
|
538
|
+
|
|
539
|
+
`--stroke-reach` is what a box standing a field row off a rule has left to spend: the
|
|
540
|
+
rung is `--_qm-nest`, of which its own block padding is already `--_qm-space`. */
|
|
524
541
|
.qm-card-meta {
|
|
542
|
+
gap: var(--_qm-space);
|
|
525
543
|
--stroke-reach: calc(var(--_qm-nest) - var(--_qm-space));
|
|
526
544
|
}
|
|
527
545
|
/* The card's two horizontals, and ranking is the one thing a horizontal is for: they
|
|
@@ -530,27 +548,35 @@
|
|
|
530
548
|
conditional on what it ranks against: `main` is headerless, and a card with no body
|
|
531
549
|
has nothing under the payload to divide it from.
|
|
532
550
|
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
551
|
+
Neither insets: a rule is drawn on the edge of the box it faces, and the air is that
|
|
552
|
+
box's own. So the section carries what its ink stands off a rule — the inset of the
|
|
553
|
+
ink facing it, which is what squares the corner: `--_qm-nest` for a field row,
|
|
554
|
+
`--_qm-space` for a heading, each the rung that ink stands off a vertical inline. The
|
|
555
|
+
air outside the pair is the `--_qm-space-3` the card spends between its blocks. */
|
|
536
556
|
.qm-meta-top {
|
|
537
557
|
border-top: var(--_qm-border-width) solid var(--_qm-border);
|
|
538
|
-
padding-top: var(--stroke-reach);
|
|
539
558
|
}
|
|
540
559
|
.qm-meta-bottom {
|
|
541
560
|
border-bottom: var(--_qm-border-width) solid var(--_qm-border);
|
|
542
|
-
padding-bottom: var(--stroke-reach);
|
|
543
561
|
}
|
|
544
|
-
/* A section's share of the boundary between sections
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
edges hold.
|
|
562
|
+
/* A section's share of the boundary between sections, one rung at each end. The
|
|
563
|
+
accordion spends the same rung from its header and its panel, where it also caps the
|
|
564
|
+
vertical those two edges hold.
|
|
548
565
|
|
|
549
|
-
No stroke
|
|
550
|
-
|
|
551
|
-
|
|
566
|
+
No stroke: a vertical would mark a section a reader has no name for. The start
|
|
567
|
+
inset is the heading's — the group's vertical plus the rung the chevron stands
|
|
568
|
+
off it — so a top-level field and a section heading share a column. */
|
|
552
569
|
.qm-section {
|
|
553
570
|
padding-block: var(--_qm-space);
|
|
571
|
+
padding-inline-start: calc(var(--_qm-space) + var(--_qm-vertical-width));
|
|
572
|
+
}
|
|
573
|
+
/* Where it faces a rule, the rung a heading already stands off one. The fields
|
|
574
|
+
sit on the heading column, not the card's edge. */
|
|
575
|
+
.qm-meta-top > .qm-section:first-child {
|
|
576
|
+
padding-top: var(--_qm-space-2);
|
|
577
|
+
}
|
|
578
|
+
.qm-meta-bottom > .qm-section:last-child {
|
|
579
|
+
padding-bottom: var(--_qm-space-2);
|
|
554
580
|
}
|
|
555
581
|
/* Two query containers, one per kind of section, so capacity follows the width the
|
|
556
582
|
fields actually get: a panel's inset makes that narrower than the card. */
|
|
@@ -597,47 +623,72 @@
|
|
|
597
623
|
than absent, so a toggle moves no text — and closed, there is nothing under the header
|
|
598
624
|
for it to gather.
|
|
599
625
|
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
boundary keeps the three rungs it stood at. What the stroke reaches into is the air of
|
|
605
|
-
that boundary, or, where the section is the payload's first or last, exactly the inset
|
|
606
|
-
its rule took — so it lands on the rule at a corner with nothing drawn longer for it.
|
|
626
|
+
A free end of the stroke caps at `--_qm-space`, the rung the subform's own vertical
|
|
627
|
+
caps at (`ObjectField`), grown as padding and handed straight back as margin so the
|
|
628
|
+
stroke lengthens and no boundary moves. Above, that is also the rung the header stands
|
|
629
|
+
off it, so the top end is the same number whether it caps free or lands on a rule.
|
|
607
630
|
One section open at a time, so no two strokes are ever visible to meet in between. */
|
|
608
631
|
.qm-group {
|
|
609
632
|
display: flex;
|
|
610
633
|
flex-direction: column;
|
|
611
|
-
border-left: var(--_qm-
|
|
612
|
-
padding-
|
|
613
|
-
margin-
|
|
614
|
-
transition:
|
|
615
|
-
|
|
634
|
+
border-left: var(--_qm-vertical-width) solid transparent;
|
|
635
|
+
padding-bottom: var(--_qm-space);
|
|
636
|
+
margin-bottom: calc(-1 * var(--_qm-space));
|
|
637
|
+
transition:
|
|
638
|
+
border-color var(--_qm-duration-slow) var(--_qm-ease-reverse),
|
|
639
|
+
padding-bottom var(--_qm-duration-slow) var(--_qm-ease-reverse),
|
|
640
|
+
margin-bottom var(--_qm-duration-slow) var(--_qm-ease-reverse);
|
|
641
|
+
}
|
|
642
|
+
/* Open, the cap is air as well as stroke: a section ending on a field row stands the
|
|
643
|
+
longer rung off what follows, and three of `--_qm-space` are what that comes to — the
|
|
644
|
+
panel's own, this cap, and the next header's. Shut, a section ends on its header and
|
|
645
|
+
stands the header's rung, so there is nothing to cap and the padding is handed back. */
|
|
616
646
|
.qm-group.qm-open {
|
|
617
647
|
border-left-color: var(--_qm-border);
|
|
648
|
+
margin-bottom: 0;
|
|
649
|
+
}
|
|
650
|
+
/* The one end that lands on a rule, where the padding is real and the rule is this
|
|
651
|
+
box's own bottom edge — so the stroke ends on the rule at every frame of a fold rather
|
|
652
|
+
than at the two ends of one, and the fields inside stand `--_qm-nest` off it. Shut,
|
|
653
|
+
the box ends on the header's block padding and the rule takes the heading's rung
|
|
654
|
+
there, the same one the rule above it takes. */
|
|
655
|
+
.qm-meta-bottom > .qm-groups:last-child > .qm-group:last-child {
|
|
656
|
+
padding-bottom: 0;
|
|
657
|
+
margin-bottom: 0;
|
|
658
|
+
}
|
|
659
|
+
.qm-meta-bottom > .qm-groups:last-child > .qm-group:last-child.qm-open {
|
|
660
|
+
padding-bottom: var(--stroke-reach);
|
|
618
661
|
}
|
|
619
|
-
/*
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
between ink and stroke, and the rotation swaps which bearing
|
|
662
|
+
/* One rung on three sides and zero on the end, the end because the row is the target
|
|
663
|
+
and an inset there is target given back. The rung is `--_qm-space` in both axes, and
|
|
664
|
+
neither is free: the block padding is the tightest that still clears WCAG 2.5.8's
|
|
665
|
+
24×24 floor, and it is the whole air a heading opening the payload keeps under its
|
|
666
|
+
rule, which a rule cannot inset past — so the inline inset is that same number or the
|
|
667
|
+
corner is square on one axis alone. The heading rides the vertical there, one
|
|
668
|
+
nesting step out from the fields under it, which is what states that it holds them.
|
|
669
|
+
What the glyph gives up for the step is the gutter: it stands in the clearance itself,
|
|
670
|
+
with only its own bearing between ink and stroke, and the rotation swaps which bearing
|
|
671
|
+
faces which.
|
|
628
672
|
|
|
629
673
|
`font: inherit` because a UA button inherits no face, then the body rung, one step
|
|
630
674
|
over the field labels beneath it: at the label rung the two read as one register and
|
|
631
675
|
the accordion stops looking like structure. Size, weight and leading sit after
|
|
632
676
|
`font`, a shorthand that carries `line-height`. */
|
|
633
677
|
.qm-group-header {
|
|
678
|
+
/* Positioned, and paint is not what it buys: a group's box grows by
|
|
679
|
+
`--stroke-reach` at both ends and hands the growth back as margin, so
|
|
680
|
+
consecutive boxes overlap in a band at every seam, and a closed group's header
|
|
681
|
+
ends inside the next group's box. In flow, the later sibling takes the presses
|
|
682
|
+
that land in the band and the bottom of the header is a dead strip; positioned,
|
|
683
|
+
the control holds its own box, and the band paints the same either way. */
|
|
684
|
+
position: relative;
|
|
634
685
|
display: flex;
|
|
635
686
|
align-items: center;
|
|
636
687
|
gap: var(--_qm-space);
|
|
637
688
|
width: 100%;
|
|
638
689
|
border: none;
|
|
639
690
|
background: transparent;
|
|
640
|
-
padding: var(--_qm-space) 0 var(--_qm-space) var(--_qm-
|
|
691
|
+
padding: var(--_qm-space) 0 var(--_qm-space) var(--_qm-space);
|
|
641
692
|
font: inherit;
|
|
642
693
|
font-size: var(--_qm-text-body);
|
|
643
694
|
font-weight: var(--_qm-weight-mid);
|
|
@@ -672,11 +723,13 @@
|
|
|
672
723
|
.qm-group.qm-open .qm-group-panel {
|
|
673
724
|
grid-template-rows: 1fr;
|
|
674
725
|
}
|
|
675
|
-
/*
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
the
|
|
679
|
-
|
|
726
|
+
/* What a toggle moves is the panel's track, and the box's own bottom edge where the
|
|
727
|
+
last section is the one toggling. A reveal's landing measures its target one flush
|
|
728
|
+
after asking — where either, mid-flight, still reads its start value — so nothing
|
|
729
|
+
about the accordion animates for it. Both panels of the move are inside the group box,
|
|
730
|
+
so the opening one and the closing one above it stand still together (`revealLeaf`). */
|
|
731
|
+
.qm-groups.qm-instant .qm-group-panel,
|
|
732
|
+
.qm-groups.qm-instant .qm-group {
|
|
680
733
|
transition: none;
|
|
681
734
|
}
|
|
682
735
|
/* Two boxes because the axes clip differently, and the track is the only thing that
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
<!--
|
|
2
2
|
Card controls, composable cards only.
|
|
3
3
|
Right-aligned in the header: a move-up/move-down chevron pair revealed while the
|
|
4
|
-
pointer or the caret is in the card (each disabled at its edge), then
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
to do it: the size is the stylesheet's below, never an attribute.
|
|
4
|
+
pointer or the caret is in the card (each disabled at its edge), then delete.
|
|
5
|
+
Reorder is buttons, not drag (V1). All three are chips (controls.css): fill arrives
|
|
6
|
+
on hover, and delete rests faded danger, full under the pointer. The card scopes
|
|
7
|
+
that reveal, so its condition lives in the parent's CSS; the pair keeps the narrower
|
|
8
|
+
guarantee here, that a focused chevron is a visible one.
|
|
10
9
|
-->
|
|
11
10
|
<script lang="ts">
|
|
12
11
|
import { wording } from './strings.js';
|
|
@@ -31,14 +30,14 @@
|
|
|
31
30
|
<div class="qm-card-reorder">
|
|
32
31
|
<button
|
|
33
32
|
type="button"
|
|
34
|
-
class="qm-
|
|
33
|
+
class="qm-chip qm-focus-ring"
|
|
35
34
|
title={t.strings.cardMoveUp}
|
|
36
35
|
disabled={isFirst}
|
|
37
36
|
onclick={onMoveUp}><Icon name="chevron-up" /></button
|
|
38
37
|
>
|
|
39
38
|
<button
|
|
40
39
|
type="button"
|
|
41
|
-
class="qm-
|
|
40
|
+
class="qm-chip qm-focus-ring"
|
|
42
41
|
title={t.strings.cardMoveDown}
|
|
43
42
|
disabled={isLast}
|
|
44
43
|
onclick={onMoveDown}><Icon name="chevron-down" /></button
|
|
@@ -46,9 +45,9 @@
|
|
|
46
45
|
</div>
|
|
47
46
|
<button
|
|
48
47
|
type="button"
|
|
49
|
-
class="qm-
|
|
48
|
+
class="qm-chip qm-card-delete qm-focus-ring"
|
|
50
49
|
title={t.strings.cardDelete}
|
|
51
|
-
onclick={onDelete}><Icon name="
|
|
50
|
+
onclick={onDelete}><Icon name="trash-2" /></button
|
|
52
51
|
>
|
|
53
52
|
</div>
|
|
54
53
|
|
|
@@ -56,20 +55,14 @@
|
|
|
56
55
|
.qm-card-controls {
|
|
57
56
|
display: flex;
|
|
58
57
|
align-items: center;
|
|
59
|
-
gap: var(--_qm-space);
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
breaks silently when the two disagree. A stylesheet beats an SVG presentation
|
|
65
|
-
attribute, so the rung wins without the attribute being removed from the icon. */
|
|
66
|
-
.qm-card-controls :global(svg) {
|
|
67
|
-
width: var(--_qm-glyph-control);
|
|
68
|
-
height: var(--_qm-glyph-control);
|
|
58
|
+
gap: var(--_qm-space-half);
|
|
59
|
+
/* One compositor layer for the row. Opacity on the pair otherwise snaps
|
|
60
|
+
that box off the header's half-pixel, against delete which never leaves
|
|
61
|
+
the document paint. */
|
|
62
|
+
transform: translateZ(0);
|
|
69
63
|
}
|
|
70
64
|
.qm-card-reorder {
|
|
71
65
|
display: flex;
|
|
72
|
-
gap: var(--_qm-space-half);
|
|
73
66
|
opacity: 0;
|
|
74
67
|
transition: opacity var(--_qm-duration-fast) var(--_qm-ease-reverse);
|
|
75
68
|
}
|
|
@@ -80,13 +73,25 @@
|
|
|
80
73
|
.qm-card-reorder:focus-within {
|
|
81
74
|
opacity: 1;
|
|
82
75
|
}
|
|
83
|
-
/*
|
|
84
|
-
is
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
76
|
+
/* Squares: the chip's inline pad is for a label. Width and height are one rung
|
|
77
|
+
so the hover fill is a square and the glyph sits in the middle. */
|
|
78
|
+
.qm-card-controls button {
|
|
79
|
+
width: var(--_qm-tap-min);
|
|
80
|
+
height: var(--_qm-tap-min);
|
|
81
|
+
padding: 0;
|
|
88
82
|
}
|
|
83
|
+
/* Hover fill comes from `.qm-chip` (controls.css). Idle recede is on the ink,
|
|
84
|
+
not the box: a layer on the chip is two rasters of the same stroke, and the
|
|
85
|
+
fill has to stay opaque. Danger mixed to the idle rung; full under the pointer. */
|
|
89
86
|
.qm-card-delete {
|
|
87
|
+
color: color-mix(
|
|
88
|
+
in oklab,
|
|
89
|
+
var(--_qm-danger) calc(100% * var(--_qm-opacity-idle)),
|
|
90
|
+
var(--_qm-surface)
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
.qm-card-delete:hover,
|
|
94
|
+
.qm-card-delete:focus-visible {
|
|
90
95
|
color: var(--_qm-danger);
|
|
91
96
|
}
|
|
92
97
|
</style>
|
|
@@ -104,8 +104,8 @@
|
|
|
104
104
|
aria-describedby={describedBy}
|
|
105
105
|
data-ghosted={unset ? '' : undefined}
|
|
106
106
|
>
|
|
107
|
-
{shown}
|
|
108
|
-
<Icon name="chevron-down" size={14} />
|
|
107
|
+
<span class="qm-select-shown">{shown}</span>
|
|
108
|
+
<Icon name="chevron-down" class="qm-select-chevron" size={14} />
|
|
109
109
|
</Select.Trigger>
|
|
110
110
|
<Select.Portal to={portalTarget}>
|
|
111
111
|
<Select.Content collisionBoundary={portalTarget ?? []} sideOffset={4}>
|
|
@@ -176,6 +176,21 @@
|
|
|
176
176
|
text-align: left;
|
|
177
177
|
cursor: pointer;
|
|
178
178
|
}
|
|
179
|
+
/* The value is one line however long it runs, and the glyph beside it keeps its rung:
|
|
180
|
+
the box is an inset plus one line box (controls.css), which a value that wraps
|
|
181
|
+
stands two lines tall, and a flex glyph with nothing holding it gives its width up
|
|
182
|
+
to the text first and is gone by the time the row is tight. The pair is the same
|
|
183
|
+
guard the element summary takes over its own title, and `min-width` is the half
|
|
184
|
+
that lets the text shrink at all. */
|
|
185
|
+
.qm-select-shown {
|
|
186
|
+
min-width: 0;
|
|
187
|
+
overflow: hidden;
|
|
188
|
+
text-overflow: ellipsis;
|
|
189
|
+
white-space: nowrap;
|
|
190
|
+
}
|
|
191
|
+
.qm-select-wrap :global(.qm-select-chevron) {
|
|
192
|
+
flex-shrink: 0;
|
|
193
|
+
}
|
|
179
194
|
/* The focus ring rides `.qm-focus-ring` on the trigger (controls.css). */
|
|
180
195
|
/* Shown-never-written: the closed control reads muted while unset, matching the
|
|
181
196
|
ghosted placeholder the text/number controls show. */
|
|
@@ -260,7 +260,7 @@
|
|
|
260
260
|
display: grid;
|
|
261
261
|
grid-template-columns: repeat(var(--cols), 1fr);
|
|
262
262
|
gap: var(--_qm-space-2);
|
|
263
|
-
border-inline-start: var(--_qm-
|
|
263
|
+
border-inline-start: var(--_qm-vertical-width) solid var(--_qm-border);
|
|
264
264
|
padding-inline-start: var(--_qm-nest);
|
|
265
265
|
padding-block: var(--_qm-space);
|
|
266
266
|
}
|
package/dist/visual/controls.css
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/* The control recipes more than one component draws: the focus ring, the box a
|
|
2
|
-
typed value sits in,
|
|
3
|
-
component because Svelte scopes a `<style>` block to the component
|
|
4
|
-
markup: a component that carries a shared class without also carrying
|
|
5
|
-
ships unstyled, and nothing raises it.
|
|
2
|
+
typed value sits in, the unboxed glyph, the add strip, and the chip. They live here
|
|
3
|
+
rather than per component because Svelte scopes a `<style>` block to the component
|
|
4
|
+
that owns the markup: a component that carries a shared class without also carrying
|
|
5
|
+
its rule ships unstyled, and nothing raises it.
|
|
6
6
|
|
|
7
7
|
Not in `core/theme.css`: that file is the derivation (public dials in, the
|
|
8
8
|
private `--_qm-*` scale out) and it mints values. This file mints none; every
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
Every selector here is `:where()`-wrapped, so a recipe computes at specificity zero.
|
|
13
13
|
That is the point twice over: a consumer's stylesheet beats the chrome without
|
|
14
14
|
`!important`, and a component's own scoped block overrides its shared base —
|
|
15
|
-
`.qm-card-delete` recolours a `.qm-
|
|
15
|
+
`.qm-card-delete` recolours a `.qm-chip` under the pointer, `.qm-json` adds the monospace face over
|
|
16
16
|
`.qm-input` — with no specificity fight. Unlayered with it, so a host's own layered
|
|
17
17
|
reset never reaches these rules whatever order the sheets load in (`core/theme.css`). */
|
|
18
18
|
|
|
@@ -116,12 +116,11 @@
|
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
/* The second recipe, and it is not the box above: a field is a box because you
|
|
119
|
-
type into it
|
|
120
|
-
no
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
would flatten that distinction rather than share a recipe.
|
|
119
|
+
type into it. A button rests with no fill; the surface arrives on hover, off the
|
|
120
|
+
rung the enum listbox already highlights with. Deliberately no `color`: the
|
|
121
|
+
callers disagree on purpose (the array remove takes danger under the pointer, the
|
|
122
|
+
tips foot inherits, a chip takes the label tone), and a base colour here would flatten
|
|
123
|
+
that distinction rather than share a recipe.
|
|
125
124
|
|
|
126
125
|
`--_qm-tap-min` is WCAG 2.5.8's floor, read rather than re-expressed per
|
|
127
126
|
control: `min-*` is outside every `check:style` axis, so a second expression of
|
|
@@ -132,9 +131,9 @@
|
|
|
132
131
|
the floor means the same height whatever element carries it; and a caller that
|
|
133
132
|
stretches one of these to its row gets a width the padding sits inside.
|
|
134
133
|
|
|
135
|
-
|
|
136
|
-
glyph
|
|
137
|
-
|
|
134
|
+
Every button family is named here rather than opting in through a marker: a
|
|
135
|
+
glyph, an add strip and a chip are not sometimes flat, so a class they could be
|
|
136
|
+
built without is a class one of them will eventually miss.
|
|
138
137
|
|
|
139
138
|
The type half is the shared rule above, which both families are named in; what
|
|
140
139
|
diverges is the leading. Where the box's height is a line box, a button's is
|
|
@@ -147,7 +146,8 @@
|
|
|
147
146
|
own block: the tips foot takes the label rung, which is that surface's decision,
|
|
148
147
|
not the family's. */
|
|
149
148
|
:where(.qm-icon-btn),
|
|
150
|
-
:where(.qm-add-affordance)
|
|
149
|
+
:where(.qm-add-affordance),
|
|
150
|
+
:where(.qm-chip) {
|
|
151
151
|
line-height: 1;
|
|
152
152
|
box-sizing: border-box;
|
|
153
153
|
min-width: var(--_qm-tap-min);
|
|
@@ -159,17 +159,19 @@
|
|
|
159
159
|
transition: background-color var(--_qm-duration-fast) var(--_qm-ease-reverse);
|
|
160
160
|
}
|
|
161
161
|
:where(.qm-icon-btn:hover:not(:disabled)),
|
|
162
|
-
:where(.qm-add-affordance:hover:not(:disabled))
|
|
162
|
+
:where(.qm-add-affordance:hover:not(:disabled)),
|
|
163
|
+
:where(.qm-chip:hover:not(:disabled)) {
|
|
163
164
|
background: var(--_qm-surface-hover);
|
|
164
165
|
}
|
|
165
166
|
:where(.qm-icon-btn:disabled),
|
|
166
|
-
:where(.qm-add-affordance:disabled)
|
|
167
|
+
:where(.qm-add-affordance:disabled),
|
|
168
|
+
:where(.qm-chip:disabled) {
|
|
167
169
|
opacity: var(--_qm-opacity-idle);
|
|
168
170
|
cursor: default;
|
|
169
171
|
}
|
|
170
172
|
|
|
171
|
-
/* A glyph
|
|
172
|
-
marker, the tips card's foot. */
|
|
173
|
+
/* A glyph riding another plane: the array remove (a slab of the well), the field
|
|
174
|
+
label's guidance marker, the tips card's foot. A named pressable is a chip. */
|
|
173
175
|
:where(.qm-icon-btn) {
|
|
174
176
|
display: inline-flex;
|
|
175
177
|
align-items: center;
|
|
@@ -178,21 +180,54 @@
|
|
|
178
180
|
padding: var(--_qm-space-half) var(--_qm-space);
|
|
179
181
|
}
|
|
180
182
|
|
|
181
|
-
/* An add
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
183
|
+
/* An add strip: the between-card trigger. A pill rather than the inner radius,
|
|
184
|
+
because it fills on hover instead of tinting ink: it rests unfilled on
|
|
185
|
+
`--_qm-opacity-idle`, so a hover shifting ink alone would have little to shift.
|
|
186
|
+
The recede ladder itself stays with the caller: it is driven by the strip's own
|
|
187
|
+
hover/focus state. The array's add is a chip. */
|
|
186
188
|
:where(.qm-add-affordance) {
|
|
187
189
|
border-radius: var(--_qm-radius-pill);
|
|
188
|
-
color: var(--_qm-ink-label);
|
|
189
190
|
transition:
|
|
190
191
|
opacity var(--_qm-duration-fast) var(--_qm-ease-reverse),
|
|
191
192
|
background-color var(--_qm-duration-fast) var(--_qm-ease-reverse);
|
|
192
193
|
}
|
|
193
|
-
|
|
194
|
+
|
|
195
|
+
/* A well spans and sinks. A chip hugs, and like every button it rests unfilled:
|
|
196
|
+
the fill arrives on hover. Named (a label) or unnamed (the glyph is the name) —
|
|
197
|
+
the array's add and the card header's reorder/delete. The card's own radius: a
|
|
198
|
+
chip sits on the card, where a well takes the inner because it is cut into it. A
|
|
199
|
+
glyph riding another plane stays `.qm-icon-btn`; a gap that is the insertion
|
|
200
|
+
stays `.qm-add-affordance`.
|
|
201
|
+
|
|
202
|
+
Ink is the label rung at rest and the body rung under the pointer, the same
|
|
203
|
+
ladder the add strip takes: a chip that sat at `--_qm-ink` read as a written
|
|
204
|
+
value. */
|
|
205
|
+
:where(.qm-chip) {
|
|
206
|
+
font: inherit;
|
|
207
|
+
font-size: var(--_qm-text-label);
|
|
208
|
+
display: inline-flex;
|
|
209
|
+
align-items: center;
|
|
210
|
+
justify-content: center;
|
|
211
|
+
gap: var(--_qm-space);
|
|
212
|
+
padding: var(--_qm-space) var(--_qm-space-2);
|
|
213
|
+
border-radius: var(--_qm-radius);
|
|
214
|
+
transition:
|
|
215
|
+
background-color var(--_qm-duration-fast) var(--_qm-ease-reverse),
|
|
216
|
+
color var(--_qm-duration-fast) var(--_qm-ease-reverse);
|
|
217
|
+
}
|
|
218
|
+
:where(.qm-add-affordance),
|
|
219
|
+
:where(.qm-chip) {
|
|
220
|
+
color: var(--_qm-ink-label);
|
|
221
|
+
}
|
|
222
|
+
:where(.qm-add-affordance:hover),
|
|
223
|
+
:where(.qm-chip:hover) {
|
|
194
224
|
color: var(--_qm-ink);
|
|
195
225
|
}
|
|
226
|
+
:where(.qm-chip svg) {
|
|
227
|
+
flex-shrink: 0;
|
|
228
|
+
width: var(--_qm-glyph-control);
|
|
229
|
+
height: var(--_qm-glyph-control);
|
|
230
|
+
}
|
|
196
231
|
|
|
197
232
|
/* The press floor, for a trigger standing in a line of text or a band of gutter
|
|
198
233
|
rather than in a row of its own, whose drawn box is therefore smaller than the target
|
|
@@ -203,8 +238,8 @@
|
|
|
203
238
|
construction: a pseudo-element has no node.
|
|
204
239
|
|
|
205
240
|
The family's floor comes off in the same rule, carrying this class being what giving
|
|
206
|
-
it up means. It sits after
|
|
207
|
-
decides. */
|
|
241
|
+
it up means. It sits after the unboxed recipes for that: same specificity, so source
|
|
242
|
+
order decides. */
|
|
208
243
|
:where(.qm-tap-floor) {
|
|
209
244
|
position: relative;
|
|
210
245
|
min-width: 0;
|
package/dist/visual/ext.d.ts
CHANGED
|
@@ -15,5 +15,12 @@ import type { Document, CardAddr } from '@quillmark/wasm';
|
|
|
15
15
|
* The drop is an explicit `delete`, not a stored `undefined`: whether a JS
|
|
16
16
|
* `undefined` survives the wasm-bindgen crossing is not a property worth depending
|
|
17
17
|
* on.
|
|
18
|
+
*
|
|
19
|
+
* **A namespace emptied of keys is removed, not stored empty.** That is
|
|
20
|
+
* `removeExtNamespace`'s one correct use: it takes the whole namespace, and there is
|
|
21
|
+
* nothing left in this one to lose. `$ext` goes with it when `editor` was the last
|
|
22
|
+
* namespace, so a document nothing has renamed or hinted carries no editor slot
|
|
23
|
+
* rather than an empty one. A patch dropping keys the namespace does not have writes
|
|
24
|
+
* nothing, so dismissing tips on a document that carries none is not a mutation.
|
|
18
25
|
*/
|
|
19
26
|
export declare function patchEditorExt(doc: Document, addr: CardAddr, patch: Record<string, unknown>): void;
|
package/dist/visual/ext.js
CHANGED
|
@@ -14,16 +14,27 @@
|
|
|
14
14
|
* The drop is an explicit `delete`, not a stored `undefined`: whether a JS
|
|
15
15
|
* `undefined` survives the wasm-bindgen crossing is not a property worth depending
|
|
16
16
|
* on.
|
|
17
|
+
*
|
|
18
|
+
* **A namespace emptied of keys is removed, not stored empty.** That is
|
|
19
|
+
* `removeExtNamespace`'s one correct use: it takes the whole namespace, and there is
|
|
20
|
+
* nothing left in this one to lose. `$ext` goes with it when `editor` was the last
|
|
21
|
+
* namespace, so a document nothing has renamed or hinted carries no editor slot
|
|
22
|
+
* rather than an empty one. A patch dropping keys the namespace does not have writes
|
|
23
|
+
* nothing, so dismissing tips on a document that carries none is not a mutation.
|
|
17
24
|
*/
|
|
18
25
|
export function patchEditorExt(doc, addr, patch) {
|
|
19
26
|
// `getExtNamespace` reads just this namespace rather than serializing the whole
|
|
20
27
|
// card to fish out one `$ext` slot.
|
|
21
|
-
const
|
|
28
|
+
const current = doc.getExtNamespace(addr, 'editor');
|
|
29
|
+
const next = { ...(current ?? {}) };
|
|
22
30
|
for (const [key, value] of Object.entries(patch)) {
|
|
23
31
|
if (value === undefined)
|
|
24
32
|
delete next[key];
|
|
25
33
|
else
|
|
26
34
|
next[key] = value;
|
|
27
35
|
}
|
|
28
|
-
|
|
36
|
+
if (Object.keys(next).length > 0)
|
|
37
|
+
doc.storeExtNamespace(addr, 'editor', next);
|
|
38
|
+
else if (current)
|
|
39
|
+
doc.removeExtNamespace(addr, 'editor');
|
|
29
40
|
}
|
|
@@ -9,9 +9,8 @@
|
|
|
9
9
|
|
|
10
10
|
interface Props extends Omit<SVGAttributes<SVGSVGElement>, 'name'> {
|
|
11
11
|
name: IconName;
|
|
12
|
-
/** The frame's edge, in px.
|
|
13
|
-
*
|
|
14
|
-
* right hang is measured against the same number. */
|
|
12
|
+
/** The frame's edge, in px. A chip sizes the glyph from `--_qm-glyph-control`
|
|
13
|
+
* in CSS, which beats this attribute; callers that are not chips pass a size. */
|
|
15
14
|
size?: number;
|
|
16
15
|
}
|
|
17
16
|
let { name, size = 24, ...rest }: Props = $props();
|
|
@@ -2,9 +2,8 @@ import { type IconName } from './nodes.js';
|
|
|
2
2
|
import type { SVGAttributes } from 'svelte/elements';
|
|
3
3
|
interface Props extends Omit<SVGAttributes<SVGSVGElement>, 'name'> {
|
|
4
4
|
name: IconName;
|
|
5
|
-
/** The frame's edge, in px.
|
|
6
|
-
*
|
|
7
|
-
* right hang is measured against the same number. */
|
|
5
|
+
/** The frame's edge, in px. A chip sizes the glyph from `--_qm-glyph-control`
|
|
6
|
+
* in CSS, which beats this attribute; callers that are not chips pass a size. */
|
|
8
7
|
size?: number;
|
|
9
8
|
}
|
|
10
9
|
declare const Icon: import("svelte").Component<Props, {}, "">;
|
package/dist/visual/strings.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ export interface VisualStrings extends TableChromeStrings, SlashStrings {
|
|
|
15
15
|
/** The card-title input's accessible name. */
|
|
16
16
|
cardTitle: string;
|
|
17
17
|
/** The trailing strip's visible words, which are also every strip's accessible
|
|
18
|
-
* name; the
|
|
18
|
+
* name; the plus rides the wording. One string over
|
|
19
19
|
* one kind and many: the trigger seeds A card, and which kind is the menu's word
|
|
20
20
|
* to say or the schema's to have already settled. */
|
|
21
21
|
addCard: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quillmark/svelte",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Editor, live-preview and source surfaces over a Quillmark WASM session.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"check": "svelte-check --tsconfig ./tsconfig.json"
|
|
67
67
|
},
|
|
68
68
|
"peerDependencies": {
|
|
69
|
-
"@quillmark/wasm": ">=0.108.
|
|
69
|
+
"@quillmark/wasm": ">=0.108.3-0",
|
|
70
70
|
"svelte": "^5.0.0"
|
|
71
71
|
},
|
|
72
72
|
"dependencies": {
|