@crewlethq/ui 0.4.3 → 0.5.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/README.md +888 -24
- package/dist/Accordion/index.js +2 -2
- package/dist/AddPill/index.js +1 -1
- package/dist/{AddPill-DFWXYLIQ.css → AddPill-IJQYCY6C.css} +9 -0
- package/dist/AppShell/AppShell.d.ts +26 -5
- package/dist/AppShell/index.js +3 -3
- package/dist/{AppShell-NVE6LHNI.css → AppShell-XARELGIH.css} +178 -25
- package/dist/Avatar/Avatar.d.ts +85 -40
- package/dist/Avatar/AvatarStack.d.ts +76 -0
- package/dist/Avatar/index.d.ts +5 -2
- package/dist/Avatar/index.js +1 -1
- package/dist/Avatar-XID7Z74C.css +200 -0
- package/dist/AvatarStack-GEJBNV7E.css +72 -0
- package/dist/BrandLockup/index.js +1 -1
- package/dist/{BrandLockup-6ISDEHPJ.css → BrandLockup-JKGXFCZF.css} +25 -19
- package/dist/Button/Button.d.ts +7 -2
- package/dist/Button/index.js +1 -1
- package/dist/{Button-D4J6B4MA.css → Button-X4B2TJAQ.css} +50 -19
- package/dist/Callout/index.js +1 -1
- package/dist/Canvas/index.js +4 -4
- package/dist/Card/Card.d.ts +9 -5
- package/dist/Card/index.js +1 -1
- package/dist/{Card-RLR254LD.css → Card-GLP7SUV6.css} +25 -18
- package/dist/Charts/BarList.d.ts +18 -1
- package/dist/Charts/ChartTooltip.d.ts +68 -0
- package/dist/Charts/StackedBar.d.ts +25 -7
- package/dist/Charts/StackedColumns.d.ts +112 -0
- package/dist/Charts/TimeSeries.d.ts +33 -2
- package/dist/Charts/dataColor.d.ts +22 -14
- package/dist/Charts/index.d.ts +6 -0
- package/dist/Charts/index.js +1 -1
- package/dist/Charts/useChartHover.d.ts +56 -0
- package/dist/Charts-B3YEF7R4.css +742 -0
- package/dist/Checkbox/index.js +1 -1
- package/dist/{Checkbox-VGW26YLQ.css → Checkbox-BOXQ747I.css} +2 -2
- package/dist/CodeBlock/index.js +4 -4
- package/dist/Combobox/index.js +5 -5
- package/dist/CommandPalette/CommandPalette.d.ts +97 -6
- package/dist/CommandPalette/index.d.ts +1 -1
- package/dist/CommandPalette/index.js +9 -7
- package/dist/CommandPalette-C5AMKGN2.css +259 -0
- package/dist/Copyable/index.js +3 -3
- package/dist/DataTable/index.js +7 -7
- package/dist/{DataTable-ITNACQ2X.css → DataTable-OLHPF7D4.css} +44 -43
- package/dist/DataView/index.js +14 -14
- package/dist/{DataView-256YF32J.css → DataView-N6JX464S.css} +5 -4
- package/dist/DateTimePicker/index.js +5 -5
- package/dist/DiffList/index.js +1 -1
- package/dist/Disclosure/index.js +2 -2
- package/dist/EntityChip/EntityChip.d.ts +9 -12
- package/dist/EntityChip/index.d.ts +1 -1
- package/dist/EntityChip/index.js +2 -2
- package/dist/ErrorBoundary/index.js +2 -2
- package/dist/{ErrorBoundary-ME36CQTA.css → ErrorBoundary-U2PA3LY2.css} +4 -4
- package/dist/IconButton/index.js +1 -1
- package/dist/{IconButton-VQGNMJDI.css → IconButton-TVEUWK6L.css} +2 -2
- package/dist/ImageUpload/ImageUpload.d.ts +10 -7
- package/dist/ImageUpload/index.js +2 -2
- package/dist/{ImageUpload-HKFIZR6D.css → ImageUpload-YCHJMUGX.css} +24 -10
- package/dist/Input/index.js +2 -2
- package/dist/Kbd/Kbd.d.ts +14 -4
- package/dist/Kbd/index.js +1 -1
- package/dist/Kbd-JPLDVJIP.css +71 -0
- package/dist/Layer/index.js +1 -1
- package/dist/Link/index.js +1 -1
- package/dist/List/index.js +1 -1
- package/dist/{List-XTHESXLR.css → List-MYJIV6MP.css} +12 -2
- package/dist/ListInput/index.js +5 -5
- package/dist/Listbox/index.js +2 -2
- package/dist/Listbox/useListbox.d.ts +16 -0
- package/dist/Listbox/useOptionKeys.d.ts +12 -1
- package/dist/{Listbox-X2DOTSQA.css → Listbox-6WJNJQVQ.css} +60 -7
- package/dist/Menu/index.js +4 -4
- package/dist/{Menu-6DE7I66I.css → Menu-BT5PMFJI.css} +15 -0
- package/dist/Meter/Meter.d.ts +103 -16
- package/dist/Meter/index.d.ts +2 -2
- package/dist/Meter/index.js +1 -1
- package/dist/{Meter-SKOOXQBC.css → Meter-5VCSFMZW.css} +46 -7
- package/dist/Modal/index.js +4 -4
- package/dist/{Modal-XYQJ4BL6.css → Modal-JAYBS2KS.css} +13 -4
- package/dist/OrgLabel/OrgLabel.d.ts +60 -24
- package/dist/OrgLabel/index.d.ts +1 -1
- package/dist/OrgLabel/index.js +2 -1
- package/dist/{OrgLabel-D7U6QJZD.css → OrgLabel-CR233G34.css} +9 -18
- package/dist/OrgNode/index.js +3 -2
- package/dist/OrgTable/OrgTable.d.ts +2 -2
- package/dist/OrgTable/index.js +8 -7
- package/dist/Popover/index.js +2 -2
- package/dist/PricingCard/index.js +3 -3
- package/dist/{PricingCard-JFI7RYXP.css → PricingCard-7EFXRSD2.css} +4 -5
- package/dist/SearchTrigger/SearchTrigger.d.ts +23 -4
- package/dist/SearchTrigger/index.d.ts +1 -1
- package/dist/SearchTrigger/index.js +1 -1
- package/dist/SearchTrigger-Z5D4AAY7.css +112 -0
- package/dist/SegmentedControl/index.js +2 -2
- package/dist/SegmentedMeter/SegmentedMeter.d.ts +107 -0
- package/dist/SegmentedMeter/index.d.ts +3 -0
- package/dist/SegmentedMeter/index.js +2 -0
- package/dist/SegmentedMeter-KQNML2TW.css +109 -0
- package/dist/Select/index.js +3 -3
- package/dist/{Select-2X77FSWR.css → Select-E24U5LBC.css} +34 -0
- package/dist/Shortcut/index.js +2 -2
- package/dist/SidebarNav/SidebarNav.d.ts +85 -25
- package/dist/SidebarNav/index.d.ts +1 -1
- package/dist/SidebarNav/index.js +1 -1
- package/dist/SidebarNav-X5NLZNWA.css +424 -0
- package/dist/StatCard/StatCard.d.ts +59 -12
- package/dist/StatCard/index.d.ts +1 -1
- package/dist/StatCard/index.js +1 -1
- package/dist/StatCard-KPAFD4E2.css +204 -0
- package/dist/StatGroup/index.js +1 -1
- package/dist/{StatGroup-TGB6AEKM.css → StatGroup-HVG6O62W.css} +8 -9
- package/dist/StatusDot/StatusDot.d.ts +24 -6
- package/dist/StatusDot/index.js +1 -1
- package/dist/StatusDot-7OMCQCZF.css +186 -0
- package/dist/Stepper/Stepper.d.ts +78 -0
- package/dist/Stepper/index.d.ts +3 -0
- package/dist/Stepper/index.js +4 -0
- package/dist/Stepper-HW4JM3YH.css +176 -0
- package/dist/Table/index.js +1 -1
- package/dist/{Table-MDOLVUAW.css → Table-TGCS4C3F.css} +14 -4
- package/dist/Tabs/index.js +1 -1
- package/dist/{Tabs-VLICJFVB.css → Tabs-XCNPHA7B.css} +79 -27
- package/dist/Tag/Tag.d.ts +29 -22
- package/dist/Tag/index.js +2 -2
- package/dist/{Tag-VNZEYLB6.css → Tag-GBE7LQJP.css} +82 -83
- package/dist/TagsInput/index.js +6 -6
- package/dist/ThemeSwitcher/ThemeSwitcher.d.ts +53 -21
- package/dist/ThemeSwitcher/index.d.ts +3 -3
- package/dist/ThemeSwitcher/index.js +4 -3
- package/dist/ThemeSwitcher/preferences.d.ts +19 -5
- package/dist/ThemeToggle/ThemeToggle.d.ts +40 -0
- package/dist/ThemeToggle/index.d.ts +2 -0
- package/dist/ThemeToggle/index.js +5 -0
- package/dist/TimeWindowPicker/index.js +8 -8
- package/dist/Toaster/index.js +2 -2
- package/dist/Toolbar/index.js +2 -2
- package/dist/{Toolbar-IP6LXN45.css → Toolbar-HUOSMNTH.css} +3 -1
- package/dist/Tooltip/index.js +2 -2
- package/dist/Tree/index.d.ts +2 -2
- package/dist/Tree/index.js +1 -1
- package/dist/Tree/layout.d.ts +103 -28
- package/dist/TreeCanvas/TreeCanvas.d.ts +60 -14
- package/dist/TreeCanvas/index.d.ts +1 -1
- package/dist/TreeCanvas/index.js +6 -6
- package/dist/TreeCanvas/motion.d.ts +3 -2
- package/dist/{TreeCanvas-WBNQPHC7.css → TreeCanvas-HVOV4SQN.css} +154 -30
- package/dist/TreeGrid/index.js +4 -4
- package/dist/{chunk-F6OE5FH3.js → chunk-2FPENTCF.js} +1 -1
- package/dist/chunk-4AK52VHB.js +88 -0
- package/dist/{chunk-7EM5T4ME.js → chunk-4IQD3HUQ.js} +2 -2
- package/dist/{chunk-YODNNSZL.js → chunk-4PZ6FJKW.js} +43 -13
- package/dist/{chunk-F27EPQ7D.js → chunk-4UQ7SMPK.js} +1 -1
- package/dist/chunk-5QWIJSQM.js +73 -0
- package/dist/{chunk-GTOUGQQK.js → chunk-6MU7HNB4.js} +13 -10
- package/dist/{chunk-S2XHHEW4.js → chunk-74KMX7YH.js} +4 -4
- package/dist/{chunk-WNI2WSJF.js → chunk-7KBNFFM3.js} +1 -1
- package/dist/{chunk-DD5BBGBE.js → chunk-AUS5FNQE.js} +9 -5
- package/dist/{chunk-CMEE37QJ.js → chunk-BMYPGGPV.js} +4 -4
- package/dist/{chunk-H4FBTAYS.js → chunk-BNCCEER3.js} +8 -8
- package/dist/chunk-C5WJUZVR.js +56 -0
- package/dist/{chunk-5WS6L6FA.js → chunk-CAIHUYXV.js} +9 -9
- package/dist/{chunk-XV6WRMBC.js → chunk-CQY5NTRS.js} +4 -1
- package/dist/{chunk-UOGSZKLT.js → chunk-D6EVJUGU.js} +2 -2
- package/dist/{chunk-6ZFVFA56.js → chunk-DHPUMOTX.js} +2 -2
- package/dist/{chunk-HZ5XZNPS.js → chunk-DS2C73RJ.js} +3 -3
- package/dist/{chunk-O6232G37.js → chunk-DSUY5F4E.js} +17 -5
- package/dist/{chunk-Q4ZPPART.js → chunk-EFYPAJT3.js} +3 -3
- package/dist/{chunk-WQX73TWF.js → chunk-ERVO6OUF.js} +18 -17
- package/dist/{chunk-BZYDZBAN.js → chunk-ETYEBKR4.js} +3 -3
- package/dist/{chunk-34VGEDVV.js → chunk-FD5UEN6X.js} +30 -30
- package/dist/{chunk-5SDBMKUO.js → chunk-FIFNP6PL.js} +3 -3
- package/dist/{chunk-7HPRF5XN.js → chunk-FUF52K7E.js} +98 -16
- package/dist/{chunk-5KPQ6D7N.js → chunk-FZVJDJFN.js} +2 -2
- package/dist/chunk-IA232OTU.js +156 -0
- package/dist/{chunk-2EOKFKHX.js → chunk-IG27QX7Q.js} +7 -7
- package/dist/chunk-IKB6HFGK.js +55 -0
- package/dist/{chunk-FBZAKNSX.js → chunk-IPVQKAHO.js} +10 -7
- package/dist/{chunk-3EYF6HKB.js → chunk-IVFJD7WY.js} +28 -9
- package/dist/{chunk-WOYYD2YR.js → chunk-JGRNTBF2.js} +11 -11
- package/dist/chunk-K3OWD7BJ.js +121 -0
- package/dist/{chunk-BJSKPEZI.js → chunk-KD4H66L6.js} +7 -20
- package/dist/{chunk-SFZOKW2G.js → chunk-KJ34ZBBI.js} +8 -3
- package/dist/{chunk-HQNHV7D6.js → chunk-LFHCXZO5.js} +6 -6
- package/dist/{chunk-LWKJQTOM.js → chunk-MICH6QSJ.js} +1 -1
- package/dist/chunk-N3DPO6HG.js +226 -0
- package/dist/{chunk-S4GZWSKR.js → chunk-OM5E3TTK.js} +1 -1
- package/dist/{chunk-3QRYCPXQ.js → chunk-OPKIKM35.js} +6 -6
- package/dist/{chunk-5EKIWVOR.js → chunk-PGRPNDWM.js} +2 -2
- package/dist/{chunk-LFJ6UJTI.js → chunk-PQNILU27.js} +9 -9
- package/dist/{chunk-QNCVHRZL.js → chunk-QVAFL2LE.js} +1 -1
- package/dist/{chunk-QEUY3A5P.js → chunk-QY7UU5ZB.js} +3 -2
- package/dist/{chunk-ITHXJHBB.js → chunk-R25RGPUB.js} +1 -0
- package/dist/{chunk-KLJCCMF3.js → chunk-R6735B37.js} +2 -2
- package/dist/{chunk-3ZP55QZE.js → chunk-R6FBDTP3.js} +4 -4
- package/dist/{chunk-7FZ53WDJ.js → chunk-RIAZM6L3.js} +1 -1
- package/dist/chunk-RJM4QCGG.js +550 -0
- package/dist/{chunk-NTRZGNEX.js → chunk-S3BCVWTU.js} +215 -46
- package/dist/chunk-S7KW47IQ.js +121 -0
- package/dist/{chunk-OFHBK7RI.js → chunk-SJQ546ID.js} +34 -14
- package/dist/{chunk-D35VTV2Z.js → chunk-SV7QAONL.js} +1 -1
- package/dist/{chunk-IAJLHVUA.js → chunk-TIWAHZZ6.js} +1 -1
- package/dist/{chunk-2PRH365R.js → chunk-UA7O3KKJ.js} +1 -1
- package/dist/{chunk-NPZY6YYL.js → chunk-UG5ZMAXW.js} +6 -6
- package/dist/{chunk-FEFTGVMF.js → chunk-V2N3BMOT.js} +7 -2
- package/dist/{chunk-NDCATSW7.js → chunk-V34H2YCY.js} +1 -1
- package/dist/chunk-WIATRXEJ.js +22 -0
- package/dist/{chunk-5C5YMZQU.js → chunk-WOFOMTGB.js} +16 -10
- package/dist/{chunk-QYOFACSP.js → chunk-WSOFKOLP.js} +3 -3
- package/dist/{chunk-MNAXYY3R.js → chunk-WUVZDFHS.js} +31 -11
- package/dist/{chunk-UG46QBLT.js → chunk-YIMOT5OO.js} +10 -10
- package/dist/{chunk-2ZQMA2WB.js → chunk-ZPSOF6VL.js} +2 -2
- package/dist/generated/index.d.ts +3 -0
- package/dist/generated/index.js +66 -62
- package/dist/index.js +66 -62
- package/dist/styles.css +2719 -799
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/tone.d.ts +7 -12
- package/package.json +4 -4
- package/scripts/check-css-literals.mjs +159 -23
- package/scripts/check-css-variables.mjs +5 -3
- package/scripts/css-source.mjs +97 -5
- package/dist/Avatar-P2KRQM2B.css +0 -156
- package/dist/Charts-D7G2BSXH.css +0 -277
- package/dist/CommandPalette-CSJDUCQA.css +0 -115
- package/dist/Kbd-W66MXQI5.css +0 -61
- package/dist/SearchTrigger-QXOYAUUY.css +0 -79
- package/dist/SidebarNav-QGSFKZYA.css +0 -319
- package/dist/StatCard-KYPKZUWX.css +0 -111
- package/dist/StatusDot-HA2L2FSX.css +0 -84
- package/dist/chunk-22O7LAW2.js +0 -41
- package/dist/chunk-2HQR4U4D.js +0 -143
- package/dist/chunk-ESCO4XYW.js +0 -144
- package/dist/chunk-F4PJZ4ED.js +0 -245
- package/dist/chunk-PNFASD6F.js +0 -98
- package/dist/chunk-PZSWF74H.js +0 -15
- /package/dist/{chunk-ZCR6YGQ4.js → chunk-PKIN4IMB.js} +0 -0
|
@@ -1,319 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* The rail's navigation.
|
|
3
|
-
*
|
|
4
|
-
* ONE VERTICAL LINE. The rail pads by --size-nav-gutter and each row pads by
|
|
5
|
-
* --size-nav-row-pad, so the mark, the group labels and every row's text start
|
|
6
|
-
* on the same line: shrink the gutter and grow the pad by the same step and
|
|
7
|
-
* nothing moves. That is why the row's own background takes the full width the
|
|
8
|
-
* gutter leaves it, rather than each row carrying a horizontal margin of its
|
|
9
|
-
* own.
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
.crewlet-sidebar-nav {
|
|
13
|
-
display: flex;
|
|
14
|
-
flex-direction: column;
|
|
15
|
-
gap: var(--spacing-1);
|
|
16
|
-
min-width: 0;
|
|
17
|
-
padding: var(--spacing-2) var(--size-nav-gutter) var(--spacing-4);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/*
|
|
21
|
-
* THE ROWS INSIDE A GROUP ARE FLUSH. A group is a run of destinations read as
|
|
22
|
-
* one block, and the space between two of them is already the row's own height
|
|
23
|
-
* against a 13px line; a step on top of that spends four pixels a rail cannot
|
|
24
|
-
* afford fifteen times over. It is what the group LABEL's bottom pad is for,
|
|
25
|
-
* and the rail's own gap between groups is what separates one run from the
|
|
26
|
-
* next.
|
|
27
|
-
*
|
|
28
|
-
* Measured rather than chosen: at one step per row the rail stood 823px in a
|
|
29
|
-
* 755px scroller, so the last two destinations in the product were reachable
|
|
30
|
-
* only by scrolling the rail. Flush it is 746px and every row is on screen.
|
|
31
|
-
*/
|
|
32
|
-
.crewlet-nav-group {
|
|
33
|
-
display: flex;
|
|
34
|
-
flex-direction: column;
|
|
35
|
-
gap: var(--spacing-0);
|
|
36
|
-
min-width: 0;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
.crewlet-nav-group__label {
|
|
40
|
-
padding: var(--spacing-3) var(--size-nav-row-pad) var(--spacing-1);
|
|
41
|
-
font-family: var(--font-family-sans);
|
|
42
|
-
font-size: var(--font-size-2xs);
|
|
43
|
-
font-weight: var(--font-weight-medium);
|
|
44
|
-
/* The rail's own micro-label register, which is one step tighter than the
|
|
45
|
-
wider step an Eyebrow takes: a group name here sits four pixels above the
|
|
46
|
-
row it names, and at the wider step "OPERATIONS" was visibly broader than
|
|
47
|
-
the rows beneath it rather than quieter than them. */
|
|
48
|
-
letter-spacing: var(--font-letter-spacing-wide);
|
|
49
|
-
text-transform: uppercase;
|
|
50
|
-
/* The 4.5:1 step: a group name is a fact a reader has to read, not
|
|
51
|
-
decoration. */
|
|
52
|
-
color: var(--color-text-tertiary);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
.crewlet-nav-item {
|
|
56
|
-
min-width: 0;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
.crewlet-nav-item__head {
|
|
60
|
-
display: flex;
|
|
61
|
-
align-items: center;
|
|
62
|
-
gap: var(--spacing-1);
|
|
63
|
-
min-width: 0;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
.crewlet-nav-item__row {
|
|
67
|
-
display: flex;
|
|
68
|
-
align-items: center;
|
|
69
|
-
gap: var(--spacing-2);
|
|
70
|
-
flex: 1 1 auto;
|
|
71
|
-
min-width: 0;
|
|
72
|
-
width: 100%;
|
|
73
|
-
min-height: var(--size-row-md);
|
|
74
|
-
padding: 0 var(--size-nav-row-pad);
|
|
75
|
-
border: none;
|
|
76
|
-
/* The chrome's radius, not a card's. A 12px corner on a 36px row leaves the
|
|
77
|
-
tint reading as a lozenge floating in the gutter rather than as a band the
|
|
78
|
-
width of the rail. */
|
|
79
|
-
border-radius: var(--radius-md);
|
|
80
|
-
background: transparent;
|
|
81
|
-
/*
|
|
82
|
-
* THE RAIL READS AT FULL INK. A destination is not secondary text: a rail of
|
|
83
|
-
* fifteen rows in the quiet step is a column of grey a reader has to hunt
|
|
84
|
-
* through, and the step down bought nothing the row's own tint does not
|
|
85
|
-
* already say. It is also the darker of the two on light and the lighter on
|
|
86
|
-
* dark, so the contrast on every ground the row can have goes up rather than
|
|
87
|
-
* down.
|
|
88
|
-
*
|
|
89
|
-
* WHAT CARRIES HOVER IS THEREFORE THE TINT, not an ink step: there is no
|
|
90
|
-
* step left above this one. The glyph is the second half of it, lifting from
|
|
91
|
-
* the decoration ramp to the row's own ink.
|
|
92
|
-
*/
|
|
93
|
-
color: var(--color-text-primary);
|
|
94
|
-
font-family: var(--font-family-sans);
|
|
95
|
-
/* THE CHROME IS NOT BODY TEXT. A rail row names a destination; it is read at
|
|
96
|
-
a glance and never read through, so it takes the compact step in the
|
|
97
|
-
medium weight, which is what keeps a one-word row legible at 13px. */
|
|
98
|
-
font-size: var(--font-size-compact);
|
|
99
|
-
font-weight: var(--font-weight-medium);
|
|
100
|
-
letter-spacing: var(--font-letter-spacing-snug);
|
|
101
|
-
line-height: var(--font-line-height-tight);
|
|
102
|
-
text-align: left;
|
|
103
|
-
text-decoration: none;
|
|
104
|
-
cursor: pointer;
|
|
105
|
-
transition:
|
|
106
|
-
background var(--motion-duration-fast) var(--motion-easing-default),
|
|
107
|
-
color var(--motion-duration-fast) var(--motion-easing-default);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
.crewlet-nav-item__row:hover {
|
|
111
|
-
background: var(--color-surface-hover);
|
|
112
|
-
text-decoration: none;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
.crewlet-nav-item__row:focus-visible {
|
|
116
|
-
outline: 2px solid var(--color-focus);
|
|
117
|
-
/* Inside the row's own box: the rail is a clipping scroller, so an outset
|
|
118
|
-
ring on the first or last row is cut off by it. */
|
|
119
|
-
outline-offset: var(--size-focus-ring-inset-offset);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/*
|
|
123
|
-
* WHERE THE READER IS: the accent's own soft tint, with the label and the
|
|
124
|
-
* glyph in the accent ink. That is the whole job of an accent in a chrome, and
|
|
125
|
-
* the rail is the one place in the chrome it appears.
|
|
126
|
-
*
|
|
127
|
-
* It was a neutral lift with the accent as a one-pixel bar outside the row's
|
|
128
|
-
* left edge, on the reading that accent text in a rail competes with the
|
|
129
|
-
* status hues beside it and cannot be separated from the row above by a reader
|
|
130
|
-
* with a colour vision deficiency. Neither holds here. Nothing in this rail
|
|
131
|
-
* carries a status hue except the attention count below, which is a tint
|
|
132
|
-
* BEHIND a word rather than a word in a hue; and the tint is what answers the
|
|
133
|
-
* second objection, because the row still lifts off its ground by more than a
|
|
134
|
-
* hovered one does whether or not the hue is seen at all (@crewlethq/tokens
|
|
135
|
-
* measures exactly that, and measures this ink on this composite: 5.76:1 in
|
|
136
|
-
* light, 5.96:1 in dark).
|
|
137
|
-
*
|
|
138
|
-
* What the bar cost was that one pixel of hue was the entire signal, at the
|
|
139
|
-
* one moment a reader is scanning the rail to find out where they are.
|
|
140
|
-
*
|
|
141
|
-
* Drawn from aria-current, so the picture and what a screen reader is told
|
|
142
|
-
* cannot come apart. It is declared after :hover deliberately: both selectors
|
|
143
|
-
* weigh the same, a row shows the current tint or the hover overlay and never
|
|
144
|
-
* both, and later is what decides which.
|
|
145
|
-
*/
|
|
146
|
-
.crewlet-nav-item__row[aria-current='page'] {
|
|
147
|
-
background: var(--color-brand-accent-soft);
|
|
148
|
-
color: var(--color-brand-accent-ink);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
.crewlet-nav-item__row[aria-disabled='true'] {
|
|
152
|
-
cursor: not-allowed;
|
|
153
|
-
opacity: 0.55;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
.crewlet-nav-item__row[aria-disabled='true']:hover {
|
|
157
|
-
background: transparent;
|
|
158
|
-
color: var(--color-text-primary);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/*
|
|
162
|
-
* THE GLYPH FOLLOWS THE LABEL. At rest it is quieter than the word beside it
|
|
163
|
-
* and takes the decoration step; on a hovered row and on the reader's own it
|
|
164
|
-
* takes the row's own colour, which on the current row is the accent ink.
|
|
165
|
-
*
|
|
166
|
-
* ONE inherit rather than a second ramp, because a second ramp is how a row
|
|
167
|
-
* comes to paint its label and its glyph two different answers to "where am
|
|
168
|
-
* I". The colour is set on the DRAWING rather than on the box around it, which
|
|
169
|
-
* is what says the decoration step is being spent on a glyph and not on text:
|
|
170
|
-
* the package's variable check holds that rule, and it is the rule the step
|
|
171
|
-
* exists for.
|
|
172
|
-
*/
|
|
173
|
-
.crewlet-nav-item__icon {
|
|
174
|
-
display: inline-flex;
|
|
175
|
-
align-items: center;
|
|
176
|
-
justify-content: center;
|
|
177
|
-
flex: none;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
.crewlet-nav-item__icon svg {
|
|
181
|
-
color: var(--color-text-muted);
|
|
182
|
-
transition: color var(--motion-duration-fast) var(--motion-easing-default);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
.crewlet-nav-item__row:hover .crewlet-nav-item__icon svg,
|
|
186
|
-
.crewlet-nav-item__row[aria-current='page'] .crewlet-nav-item__icon svg {
|
|
187
|
-
color: inherit;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
.crewlet-nav-item__label {
|
|
191
|
-
flex: 1 1 auto;
|
|
192
|
-
min-width: 0;
|
|
193
|
-
overflow: hidden;
|
|
194
|
-
text-overflow: ellipsis;
|
|
195
|
-
white-space: nowrap;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
.crewlet-nav-item__badge {
|
|
199
|
-
display: inline-flex;
|
|
200
|
-
align-items: center;
|
|
201
|
-
flex: none;
|
|
202
|
-
margin-left: auto;
|
|
203
|
-
font-size: var(--font-size-2xs);
|
|
204
|
-
font-variant-numeric: tabular-nums;
|
|
205
|
-
color: var(--color-text-tertiary);
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
/*
|
|
209
|
-
* THE SLOT IS WHAT PAINTS. A caller hands in the figure and the name a screen
|
|
210
|
-
* reader reads after the row's own ("3 things waiting on somebody"); the rail
|
|
211
|
-
* decides whether that is a quiet number at the end of the row or the one
|
|
212
|
-
* thing on the screen that should pull the eye. So whatever arrives
|
|
213
|
-
* contributes its text and its accessible name and nothing else, which is why
|
|
214
|
-
* a <Count> here draws its own text rather than a second pill inside this one.
|
|
215
|
-
*/
|
|
216
|
-
.crewlet-nav-item__badge > * {
|
|
217
|
-
padding: 0;
|
|
218
|
-
border: none;
|
|
219
|
-
border-radius: 0;
|
|
220
|
-
background: transparent;
|
|
221
|
-
color: inherit;
|
|
222
|
-
min-width: 0;
|
|
223
|
-
font-size: inherit;
|
|
224
|
-
font-weight: inherit;
|
|
225
|
-
/* Not the `font` shorthand, which would reset font-variant and take the
|
|
226
|
-
tabular figures with it. */
|
|
227
|
-
font-variant-numeric: inherit;
|
|
228
|
-
line-height: inherit;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
/* A quiet badge takes the row's ink, the current row's accent included. The
|
|
232
|
-
attention badge keeps its own, which is the whole point of it, and the
|
|
233
|
-
:not() is what says so: both selectors would otherwise weigh the same and a
|
|
234
|
-
tone would be decided by which rule a later edit happened to move. */
|
|
235
|
-
.crewlet-nav-item__row[aria-current='page'] .crewlet-nav-item__badge:not(.crewlet-nav-item__badge--attention) {
|
|
236
|
-
color: inherit;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
/*
|
|
240
|
-
* THE ONE BADGE IN THE CHROME ALLOWED A STATUS HUE. A count of what is waiting
|
|
241
|
-
* on a person is the one thing that should pull the eye out of whatever screen
|
|
242
|
-
* the reader is on, and it stays a tint BEHIND a word rather than a word in a
|
|
243
|
-
* hue, so it reads to somebody who cannot separate the hue at all.
|
|
244
|
-
*
|
|
245
|
-
* Measured on every ground a row can have, the reader's own row included,
|
|
246
|
-
* which is a warning tint on the accent tint on the rail: @crewlethq/tokens'
|
|
247
|
-
* palette suite has that composite by name, at 5.08:1 in light and 9.75:1 in
|
|
248
|
-
* dark.
|
|
249
|
-
*/
|
|
250
|
-
.crewlet-nav-item__badge--attention {
|
|
251
|
-
padding: 0 var(--spacing-2);
|
|
252
|
-
border-radius: var(--radius-pill);
|
|
253
|
-
background: var(--color-feedback-warning-soft);
|
|
254
|
-
color: var(--color-feedback-warning-ink);
|
|
255
|
-
font-weight: var(--font-weight-semibold);
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
.crewlet-nav-item__toggle {
|
|
259
|
-
display: inline-flex;
|
|
260
|
-
align-items: center;
|
|
261
|
-
justify-content: center;
|
|
262
|
-
flex: none;
|
|
263
|
-
width: var(--size-control-sm);
|
|
264
|
-
height: var(--size-control-sm);
|
|
265
|
-
padding: 0;
|
|
266
|
-
border: none;
|
|
267
|
-
border-radius: var(--radius-sm);
|
|
268
|
-
background: transparent;
|
|
269
|
-
color: var(--color-text-tertiary);
|
|
270
|
-
cursor: pointer;
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
.crewlet-nav-item__toggle:hover {
|
|
274
|
-
background: var(--color-surface-hover);
|
|
275
|
-
color: var(--color-text-primary);
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
.crewlet-nav-item__toggle:focus-visible {
|
|
279
|
-
outline: 2px solid var(--color-focus);
|
|
280
|
-
outline-offset: var(--size-focus-ring-inset-offset);
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
.crewlet-nav-item__chevron {
|
|
284
|
-
display: inline-flex;
|
|
285
|
-
transition: transform var(--motion-duration-fast) var(--motion-easing-default);
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
.crewlet-nav-item__chevron--open {
|
|
289
|
-
transform: rotate(180deg);
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
/*
|
|
293
|
-
* Nested rows carry an indent guide rather than more padding, because a run of
|
|
294
|
-
* indents with no line is a hierarchy a reader has to measure by eye. The
|
|
295
|
-
* guide takes the accent on the path the reader is on, which is the same
|
|
296
|
-
* signal the top-level rail gives.
|
|
297
|
-
*/
|
|
298
|
-
.crewlet-nav-item__children {
|
|
299
|
-
display: flex;
|
|
300
|
-
flex-direction: column;
|
|
301
|
-
gap: var(--spacing-1);
|
|
302
|
-
margin-left: var(--size-nav-row-pad);
|
|
303
|
-
padding-left: var(--spacing-2);
|
|
304
|
-
border-left: 1px solid var(--color-border-default);
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
/* No type step of its own any more: every row in the rail reads at the compact
|
|
308
|
-
step now, and the indent guide is what says a row is nested. */
|
|
309
|
-
.crewlet-nav-item__children:has(.crewlet-nav-item__row[aria-current='page']) {
|
|
310
|
-
border-left-color: var(--color-brand-accent);
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
@media (prefers-reduced-motion: reduce) {
|
|
314
|
-
.crewlet-nav-item__row,
|
|
315
|
-
.crewlet-nav-item__icon svg,
|
|
316
|
-
.crewlet-nav-item__chevron {
|
|
317
|
-
transition: none;
|
|
318
|
-
}
|
|
319
|
-
}
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* The stat tile.
|
|
3
|
-
*
|
|
4
|
-
* THE TONE PAINTS THE VALUE, which is what the props always said and what the
|
|
5
|
-
* stylesheet never did: 0.2.0 tinted the ICON, so a caller who passed a tone
|
|
6
|
-
* and no icon got a tile identical to a neutral one. Ink only, and never a
|
|
7
|
-
* fill: a tinted block behind a 24px number reads as a button.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
.crewlet-statcard {
|
|
11
|
-
display: flex;
|
|
12
|
-
flex-direction: column;
|
|
13
|
-
gap: var(--spacing-1);
|
|
14
|
-
padding: var(--spacing-3) var(--spacing-4);
|
|
15
|
-
/* The panel recipe: the surface, the hairline, the 12px corner and the
|
|
16
|
-
elevation the engine gives every card on a screen, so a lone tile is the
|
|
17
|
-
same object as the panel beside it rather than a flatter cousin. */
|
|
18
|
-
background: var(--color-surface-subtle);
|
|
19
|
-
border: 1px solid var(--color-border-default);
|
|
20
|
-
border-radius: var(--radius-lg);
|
|
21
|
-
box-shadow: var(--shadow-xs), var(--shadow-hairline);
|
|
22
|
-
color: var(--color-text-primary);
|
|
23
|
-
font-family: var(--font-family-sans);
|
|
24
|
-
min-width: 0;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/* Inside a StatGroup the row is one card and the tiles are its columns, so a
|
|
28
|
-
tile brings no surface of its own. */
|
|
29
|
-
.crewlet-statcard--flush {
|
|
30
|
-
background: transparent;
|
|
31
|
-
border: 0;
|
|
32
|
-
border-radius: var(--radius-none);
|
|
33
|
-
box-shadow: none;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
.crewlet-statcard__value {
|
|
37
|
-
display: flex;
|
|
38
|
-
align-items: baseline;
|
|
39
|
-
gap: var(--spacing-2);
|
|
40
|
-
min-width: 0;
|
|
41
|
-
font-size: var(--font-size-2xl);
|
|
42
|
-
font-weight: var(--font-weight-semibold);
|
|
43
|
-
letter-spacing: var(--font-letter-spacing-tight);
|
|
44
|
-
/* 1.1, the engine's, which is tighter than the tight step: a 24px number
|
|
45
|
-
with 1.2 of leading sits low in its box and opens a gap between the value
|
|
46
|
-
and the line under it that the 4px gap was already spending. */
|
|
47
|
-
line-height: 1.1;
|
|
48
|
-
/* A number that ticks up must not move the label under it. */
|
|
49
|
-
font-variant-numeric: tabular-nums;
|
|
50
|
-
overflow: hidden;
|
|
51
|
-
text-overflow: ellipsis;
|
|
52
|
-
white-space: nowrap;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
.crewlet-statcard__unit {
|
|
56
|
-
font-size: var(--font-size-sm);
|
|
57
|
-
font-weight: var(--font-weight-regular);
|
|
58
|
-
letter-spacing: var(--font-letter-spacing-normal);
|
|
59
|
-
color: var(--color-text-tertiary);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/*
|
|
63
|
-
* The placeholder is a line, not a pair of dashes. `--` is read aloud as
|
|
64
|
-
* "dash dash" and looks exactly like a measured value of nothing; the tile
|
|
65
|
-
* carries aria-busy instead, and the line says the number is on its way.
|
|
66
|
-
*/
|
|
67
|
-
.crewlet-statcard__placeholder {
|
|
68
|
-
display: inline-block;
|
|
69
|
-
width: 3ch;
|
|
70
|
-
height: 0.7em;
|
|
71
|
-
border-radius: var(--radius-xs);
|
|
72
|
-
background: var(--color-surface-inset);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
.crewlet-statcard__label {
|
|
76
|
-
display: flex;
|
|
77
|
-
align-items: center;
|
|
78
|
-
gap: var(--spacing-1);
|
|
79
|
-
font-size: var(--font-size-2xs);
|
|
80
|
-
font-weight: var(--font-weight-medium);
|
|
81
|
-
letter-spacing: var(--font-letter-spacing-wide);
|
|
82
|
-
text-transform: uppercase;
|
|
83
|
-
color: var(--color-text-tertiary);
|
|
84
|
-
min-width: 0;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
.crewlet-statcard__icon {
|
|
88
|
-
display: inline-flex;
|
|
89
|
-
flex: none;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/*
|
|
93
|
-
* The second line keeps its space whether or not there is one, so a row of
|
|
94
|
-
* tiles where only some carry a sub still sits on one baseline.
|
|
95
|
-
*/
|
|
96
|
-
.crewlet-statcard__sub {
|
|
97
|
-
min-height: 1.2em;
|
|
98
|
-
font-size: var(--font-size-xs);
|
|
99
|
-
/* The quiet step, with the label. The sub qualifies the number rather than
|
|
100
|
-
being a second one, and the engine keeps both of them a step under the
|
|
101
|
-
value they belong to. */
|
|
102
|
-
color: var(--color-text-tertiary);
|
|
103
|
-
overflow: hidden;
|
|
104
|
-
text-overflow: ellipsis;
|
|
105
|
-
white-space: nowrap;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
.crewlet-statcard--success .crewlet-statcard__value { color: var(--color-feedback-success-ink); }
|
|
109
|
-
.crewlet-statcard--warning .crewlet-statcard__value { color: var(--color-feedback-warning-ink); }
|
|
110
|
-
.crewlet-statcard--danger .crewlet-statcard__value { color: var(--color-feedback-danger-ink); }
|
|
111
|
-
.crewlet-statcard--info .crewlet-statcard__value { color: var(--color-feedback-info-ink); }
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* The status dot: a 6px mark in its tone's fill, beside the word it belongs
|
|
3
|
-
* to. See the component doc for why it is hidden from assistive technology.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
.crewlet-status-dot {
|
|
7
|
-
display: inline-block;
|
|
8
|
-
width: 6px;
|
|
9
|
-
height: 6px;
|
|
10
|
-
border-radius: var(--radius-circle);
|
|
11
|
-
/*
|
|
12
|
-
* The quiet state is still a mark, so it takes the tertiary step rather than
|
|
13
|
-
* the decoration one the engine spends here: a 6px dot has to clear 3:1 to
|
|
14
|
-
* be seen at all, and --color-text-muted measures 2.33:1 on a light page and
|
|
15
|
-
* 2.25:1 on a dark one at their worst grounds. The tertiary step measures
|
|
16
|
-
* 4.87:1 and 4.65:1 on the same pair, and is the nearest step that holds.
|
|
17
|
-
*/
|
|
18
|
-
background: var(--color-text-tertiary);
|
|
19
|
-
flex: none;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
.crewlet-status-dot--info {
|
|
23
|
-
background: var(--color-feedback-info);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
.crewlet-status-dot--success {
|
|
27
|
-
background: var(--color-feedback-success);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
.crewlet-status-dot--warning {
|
|
31
|
-
background: var(--color-feedback-warning);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
.crewlet-status-dot--danger {
|
|
35
|
-
background: var(--color-feedback-danger);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
.crewlet-status-dot--brand {
|
|
39
|
-
background: var(--color-brand-accent);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
.crewlet-status-dot--phase-onboarding {
|
|
43
|
-
background: var(--color-phase-onboarding);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
.crewlet-status-dot--phase-execute {
|
|
47
|
-
background: var(--color-phase-execute);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
.crewlet-status-dot--phase-review {
|
|
51
|
-
background: var(--color-phase-review);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/*
|
|
55
|
-
* Still happening. Three things are deliberate: the pulse never goes to
|
|
56
|
-
* nothing, because a mark that disappears reads as a fault rather than as work
|
|
57
|
-
* in progress; it alternates rather than sawtooths, so the mark comes back the
|
|
58
|
-
* way it went; and the round trip is 1.8s, which is the engine's own breath
|
|
59
|
-
* and is 0.55 flashes a second, well clear of the three that are a seizure
|
|
60
|
-
* risk. Three of the slow step each way makes that round trip.
|
|
61
|
-
*/
|
|
62
|
-
.crewlet-status-dot.is-pulsing {
|
|
63
|
-
animation: crewlet-status-dot-pulse calc(var(--motion-duration-slow) * 3) var(--motion-easing-default) infinite
|
|
64
|
-
alternate;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
@keyframes crewlet-status-dot-pulse {
|
|
68
|
-
from {
|
|
69
|
-
opacity: 1;
|
|
70
|
-
}
|
|
71
|
-
to {
|
|
72
|
-
opacity: 0.35;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/*
|
|
77
|
-
* A mark that cannot move should not pretend to. The dot still reads as its
|
|
78
|
-
* tone, and the word beside it still says what is happening.
|
|
79
|
-
*/
|
|
80
|
-
@media (prefers-reduced-motion: reduce) {
|
|
81
|
-
.crewlet-status-dot.is-pulsing {
|
|
82
|
-
animation: none;
|
|
83
|
-
}
|
|
84
|
-
}
|
package/dist/chunk-22O7LAW2.js
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { VisuallyHidden } from './chunk-BZFWDIV6.js';
|
|
2
|
-
import { cx } from './chunk-ODEQTPFM.js';
|
|
3
|
-
import './StatCard-KYPKZUWX.css';
|
|
4
|
-
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
5
|
-
|
|
6
|
-
var StatCard = ({
|
|
7
|
-
label,
|
|
8
|
-
value,
|
|
9
|
-
unit,
|
|
10
|
-
sub,
|
|
11
|
-
icon,
|
|
12
|
-
tone = "neutral",
|
|
13
|
-
loading = false,
|
|
14
|
-
loadingLabel = "Loading",
|
|
15
|
-
flush = false,
|
|
16
|
-
className,
|
|
17
|
-
...rest
|
|
18
|
-
}) => /* @__PURE__ */ jsxs(
|
|
19
|
-
"div",
|
|
20
|
-
{
|
|
21
|
-
...rest,
|
|
22
|
-
className: cx("crewlet-statcard", `crewlet-statcard--${tone}`, flush && "crewlet-statcard--flush", className),
|
|
23
|
-
"aria-busy": loading || void 0,
|
|
24
|
-
children: [
|
|
25
|
-
/* @__PURE__ */ jsxs("div", { className: "crewlet-statcard__label", children: [
|
|
26
|
-
icon ? /* @__PURE__ */ jsx("span", { className: "crewlet-statcard__icon", "aria-hidden": true, children: icon }) : null,
|
|
27
|
-
label
|
|
28
|
-
] }),
|
|
29
|
-
/* @__PURE__ */ jsx("div", { className: "crewlet-statcard__value", children: loading ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
30
|
-
/* @__PURE__ */ jsx("span", { className: "crewlet-statcard__placeholder", "aria-hidden": true }),
|
|
31
|
-
/* @__PURE__ */ jsx(VisuallyHidden, { children: loadingLabel })
|
|
32
|
-
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
33
|
-
value,
|
|
34
|
-
unit ? /* @__PURE__ */ jsx("span", { className: "crewlet-statcard__unit", children: unit }) : null
|
|
35
|
-
] }) }),
|
|
36
|
-
/* @__PURE__ */ jsx("div", { className: "crewlet-statcard__sub", children: sub })
|
|
37
|
-
]
|
|
38
|
-
}
|
|
39
|
-
);
|
|
40
|
-
|
|
41
|
-
export { StatCard };
|
package/dist/chunk-2HQR4U4D.js
DELETED
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
import { SegmentedControl } from './chunk-6ZFVFA56.js';
|
|
2
|
-
import { LightModeGlyph, ComputerGlyph, DarkModeGlyph } from '@crewlethq/icons/glyphs';
|
|
3
|
-
import { useState, useEffect, useCallback } from 'react';
|
|
4
|
-
import { jsx } from 'react/jsx-runtime';
|
|
5
|
-
|
|
6
|
-
var THEMES = ["system", "light", "dark"];
|
|
7
|
-
var DENSITIES = ["normal", "compact", "comfortable"];
|
|
8
|
-
function read(key, allowed, fallback) {
|
|
9
|
-
try {
|
|
10
|
-
const held = globalThis.localStorage?.getItem(key);
|
|
11
|
-
return allowed.includes(held) ? held : fallback;
|
|
12
|
-
} catch {
|
|
13
|
-
return fallback;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
function write(key, value) {
|
|
17
|
-
try {
|
|
18
|
-
globalThis.localStorage?.setItem(key, value);
|
|
19
|
-
} catch {
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
function root() {
|
|
23
|
-
return typeof document === "undefined" ? null : document.documentElement;
|
|
24
|
-
}
|
|
25
|
-
function applyTheme(theme) {
|
|
26
|
-
const el = root();
|
|
27
|
-
if (!el) return;
|
|
28
|
-
if (theme === "system") el.removeAttribute("data-theme");
|
|
29
|
-
else el.setAttribute("data-theme", theme);
|
|
30
|
-
}
|
|
31
|
-
function applyDensity(density) {
|
|
32
|
-
const el = root();
|
|
33
|
-
if (!el) return;
|
|
34
|
-
if (density === "normal") el.removeAttribute("data-density");
|
|
35
|
-
else el.setAttribute("data-density", density);
|
|
36
|
-
}
|
|
37
|
-
function useThemePreference({
|
|
38
|
-
storageKey
|
|
39
|
-
}) {
|
|
40
|
-
const [theme, setTheme] = useState(() => read(storageKey, THEMES, "system"));
|
|
41
|
-
useEffect(() => {
|
|
42
|
-
applyTheme(theme);
|
|
43
|
-
}, [theme]);
|
|
44
|
-
const choose = useCallback(
|
|
45
|
-
(next) => {
|
|
46
|
-
setTheme(next);
|
|
47
|
-
applyTheme(next);
|
|
48
|
-
write(storageKey, next);
|
|
49
|
-
},
|
|
50
|
-
[storageKey]
|
|
51
|
-
);
|
|
52
|
-
return [theme, choose];
|
|
53
|
-
}
|
|
54
|
-
function useDensityPreference({
|
|
55
|
-
storageKey
|
|
56
|
-
}) {
|
|
57
|
-
const [density, setDensity] = useState(
|
|
58
|
-
() => read(storageKey, DENSITIES, "normal")
|
|
59
|
-
);
|
|
60
|
-
useEffect(() => {
|
|
61
|
-
applyDensity(density);
|
|
62
|
-
}, [density]);
|
|
63
|
-
const choose = useCallback(
|
|
64
|
-
(next) => {
|
|
65
|
-
setDensity(next);
|
|
66
|
-
applyDensity(next);
|
|
67
|
-
write(storageKey, next);
|
|
68
|
-
},
|
|
69
|
-
[storageKey]
|
|
70
|
-
);
|
|
71
|
-
return [density, choose];
|
|
72
|
-
}
|
|
73
|
-
function applyStoredPreferences({ themeKey, densityKey }) {
|
|
74
|
-
const theme = themeKey ? read(themeKey, THEMES, "system") : "system";
|
|
75
|
-
const density = densityKey ? read(densityKey, DENSITIES, "normal") : "normal";
|
|
76
|
-
applyTheme(theme);
|
|
77
|
-
applyDensity(density);
|
|
78
|
-
return { theme, density };
|
|
79
|
-
}
|
|
80
|
-
function ThemeSwitcher({
|
|
81
|
-
storageKey = "crewlet_theme",
|
|
82
|
-
label = "Theme",
|
|
83
|
-
lightLabel = "Light",
|
|
84
|
-
systemLabel = "Follow the system",
|
|
85
|
-
darkLabel = "Dark",
|
|
86
|
-
size = "sm",
|
|
87
|
-
className
|
|
88
|
-
}) {
|
|
89
|
-
const [theme, choose] = useThemePreference({ storageKey });
|
|
90
|
-
return /* @__PURE__ */ jsx(
|
|
91
|
-
SegmentedControl,
|
|
92
|
-
{
|
|
93
|
-
label,
|
|
94
|
-
semantics: "radio",
|
|
95
|
-
size,
|
|
96
|
-
className,
|
|
97
|
-
value: theme,
|
|
98
|
-
onValueChange: choose,
|
|
99
|
-
options: [
|
|
100
|
-
{ value: "light", icon: /* @__PURE__ */ jsx(LightModeGlyph, {}), srLabel: lightLabel, title: lightLabel },
|
|
101
|
-
{ value: "system", icon: /* @__PURE__ */ jsx(ComputerGlyph, {}), srLabel: systemLabel, title: systemLabel },
|
|
102
|
-
{ value: "dark", icon: /* @__PURE__ */ jsx(DarkModeGlyph, {}), srLabel: darkLabel, title: darkLabel }
|
|
103
|
-
]
|
|
104
|
-
}
|
|
105
|
-
);
|
|
106
|
-
}
|
|
107
|
-
function DensitySwitcher({
|
|
108
|
-
storageKey = "crewlet_density",
|
|
109
|
-
label = "Density",
|
|
110
|
-
compactLabel = "Compact",
|
|
111
|
-
normalLabel = "Normal",
|
|
112
|
-
comfortableLabel = "Comfortable",
|
|
113
|
-
compactMark = "S",
|
|
114
|
-
normalMark = "M",
|
|
115
|
-
comfortableMark = "L",
|
|
116
|
-
size = "sm",
|
|
117
|
-
className
|
|
118
|
-
}) {
|
|
119
|
-
const [density, choose] = useDensityPreference({ storageKey });
|
|
120
|
-
return /* @__PURE__ */ jsx(
|
|
121
|
-
SegmentedControl,
|
|
122
|
-
{
|
|
123
|
-
label,
|
|
124
|
-
semantics: "radio",
|
|
125
|
-
size,
|
|
126
|
-
className,
|
|
127
|
-
value: density,
|
|
128
|
-
onValueChange: choose,
|
|
129
|
-
options: [
|
|
130
|
-
{ value: "compact", label: compactMark, srLabel: compactLabel, title: compactLabel },
|
|
131
|
-
{ value: "normal", label: normalMark, srLabel: normalLabel, title: normalLabel },
|
|
132
|
-
{
|
|
133
|
-
value: "comfortable",
|
|
134
|
-
label: comfortableMark,
|
|
135
|
-
srLabel: comfortableLabel,
|
|
136
|
-
title: comfortableLabel
|
|
137
|
-
}
|
|
138
|
-
]
|
|
139
|
-
}
|
|
140
|
-
);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
export { DensitySwitcher, ThemeSwitcher, applyDensity, applyStoredPreferences, applyTheme, useDensityPreference, useThemePreference };
|