@junoput01/junoui 0.5.0 → 0.7.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/CHANGELOG.md +188 -0
- package/README.md +44 -14
- package/dist/classes.json +1614 -0
- package/dist/css/juno.css +339 -37
- package/dist/icons/inline.js +7 -9
- package/dist/icons/install.js +26 -0
- package/docs/accessibility.md +6 -0
- package/docs/browser-support.md +176 -0
- package/docs/components/button.md +11 -2
- package/docs/components/dock.md +34 -0
- package/docs/components/fold-slot.md +26 -1
- package/docs/conformance-kit.md +243 -0
- package/docs/getting-started.md +36 -0
- package/docs/icon-subsetting.md +29 -0
- package/docs/integration.md +52 -6
- package/docs/ios-conformance.md +403 -4
- package/docs/ios-pwa.md +273 -0
- package/docs/layout.md +35 -0
- package/package.json +15 -3
- package/src/css/base.css +103 -23
- package/src/css/components/button.css +42 -2
- package/src/css/components/dock.css +65 -6
- package/src/css/components/fold-slot.css +49 -3
- package/src/css/components/input.css +12 -0
- package/src/css/components/pillbar.css +1 -1
- package/src/css/components/segmented.css +15 -2
- package/src/css/overrides.css +51 -0
- package/tools/testing.mjs +177 -0
package/dist/css/juno.css
CHANGED
|
@@ -370,13 +370,69 @@
|
|
|
370
370
|
/* Floating-nav scroll clearance — a page/scroller that a fixed dock or
|
|
371
371
|
pillbar floats over reserves this much room at its foot so the last row
|
|
372
372
|
clears the overlay. Consumers write `padding-block-end:
|
|
373
|
-
var(--juno-dock-clearance)
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
373
|
+
var(--juno-dock-clearance)`. Web-only (they carry env()), so they live in
|
|
374
|
+
the CSS layer, not the cross-platform token set.
|
|
375
|
+
|
|
376
|
+
DERIVED, not constant. These used to be `space-72 + space-20 + env()`,
|
|
377
|
+
which promised in this very comment to "stay correct when the dock
|
|
378
|
+
geometry changes" and could not: the floating pill measures 62px with the
|
|
379
|
+
default 44px bubble, and junoui explicitly invites a consumer to
|
|
380
|
+
parameterize that bubble (--juno-size-tap-comfortable). Past a 58px bubble
|
|
381
|
+
the old constant reserved LESS than the pill's own height plus its margin
|
|
382
|
+
— content hid under the dock, silently, on exactly the consumers who took
|
|
383
|
+
the invitation (20260815-026).
|
|
384
|
+
|
|
385
|
+
So the parts are named and the arithmetic is visible:
|
|
386
|
+
--juno-dock-h the pill's laid-out height: the bubble, the item's
|
|
387
|
+
padding-block, the pill's own padding, its border.
|
|
388
|
+
* -clearance-scale consumers that SHRINK the bar while scrolling
|
|
389
|
+
reserve at the small size, not the live one — a
|
|
390
|
+
reservation that tracks a value which changes after
|
|
391
|
+
the last scroll event relayouts content under a
|
|
392
|
+
finger that has already stopped moving. Default 1.
|
|
393
|
+
+ space-16 + env() the pill's own bottom margin (dock.css), additive
|
|
394
|
+
because a floating element sits OFF the edge —
|
|
395
|
+
docs/ios-conformance.md, "max() vs addition".
|
|
396
|
+
+ space-8 breathing room, so the last row is not flush. */
|
|
397
|
+
--juno-dock-h: calc(
|
|
398
|
+
var(--juno-size-tap-comfortable) + 4 * var(--juno-space-4) + 2 * var(--juno-border-width-1)
|
|
399
|
+
);
|
|
400
|
+
--juno-dock-clearance-scale: 1;
|
|
401
|
+
|
|
402
|
+
/* The bar's own offset from the bottom edge — declared ONCE and consumed by
|
|
403
|
+
both the bar's margin (dock.css) and the clearance below, so the two cannot
|
|
404
|
+
disagree about where the bar sits.
|
|
405
|
+
|
|
406
|
+
That is the whole reason this is a token rather than a literal in each
|
|
407
|
+
place. junoui's default is additive, per docs/ios-conformance.md: a
|
|
408
|
+
FLOATING element sits off the edge, so its gap and the inset stack. A
|
|
409
|
+
consumer whose design wants the bar flush above the home indicator instead
|
|
410
|
+
writes `max(8px, env(safe-area-inset-bottom, 0px))` here and BOTH the
|
|
411
|
+
margin and the reservation follow it. Before this token the form was baked
|
|
412
|
+
into each site separately, so a consumer that changed one silently
|
|
413
|
+
disagreed with the other — measured at 16px of dead band at inset 0 and
|
|
414
|
+
24px at inset 34 (20260815-055), and no single --juno-dock-h could
|
|
415
|
+
reconcile them because one side added the inset and the other maxed it. */
|
|
416
|
+
--juno-dock-edge-offset: calc(var(--juno-space-16) + env(safe-area-inset-bottom, 0px));
|
|
417
|
+
|
|
418
|
+
/* Gap between the bar's top edge and the last row of content. Zero is a
|
|
419
|
+
legitimate setting: a translucent bar that content is MEANT to scroll under
|
|
420
|
+
wants overlap, not breathing room. */
|
|
421
|
+
--juno-dock-clearance-breathing: var(--juno-space-8);
|
|
422
|
+
--juno-dock-clearance: calc(
|
|
423
|
+
var(--juno-dock-h) * var(--juno-dock-clearance-scale) + var(--juno-dock-edge-offset) +
|
|
424
|
+
var(--juno-dock-clearance-breathing)
|
|
425
|
+
);
|
|
426
|
+
|
|
427
|
+
/* The pillbar is the same shape one size down: no bubble, so its height is
|
|
428
|
+
the tap target plus its own padding and border. */
|
|
429
|
+
--juno-pillbar-h: calc(
|
|
430
|
+
var(--juno-size-tap-comfortable) + 2 * var(--juno-space-4) + 2 * var(--juno-border-width-1)
|
|
431
|
+
);
|
|
432
|
+
--juno-pillbar-clearance: calc(
|
|
433
|
+
var(--juno-pillbar-h) * var(--juno-dock-clearance-scale) + var(--juno-dock-edge-offset) +
|
|
434
|
+
var(--juno-dock-clearance-breathing)
|
|
435
|
+
);
|
|
380
436
|
|
|
381
437
|
/* JS-readable motion contract. CSS-only `prefers-reduced-motion` never reaches
|
|
382
438
|
imperative JS (scrollTo/scrollIntoView smooth behavior, rAF-driven transforms,
|
|
@@ -478,8 +534,11 @@ code, kbd, samp, pre { font-family: var(--juno-font-family-mono); }
|
|
|
478
534
|
is harmless either way: hold text-entry controls (.juno-input covers input,
|
|
479
535
|
textarea and the select's inner control) at a 16px floor on touch. max()
|
|
480
536
|
keeps the floor even under a scaled-down --juno-font-scale, and still grows
|
|
481
|
-
when scaled up.
|
|
482
|
-
|
|
537
|
+
when scaled up.
|
|
538
|
+
THE RULE ITSELF LIVES IN components/input.css, not here: a media query adds
|
|
539
|
+
no specificity, so this file's `.juno-input` would lose to input.css's own
|
|
540
|
+
`.juno-input` font-size later in the bundle. It did, silently, until
|
|
541
|
+
20260815-006's coarse-pointer project measured it. */
|
|
483
542
|
|
|
484
543
|
/* Kill the UA tap-highlight square on the interactive surfaces so it never
|
|
485
544
|
flashes past a rounded control on tap. Consumers were adding this by hand
|
|
@@ -489,7 +548,7 @@ code, kbd, samp, pre { font-family: var(--juno-font-family-mono); }
|
|
|
489
548
|
.juno-dock__item,
|
|
490
549
|
.juno-pillbar__item,
|
|
491
550
|
.juno-tabs__tab,
|
|
492
|
-
.juno-
|
|
551
|
+
.juno-list__row,
|
|
493
552
|
.juno-menu__item
|
|
494
553
|
) {
|
|
495
554
|
-webkit-tap-highlight-color: transparent;
|
|
@@ -514,9 +573,9 @@ code, kbd, samp, pre { font-family: var(--juno-font-family-mono); }
|
|
|
514
573
|
.juno-pillbar__item,
|
|
515
574
|
.juno-pillbar__overflow,
|
|
516
575
|
.juno-tabs__tab,
|
|
517
|
-
.juno-
|
|
576
|
+
.juno-list__row,
|
|
518
577
|
.juno-menu__item,
|
|
519
|
-
.juno-
|
|
578
|
+
.juno-seg__opt,
|
|
520
579
|
.juno-chip,
|
|
521
580
|
.juno-toggle-btn
|
|
522
581
|
) {
|
|
@@ -580,17 +639,11 @@ code, kbd, samp, pre { font-family: var(--juno-font-family-mono); }
|
|
|
580
639
|
:root { --juno-border: var(--juno-border-strong); }
|
|
581
640
|
}
|
|
582
641
|
|
|
583
|
-
/* Windows High Contrast / forced-colors:
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
.juno-badge,
|
|
589
|
-
.juno-btn,
|
|
590
|
-
.juno-card,
|
|
591
|
-
.juno-readout { border: 1px solid CanvasText; }
|
|
592
|
-
.juno-badge { forced-color-adjust: none; } /* keep status fill meaningful */
|
|
593
|
-
}
|
|
642
|
+
/* Windows High Contrast / forced-colors: the opt-in lives in
|
|
643
|
+
overrides.css, NOT here. A media query adds no specificity, and this file is
|
|
644
|
+
bundled BEFORE components/, so `.juno-btn { border: … }` in button.css beat
|
|
645
|
+
the forced-colors border every time — same 0,1,0 selector, later in the
|
|
646
|
+
bundle. See src/css/overrides.css and ticket 20260815-029. */
|
|
594
647
|
|
|
595
648
|
/* ── iOS standalone letterbox unlock ─────────────────────────────────────────
|
|
596
649
|
iOS WebKit (observed through 26.6, iPhone 16 Pro, iOS 18.7) sizes a
|
|
@@ -640,6 +693,33 @@ code, kbd, samp, pre { font-family: var(--juno-font-family-mono); }
|
|
|
640
693
|
}
|
|
641
694
|
}
|
|
642
695
|
|
|
696
|
+
/* ── Popover API absent (Safari/iOS < 17.0) ──────────────────────────────────
|
|
697
|
+
junoui's overlay surfaces are built on the native Popover API. Without it
|
|
698
|
+
`popovertarget` does nothing, so they cannot open — an inconvenience. The
|
|
699
|
+
part that is a BUG is that the UA rule which hides a closed popover
|
|
700
|
+
(`[popover]:not(:popover-open) { display: none }`) does not exist either, so
|
|
701
|
+
the panel participates in layout: .juno-menu and .juno-popover are
|
|
702
|
+
`position: fixed` with `opacity: 0` and no pointer-events reset, i.e. a
|
|
703
|
+
256-280px INVISIBLE panel parked at its static position, swallowing taps on
|
|
704
|
+
whatever it covers. (.juno-tooltip__bubble escapes it — it inherits
|
|
705
|
+
`pointer-events: none` from the CSS-only tooltip rule — and is listed anyway
|
|
706
|
+
so the set matches the docs.)
|
|
707
|
+
|
|
708
|
+
So: hide them. Absent beats invisibly-present. Apps detect the same condition
|
|
709
|
+
with CSS.supports('selector(:popover-open)') and render a fallback.
|
|
710
|
+
|
|
711
|
+
@supports selector() is itself Safari 14.1+; below that this condition is
|
|
712
|
+
invalid, the block is skipped, and behaviour is what it is today. Fail-open,
|
|
713
|
+
and far below any supported floor. Guards live here rather than per component
|
|
714
|
+
so the next popover-based component inherits it — see docs/browser-support.md
|
|
715
|
+
for the rule about when a feature gap earns a guard at all (functional
|
|
716
|
+
failures only; a missing animation does not get one). */
|
|
717
|
+
@supports not selector(:popover-open) {
|
|
718
|
+
.juno-menu[popover],
|
|
719
|
+
.juno-popover[popover],
|
|
720
|
+
.juno-tooltip__bubble[popover] { display: none; }
|
|
721
|
+
}
|
|
722
|
+
|
|
643
723
|
/* ════════════════════════════════════════════════════════════════════
|
|
644
724
|
* junoui — layout layer (intrinsic & responsive)
|
|
645
725
|
*
|
|
@@ -1342,8 +1422,10 @@ details.juno-accordion__item:only-child {
|
|
|
1342
1422
|
.juno-btn--ghost:hover { background: var(--juno-s2); filter: none; }
|
|
1343
1423
|
|
|
1344
1424
|
/* Small — for dense desktop toolbars (40–46px bars) where the default
|
|
1345
|
-
control would not fit.
|
|
1346
|
-
|
|
1425
|
+
control would not fit. Combines with --ghost + roles.
|
|
1426
|
+
On a FINE pointer this is 24px: the WCAG 2.2 AA floor (2.5.8) exactly, and
|
|
1427
|
+
no more. On a coarse pointer it promotes to the comfortable target — see
|
|
1428
|
+
below. */
|
|
1347
1429
|
.juno-btn--sm {
|
|
1348
1430
|
min-height: var(--juno-space-24);
|
|
1349
1431
|
font-size: var(--juno-font-size-11);
|
|
@@ -1352,6 +1434,44 @@ details.juno-accordion__item:only-child {
|
|
|
1352
1434
|
border-radius: var(--juno-radius-3);
|
|
1353
1435
|
}
|
|
1354
1436
|
|
|
1437
|
+
/* --sm names a DENSITY, and consumers reach for it as a SEMANTIC. Audited
|
|
1438
|
+
across one app: 40 call sites, nearly all of them `--sm --ghost` meaning
|
|
1439
|
+
"secondary", shipping a 24px target on a phone — and junoui's own showcase
|
|
1440
|
+
does it twice in a navbar action slot. A size modifier should not quietly
|
|
1441
|
+
become a tap-target decision, so on touch it holds the same floor every
|
|
1442
|
+
other control does. Type and padding still shrink: --sm stays a density
|
|
1443
|
+
modifier, it just stops being a touch-target one (20260826-026).
|
|
1444
|
+
|
|
1445
|
+
THE RULE LIVES HERE, not in base.css's (pointer: coarse) block: a media
|
|
1446
|
+
query adds no specificity, so a `.juno-btn--sm` there would lose to this
|
|
1447
|
+
file's own `.juno-btn--sm` later in the bundle. That is not a guess — it is
|
|
1448
|
+
what silently happened to the .juno-input font floor until 20260815-006
|
|
1449
|
+
measured it.
|
|
1450
|
+
|
|
1451
|
+
--dense is the opt-out, and it is deliberately only meaningful ON --sm:
|
|
1452
|
+
a dense touch toolbar is a real thing (a media scrubber, an editor rail),
|
|
1453
|
+
but it is a decision someone has to make by name rather than inherit from a
|
|
1454
|
+
size.
|
|
1455
|
+
|
|
1456
|
+
The two rules below are REDUNDANT ON PURPOSE, and mutation testing is how
|
|
1457
|
+
that became a decision rather than an accident: deleting either one leaves
|
|
1458
|
+
--dense at 24px. The `:not()` excludes a dense button from the promotion, so
|
|
1459
|
+
the pairing below it is dead weight — until the `:not()` names the wrong
|
|
1460
|
+
class, at which point the pairing (also (0,2,0), and later in the file) is
|
|
1461
|
+
the only thing holding the opt-out. Each covers the other's failure, so a
|
|
1462
|
+
single edit to either cannot silently promote a --dense button. Both
|
|
1463
|
+
selectors are (0,2,0) and mutually exclusive in the correct state, so they
|
|
1464
|
+
never race. */
|
|
1465
|
+
@media (pointer: coarse) {
|
|
1466
|
+
.juno-btn--sm:not(.juno-btn--dense) {
|
|
1467
|
+
min-height: var(--juno-size-tap-min);
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1470
|
+
.juno-btn--sm.juno-btn--dense {
|
|
1471
|
+
min-height: var(--juno-space-24);
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1355
1475
|
.juno-btn:disabled {
|
|
1356
1476
|
background: var(--juno-muted);
|
|
1357
1477
|
color: var(--juno-label);
|
|
@@ -1691,6 +1811,55 @@ button.juno-chip {
|
|
|
1691
1811
|
media query. */
|
|
1692
1812
|
--juno-dock-scale: 1;
|
|
1693
1813
|
|
|
1814
|
+
/* ── Horizontal budget contract ──────────────────────────────────────
|
|
1815
|
+
Published so a consumer's capacity planner ("how many items fit, and
|
|
1816
|
+
do they still hold a tap target?") reads junoui's real geometry
|
|
1817
|
+
instead of re-deriving it from the numbers in this file. Two
|
|
1818
|
+
consumers had derived it by hand, twice, in prose — and both had
|
|
1819
|
+
drifted: they subtracted 12px of inline padding where the pill
|
|
1820
|
+
actually spends 8, so their per-item width came out ~0.8px low at
|
|
1821
|
+
every viewport (20260826-027).
|
|
1822
|
+
|
|
1823
|
+
--juno-dock-items the item budget. junoui does not enforce it —
|
|
1824
|
+
__item is `flex: 1 1 0`, so the layout divides
|
|
1825
|
+
by however many items are present — it is the
|
|
1826
|
+
number the DERIVATIONS below are about, and the
|
|
1827
|
+
consumer sets it to what it renders.
|
|
1828
|
+
--juno-dock-item-inline the width one item gets. A prediction of what
|
|
1829
|
+
the flex layout produces, not an input to it;
|
|
1830
|
+
asserted against the measured box in the test
|
|
1831
|
+
suite so it cannot drift from the layout.
|
|
1832
|
+
--juno-dock-fit-inline the narrowest viewport at which every item
|
|
1833
|
+
still holds --juno-size-tap-comfortable. Use it
|
|
1834
|
+
in a media query and DROP an item; that is the
|
|
1835
|
+
answer junoui can give exactly.
|
|
1836
|
+
|
|
1837
|
+
A SCALE floor (44px / the item's width) is deliberately not published:
|
|
1838
|
+
it is a ratio of two lengths, and CSS cannot divide by a length. A
|
|
1839
|
+
consumer that must scale rather than drop compares
|
|
1840
|
+
--juno-dock-item-inline against --juno-size-tap-comfortable itself.
|
|
1841
|
+
|
|
1842
|
+
The three inline terms are declared ONCE here and consumed by both the
|
|
1843
|
+
variants' own margin/padding/border and the sums below, so the budget
|
|
1844
|
+
cannot disagree with the bar it describes — the same reason
|
|
1845
|
+
--juno-dock-edge-offset exists (20260815-055). The base bar is
|
|
1846
|
+
full-bleed with a top-edge border only, so all three are zero; --pill
|
|
1847
|
+
and --float set them. */
|
|
1848
|
+
--juno-dock-items: 5;
|
|
1849
|
+
--juno-dock-margin-inline: 0px;
|
|
1850
|
+
--juno-dock-pad-inline: 0px;
|
|
1851
|
+
--juno-dock-border-inline: 0px;
|
|
1852
|
+
--juno-dock-chrome-inline: calc(
|
|
1853
|
+
2 * (var(--juno-dock-margin-inline) + var(--juno-dock-pad-inline) + var(--juno-dock-border-inline))
|
|
1854
|
+
);
|
|
1855
|
+
--juno-dock-avail: 100vw;
|
|
1856
|
+
--juno-dock-item-inline: calc(
|
|
1857
|
+
(var(--juno-dock-avail) - var(--juno-dock-chrome-inline)) / var(--juno-dock-items)
|
|
1858
|
+
);
|
|
1859
|
+
--juno-dock-fit-inline: calc(
|
|
1860
|
+
var(--juno-dock-items) * var(--juno-size-tap-comfortable) + var(--juno-dock-chrome-inline)
|
|
1861
|
+
);
|
|
1862
|
+
|
|
1694
1863
|
position: sticky;
|
|
1695
1864
|
inset-block-end: 0;
|
|
1696
1865
|
z-index: var(--juno-z-raised);
|
|
@@ -1785,16 +1954,21 @@ button.juno-chip {
|
|
|
1785
1954
|
.juno-dock--pill {
|
|
1786
1955
|
--juno-role: var(--juno-active);
|
|
1787
1956
|
|
|
1957
|
+
/* the three inline terms the budget contract sums — see .juno-dock */
|
|
1958
|
+
--juno-dock-margin-inline: var(--juno-space-12);
|
|
1959
|
+
--juno-dock-pad-inline: var(--juno-space-4);
|
|
1960
|
+
--juno-dock-border-inline: var(--juno-border-width-1);
|
|
1961
|
+
|
|
1788
1962
|
position: fixed;
|
|
1789
1963
|
inset-inline: 0;
|
|
1790
1964
|
inset-block-end: 0;
|
|
1791
1965
|
z-index: var(--juno-z-raised);
|
|
1792
|
-
margin: 0 var(--juno-
|
|
1793
|
-
padding: var(--juno-
|
|
1966
|
+
margin: 0 var(--juno-dock-margin-inline) var(--juno-dock-edge-offset);
|
|
1967
|
+
padding: var(--juno-dock-pad-inline);
|
|
1794
1968
|
background: color-mix(in srgb, var(--juno-s1) 88%, transparent);
|
|
1795
1969
|
-webkit-backdrop-filter: blur(12px);
|
|
1796
1970
|
backdrop-filter: blur(12px);
|
|
1797
|
-
border: var(--juno-border-
|
|
1971
|
+
border: var(--juno-dock-border-inline) solid var(--juno-border);
|
|
1798
1972
|
border-radius: 999px;
|
|
1799
1973
|
box-shadow: var(--juno-shadow-2);
|
|
1800
1974
|
}
|
|
@@ -1888,17 +2062,22 @@ button.juno-chip {
|
|
|
1888
2062
|
Out of flow (fixed) so the page scrolls UNDER it — reserve room on the
|
|
1889
2063
|
scroller with padding-block-end: var(--juno-dock-clearance). */
|
|
1890
2064
|
.juno-dock--float {
|
|
2065
|
+
/* the three inline terms the budget contract sums — see .juno-dock */
|
|
2066
|
+
--juno-dock-margin-inline: var(--juno-space-12);
|
|
2067
|
+
--juno-dock-pad-inline: var(--juno-space-4);
|
|
2068
|
+
--juno-dock-border-inline: var(--juno-border-width-1);
|
|
2069
|
+
|
|
1891
2070
|
position: fixed;
|
|
1892
2071
|
inset-inline: 0;
|
|
1893
2072
|
inset-block-end: 0;
|
|
1894
2073
|
z-index: var(--juno-z-raised);
|
|
1895
|
-
margin: 0 var(--juno-
|
|
1896
|
-
padding: var(--juno-
|
|
2074
|
+
margin: 0 var(--juno-dock-margin-inline) var(--juno-dock-edge-offset);
|
|
2075
|
+
padding: var(--juno-dock-pad-inline);
|
|
1897
2076
|
overflow: hidden;
|
|
1898
2077
|
background: color-mix(in srgb, var(--juno-s1) 88%, transparent);
|
|
1899
2078
|
-webkit-backdrop-filter: blur(12px);
|
|
1900
2079
|
backdrop-filter: blur(12px);
|
|
1901
|
-
border: var(--juno-border-
|
|
2080
|
+
border: var(--juno-dock-border-inline) solid var(--juno-border);
|
|
1902
2081
|
border-radius: 999px;
|
|
1903
2082
|
box-shadow: var(--juno-shadow-2);
|
|
1904
2083
|
}
|
|
@@ -2276,17 +2455,44 @@ button.juno-chip {
|
|
|
2276
2455
|
* gap, the folded slot still occupies one gap — name it in
|
|
2277
2456
|
* --juno-fold-gap and the fold swallows it with a negative margin.
|
|
2278
2457
|
*
|
|
2458
|
+
* COMPOSITION. The canonical use puts .juno-fold on an element that is
|
|
2459
|
+
* already a component — a .juno-pillbar__item, a .juno-btn, a .juno-chip
|
|
2460
|
+
* — because that is where the capsule chrome (tap floor, padding, hover,
|
|
2461
|
+
* focus ring, aria-pressed) lives. Two things follow, and both are
|
|
2462
|
+
* load-bearing rather than defensive:
|
|
2463
|
+
*
|
|
2464
|
+
* 1. The fold's own declarations are stated at ATTRIBUTE specificity
|
|
2465
|
+
* (0,2,0), on both branches of data-juno-in, i.e. always. A component
|
|
2466
|
+
* class is (0,1,0), and `transition` is a SHORTHAND: a later rule does
|
|
2467
|
+
* not add to the list, it replaces it. Measured in Chromium against the
|
|
2468
|
+
* built bundle, before this was raised: on a
|
|
2469
|
+
* .juno-fold.juno-pillbar__item, transition-property resolved to
|
|
2470
|
+
* `color, background-color` — pillbar.css sorts after this file, so the
|
|
2471
|
+
* fold had no transition at all and jumped shut instead of folding.
|
|
2472
|
+
* inline-size and overflow would lose the same way to a component that
|
|
2473
|
+
* sets either.
|
|
2474
|
+
*
|
|
2475
|
+
* 2. Owning `transition` means owning ALL of it, so the capsule chrome
|
|
2476
|
+
* properties are in the fold's list too, at the quick duration the
|
|
2477
|
+
* components themselves use. Dropping them would trade a broken fold
|
|
2478
|
+
* for a broken hover.
|
|
2479
|
+
*
|
|
2480
|
+
* Which floors the fold RELEASES when folded — see the folded rule below:
|
|
2481
|
+
* min-inline-size, padding-inline, border-inline-width. Those are exactly
|
|
2482
|
+
* the three inputs that can hold a border-box inline size above zero.
|
|
2483
|
+
*
|
|
2279
2484
|
* Canonical use: a transient action in a toolbar/pill row (a
|
|
2280
2485
|
* scroll-to-top arrow, a contextual button) whose arrival should slide
|
|
2281
2486
|
* the row open rather than jump it.
|
|
2282
2487
|
* Usage:
|
|
2283
2488
|
* <div style="display:flex; gap:4px"> (any row)
|
|
2284
|
-
* <button class="juno-fold" data-juno-in aria-label="Scroll to top">…</button>
|
|
2489
|
+
* <button class="juno-fold juno-pillbar__item" data-juno-in aria-label="Scroll to top">…</button>
|
|
2285
2490
|
* …other members…
|
|
2286
2491
|
* </div>
|
|
2287
2492
|
* prefers-reduced-motion needs nothing component-local — the base
|
|
2288
2493
|
* layer zeroes every transition duration. */
|
|
2289
|
-
.juno-fold
|
|
2494
|
+
.juno-fold[data-juno-in],
|
|
2495
|
+
.juno-fold:not([data-juno-in]) {
|
|
2290
2496
|
--juno-fold-size: var(--juno-size-tap-comfortable);
|
|
2291
2497
|
--juno-fold-gap: 0px;
|
|
2292
2498
|
|
|
@@ -2295,13 +2501,32 @@ button.juno-chip {
|
|
|
2295
2501
|
overflow: hidden;
|
|
2296
2502
|
transition:
|
|
2297
2503
|
inline-size var(--juno-motion-duration-base) var(--juno-motion-ease-standard),
|
|
2504
|
+
min-inline-size var(--juno-motion-duration-base) var(--juno-motion-ease-standard),
|
|
2505
|
+
padding var(--juno-motion-duration-base) var(--juno-motion-ease-standard),
|
|
2506
|
+
border-width var(--juno-motion-duration-base) var(--juno-motion-ease-standard),
|
|
2298
2507
|
margin var(--juno-motion-duration-base) var(--juno-motion-ease-standard),
|
|
2299
2508
|
opacity var(--juno-motion-duration-base) var(--juno-motion-ease-standard),
|
|
2300
|
-
visibility var(--juno-motion-duration-base) var(--juno-motion-ease-standard)
|
|
2509
|
+
visibility var(--juno-motion-duration-base) var(--juno-motion-ease-standard),
|
|
2510
|
+
color var(--juno-motion-duration-quick) var(--juno-motion-ease-standard),
|
|
2511
|
+
background-color var(--juno-motion-duration-quick) var(--juno-motion-ease-standard);
|
|
2301
2512
|
}
|
|
2302
2513
|
|
|
2514
|
+
/* Folded away. A min-* floor clamps the USED value whichever rule won the
|
|
2515
|
+
cascade, and a border-box inline size can never resolve below its own
|
|
2516
|
+
padding plus border — so a composed capsule holds the slot open however
|
|
2517
|
+
hard the fold pushes. Measured against the built bundle, composed with
|
|
2518
|
+
.juno-pillbar__item at a 390px viewport: 44px with both floors in place
|
|
2519
|
+
(the tap target), 20px with min-inline-size released (the padding alone),
|
|
2520
|
+
0px with all of them released.
|
|
2521
|
+
min-inline-size is in the transition list above for the OPENING half:
|
|
2522
|
+
released to 0 it would otherwise snap back to the capsule's tap floor the
|
|
2523
|
+
instant data-juno-in returns, and the used width — max(inline-size,
|
|
2524
|
+
min-inline-size) — would jump to full width with nothing to animate. */
|
|
2303
2525
|
.juno-fold:not([data-juno-in]) {
|
|
2304
2526
|
inline-size: 0;
|
|
2527
|
+
min-inline-size: 0;
|
|
2528
|
+
padding-inline: 0;
|
|
2529
|
+
border-inline-width: 0;
|
|
2305
2530
|
margin-inline-end: calc(-1 * var(--juno-fold-gap));
|
|
2306
2531
|
opacity: 0;
|
|
2307
2532
|
visibility: hidden;
|
|
@@ -2522,6 +2747,18 @@ button.juno-chip {
|
|
|
2522
2747
|
color: var(--juno-data);
|
|
2523
2748
|
}
|
|
2524
2749
|
|
|
2750
|
+
/* The iOS focus-zoom floor, and it has to live HERE, not in base.css's
|
|
2751
|
+
`@media (pointer: coarse)` block where it was written. A media query adds no
|
|
2752
|
+
specificity, so `.juno-input { font-size: var(--juno-font-size-14) }` above —
|
|
2753
|
+
same 0,1,0 selector, later in the bundle (base.css sorts before components/)
|
|
2754
|
+
— simply won it, and the floor never applied on any touch device. Nothing
|
|
2755
|
+
caught it because the suite had no coarse-pointer project until 20260815-006
|
|
2756
|
+
added one; the numeric assertion in test/visual/tap-targets.spec.mjs is what
|
|
2757
|
+
surfaced it. See base.css for the sourcing caveat on the behavior itself. */
|
|
2758
|
+
@media (pointer: coarse) {
|
|
2759
|
+
.juno-input { font-size: max(16px, var(--juno-font-size-16)); }
|
|
2760
|
+
}
|
|
2761
|
+
|
|
2525
2762
|
.juno-input--sans { font-family: var(--juno-font-family-sans); }
|
|
2526
2763
|
|
|
2527
2764
|
.juno-input::placeholder { color: var(--juno-muted); }
|
|
@@ -3734,7 +3971,7 @@ button.juno-list__row:disabled {
|
|
|
3734
3971
|
<svg class="juno-icon" aria-hidden="true"><use href="…#juno-i-dots-three" /></svg>
|
|
3735
3972
|
</button>
|
|
3736
3973
|
<div class="juno-pillbar__tray">
|
|
3737
|
-
<div
|
|
3974
|
+
<div>\3c !-- single wrapper, any element -->
|
|
3738
3975
|
…the usual __item / __sep / __input children…
|
|
3739
3976
|
</div>
|
|
3740
3977
|
</div>
|
|
@@ -4116,11 +4353,20 @@ button.juno-list__row:disabled {
|
|
|
4116
4353
|
opacity: 0;
|
|
4117
4354
|
}
|
|
4118
4355
|
|
|
4119
|
-
/* the pill — a span after the radio, or the aria-pressed button itself
|
|
4356
|
+
/* the pill — a span after the radio, or the aria-pressed button itself.
|
|
4357
|
+
The tap floor is on the PAINTED box, not on the label that wraps it: the
|
|
4358
|
+
label is a bare inline-flex and takes its height from this. Segmented is a
|
|
4359
|
+
phone-first control and is routinely the only control on a whole settings
|
|
4360
|
+
section, so it holds --juno-size-tap-min like .juno-btn does — 24px (WCAG
|
|
4361
|
+
2.2 AA, 2.5.8) on a fine pointer, promoted to the 44px comfortable target
|
|
4362
|
+
under (pointer: coarse) by base.css. Without it the pill computed ~25px
|
|
4363
|
+
from its padding alone, which is the AA floor by accident and nothing on
|
|
4364
|
+
touch. See 20260826-025. */
|
|
4120
4365
|
.juno-seg__opt input + span,
|
|
4121
4366
|
button.juno-seg__opt {
|
|
4122
4367
|
display: inline-flex;
|
|
4123
4368
|
align-items: center;
|
|
4369
|
+
min-block-size: var(--juno-size-tap-min);
|
|
4124
4370
|
gap: var(--juno-gap-control);
|
|
4125
4371
|
font-family: var(--juno-font-family-sans);
|
|
4126
4372
|
font-size: var(--juno-font-size-11);
|
|
@@ -4168,7 +4414,11 @@ button.juno-seg__opt:disabled {
|
|
|
4168
4414
|
cursor: not-allowed;
|
|
4169
4415
|
}
|
|
4170
4416
|
|
|
4171
|
-
/* Small —
|
|
4417
|
+
/* Small — dense toolbars: less type, tighter padding. UNLIKE .juno-btn--sm it
|
|
4418
|
+
does NOT drop below the tap floor, which the base rule above holds: --sm is a
|
|
4419
|
+
density modifier here, not an opt-out of the touch target. A segmented row is
|
|
4420
|
+
often the only control on a settings section, so a sub-tap variant of it has
|
|
4421
|
+
no safe use on a phone. */
|
|
4172
4422
|
.juno-seg--sm .juno-seg__opt input + span,
|
|
4173
4423
|
.juno-seg--sm > button.juno-seg__opt {
|
|
4174
4424
|
font-size: var(--juno-font-size-10);
|
|
@@ -5794,3 +6044,55 @@ button.juno-seg__opt:disabled {
|
|
|
5794
6044
|
white-space: nowrap;
|
|
5795
6045
|
border: 0;
|
|
5796
6046
|
}
|
|
6047
|
+
|
|
6048
|
+
/* ════════════════════════════════════════════════════════════════════
|
|
6049
|
+
* Overrides — cross-cutting gates, bundled LAST
|
|
6050
|
+
* ════════════════════════════════════════════════════════════════════
|
|
6051
|
+
* A @media or @supports block adds NO specificity. So a gate written in
|
|
6052
|
+
* base.css — which the bundler emits before components/ — loses to any
|
|
6053
|
+
* component rule declaring the same property on the same selector, purely
|
|
6054
|
+
* on source order, and loses SILENTLY: the gate looks right in the file it
|
|
6055
|
+
* was written in, and there is no error anywhere.
|
|
6056
|
+
*
|
|
6057
|
+
* Four instances of that shipped before this file existed (2026-08-15):
|
|
6058
|
+
* - .juno-input's 16px iOS focus-zoom floor, beaten by input.css. The floor
|
|
6059
|
+
* never applied on any touch device, in any release (20260815-011).
|
|
6060
|
+
* - the forced-colors border below, beaten by button.css / badge.css /
|
|
6061
|
+
* card.css (20260815-029).
|
|
6062
|
+
* - the Popover fallback, which happens to win today only because nothing
|
|
6063
|
+
* later declares `display` on those selectors — pinned by a test rather
|
|
6064
|
+
* than by structure (20260815-013).
|
|
6065
|
+
*
|
|
6066
|
+
* So: gates whose whole job is to BEAT a component default live here, after
|
|
6067
|
+
* everything they guard. Same reasoning the bundler already applies to
|
|
6068
|
+
* utilities.css (role helpers must outrank component defaults) — see
|
|
6069
|
+
* scripts/bundle-css.mjs.
|
|
6070
|
+
*
|
|
6071
|
+
* What does NOT belong here: a gate that only has to beat the UA or another
|
|
6072
|
+
* rule in its own file. Keep those next to what they modify; this file is for
|
|
6073
|
+
* the cross-file case, or it becomes a dumping ground and the cascade gets
|
|
6074
|
+
* harder to read rather than easier.
|
|
6075
|
+
*
|
|
6076
|
+
* A build test (test/build.test.mjs) asserts the bundle contains no gated
|
|
6077
|
+
* declaration that a later ungated rule overrides at equal-or-lower
|
|
6078
|
+
* specificity. It asserts an EMPTY SET — no allowlist, because an allowlist
|
|
6079
|
+
* is where violations go to be forgotten.
|
|
6080
|
+
* ════════════════════════════════════════════════════════════════════ */
|
|
6081
|
+
|
|
6082
|
+
/* Windows High Contrast / forced-colors: opt into the system palette so
|
|
6083
|
+
borders and focus stay visible when the user's palette replaces ours.
|
|
6084
|
+
|
|
6085
|
+
.juno-badge additionally sets `forced-color-adjust: none` to keep its status
|
|
6086
|
+
fill meaningful — and that opt-out is why the badge was the one element where
|
|
6087
|
+
the lost cascade actually reached the screen: it also disables the UA's own
|
|
6088
|
+
repaint, which was silently rescuing .juno-btn and .juno-card. Measured, not
|
|
6089
|
+
inferred (20260815-029). */
|
|
6090
|
+
@media (forced-colors: active) {
|
|
6091
|
+
*:focus-visible { outline-color: Highlight; }
|
|
6092
|
+
|
|
6093
|
+
.juno-badge,
|
|
6094
|
+
.juno-btn,
|
|
6095
|
+
.juno-card,
|
|
6096
|
+
.juno-readout { border: 1px solid CanvasText; }
|
|
6097
|
+
.juno-badge { forced-color-adjust: none; } /* keep status fill meaningful */
|
|
6098
|
+
}
|
package/dist/icons/inline.js
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
|
-
// junoui — inline icon sprite injector. Generated; do not edit.
|
|
1
|
+
// junoui — inline icon sprite injector (full set). Generated; do not edit.
|
|
2
2
|
// Fixes Safari dropping external <use href="file.svg#id"> refs: this injects
|
|
3
3
|
// the sprite into the document so you reference icons same-document instead:
|
|
4
4
|
// import '@junoput01/junoui/icons/inline';
|
|
5
5
|
// <svg class="juno-icon"><use href="#juno-i-gear" /></svg>
|
|
6
|
+
// Shipping a SUBSET instead? Import junoui/icons/install and pass it, so this
|
|
7
|
+
// module's 25 kB of symbols never enters your bundle.
|
|
8
|
+
import { installSprite } from './install.js';
|
|
9
|
+
|
|
6
10
|
const SPRITE = "<svg xmlns=\"http://www.w3.org/2000/svg\" style=\"display:none\" fill=\"currentColor\">\n <symbol id=\"juno-i-arrow-clockwise\" viewBox=\"0 0 256 256\"><path d=\"M244,56v48a12,12,0,0,1-12,12H184a12,12,0,1,1,0-24H201.1l-19-17.38c-.13-.12-.26-.24-.38-.37A76,76,0,1,0,127,204h1a75.53,75.53,0,0,0,52.15-20.72,12,12,0,0,1,16.49,17.45A99.45,99.45,0,0,1,128,228h-1.37A100,100,0,1,1,198.51,57.06L220,76.72V56a12,12,0,0,1,24,0Z\"/></symbol>\n <symbol id=\"juno-i-arrow-down\" viewBox=\"0 0 256 256\"><path d=\"M208.49,152.49l-72,72a12,12,0,0,1-17,0l-72-72a12,12,0,0,1,17-17L116,187V40a12,12,0,0,1,24,0V187l51.51-51.52a12,12,0,0,1,17,17Z\"/></symbol>\n <symbol id=\"juno-i-arrow-left\" viewBox=\"0 0 256 256\"><path d=\"M228,128a12,12,0,0,1-12,12H69l51.52,51.51a12,12,0,0,1-17,17l-72-72a12,12,0,0,1,0-17l72-72a12,12,0,0,1,17,17L69,116H216A12,12,0,0,1,228,128Z\"/></symbol>\n <symbol id=\"juno-i-arrow-right\" viewBox=\"0 0 256 256\"><path d=\"M224.49,136.49l-72,72a12,12,0,0,1-17-17L187,140H40a12,12,0,0,1,0-24H187L135.51,64.48a12,12,0,0,1,17-17l72,72A12,12,0,0,1,224.49,136.49Z\"/></symbol>\n <symbol id=\"juno-i-arrow-up\" viewBox=\"0 0 256 256\"><path d=\"M208.49,120.49a12,12,0,0,1-17,0L140,69V216a12,12,0,0,1-24,0V69L64.49,120.49a12,12,0,0,1-17-17l72-72a12,12,0,0,1,17,0l72,72A12,12,0,0,1,208.49,120.49Z\"/></symbol>\n <symbol id=\"juno-i-arrows-clockwise\" viewBox=\"0 0 256 256\"><path d=\"M228,48V96a12,12,0,0,1-12,12H168a12,12,0,0,1,0-24h19l-7.8-7.8a75.55,75.55,0,0,0-53.32-22.26h-.43A75.49,75.49,0,0,0,72.39,75.57,12,12,0,1,1,55.61,58.41a99.38,99.38,0,0,1,69.87-28.47H126A99.42,99.42,0,0,1,196.2,59.23L204,67V48a12,12,0,0,1,24,0ZM183.61,180.43a75.49,75.49,0,0,1-53.09,21.63h-.43A75.55,75.55,0,0,1,76.77,179.8L69,172H88a12,12,0,0,0,0-24H40a12,12,0,0,0-12,12v48a12,12,0,0,0,24,0V189l7.8,7.8A99.42,99.42,0,0,0,130,226.06h.56a99.38,99.38,0,0,0,69.87-28.47,12,12,0,0,0-16.78-17.16Z\"/></symbol>\n <symbol id=\"juno-i-arrows-out\" viewBox=\"0 0 256 256\"><path d=\"M220,48V96a12,12,0,0,1-24,0V77l-35.51,35.52a12,12,0,0,1-17-17L179,60H160a12,12,0,0,1,0-24h48A12,12,0,0,1,220,48ZM95.51,143.51,60,179V160a12,12,0,0,0-24,0v48a12,12,0,0,0,12,12H96a12,12,0,0,0,0-24H77l35.52-35.51a12,12,0,0,0-17-17ZM208,148a12,12,0,0,0-12,12v19l-35.51-35.52a12,12,0,0,0-17,17L179,196H160a12,12,0,0,0,0,24h48a12,12,0,0,0,12-12V160A12,12,0,0,0,208,148ZM77,60H96a12,12,0,0,0,0-24H48A12,12,0,0,0,36,48V96a12,12,0,0,0,24,0V77l35.51,35.52a12,12,0,0,0,17-17Z\"/></symbol>\n <symbol id=\"juno-i-bell\" viewBox=\"0 0 256 256\"><path d=\"M225.29,165.93C216.61,151,212,129.57,212,104a84,84,0,0,0-168,0c0,25.58-4.59,47-13.27,61.93A20.08,20.08,0,0,0,30.66,186,19.77,19.77,0,0,0,48,196H84.18a44,44,0,0,0,87.64,0H208a19.77,19.77,0,0,0,17.31-10A20.08,20.08,0,0,0,225.29,165.93ZM128,212a20,20,0,0,1-19.6-16h39.2A20,20,0,0,1,128,212ZM54.66,172C63.51,154,68,131.14,68,104a60,60,0,0,1,120,0c0,27.13,4.48,50,13.33,68Z\"/></symbol>\n <symbol id=\"juno-i-calendar-blank\" viewBox=\"0 0 256 256\"><path d=\"M208,28H188V24a12,12,0,0,0-24,0v4H92V24a12,12,0,0,0-24,0v4H48A20,20,0,0,0,28,48V208a20,20,0,0,0,20,20H208a20,20,0,0,0,20-20V48A20,20,0,0,0,208,28ZM68,52a12,12,0,0,0,24,0h72a12,12,0,0,0,24,0h16V76H52V52ZM52,204V100H204V204Z\"/></symbol>\n <symbol id=\"juno-i-caret-down\" viewBox=\"0 0 256 256\"><path d=\"M216.49,104.49l-80,80a12,12,0,0,1-17,0l-80-80a12,12,0,0,1,17-17L128,159l71.51-71.52a12,12,0,0,1,17,17Z\"/></symbol>\n <symbol id=\"juno-i-caret-left\" viewBox=\"0 0 256 256\"><path d=\"M168.49,199.51a12,12,0,0,1-17,17l-80-80a12,12,0,0,1,0-17l80-80a12,12,0,0,1,17,17L97,128Z\"/></symbol>\n <symbol id=\"juno-i-caret-right\" viewBox=\"0 0 256 256\"><path d=\"M184.49,136.49l-80,80a12,12,0,0,1-17-17L159,128,87.51,56.49a12,12,0,1,1,17-17l80,80A12,12,0,0,1,184.49,136.49Z\"/></symbol>\n <symbol id=\"juno-i-caret-up\" viewBox=\"0 0 256 256\"><path d=\"M216.49,168.49a12,12,0,0,1-17,0L128,97,56.49,168.49a12,12,0,0,1-17-17l80-80a12,12,0,0,1,17,0l80,80A12,12,0,0,1,216.49,168.49Z\"/></symbol>\n <symbol id=\"juno-i-chat-circle\" viewBox=\"0 0 256 256\"><path d=\"M128,20A108,108,0,0,0,31.85,177.23L21,209.66A20,20,0,0,0,46.34,235l32.43-10.81A108,108,0,1,0,128,20Zm0,192a84,84,0,0,1-42.06-11.27,12,12,0,0,0-6-1.62,12.1,12.1,0,0,0-3.8.62l-29.79,9.93,9.93-29.79a12,12,0,0,0-1-9.81A84,84,0,1,1,128,212Z\"/></symbol>\n <symbol id=\"juno-i-check-circle\" viewBox=\"0 0 256 256\"><path d=\"M176.49,95.51a12,12,0,0,1,0,17l-56,56a12,12,0,0,1-17,0l-24-24a12,12,0,1,1,17-17L112,143l47.51-47.52A12,12,0,0,1,176.49,95.51ZM236,128A108,108,0,1,1,128,20,108.12,108.12,0,0,1,236,128Zm-24,0a84,84,0,1,0-84,84A84.09,84.09,0,0,0,212,128Z\"/></symbol>\n <symbol id=\"juno-i-check\" viewBox=\"0 0 256 256\"><path d=\"M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z\"/></symbol>\n <symbol id=\"juno-i-clock\" viewBox=\"0 0 256 256\"><path d=\"M128,20A108,108,0,1,0,236,128,108.12,108.12,0,0,0,128,20Zm0,192a84,84,0,1,1,84-84A84.09,84.09,0,0,1,128,212Zm68-84a12,12,0,0,1-12,12H128a12,12,0,0,1-12-12V72a12,12,0,0,1,24,0v44h44A12,12,0,0,1,196,128Z\"/></symbol>\n <symbol id=\"juno-i-cloud-arrow-down\" viewBox=\"0 0 256 256\"><path d=\"M192.49,167.51a12,12,0,0,1,0,17l-32,32a12,12,0,0,1-17,0l-32-32a12,12,0,1,1,17-17L140,179V128a12,12,0,0,1,24,0v51l11.51-11.52A12,12,0,0,1,192.49,167.51ZM160,36A92.08,92.08,0,0,0,79,84.37,68,68,0,1,0,72,220H84a12,12,0,0,0,0-24H72a44,44,0,0,1-1.81-87.95A91.7,91.7,0,0,0,68,128a12,12,0,0,0,24,0,68,68,0,0,1,136,0,67.27,67.27,0,0,1-7.25,30.59,12,12,0,1,0,21.42,10.82A91.08,91.08,0,0,0,252,128,92.1,92.1,0,0,0,160,36Z\"/></symbol>\n <symbol id=\"juno-i-cloud-slash\" viewBox=\"0 0 256 256\"><path d=\"M56.88,31.93A12,12,0,1,0,39.12,48.07L71.79,84A68,68,0,0,0,72,220h88a91.26,91.26,0,0,0,30.66-5.24l8.46,9.31a12,12,0,0,0,17.76-16.14ZM160,196H72a44,44,0,0,1-1.8-87.95A91.91,91.91,0,0,0,68,128a12,12,0,0,0,24,0,68.22,68.22,0,0,1,2.66-18.84l77.88,85.67A68.67,68.67,0,0,1,160,196Zm92-68a91.32,91.32,0,0,1-17.53,54,12,12,0,1,1-19.41-14.11,68,68,0,0,0-89.57-98.53,12,12,0,0,1-12.2-20.66A92,92,0,0,1,252,128Z\"/></symbol>\n <symbol id=\"juno-i-cloud\" viewBox=\"0 0 256 256\"><path d=\"M160,36A92.09,92.09,0,0,0,79,84.36,68,68,0,1,0,72,220h88a92,92,0,0,0,0-184Zm0,160H72a44,44,0,0,1-1.82-88A91.86,91.86,0,0,0,68,128a12,12,0,0,0,24,0,68,68,0,1,1,68,68Z\"/></symbol>\n <symbol id=\"juno-i-copy\" viewBox=\"0 0 256 256\"><path d=\"M216,28H88A12,12,0,0,0,76,40V76H40A12,12,0,0,0,28,88V216a12,12,0,0,0,12,12H168a12,12,0,0,0,12-12V180h36a12,12,0,0,0,12-12V40A12,12,0,0,0,216,28ZM156,204H52V100H156Zm48-48H180V88a12,12,0,0,0-12-12H100V52H204Z\"/></symbol>\n <symbol id=\"juno-i-cpu\" viewBox=\"0 0 256 256\"><path d=\"M156,88H100a12,12,0,0,0-12,12v56a12,12,0,0,0,12,12h56a12,12,0,0,0,12-12V100A12,12,0,0,0,156,88Zm-12,56H112V112h32Zm88-4H220V116h12a12,12,0,0,0,0-24H220V56a20,20,0,0,0-20-20H164V24a12,12,0,0,0-24,0V36H116V24a12,12,0,0,0-24,0V36H56A20,20,0,0,0,36,56V92H24a12,12,0,0,0,0,24H36v24H24a12,12,0,0,0,0,24H36v36a20,20,0,0,0,20,20H92v12a12,12,0,0,0,24,0V220h24v12a12,12,0,0,0,24,0V220h36a20,20,0,0,0,20-20V164h12a12,12,0,0,0,0-24Zm-36,56H60V60H196Z\"/></symbol>\n <symbol id=\"juno-i-dots-three-vertical\" viewBox=\"0 0 256 256\"><path d=\"M112,60a16,16,0,1,1,16,16A16,16,0,0,1,112,60Zm16,52a16,16,0,1,0,16,16A16,16,0,0,0,128,112Zm0,68a16,16,0,1,0,16,16A16,16,0,0,0,128,180Z\"/></symbol>\n <symbol id=\"juno-i-dots-three\" viewBox=\"0 0 256 256\"><path d=\"M144,128a16,16,0,1,1-16-16A16,16,0,0,1,144,128ZM60,112a16,16,0,1,0,16,16A16,16,0,0,0,60,112Zm136,0a16,16,0,1,0,16,16A16,16,0,0,0,196,112Z\"/></symbol>\n <symbol id=\"juno-i-download\" viewBox=\"0 0 256 256\"><path d=\"M71.51,88.49a12,12,0,0,1,17-17L116,99V24a12,12,0,0,1,24,0V99l27.51-27.52a12,12,0,0,1,17,17l-48,48a12,12,0,0,1-17,0ZM224,116H188a12,12,0,0,0,0,24h32v56H36V140H68a12,12,0,0,0,0-24H32a20,20,0,0,0-20,20v64a20,20,0,0,0,20,20H224a20,20,0,0,0,20-20V136A20,20,0,0,0,224,116Zm-20,52a16,16,0,1,0-16,16A16,16,0,0,0,204,168Z\"/></symbol>\n <symbol id=\"juno-i-envelope\" viewBox=\"0 0 256 256\"><path d=\"M224,44H32A12,12,0,0,0,20,56V192a20,20,0,0,0,20,20H216a20,20,0,0,0,20-20V56A12,12,0,0,0,224,44Zm-96,83.72L62.85,68h130.3ZM92.79,128,44,172.72V83.28Zm17.76,16.28,9.34,8.57a12,12,0,0,0,16.22,0l9.34-8.57L193.15,188H62.85ZM163.21,128,212,83.28v89.44Z\"/></symbol>\n <symbol id=\"juno-i-eye-slash\" viewBox=\"0 0 256 256\"><path d=\"M56.88,31.93A12,12,0,1,0,39.12,48.07l16,17.65C20.67,88.66,5.72,121.58,5,123.13a12.08,12.08,0,0,0,0,9.75c.37.82,9.13,20.26,28.49,39.61C59.37,198.34,92,212,128,212a131.34,131.34,0,0,0,51-10l20.09,22.1a12,12,0,0,0,17.76-16.14ZM128,188c-29.59,0-55.47-10.73-76.91-31.88A130.69,130.69,0,0,1,29.52,128c5.27-9.31,18.79-29.9,42-44.29l90.09,99.11A109.33,109.33,0,0,1,128,188Zm123-55.12c-.36.81-9,20-28,39.16a12,12,0,1,1-17-16.9A130.48,130.48,0,0,0,226.48,128a130.36,130.36,0,0,0-21.57-28.12C183.46,78.73,157.59,68,128,68c-3.35,0-6.7.14-10,.42a12,12,0,1,1-2-23.91c3.93-.34,8-.51,12-.51,36,0,68.63,13.67,94.49,39.52,19.35,19.35,28.11,38.8,28.48,39.61A12.08,12.08,0,0,1,251,132.88Z\"/></symbol>\n <symbol id=\"juno-i-eye\" viewBox=\"0 0 256 256\"><path d=\"M251,123.13c-.37-.81-9.13-20.26-28.48-39.61C196.63,57.67,164,44,128,44S59.37,57.67,33.51,83.52C14.16,102.87,5.4,122.32,5,123.13a12.08,12.08,0,0,0,0,9.75c.37.82,9.13,20.26,28.49,39.61C59.37,198.34,92,212,128,212s68.63-13.66,94.48-39.51c19.36-19.35,28.12-38.79,28.49-39.61A12.08,12.08,0,0,0,251,123.13Zm-46.06,33C183.47,177.27,157.59,188,128,188s-55.47-10.73-76.91-31.88A130.36,130.36,0,0,1,29.52,128,130.45,130.45,0,0,1,51.09,99.89C72.54,78.73,98.41,68,128,68s55.46,10.73,76.91,31.89A130.36,130.36,0,0,1,226.48,128,130.45,130.45,0,0,1,204.91,156.12ZM128,84a44,44,0,1,0,44,44A44.05,44.05,0,0,0,128,84Zm0,64a20,20,0,1,1,20-20A20,20,0,0,1,128,148Z\"/></symbol>\n <symbol id=\"juno-i-file\" viewBox=\"0 0 256 256\"><path d=\"M216.49,79.52l-56-56A12,12,0,0,0,152,20H56A20,20,0,0,0,36,40V216a20,20,0,0,0,20,20H200a20,20,0,0,0,20-20V88A12,12,0,0,0,216.49,79.52ZM160,57l23,23H160ZM60,212V44h76V92a12,12,0,0,0,12,12h48V212Z\"/></symbol>\n <symbol id=\"juno-i-film-strip\" viewBox=\"0 0 256 256\"><path d=\"M216,36H40A20,20,0,0,0,20,56V200a20,20,0,0,0,20,20H216a20,20,0,0,0,20-20V56A20,20,0,0,0,216,36ZM44,100h72v56H44Zm96-24V60h24V76Zm-24,0H92V60h24Zm0,104v16H92V180Zm24,0h24v16H140Zm0-24V100h72v56Zm72-80H188V60h24ZM68,60V76H44V60ZM44,180H68v16H44Zm144,16V180h24v16Z\"/></symbol>\n <symbol id=\"juno-i-floppy-disk\" viewBox=\"0 0 256 256\"><path d=\"M222.14,69.17,186.83,33.86A19.86,19.86,0,0,0,172.69,28H48A20,20,0,0,0,28,48V208a20,20,0,0,0,20,20H208a20,20,0,0,0,20-20V83.31A19.86,19.86,0,0,0,222.14,69.17ZM164,204H92V160h72Zm40,0H188V156a20,20,0,0,0-20-20H88a20,20,0,0,0-20,20v48H52V52H171l33,33ZM164,84a12,12,0,0,1-12,12H96a12,12,0,0,1,0-24h56A12,12,0,0,1,164,84Z\"/></symbol>\n <symbol id=\"juno-i-folder\" viewBox=\"0 0 256 256\"><path d=\"M216,68H133.39l-26-29.29a20,20,0,0,0-15-6.71H40A20,20,0,0,0,20,52V200.62A19.41,19.41,0,0,0,39.38,220H216.89A19.13,19.13,0,0,0,236,200.89V88A20,20,0,0,0,216,68ZM44,56H90.61l10.67,12H44ZM212,196H44V92H212Z\"/></symbol>\n <symbol id=\"juno-i-funnel\" viewBox=\"0 0 256 256\"><path d=\"M234.29,47.91A20,20,0,0,0,216,36H40A20,20,0,0,0,25.2,69.45l.12.14L92,140.75V216a20,20,0,0,0,31.1,16.64l32-21.33A20,20,0,0,0,164,194.66V140.75l66.67-71.16.12-.14A20,20,0,0,0,234.29,47.91Zm-91,79.89A12,12,0,0,0,140,136v56.52l-24,16V136a12,12,0,0,0-3.25-8.2L49.23,60H206.77Z\"/></symbol>\n <symbol id=\"juno-i-gear\" viewBox=\"0 0 256 256\"><path d=\"M128,76a52,52,0,1,0,52,52A52.06,52.06,0,0,0,128,76Zm0,80a28,28,0,1,1,28-28A28,28,0,0,1,128,156Zm92-27.21v-1.58l14-17.51a12,12,0,0,0,2.23-10.59A111.75,111.75,0,0,0,225,71.89,12,12,0,0,0,215.89,66L193.61,63.5l-1.11-1.11L190,40.1A12,12,0,0,0,184.11,31a111.67,111.67,0,0,0-27.23-11.27A12,12,0,0,0,146.3,22L128.79,36h-1.58L109.7,22a12,12,0,0,0-10.59-2.23A111.75,111.75,0,0,0,71.89,31.05,12,12,0,0,0,66,40.11L63.5,62.39,62.39,63.5,40.1,66A12,12,0,0,0,31,71.89,111.67,111.67,0,0,0,19.77,99.12,12,12,0,0,0,22,109.7l14,17.51v1.58L22,146.3a12,12,0,0,0-2.23,10.59,111.75,111.75,0,0,0,11.29,27.22A12,12,0,0,0,40.11,190l22.28,2.48,1.11,1.11L66,215.9A12,12,0,0,0,71.89,225a111.67,111.67,0,0,0,27.23,11.27A12,12,0,0,0,109.7,234l17.51-14h1.58l17.51,14a12,12,0,0,0,10.59,2.23A111.75,111.75,0,0,0,184.11,225a12,12,0,0,0,5.91-9.06l2.48-22.28,1.11-1.11L215.9,190a12,12,0,0,0,9.06-5.91,111.67,111.67,0,0,0,11.27-27.23A12,12,0,0,0,234,146.3Zm-24.12-4.89a70.1,70.1,0,0,1,0,8.2,12,12,0,0,0,2.61,8.22l12.84,16.05A86.47,86.47,0,0,1,207,166.86l-20.43,2.27a12,12,0,0,0-7.65,4,69,69,0,0,1-5.8,5.8,12,12,0,0,0-4,7.65L166.86,207a86.47,86.47,0,0,1-10.49,4.35l-16.05-12.85a12,12,0,0,0-7.5-2.62c-.24,0-.48,0-.72,0a70.1,70.1,0,0,1-8.2,0,12.06,12.06,0,0,0-8.22,2.6L99.63,211.33A86.47,86.47,0,0,1,89.14,207l-2.27-20.43a12,12,0,0,0-4-7.65,69,69,0,0,1-5.8-5.8,12,12,0,0,0-7.65-4L49,166.86a86.47,86.47,0,0,1-4.35-10.49l12.84-16.05a12,12,0,0,0,2.61-8.22,70.1,70.1,0,0,1,0-8.2,12,12,0,0,0-2.61-8.22L44.67,99.63A86.47,86.47,0,0,1,49,89.14l20.43-2.27a12,12,0,0,0,7.65-4,69,69,0,0,1,5.8-5.8,12,12,0,0,0,4-7.65L89.14,49a86.47,86.47,0,0,1,10.49-4.35l16.05,12.85a12.06,12.06,0,0,0,8.22,2.6,70.1,70.1,0,0,1,8.2,0,12,12,0,0,0,8.22-2.6l16.05-12.85A86.47,86.47,0,0,1,166.86,49l2.27,20.43a12,12,0,0,0,4,7.65,69,69,0,0,1,5.8,5.8,12,12,0,0,0,7.65,4L207,89.14a86.47,86.47,0,0,1,4.35,10.49l-12.84,16.05A12,12,0,0,0,195.88,123.9Z\"/></symbol>\n <symbol id=\"juno-i-hard-drives\" viewBox=\"0 0 256 256\"><path d=\"M208,36H48A20,20,0,0,0,28,56V200a20,20,0,0,0,20,20H208a20,20,0,0,0,20-20V56A20,20,0,0,0,208,36Zm-4,24v56H52V60ZM52,196V140H204v56ZM160,88a16,16,0,1,1,16,16A16,16,0,0,1,160,88Zm32,80a16,16,0,1,1-16-16A16,16,0,0,1,192,168Z\"/></symbol>\n <symbol id=\"juno-i-heart\" viewBox=\"0 0 256 256\"><path d=\"M178,36c-20.09,0-37.92,7.93-50,21.56C115.92,43.93,98.09,36,78,36a66.08,66.08,0,0,0-66,66c0,72.34,105.81,130.14,110.31,132.57a12,12,0,0,0,11.38,0C138.19,232.14,244,174.34,244,102A66.08,66.08,0,0,0,178,36Zm-5.49,142.36A328.69,328.69,0,0,1,128,210.16a328.69,328.69,0,0,1-44.51-31.8C61.82,159.77,36,131.42,36,102A42,42,0,0,1,78,60c17.8,0,32.7,9.4,38.89,24.54a12,12,0,0,0,22.22,0C145.3,69.4,160.2,60,178,60a42,42,0,0,1,42,42C220,131.42,194.18,159.77,172.51,178.36Z\"/></symbol>\n <symbol id=\"juno-i-hexagon\" viewBox=\"0 0 256 256\"><path d=\"M225.6,62.64l-88-48.17a19.91,19.91,0,0,0-19.2,0l-88,48.17A20,20,0,0,0,20,80.19v95.62a20,20,0,0,0,10.4,17.55l88,48.17a19.89,19.89,0,0,0,19.2,0l88-48.17A20,20,0,0,0,236,175.81V80.19A20,20,0,0,0,225.6,62.64ZM212,173.44l-84,46-84-46V82.56l84-46,84,46Z\"/></symbol>\n <symbol id=\"juno-i-house\" viewBox=\"0 0 256 256\"><path d=\"M222.14,105.85l-80-80a20,20,0,0,0-28.28,0l-80,80A19.86,19.86,0,0,0,28,120v96a12,12,0,0,0,12,12h64a12,12,0,0,0,12-12V164h24v52a12,12,0,0,0,12,12h64a12,12,0,0,0,12-12V120A19.86,19.86,0,0,0,222.14,105.85ZM204,204H164V152a12,12,0,0,0-12-12H104a12,12,0,0,0-12,12v52H52V121.65l76-76,76,76Z\"/></symbol>\n <symbol id=\"juno-i-images\" viewBox=\"0 0 256 256\"><path d=\"M160,88a16,16,0,1,1,16,16A16,16,0,0,1,160,88Zm76-32V160a20,20,0,0,1-20,20H204v20a20,20,0,0,1-20,20H40a20,20,0,0,1-20-20V88A20,20,0,0,1,40,68H60V56A20,20,0,0,1,80,36H216A20,20,0,0,1,236,56ZM180,180H80a20,20,0,0,1-20-20V92H44V196H180Zm-21.66-24L124,121.66,89.66,156ZM212,60H84v67.72l25.86-25.86a20,20,0,0,1,28.28,0L192.28,156H212Z\"/></symbol>\n <symbol id=\"juno-i-info\" viewBox=\"0 0 256 256\"><path d=\"M108,84a16,16,0,1,1,16,16A16,16,0,0,1,108,84Zm128,44A108,108,0,1,1,128,20,108.12,108.12,0,0,1,236,128Zm-24,0a84,84,0,1,0-84,84A84.09,84.09,0,0,0,212,128Zm-72,36.68V132a20,20,0,0,0-20-20,12,12,0,0,0-4,23.32V168a20,20,0,0,0,20,20,12,12,0,0,0,4-23.32Z\"/></symbol>\n <symbol id=\"juno-i-link\" viewBox=\"0 0 256 256\"><path d=\"M117.18,188.74a12,12,0,0,1,0,17l-5.12,5.12A58.26,58.26,0,0,1,70.6,228h0A58.62,58.62,0,0,1,29.14,127.92L63.89,93.17a58.64,58.64,0,0,1,98.56,28.11,12,12,0,1,1-23.37,5.44,34.65,34.65,0,0,0-58.22-16.58L46.11,144.89A34.62,34.62,0,0,0,70.57,204h0a34.41,34.41,0,0,0,24.49-10.14l5.11-5.12A12,12,0,0,1,117.18,188.74ZM226.83,45.17a58.65,58.65,0,0,0-82.93,0l-5.11,5.11a12,12,0,0,0,17,17l5.12-5.12a34.63,34.63,0,1,1,49,49L175.1,145.86A34.39,34.39,0,0,1,150.61,156h0a34.63,34.63,0,0,1-33.69-26.72,12,12,0,0,0-23.38,5.44A58.64,58.64,0,0,0,150.56,180h.05a58.28,58.28,0,0,0,41.47-17.17l34.75-34.75a58.62,58.62,0,0,0,0-82.91Z\"/></symbol>\n <symbol id=\"juno-i-list\" viewBox=\"0 0 256 256\"><path d=\"M228,128a12,12,0,0,1-12,12H40a12,12,0,0,1,0-24H216A12,12,0,0,1,228,128ZM40,76H216a12,12,0,0,0,0-24H40a12,12,0,0,0,0,24ZM216,180H40a12,12,0,0,0,0,24H216a12,12,0,0,0,0-24Z\"/></symbol>\n <symbol id=\"juno-i-lock-open\" viewBox=\"0 0 256 256\"><path d=\"M208,76H100V56a28,28,0,0,1,28-28c13.51,0,25.65,9.62,28.24,22.39a12,12,0,1,0,23.52-4.78C174.87,21.5,153.1,4,128,4A52.06,52.06,0,0,0,76,56V76H48A20,20,0,0,0,28,96V208a20,20,0,0,0,20,20H208a20,20,0,0,0,20-20V96A20,20,0,0,0,208,76Zm-4,128H52V100H204Zm-92-52a16,16,0,1,1,16,16A16,16,0,0,1,112,152Z\"/></symbol>\n <symbol id=\"juno-i-lock\" viewBox=\"0 0 256 256\"><path d=\"M208,76H180V56A52,52,0,0,0,76,56V76H48A20,20,0,0,0,28,96V208a20,20,0,0,0,20,20H208a20,20,0,0,0,20-20V96A20,20,0,0,0,208,76ZM100,56a28,28,0,0,1,56,0V76H100ZM204,204H52V100H204Zm-60-52a16,16,0,1,1-16-16A16,16,0,0,1,144,152Z\"/></symbol>\n <symbol id=\"juno-i-magnifying-glass\" viewBox=\"0 0 256 256\"><path d=\"M232.49,215.51,185,168a92.12,92.12,0,1,0-17,17l47.53,47.54a12,12,0,0,0,17-17ZM44,112a68,68,0,1,1,68,68A68.07,68.07,0,0,1,44,112Z\"/></symbol>\n <symbol id=\"juno-i-minus\" viewBox=\"0 0 256 256\"><path d=\"M228,128a12,12,0,0,1-12,12H40a12,12,0,0,1,0-24H216A12,12,0,0,1,228,128Z\"/></symbol>\n <symbol id=\"juno-i-moon\" viewBox=\"0 0 256 256\"><path d=\"M236.37,139.4a12,12,0,0,0-12-3A84.07,84.07,0,0,1,119.6,31.59a12,12,0,0,0-15-15A108.86,108.86,0,0,0,49.69,55.07,108,108,0,0,0,136,228a107.09,107.09,0,0,0,64.93-21.69,108.86,108.86,0,0,0,38.44-54.94A12,12,0,0,0,236.37,139.4Zm-49.88,47.74A84,84,0,0,1,68.86,69.51,84.93,84.93,0,0,1,92.27,48.29Q92,52.13,92,56A108.12,108.12,0,0,0,200,164q3.87,0,7.71-.27A84.79,84.79,0,0,1,186.49,187.14Z\"/></symbol>\n <symbol id=\"juno-i-pencil-simple\" viewBox=\"0 0 256 256\"><path d=\"M230.14,70.54,185.46,25.85a20,20,0,0,0-28.29,0L33.86,149.17A19.85,19.85,0,0,0,28,163.31V208a20,20,0,0,0,20,20H92.69a19.86,19.86,0,0,0,14.14-5.86L230.14,98.82a20,20,0,0,0,0-28.28ZM91,204H52V165l84-84,39,39ZM192,103,153,64l18.34-18.34,39,39Z\"/></symbol>\n <symbol id=\"juno-i-play\" viewBox=\"0 0 256 256\"><path d=\"M234.49,111.07,90.41,22.94A20,20,0,0,0,60,39.87V216.13a20,20,0,0,0,30.41,16.93l144.08-88.13a19.82,19.82,0,0,0,0-33.86ZM84,208.85V47.15L216.16,128Z\"/></symbol>\n <symbol id=\"juno-i-plus\" viewBox=\"0 0 256 256\"><path d=\"M228,128a12,12,0,0,1-12,12H140v76a12,12,0,0,1-24,0V140H40a12,12,0,0,1,0-24h76V40a12,12,0,0,1,24,0v76h76A12,12,0,0,1,228,128Z\"/></symbol>\n <symbol id=\"juno-i-puzzle-piece\" viewBox=\"0 0 256 256\"><path d=\"M222.41,155.16a12,12,0,0,0-11.56-.69A16,16,0,0,1,188,139,16.2,16.2,0,0,1,202.8,124a15.83,15.83,0,0,1,8,1.5A12,12,0,0,0,228,114.7V72a20,20,0,0,0-20-20H176a40.15,40.15,0,0,0-12.62-29.16,39.67,39.67,0,0,0-29.94-10.76,40.08,40.08,0,0,0-37.34,37C96,50.07,96,51,96,52H64A20,20,0,0,0,44,72v28a40.15,40.15,0,0,0-29.16,12.62A40,40,0,0,0,41.1,179.9a28.3,28.3,0,0,0,2.9.1v28a20,20,0,0,0,20,20H208a20,20,0,0,0,20-20V165.31A12,12,0,0,0,222.41,155.16ZM204,204H68V165.31a12,12,0,0,0-17.15-10.84A15.9,15.9,0,0,1,42.8,156,16.2,16.2,0,0,1,28,141.06a16,16,0,0,1,22.82-15.52A12,12,0,0,0,68,114.7V76h42.7a12,12,0,0,0,10.83-17.15A15.9,15.9,0,0,1,120,50.8,16.19,16.19,0,0,1,134.94,36a16,16,0,0,1,15.53,22.81A12,12,0,0,0,161.31,76H204v24c-1,0-1.93,0-2.9.11A40,40,0,0,0,204,180h0Z\"/></symbol>\n <symbol id=\"juno-i-question\" viewBox=\"0 0 256 256\"><path d=\"M144,180a16,16,0,1,1-16-16A16,16,0,0,1,144,180Zm92-52A108,108,0,1,1,128,20,108.12,108.12,0,0,1,236,128Zm-24,0a84,84,0,1,0-84,84A84.09,84.09,0,0,0,212,128ZM128,64c-24.26,0-44,17.94-44,40v4a12,12,0,0,0,24,0v-4c0-8.82,9-16,20-16s20,7.18,20,16-9,16-20,16a12,12,0,0,0-12,12v8a12,12,0,0,0,23.73,2.56C158.31,137.88,172,122.37,172,104,172,81.94,152.26,64,128,64Z\"/></symbol>\n <symbol id=\"juno-i-sliders-horizontal\" viewBox=\"0 0 256 256\"><path d=\"M40,92H70.06a36,36,0,0,0,67.88,0H216a12,12,0,0,0,0-24H137.94a36,36,0,0,0-67.88,0H40a12,12,0,0,0,0,24Zm64-24A12,12,0,1,1,92,80,12,12,0,0,1,104,68Zm112,96H201.94a36,36,0,0,0-67.88,0H40a12,12,0,0,0,0,24h94.06a36,36,0,0,0,67.88,0H216a12,12,0,0,0,0-24Zm-48,24a12,12,0,1,1,12-12A12,12,0,0,1,168,188Z\"/></symbol>\n <symbol id=\"juno-i-sliders\" viewBox=\"0 0 256 256\"><path d=\"M68,102.06V40a12,12,0,0,0-24,0v62.06a36,36,0,0,0,0,67.88V216a12,12,0,0,0,24,0V169.94a36,36,0,0,0,0-67.88ZM56,148a12,12,0,1,1,12-12A12,12,0,0,1,56,148ZM164,88a36.07,36.07,0,0,0-24-33.94V40a12,12,0,0,0-24,0V54.06a36,36,0,0,0,0,67.88V216a12,12,0,0,0,24,0V121.94A36.07,36.07,0,0,0,164,88Zm-36,12a12,12,0,1,1,12-12A12,12,0,0,1,128,100Zm108,68a36.07,36.07,0,0,0-24-33.94V40a12,12,0,0,0-24,0v94.06a36,36,0,0,0,0,67.88V216a12,12,0,0,0,24,0V201.94A36.07,36.07,0,0,0,236,168Zm-36,12a12,12,0,1,1,12-12A12,12,0,0,1,200,180Z\"/></symbol>\n <symbol id=\"juno-i-squares-four\" viewBox=\"0 0 256 256\"><path d=\"M100,36H56A20,20,0,0,0,36,56v44a20,20,0,0,0,20,20h44a20,20,0,0,0,20-20V56A20,20,0,0,0,100,36ZM96,96H60V60H96ZM200,36H156a20,20,0,0,0-20,20v44a20,20,0,0,0,20,20h44a20,20,0,0,0,20-20V56A20,20,0,0,0,200,36Zm-4,60H160V60h36Zm-96,40H56a20,20,0,0,0-20,20v44a20,20,0,0,0,20,20h44a20,20,0,0,0,20-20V156A20,20,0,0,0,100,136Zm-4,60H60V160H96Zm104-60H156a20,20,0,0,0-20,20v44a20,20,0,0,0,20,20h44a20,20,0,0,0,20-20V156A20,20,0,0,0,200,136Zm-4,60H160V160h36Z\"/></symbol>\n <symbol id=\"juno-i-star\" viewBox=\"0 0 256 256\"><path d=\"M243,96a20.33,20.33,0,0,0-17.74-14l-56.59-4.57L146.83,24.62a20.36,20.36,0,0,0-37.66,0L87.35,77.44,30.76,82A20.45,20.45,0,0,0,19.1,117.88l43.18,37.24-13.2,55.7A20.37,20.37,0,0,0,79.57,233L128,203.19,176.43,233a20.39,20.39,0,0,0,30.49-22.15l-13.2-55.7,43.18-37.24A20.43,20.43,0,0,0,243,96ZM172.53,141.7a12,12,0,0,0-3.84,11.86L181.58,208l-47.29-29.08a12,12,0,0,0-12.58,0L74.42,208l12.89-54.4a12,12,0,0,0-3.84-11.86L41.2,105.24l55.4-4.47a12,12,0,0,0,10.13-7.38L128,41.89l21.27,51.5a12,12,0,0,0,10.13,7.38l55.4,4.47Z\"/></symbol>\n <symbol id=\"juno-i-sun\" viewBox=\"0 0 256 256\"><path d=\"M116,36V20a12,12,0,0,1,24,0V36a12,12,0,0,1-24,0Zm80,92a68,68,0,1,1-68-68A68.07,68.07,0,0,1,196,128Zm-24,0a44,44,0,1,0-44,44A44.05,44.05,0,0,0,172,128ZM51.51,68.49a12,12,0,1,0,17-17l-12-12a12,12,0,0,0-17,17Zm0,119-12,12a12,12,0,0,0,17,17l12-12a12,12,0,1,0-17-17ZM196,72a12,12,0,0,0,8.49-3.51l12-12a12,12,0,0,0-17-17l-12,12A12,12,0,0,0,196,72Zm8.49,115.51a12,12,0,0,0-17,17l12,12a12,12,0,0,0,17-17ZM48,128a12,12,0,0,0-12-12H20a12,12,0,0,0,0,24H36A12,12,0,0,0,48,128Zm80,80a12,12,0,0,0-12,12v16a12,12,0,0,0,24,0V220A12,12,0,0,0,128,208Zm108-92H220a12,12,0,0,0,0,24h16a12,12,0,0,0,0-24Z\"/></symbol>\n <symbol id=\"juno-i-trash\" viewBox=\"0 0 256 256\"><path d=\"M216,48H180V36A28,28,0,0,0,152,8H104A28,28,0,0,0,76,36V48H40a12,12,0,0,0,0,24h4V208a20,20,0,0,0,20,20H192a20,20,0,0,0,20-20V72h4a12,12,0,0,0,0-24ZM100,36a4,4,0,0,1,4-4h48a4,4,0,0,1,4,4V48H100Zm88,168H68V72H188ZM116,104v64a12,12,0,0,1-24,0V104a12,12,0,0,1,24,0Zm48,0v64a12,12,0,0,1-24,0V104a12,12,0,0,1,24,0Z\"/></symbol>\n <symbol id=\"juno-i-upload-simple\" viewBox=\"0 0 256 256\"><path d=\"M228,144v64a12,12,0,0,1-12,12H40a12,12,0,0,1-12-12V144a12,12,0,0,1,24,0v52H204V144a12,12,0,0,1,24,0ZM96.49,80.49,116,61v83a12,12,0,0,0,24,0V61l19.51,19.52a12,12,0,1,0,17-17l-40-40a12,12,0,0,0-17,0l-40,40a12,12,0,1,0,17,17Z\"/></symbol>\n <symbol id=\"juno-i-upload\" viewBox=\"0 0 256 256\"><path d=\"M188,184a16,16,0,1,1,16-16A16,16,0,0,1,188,184Zm36-68H180a12,12,0,0,0,0,24h40v56H36V140H76a12,12,0,0,0,0-24H32a20,20,0,0,0-20,20v64a20,20,0,0,0,20,20H224a20,20,0,0,0,20-20V136A20,20,0,0,0,224,116ZM88.49,80.49,116,53v75a12,12,0,0,0,24,0V53l27.51,27.52a12,12,0,1,0,17-17l-48-48a12,12,0,0,0-17,0l-48,48a12,12,0,1,0,17,17Z\"/></symbol>\n <symbol id=\"juno-i-user\" viewBox=\"0 0 256 256\"><path d=\"M234.38,210a123.36,123.36,0,0,0-60.78-53.23,76,76,0,1,0-91.2,0A123.36,123.36,0,0,0,21.62,210a12,12,0,1,0,20.77,12c18.12-31.32,50.12-50,85.61-50s67.49,18.69,85.61,50a12,12,0,0,0,20.77-12ZM76,96a52,52,0,1,1,52,52A52.06,52.06,0,0,1,76,96Z\"/></symbol>\n <symbol id=\"juno-i-users\" viewBox=\"0 0 256 256\"><path d=\"M125.18,156.94a64,64,0,1,0-82.36,0,100.23,100.23,0,0,0-39.49,32,12,12,0,0,0,19.35,14.2,76,76,0,0,1,122.64,0,12,12,0,0,0,19.36-14.2A100.33,100.33,0,0,0,125.18,156.94ZM44,108a40,40,0,1,1,40,40A40,40,0,0,1,44,108Zm206.1,97.67a12,12,0,0,1-16.78-2.57A76.31,76.31,0,0,0,172,172a12,12,0,0,1,0-24,40,40,0,1,0-10.3-78.67,12,12,0,1,1-6.16-23.19,64,64,0,0,1,57.64,110.8,100.23,100.23,0,0,1,39.49,32A12,12,0,0,1,250.1,205.67Z\"/></symbol>\n <symbol id=\"juno-i-warning-circle\" viewBox=\"0 0 256 256\"><path d=\"M128,20A108,108,0,1,0,236,128,108.12,108.12,0,0,0,128,20Zm0,192a84,84,0,1,1,84-84A84.09,84.09,0,0,1,128,212Zm-12-80V80a12,12,0,0,1,24,0v52a12,12,0,0,1-24,0Zm28,40a16,16,0,1,1-16-16A16,16,0,0,1,144,172Z\"/></symbol>\n <symbol id=\"juno-i-warning\" viewBox=\"0 0 256 256\"><path d=\"M240.26,186.1,152.81,34.23h0a28.74,28.74,0,0,0-49.62,0L15.74,186.1a27.45,27.45,0,0,0,0,27.71A28.31,28.31,0,0,0,40.55,228h174.9a28.31,28.31,0,0,0,24.79-14.19A27.45,27.45,0,0,0,240.26,186.1Zm-20.8,15.7a4.46,4.46,0,0,1-4,2.2H40.55a4.46,4.46,0,0,1-4-2.2,3.56,3.56,0,0,1,0-3.73L124,46.2a4.77,4.77,0,0,1,8,0l87.44,151.87A3.56,3.56,0,0,1,219.46,201.8ZM116,136V104a12,12,0,0,1,24,0v32a12,12,0,0,1-24,0Zm28,40a16,16,0,1,1-16-16A16,16,0,0,1,144,176Z\"/></symbol>\n <symbol id=\"juno-i-x-circle\" viewBox=\"0 0 256 256\"><path d=\"M168.49,104.49,145,128l23.52,23.51a12,12,0,0,1-17,17L128,145l-23.51,23.52a12,12,0,0,1-17-17L111,128,87.51,104.49a12,12,0,0,1,17-17L128,111l23.51-23.52a12,12,0,0,1,17,17ZM236,128A108,108,0,1,1,128,20,108.12,108.12,0,0,1,236,128Zm-24,0a84,84,0,1,0-84,84A84.09,84.09,0,0,0,212,128Z\"/></symbol>\n <symbol id=\"juno-i-x\" viewBox=\"0 0 256 256\"><path d=\"M208.49,191.51a12,12,0,0,1-17,17L128,145,64.49,208.49a12,12,0,0,1-17-17L111,128,47.51,64.49a12,12,0,0,1,17-17L128,111l63.51-63.52a12,12,0,0,1,17,17L145,128Z\"/></symbol>\n</svg>\n";
|
|
7
11
|
|
|
8
|
-
/** Inject the sprite into `doc` once (id-guarded, safe to call repeatedly). */
|
|
12
|
+
/** Inject the full sprite into `doc` once (id-guarded, safe to call repeatedly). */
|
|
9
13
|
export function installJunoIcons(doc = typeof document !== 'undefined' ? document : undefined) {
|
|
10
|
-
|
|
11
|
-
const holder = doc.createElement('div');
|
|
12
|
-
holder.id = 'juno-icon-sprite';
|
|
13
|
-
holder.style.display = 'none';
|
|
14
|
-
holder.setAttribute('aria-hidden', 'true');
|
|
15
|
-
holder.innerHTML = SPRITE;
|
|
16
|
-
(doc.body || doc.documentElement).prepend(holder);
|
|
14
|
+
installSprite(SPRITE, doc);
|
|
17
15
|
}
|
|
18
16
|
|
|
19
17
|
// Auto-install on import in a browser (no-op server-side / pre-hydration).
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// junoui — icon sprite injector, no payload. Generated; do not edit.
|
|
2
|
+
// Same-document injection, because Safari drops external <use href="file.svg#id">
|
|
3
|
+
// refs intermittently. Pair with junoui/subset when you ship a subset:
|
|
4
|
+
// import { installSprite } from '@junoput01/junoui/icons/install';
|
|
5
|
+
// import sprite from 'virtual:my-icon-subset';
|
|
6
|
+
// installSprite(sprite);
|
|
7
|
+
export const JUNO_SPRITE_ID = 'juno-icon-sprite';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Inject `svg` (sprite source) into `doc` once. Id-guarded, so calling it
|
|
11
|
+
* repeatedly — or alongside junoui/icons/inline — installs exactly one sprite:
|
|
12
|
+
* whichever ran first wins, and a second call is a no-op rather than a second
|
|
13
|
+
* hidden holder shadowing the first.
|
|
14
|
+
*/
|
|
15
|
+
export function installSprite(svg, doc = typeof document !== 'undefined' ? document : undefined) {
|
|
16
|
+
if (!doc || !svg || doc.getElementById(JUNO_SPRITE_ID)) return false;
|
|
17
|
+
const holder = doc.createElement('div');
|
|
18
|
+
holder.id = JUNO_SPRITE_ID;
|
|
19
|
+
holder.style.display = 'none';
|
|
20
|
+
holder.setAttribute('aria-hidden', 'true');
|
|
21
|
+
holder.innerHTML = svg;
|
|
22
|
+
(doc.body || doc.documentElement).prepend(holder);
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default installSprite;
|