@crewlethq/ui 0.15.1 → 0.16.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 +32 -6
- package/dist/AppShell/AccountRow.d.ts +40 -0
- package/dist/AppShell/AppShell.d.ts +1 -0
- package/dist/AppShell/index.d.ts +2 -0
- package/dist/AppShell/index.js +1 -1
- package/dist/{AppShell-6QUD7NWM.css → AppShell-RUNVM4WH.css} +93 -0
- package/dist/AuthLayout/AuthLayout.d.ts +35 -0
- package/dist/AuthLayout/index.d.ts +3 -0
- package/dist/AuthLayout/index.js +8 -0
- package/dist/AuthLayout-ODHBUPHQ.css +54 -0
- package/dist/Avatar/Avatar.d.ts +22 -2
- package/dist/Avatar/index.d.ts +1 -1
- package/dist/Avatar/index.js +2 -2
- package/dist/{Avatar-I4NFP3WQ.css → Avatar-MBUPR5E5.css} +19 -0
- package/dist/AvatarPicker/index.js +4 -4
- package/dist/Callout/Callout.d.ts +7 -1
- package/dist/Callout/index.js +1 -1
- package/dist/{Callout-S7QDWHDL.css → Callout-SXXK4B5R.css} +3 -1
- package/dist/CharacterPicker/index.js +2 -2
- package/dist/Checkbox/CheckboxGroup.d.ts +30 -0
- package/dist/Checkbox/index.d.ts +2 -0
- package/dist/Checkbox/index.js +5 -1
- package/dist/{Checkbox-UE7TEPAM.css → Checkbox-KT7RS6QQ.css} +16 -0
- package/dist/CodeBlock/index.js +4 -3
- package/dist/Combobox/index.js +3 -3
- package/dist/CommandPalette/index.js +5 -5
- package/dist/Composer/index.js +3 -3
- package/dist/ConfirmField/ConfirmField.d.ts +43 -0
- package/dist/ConfirmField/index.d.ts +2 -0
- package/dist/ConfirmField/index.js +7 -0
- package/dist/Copyable/CopyButton.d.ts +13 -6
- package/dist/Copyable/index.js +3 -2
- package/dist/DataTable/index.js +7 -5
- package/dist/DataView/index.js +12 -11
- package/dist/DateTimePicker/index.js +2 -2
- package/dist/DownloadButton/DownloadButton.d.ts +52 -0
- package/dist/DownloadButton/index.d.ts +2 -0
- package/dist/DownloadButton/index.js +6 -0
- package/dist/EntityChip/index.js +3 -3
- package/dist/ImageUpload/index.js +3 -3
- package/dist/InlineCode/InlineCode.d.ts +8 -1
- package/dist/InlineCode/index.js +1 -1
- package/dist/{InlineCode-6WSR5COL.css → InlineCode-ASYHLN3E.css} +9 -0
- package/dist/Input/index.js +2 -2
- package/dist/{Input-RAKNQJCV.css → Input-3KVSNUO5.css} +11 -0
- package/dist/ListInput/index.js +3 -3
- package/dist/MarkdownEditor/index.js +1 -1
- package/dist/Modal/index.js +2 -2
- package/dist/ObjectHeader/ObjectHeader.d.ts +138 -0
- package/dist/ObjectHeader/index.d.ts +3 -0
- package/dist/ObjectHeader/index.js +4 -0
- package/dist/ObjectHeader-UNVYM2KD.css +174 -0
- package/dist/OrgLabel/index.js +3 -3
- package/dist/OrgNode/index.js +4 -4
- package/dist/OrgTable/index.js +4 -4
- package/dist/QrCode/QrCode.d.ts +58 -0
- package/dist/QrCode/index.d.ts +3 -0
- package/dist/QrCode/index.js +2 -0
- package/dist/QrCode-JWJTWMU5.css +19 -0
- package/dist/Switcher/index.js +4 -4
- package/dist/Text/Text.d.ts +7 -1
- package/dist/Text/index.js +1 -1
- package/dist/{Text-XIPYYZX2.css → Text-S3Q4O3IG.css} +11 -0
- package/dist/TimeWindowPicker/index.js +4 -4
- package/dist/{chunk-FTEJPHBI.js → chunk-4GB57WIT.js} +2 -2
- package/dist/{chunk-NN62JQLR.js → chunk-5CLW2CXT.js} +3 -1
- package/dist/{chunk-4EOJR52M.js → chunk-5EFRWWGX.js} +4 -4
- package/dist/{chunk-22M7OXKW.js → chunk-6DQWF5Y4.js} +1 -1
- package/dist/{chunk-QSLIN64M.js → chunk-6NIMZ5XC.js} +1 -1
- package/dist/{chunk-YCTMKKRA.js → chunk-75CLJNDQ.js} +12 -2
- package/dist/chunk-7QFAORCY.js +37 -0
- package/dist/chunk-BJCFNRGH.js +53 -0
- package/dist/{chunk-FY2R4U4Q.js → chunk-CGNQPGJL.js} +1 -1
- package/dist/{chunk-DDTDN5L2.js → chunk-CKB3OHL3.js} +1 -1
- package/dist/chunk-CXBAIVYZ.js +39 -0
- package/dist/chunk-DTIW4CHZ.js +37 -0
- package/dist/{chunk-YXMCUKFI.js → chunk-DZ2YR6MV.js} +1 -1
- package/dist/{chunk-TK6YC5QT.js → chunk-EIOTVNYX.js} +4 -4
- package/dist/chunk-F6NZOVWL.js +68 -0
- package/dist/{chunk-LCF4WPYS.js → chunk-FA2V2VT6.js} +2 -2
- package/dist/{chunk-EFNHOVC2.js → chunk-FAEN3HYI.js} +2 -2
- package/dist/{chunk-HI6Q2UXQ.js → chunk-FY4SP3HF.js} +11 -3
- package/dist/{chunk-KGTQ5CVD.js → chunk-GDDE4UM7.js} +1 -1
- package/dist/chunk-I7WXZOWA.js +90 -0
- package/dist/{chunk-23DHIMJA.js → chunk-IKBK4A5O.js} +1 -1
- package/dist/{chunk-DY77H372.js → chunk-JF7X673Z.js} +2 -2
- package/dist/{chunk-DJMLHCLD.js → chunk-KLESCRTS.js} +1 -1
- package/dist/{chunk-YYBD73OI.js → chunk-OFMPIRGD.js} +1 -1
- package/dist/{chunk-H3XOMT7W.js → chunk-OYOQU7O5.js} +44 -3
- package/dist/{chunk-IYZZL3MZ.js → chunk-PQ63NLFC.js} +3 -3
- package/dist/{chunk-5VNUYO76.js → chunk-STJ7QBC3.js} +8 -25
- package/dist/{chunk-R6FBDTP3.js → chunk-SVSCLHHI.js} +1 -1
- package/dist/{chunk-GARACZAH.js → chunk-T3ZWBZ65.js} +1 -1
- package/dist/{chunk-ZPWUVVIB.js → chunk-UAMDRJD6.js} +2 -2
- package/dist/{chunk-YACKC3K2.js → chunk-W46LPU4R.js} +8 -8
- package/dist/chunk-Y56FM3K4.js +57 -0
- package/dist/{chunk-4Y7WKXAW.js → chunk-ZFH7H7GS.js} +1 -1
- package/dist/generated/index.d.ts +5 -0
- package/dist/generated/index.js +67 -60
- package/dist/index.js +67 -60
- package/dist/styles.css +425 -8
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.js +4 -2
- package/dist/utils/useClipboard.d.ts +6 -3
- package/dist/utils/useDownload.d.ts +63 -0
- package/dist/utils/useOutcome.d.ts +44 -0
- package/package.json +4 -3
- package/dist/{chunk-GUHP5JHC.js → chunk-2UU5IGZI.js} +1 -1
- package/dist/{chunk-6AR2T5Y4.js → chunk-CRVETI5L.js} +0 -0
- package/dist/{chunk-K4VORB64.js → chunk-DEEVA6TV.js} +1 -1
- /package/dist/{chunk-AER7UDD4.js → chunk-U5LQ2AS5.js} +0 -0
package/dist/styles.css
CHANGED
|
@@ -537,7 +537,7 @@
|
|
|
537
537
|
}
|
|
538
538
|
|
|
539
539
|
|
|
540
|
-
/* AppShell-
|
|
540
|
+
/* AppShell-RUNVM4WH.css */
|
|
541
541
|
/*
|
|
542
542
|
* The application frame: a rail on the FRAME, and the screen on a SHEET that
|
|
543
543
|
* floats beside it.
|
|
@@ -1162,8 +1162,158 @@
|
|
|
1162
1162
|
}
|
|
1163
1163
|
}
|
|
1164
1164
|
|
|
1165
|
+
/* ── the account row ───────────────────────────────────────────────────── */
|
|
1165
1166
|
|
|
1166
|
-
/*
|
|
1167
|
+
/*
|
|
1168
|
+
* The signed-in reader at the foot of the rail, with the row's controls at
|
|
1169
|
+
* its end. The link takes the room, so a long name is cut rather than pushing
|
|
1170
|
+
* the controls off the rail.
|
|
1171
|
+
*/
|
|
1172
|
+
.crewlet-account-row {
|
|
1173
|
+
display: flex;
|
|
1174
|
+
align-items: center;
|
|
1175
|
+
gap: var(--spacing-1);
|
|
1176
|
+
min-width: 0;
|
|
1177
|
+
padding: var(--spacing-1) 0;
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
.crewlet-account-row__who {
|
|
1181
|
+
display: flex;
|
|
1182
|
+
flex: 1 1 auto;
|
|
1183
|
+
align-items: center;
|
|
1184
|
+
gap: var(--spacing-2);
|
|
1185
|
+
min-width: 0;
|
|
1186
|
+
padding: var(--spacing-1);
|
|
1187
|
+
border-radius: var(--radius-md);
|
|
1188
|
+
color: var(--color-text-primary);
|
|
1189
|
+
text-decoration: none;
|
|
1190
|
+
/* The fill eases under the pointer, as the rail's rows do. */
|
|
1191
|
+
transition: background var(--motion-duration-fast) var(--motion-easing-default);
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
a.crewlet-account-row__who:hover {
|
|
1195
|
+
background: var(--color-surface-hover);
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
/* After :hover, so the current row shows the lift rather than the overlay. */
|
|
1199
|
+
a.crewlet-account-row__who[aria-current='page'] {
|
|
1200
|
+
background: var(--color-surface-elevated);
|
|
1201
|
+
outline: 1px solid var(--color-border-default);
|
|
1202
|
+
outline-offset: -1px;
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
a.crewlet-account-row__who:focus-visible {
|
|
1206
|
+
outline: 2px solid var(--color-focus);
|
|
1207
|
+
outline-offset: var(--size-focus-ring-inset-offset);
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
.crewlet-account-row__avatar {
|
|
1211
|
+
display: inline-flex;
|
|
1212
|
+
flex: none;
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
.crewlet-account-row__text {
|
|
1216
|
+
display: flex;
|
|
1217
|
+
flex-direction: column;
|
|
1218
|
+
min-width: 0;
|
|
1219
|
+
line-height: var(--font-line-height-snug);
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
.crewlet-account-row__name,
|
|
1223
|
+
.crewlet-account-row__detail {
|
|
1224
|
+
overflow: hidden;
|
|
1225
|
+
text-overflow: ellipsis;
|
|
1226
|
+
white-space: nowrap;
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
.crewlet-account-row__name {
|
|
1230
|
+
font-size: var(--font-size-xs);
|
|
1231
|
+
font-weight: var(--font-weight-medium);
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
.crewlet-account-row__detail {
|
|
1235
|
+
font-size: var(--font-size-2xs);
|
|
1236
|
+
color: var(--color-text-tertiary);
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
.crewlet-account-row__go {
|
|
1240
|
+
flex: none;
|
|
1241
|
+
margin-left: auto;
|
|
1242
|
+
color: var(--color-text-tertiary);
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1245
|
+
.crewlet-account-row__actions {
|
|
1246
|
+
display: flex;
|
|
1247
|
+
flex: none;
|
|
1248
|
+
align-items: center;
|
|
1249
|
+
gap: var(--spacing-1);
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1253
|
+
.crewlet-account-row__who {
|
|
1254
|
+
transition: none;
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1258
|
+
|
|
1259
|
+
/* AuthLayout-ODHBUPHQ.css */
|
|
1260
|
+
/*
|
|
1261
|
+
* The sign-in page: one narrow column near the top of the window.
|
|
1262
|
+
*
|
|
1263
|
+
* THE PAGE SCROLLS ITSELF, at the viewport's dynamic height, because it is
|
|
1264
|
+
* drawn outside any shell that would: on a phone with the keyboard up, a form
|
|
1265
|
+
* taller than what is left of the window has to scroll, not be cut off.
|
|
1266
|
+
*/
|
|
1267
|
+
.crewlet-auth-layout {
|
|
1268
|
+
display: flex;
|
|
1269
|
+
justify-content: center;
|
|
1270
|
+
height: 100dvh;
|
|
1271
|
+
overflow-y: auto;
|
|
1272
|
+
padding: var(--spacing-8) var(--spacing-4);
|
|
1273
|
+
background: var(--color-surface-background);
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
/* A sentence's measure wide, and held at the top: the form does not jump when
|
|
1277
|
+
an error line appears under a field. */
|
|
1278
|
+
.crewlet-auth-layout__column {
|
|
1279
|
+
display: flex;
|
|
1280
|
+
flex-direction: column;
|
|
1281
|
+
gap: var(--spacing-5);
|
|
1282
|
+
width: 100%;
|
|
1283
|
+
max-width: 52ch;
|
|
1284
|
+
margin-block-end: auto;
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1287
|
+
/* The lockup is centred over the card, and takes none of the rail's inset,
|
|
1288
|
+
which is what its own padding is for. */
|
|
1289
|
+
.crewlet-auth-layout__brand {
|
|
1290
|
+
align-self: center;
|
|
1291
|
+
padding: 0;
|
|
1292
|
+
}
|
|
1293
|
+
|
|
1294
|
+
/* The form's parts stand one field step apart, under the title and lede. */
|
|
1295
|
+
.crewlet-auth-layout__body {
|
|
1296
|
+
display: flex;
|
|
1297
|
+
flex-direction: column;
|
|
1298
|
+
gap: var(--spacing-4);
|
|
1299
|
+
margin-top: var(--spacing-4);
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1302
|
+
/* A submit does not stretch: every button here states one gesture, and a
|
|
1303
|
+
full-width bar reads as the page's edge rather than a control. */
|
|
1304
|
+
.crewlet-auth-layout__body > form {
|
|
1305
|
+
display: flex;
|
|
1306
|
+
flex-direction: column;
|
|
1307
|
+
gap: var(--spacing-4);
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
.crewlet-auth-layout__body > form > button,
|
|
1311
|
+
.crewlet-auth-layout__body > button {
|
|
1312
|
+
align-self: flex-start;
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
|
|
1316
|
+
/* Avatar-MBUPR5E5.css */
|
|
1167
1317
|
/*
|
|
1168
1318
|
* The identity badge.
|
|
1169
1319
|
*
|
|
@@ -1292,6 +1442,25 @@
|
|
|
1292
1442
|
object-fit: cover;
|
|
1293
1443
|
}
|
|
1294
1444
|
|
|
1445
|
+
/*
|
|
1446
|
+
* A GLYPH IN PLACE OF THE INITIALS, for a principal whose name's initials
|
|
1447
|
+
* mean nothing (an API token, a service account). It takes a little over half
|
|
1448
|
+
* the box, the share the initials' cap height and width take, so a key badge
|
|
1449
|
+
* beside a person's badge reads as the same size of mark.
|
|
1450
|
+
*/
|
|
1451
|
+
.crewlet-avatar__icon {
|
|
1452
|
+
display: inline-flex;
|
|
1453
|
+
align-items: center;
|
|
1454
|
+
justify-content: center;
|
|
1455
|
+
width: 55%;
|
|
1456
|
+
height: 55%;
|
|
1457
|
+
}
|
|
1458
|
+
|
|
1459
|
+
.crewlet-avatar__icon > * {
|
|
1460
|
+
width: 100%;
|
|
1461
|
+
height: 100%;
|
|
1462
|
+
}
|
|
1463
|
+
|
|
1295
1464
|
/* ── tones ─────────────────────────────────────────────────────────────── */
|
|
1296
1465
|
|
|
1297
1466
|
.crewlet-avatar--fallback {
|
|
@@ -2418,7 +2587,7 @@ a.crewlet-breadcrumb__crumb:focus-visible {
|
|
|
2418
2587
|
}
|
|
2419
2588
|
|
|
2420
2589
|
|
|
2421
|
-
/* Callout-
|
|
2590
|
+
/* Callout-SXXK4B5R.css */
|
|
2422
2591
|
/*
|
|
2423
2592
|
* The callout: a status that stays in the content flow.
|
|
2424
2593
|
*
|
|
@@ -2473,8 +2642,10 @@ a.crewlet-breadcrumb__crumb:focus-visible {
|
|
|
2473
2642
|
}
|
|
2474
2643
|
|
|
2475
2644
|
.crewlet-callout__title {
|
|
2645
|
+
/* A LINE OF ITS OWN above the message, so the heading and the first
|
|
2646
|
+
sentence are never read as one run-on sentence. */
|
|
2647
|
+
display: block;
|
|
2476
2648
|
font-weight: var(--font-weight-semibold);
|
|
2477
|
-
margin-right: var(--spacing-2);
|
|
2478
2649
|
}
|
|
2479
2650
|
|
|
2480
2651
|
.crewlet-callout__action {
|
|
@@ -4219,7 +4390,7 @@ a.crewlet-breadcrumb__crumb:focus-visible {
|
|
|
4219
4390
|
}
|
|
4220
4391
|
|
|
4221
4392
|
|
|
4222
|
-
/* Checkbox-
|
|
4393
|
+
/* Checkbox-KT7RS6QQ.css */
|
|
4223
4394
|
/*
|
|
4224
4395
|
* Checkbox: a box, its label and its consequence as one target.
|
|
4225
4396
|
*
|
|
@@ -4340,6 +4511,22 @@ a.crewlet-breadcrumb__crumb:focus-visible {
|
|
|
4340
4511
|
outline-offset: 0;
|
|
4341
4512
|
}
|
|
4342
4513
|
|
|
4514
|
+
/*
|
|
4515
|
+
* A group of boxes under one legend. The boxes keep a field's inner rhythm,
|
|
4516
|
+
* one step apart, so the group reads as one field and its boxes as its parts.
|
|
4517
|
+
*/
|
|
4518
|
+
.crewlet-checkbox-group__options {
|
|
4519
|
+
display: flex;
|
|
4520
|
+
flex-direction: column;
|
|
4521
|
+
gap: var(--spacing-1);
|
|
4522
|
+
}
|
|
4523
|
+
|
|
4524
|
+
.crewlet-checkbox-group__empty {
|
|
4525
|
+
margin: 0;
|
|
4526
|
+
font-size: var(--font-size-xs);
|
|
4527
|
+
color: var(--color-text-secondary);
|
|
4528
|
+
}
|
|
4529
|
+
|
|
4343
4530
|
|
|
4344
4531
|
/* ChoiceButtons-DJ5EOGUA.css */
|
|
4345
4532
|
/*
|
|
@@ -9953,7 +10140,7 @@ svg.crewlet-datetime__chevron {
|
|
|
9953
10140
|
}
|
|
9954
10141
|
|
|
9955
10142
|
|
|
9956
|
-
/* InlineCode-
|
|
10143
|
+
/* InlineCode-ASYHLN3E.css */
|
|
9957
10144
|
/*
|
|
9958
10145
|
* One identifier inside a sentence: a mono chip on the inset surface.
|
|
9959
10146
|
*
|
|
@@ -10011,6 +10198,15 @@ svg.crewlet-datetime__chevron {
|
|
|
10011
10198
|
color: inherit;
|
|
10012
10199
|
}
|
|
10013
10200
|
|
|
10201
|
+
/*
|
|
10202
|
+
* A short token read as one: it moves to the next line whole rather than
|
|
10203
|
+
* splitting, which `overflow-wrap: anywhere` would otherwise allow.
|
|
10204
|
+
*/
|
|
10205
|
+
.crewlet-inline-code--whole {
|
|
10206
|
+
overflow-wrap: normal;
|
|
10207
|
+
white-space: nowrap;
|
|
10208
|
+
}
|
|
10209
|
+
|
|
10014
10210
|
.crewlet-inline-code--truncate {
|
|
10015
10211
|
display: inline-block;
|
|
10016
10212
|
max-width: 100%;
|
|
@@ -10021,7 +10217,7 @@ svg.crewlet-datetime__chevron {
|
|
|
10021
10217
|
}
|
|
10022
10218
|
|
|
10023
10219
|
|
|
10024
|
-
/* Input-
|
|
10220
|
+
/* Input-3KVSNUO5.css */
|
|
10025
10221
|
/*
|
|
10026
10222
|
* The form row: Input, Textarea, Label, FormField, FormRow, FormSection and
|
|
10027
10223
|
* ReadOnlyField.
|
|
@@ -10459,6 +10655,17 @@ svg.crewlet-datetime__chevron {
|
|
|
10459
10655
|
color: var(--color-text-tertiary);
|
|
10460
10656
|
}
|
|
10461
10657
|
|
|
10658
|
+
/*
|
|
10659
|
+
* A LITERAL INSIDE A LABEL KEEPS ITS CASE. The label is set in capitals, and
|
|
10660
|
+
* a value a reader has to type back exactly ("Type jane.founder to confirm")
|
|
10661
|
+
* read as JANE.FOUNDER, which is not what the field accepts.
|
|
10662
|
+
*/
|
|
10663
|
+
.crewlet-label code,
|
|
10664
|
+
.crewlet-label__text code {
|
|
10665
|
+
text-transform: none;
|
|
10666
|
+
letter-spacing: normal;
|
|
10667
|
+
}
|
|
10668
|
+
|
|
10462
10669
|
.crewlet-label--with-action {
|
|
10463
10670
|
display: flex;
|
|
10464
10671
|
justify-content: space-between;
|
|
@@ -12755,6 +12962,183 @@ svg.crewlet-datetime__chevron {
|
|
|
12755
12962
|
}
|
|
12756
12963
|
|
|
12757
12964
|
|
|
12965
|
+
/* ObjectHeader-UNVYM2KD.css */
|
|
12966
|
+
/*
|
|
12967
|
+
* The header of an object: its eyebrow, its head row and its fact line.
|
|
12968
|
+
*/
|
|
12969
|
+
.crewlet-object-header {
|
|
12970
|
+
display: flex;
|
|
12971
|
+
flex-direction: column;
|
|
12972
|
+
gap: var(--spacing-1);
|
|
12973
|
+
min-width: 0;
|
|
12974
|
+
padding: var(--spacing-4) 0 var(--spacing-3);
|
|
12975
|
+
}
|
|
12976
|
+
|
|
12977
|
+
.crewlet-object-header--peek {
|
|
12978
|
+
padding: var(--spacing-3) 0 var(--spacing-2);
|
|
12979
|
+
}
|
|
12980
|
+
|
|
12981
|
+
.crewlet-object-header__eyebrow {
|
|
12982
|
+
display: flex;
|
|
12983
|
+
align-items: center;
|
|
12984
|
+
gap: var(--spacing-2);
|
|
12985
|
+
min-width: 0;
|
|
12986
|
+
font-size: var(--font-size-2xs);
|
|
12987
|
+
letter-spacing: var(--font-letter-spacing-wide);
|
|
12988
|
+
text-transform: uppercase;
|
|
12989
|
+
color: var(--color-text-tertiary);
|
|
12990
|
+
}
|
|
12991
|
+
|
|
12992
|
+
.crewlet-object-header__icon {
|
|
12993
|
+
display: inline-flex;
|
|
12994
|
+
flex: none;
|
|
12995
|
+
}
|
|
12996
|
+
|
|
12997
|
+
/* A key or a name keeps its own case: in capitals a name is a shout. */
|
|
12998
|
+
.crewlet-object-header__id {
|
|
12999
|
+
min-width: 0;
|
|
13000
|
+
overflow: hidden;
|
|
13001
|
+
text-overflow: ellipsis;
|
|
13002
|
+
white-space: nowrap;
|
|
13003
|
+
letter-spacing: normal;
|
|
13004
|
+
text-transform: none;
|
|
13005
|
+
}
|
|
13006
|
+
|
|
13007
|
+
.crewlet-object-header__id--mono {
|
|
13008
|
+
font-family: var(--font-family-mono);
|
|
13009
|
+
}
|
|
13010
|
+
|
|
13011
|
+
/* The head row wraps: the marks and the actions take a line under the title
|
|
13012
|
+
rather than every pill on the row giving up a few characters. */
|
|
13013
|
+
.crewlet-object-header__head {
|
|
13014
|
+
display: flex;
|
|
13015
|
+
flex-wrap: wrap;
|
|
13016
|
+
align-items: center;
|
|
13017
|
+
gap: var(--spacing-2);
|
|
13018
|
+
min-width: 0;
|
|
13019
|
+
}
|
|
13020
|
+
|
|
13021
|
+
/* TWO LINES, AND THAT IS THE CEILING, which catches a title written as a
|
|
13022
|
+
paragraph and holds every real one. */
|
|
13023
|
+
.crewlet-object-header__title {
|
|
13024
|
+
display: -webkit-box;
|
|
13025
|
+
-webkit-box-orient: vertical;
|
|
13026
|
+
-webkit-line-clamp: 2;
|
|
13027
|
+
line-clamp: 2;
|
|
13028
|
+
overflow: hidden;
|
|
13029
|
+
flex: 0 1 auto;
|
|
13030
|
+
min-width: 0;
|
|
13031
|
+
margin: 0;
|
|
13032
|
+
font-size: var(--font-size-xl);
|
|
13033
|
+
font-weight: var(--font-weight-semibold);
|
|
13034
|
+
line-height: var(--font-line-height-snug);
|
|
13035
|
+
color: var(--color-text-primary);
|
|
13036
|
+
}
|
|
13037
|
+
|
|
13038
|
+
.crewlet-object-header--peek .crewlet-object-header__title {
|
|
13039
|
+
font-size: var(--font-size-lg);
|
|
13040
|
+
}
|
|
13041
|
+
|
|
13042
|
+
/* The state keeps its width: a pill squeezed to "13 pro…" says something
|
|
13043
|
+
else. The marks travel together when the row wraps. */
|
|
13044
|
+
.crewlet-object-header__status,
|
|
13045
|
+
.crewlet-object-header__actions {
|
|
13046
|
+
display: flex;
|
|
13047
|
+
flex: 0 0 auto;
|
|
13048
|
+
flex-wrap: wrap;
|
|
13049
|
+
align-items: center;
|
|
13050
|
+
gap: var(--spacing-1);
|
|
13051
|
+
}
|
|
13052
|
+
|
|
13053
|
+
.crewlet-object-header__actions {
|
|
13054
|
+
margin-left: auto;
|
|
13055
|
+
}
|
|
13056
|
+
|
|
13057
|
+
/* ── the fact line ─────────────────────────────────────────────────────── */
|
|
13058
|
+
|
|
13059
|
+
/* THE TRACK FLOOR IS 7.5rem, which fits seven facts on one line at 1280px and
|
|
13060
|
+
still holds every label and a two-line value. */
|
|
13061
|
+
.crewlet-fact-line {
|
|
13062
|
+
display: grid;
|
|
13063
|
+
grid-template-columns: repeat(auto-fill, minmax(min(7.5rem, 100%), 1fr));
|
|
13064
|
+
column-gap: var(--spacing-4);
|
|
13065
|
+
row-gap: var(--spacing-3);
|
|
13066
|
+
padding-top: var(--spacing-1);
|
|
13067
|
+
}
|
|
13068
|
+
|
|
13069
|
+
/* Two bands: the label, then the value with its footnotes in one cell. */
|
|
13070
|
+
.crewlet-fact-line__fact {
|
|
13071
|
+
display: grid;
|
|
13072
|
+
grid-template-rows: subgrid;
|
|
13073
|
+
grid-row: span 2;
|
|
13074
|
+
row-gap: 0;
|
|
13075
|
+
min-width: 0;
|
|
13076
|
+
}
|
|
13077
|
+
|
|
13078
|
+
/* A token and a set of chips take two tracks. */
|
|
13079
|
+
.crewlet-fact-line__fact--token,
|
|
13080
|
+
.crewlet-fact-line__fact--set {
|
|
13081
|
+
grid-column: span 2;
|
|
13082
|
+
}
|
|
13083
|
+
|
|
13084
|
+
.crewlet-fact-line__body {
|
|
13085
|
+
display: flex;
|
|
13086
|
+
flex-direction: column;
|
|
13087
|
+
min-width: 0;
|
|
13088
|
+
}
|
|
13089
|
+
|
|
13090
|
+
.crewlet-fact-line__label {
|
|
13091
|
+
font-size: var(--font-size-2xs);
|
|
13092
|
+
letter-spacing: var(--font-letter-spacing-wide);
|
|
13093
|
+
text-transform: uppercase;
|
|
13094
|
+
color: var(--color-text-tertiary);
|
|
13095
|
+
}
|
|
13096
|
+
|
|
13097
|
+
.crewlet-fact-line__value {
|
|
13098
|
+
min-width: 0;
|
|
13099
|
+
font-size: var(--font-size-compact);
|
|
13100
|
+
color: var(--color-text-primary);
|
|
13101
|
+
overflow-wrap: anywhere;
|
|
13102
|
+
}
|
|
13103
|
+
|
|
13104
|
+
.crewlet-fact-line__value--clamp {
|
|
13105
|
+
display: -webkit-box;
|
|
13106
|
+
-webkit-box-orient: vertical;
|
|
13107
|
+
-webkit-line-clamp: 2;
|
|
13108
|
+
line-clamp: 2;
|
|
13109
|
+
overflow: hidden;
|
|
13110
|
+
}
|
|
13111
|
+
|
|
13112
|
+
/* One token, one line, cut with an ellipsis where two tracks are too narrow;
|
|
13113
|
+
its title carries the whole of it. */
|
|
13114
|
+
.crewlet-fact-line__value--token {
|
|
13115
|
+
display: block;
|
|
13116
|
+
overflow: hidden;
|
|
13117
|
+
text-overflow: ellipsis;
|
|
13118
|
+
white-space: nowrap;
|
|
13119
|
+
overflow-wrap: normal;
|
|
13120
|
+
}
|
|
13121
|
+
|
|
13122
|
+
/* A footnote may not set its column's width: the track does, and the note
|
|
13123
|
+
wraps inside it, balanced so the wrap reads as deliberate. */
|
|
13124
|
+
.crewlet-fact-line__note,
|
|
13125
|
+
.crewlet-fact-line__set-by {
|
|
13126
|
+
font-size: var(--font-size-2xs);
|
|
13127
|
+
color: var(--color-text-tertiary);
|
|
13128
|
+
text-wrap: balance;
|
|
13129
|
+
}
|
|
13130
|
+
|
|
13131
|
+
/* ── the by-line ───────────────────────────────────────────────────────── */
|
|
13132
|
+
|
|
13133
|
+
/* The word and its arrow are one atomic box, so the arrow never takes a line
|
|
13134
|
+
of its own. */
|
|
13135
|
+
.crewlet-set-by__turn {
|
|
13136
|
+
display: inline-flex;
|
|
13137
|
+
align-items: center;
|
|
13138
|
+
gap: 0.25em;
|
|
13139
|
+
}
|
|
13140
|
+
|
|
13141
|
+
|
|
12758
13142
|
/* OrgLabel-R5KY7C3W.css */
|
|
12759
13143
|
/*
|
|
12760
13144
|
* What a node of an org chart and a row of an org table both say
|
|
@@ -14482,6 +14866,28 @@ svg.crewlet-datetime__chevron {
|
|
|
14482
14866
|
}
|
|
14483
14867
|
|
|
14484
14868
|
|
|
14869
|
+
/* QrCode-JWJTWMU5.css */
|
|
14870
|
+
/*
|
|
14871
|
+
* A QR code on its own plate.
|
|
14872
|
+
*
|
|
14873
|
+
* A FIXED BOX, because a camera needs modules of a readable size: at 208px a
|
|
14874
|
+
* second factor's code (a version 7 symbol and its quiet zone) draws each
|
|
14875
|
+
* module at about 4.3px. A consumer that needs another size sets the variable.
|
|
14876
|
+
*
|
|
14877
|
+
* ITS INKS ARE KEPT UNDER FORCED COLOURS. A high-contrast mode repaints fills
|
|
14878
|
+
* to system colours, and a plate repainted dark is a code no scanner reads.
|
|
14879
|
+
*/
|
|
14880
|
+
.crewlet-qr-code {
|
|
14881
|
+
--crewlet-qr-code-size: 208px;
|
|
14882
|
+
display: block;
|
|
14883
|
+
flex: none;
|
|
14884
|
+
width: var(--crewlet-qr-code-size);
|
|
14885
|
+
height: var(--crewlet-qr-code-size);
|
|
14886
|
+
border-radius: var(--radius-sm);
|
|
14887
|
+
forced-color-adjust: none;
|
|
14888
|
+
}
|
|
14889
|
+
|
|
14890
|
+
|
|
14485
14891
|
/* ReadingPane-5UOLPWY5.css */
|
|
14486
14892
|
/*
|
|
14487
14893
|
* One item read in full, in one column.
|
|
@@ -18969,7 +19375,7 @@ b.crewlet-switcher__match {
|
|
|
18969
19375
|
}
|
|
18970
19376
|
|
|
18971
19377
|
|
|
18972
|
-
/* Text-
|
|
19378
|
+
/* Text-S3Q4O3IG.css */
|
|
18973
19379
|
/*
|
|
18974
19380
|
* The type registers, one rule each.
|
|
18975
19381
|
*
|
|
@@ -19021,6 +19427,17 @@ b.crewlet-switcher__match {
|
|
|
19021
19427
|
color: var(--color-text-primary);
|
|
19022
19428
|
}
|
|
19023
19429
|
|
|
19430
|
+
/*
|
|
19431
|
+
* The register around it: nothing is set, so the run keeps its sentence's
|
|
19432
|
+
* size, weight, tracking and ink, and only a modifier (mono, numeric) or a
|
|
19433
|
+
* tone changes it.
|
|
19434
|
+
*/
|
|
19435
|
+
.crewlet-text--inherit {
|
|
19436
|
+
font-size: inherit;
|
|
19437
|
+
line-height: inherit;
|
|
19438
|
+
color: inherit;
|
|
19439
|
+
}
|
|
19440
|
+
|
|
19024
19441
|
.crewlet-text--body {
|
|
19025
19442
|
font-size: var(--font-size-sm);
|
|
19026
19443
|
line-height: var(--font-line-height-normal);
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
export { cx } from './cx.js';
|
|
2
2
|
export { useClipboard, writeClipboard } from './useClipboard.js';
|
|
3
3
|
export type { Clipboard, ClipboardOptions, ClipboardState } from './useClipboard.js';
|
|
4
|
+
export { useOutcome } from './useOutcome.js';
|
|
5
|
+
export type { Outcome, OutcomeOptions, OutcomeState } from './useOutcome.js';
|
|
6
|
+
export { downloadText, safeFilename, useDownload } from './useDownload.js';
|
|
7
|
+
export type { Download, DownloadState } from './useDownload.js';
|
|
4
8
|
export type { Tone } from './tone.js';
|
|
5
9
|
export { NODE_HUES, NODE_HUE_NAMES, isNodeHue } from './nodeHue.js';
|
|
6
10
|
export type { NodeHue } from './nodeHue.js';
|
package/dist/utils/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import '../chunk-
|
|
2
|
-
export {
|
|
1
|
+
import '../chunk-U5LQ2AS5.js';
|
|
2
|
+
export { downloadText, safeFilename, useDownload } from '../chunk-F6NZOVWL.js';
|
|
3
|
+
export { useClipboard, writeClipboard } from '../chunk-STJ7QBC3.js';
|
|
4
|
+
export { useOutcome } from '../chunk-DTIW4CHZ.js';
|
|
3
5
|
export { HeadingLevelProvider, headingTag, nextHeadingLevel, useHeadingLevel } from '../chunk-PQADV6P6.js';
|
|
4
6
|
export { NODE_HUES, NODE_HUE_NAMES, isNodeHue } from '../chunk-AYKXMIOR.js';
|
|
5
7
|
export { cx } from '../chunk-ODEQTPFM.js';
|
|
@@ -33,6 +33,8 @@ export interface ClipboardOptions {
|
|
|
33
33
|
}
|
|
34
34
|
export interface Clipboard {
|
|
35
35
|
state: ClipboardState;
|
|
36
|
+
/** How many copies have settled. See [Outcome.attempt]. */
|
|
37
|
+
attempt: number;
|
|
36
38
|
copy: (text: string | (() => string)) => Promise<boolean>;
|
|
37
39
|
}
|
|
38
40
|
/**
|
|
@@ -56,9 +58,10 @@ export interface Clipboard {
|
|
|
56
58
|
* timer exists AT THAT MOMENT, and for a write still in flight that is
|
|
57
59
|
* none: the settle then ran after the cleanup and armed a fresh timer with
|
|
58
60
|
* nothing left alive to clear it, so the hook leaked a timer per abandoned
|
|
59
|
-
* copy and wrote state to a component that was gone.
|
|
60
|
-
*
|
|
61
|
-
*
|
|
61
|
+
* copy and wrote state to a component that was gone. [useOutcome], the
|
|
62
|
+
* machine this and `useDownload` share, checks whether the component is
|
|
63
|
+
* still mounted AFTER the await rather than before, because the await is
|
|
64
|
+
* the whole of the gap.
|
|
62
65
|
*
|
|
63
66
|
* The text may be a THUNK, resolved on the press. On a live screen the thing
|
|
64
67
|
* worth copying is assembled from everything on it, so a string prop means
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { type OutcomeOptions } from './useOutcome.js';
|
|
2
|
+
/** Where a download stands: not tried, handed to the browser, or refused. */
|
|
3
|
+
export type DownloadState = 'idle' | 'started' | 'failed';
|
|
4
|
+
export interface Download {
|
|
5
|
+
state: DownloadState;
|
|
6
|
+
/** How many downloads have settled. See [Outcome.attempt]. */
|
|
7
|
+
attempt: number;
|
|
8
|
+
/**
|
|
9
|
+
* Offers `text` as a file, and answers whether the browser took it. The
|
|
10
|
+
* text may be a thunk, resolved on the press.
|
|
11
|
+
*/
|
|
12
|
+
download: (text: string | (() => string), filename: string, mime?: string) => Promise<boolean>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Handing text to the reader as a file, and saying whether it landed: the
|
|
16
|
+
* mirror of `useClipboard`, on the same state machine.
|
|
17
|
+
*
|
|
18
|
+
* "STARTED", NOT "SAVED". There is no completion event on an `<a download>`:
|
|
19
|
+
* the browser took the click, and a gate such as Chrome's automatic multiple
|
|
20
|
+
* download prompt can still stop it silently after that. What the control can
|
|
21
|
+
* honestly say is that the download was handed over, and under which name.
|
|
22
|
+
*/
|
|
23
|
+
export declare function useDownload(options?: OutcomeOptions): Download;
|
|
24
|
+
/**
|
|
25
|
+
* Saves `text` on the reader's machine and reports whether the browser took
|
|
26
|
+
* it, with the name it was offered under ([safeFilename] of `filename`).
|
|
27
|
+
*
|
|
28
|
+
* For a control that cannot say so on itself, such as a menu item that
|
|
29
|
+
* closes on the press: the caller raises a toast from the answer.
|
|
30
|
+
*
|
|
31
|
+
* TWO THINGS ARE CHECKED UP FRONT rather than assumed. Without
|
|
32
|
+
* `URL.createObjectURL` there is nothing to point a saveable link at, and a
|
|
33
|
+
* `data:` URL is the wrong fallback because several engines cap it near two
|
|
34
|
+
* megabytes, so it would fail silently on exactly the large files. Without the
|
|
35
|
+
* `download` attribute the click NAVIGATES to the text instead of saving it,
|
|
36
|
+
* which looks enough like something happening that nobody checks.
|
|
37
|
+
*
|
|
38
|
+
* The blob URL is revoked on the NEXT macrotask: the click only queues the
|
|
39
|
+
* download, and freeing the entry inside the same task races the fetch that is
|
|
40
|
+
* about to read it. Never revoking is the other failure, a second copy of the
|
|
41
|
+
* text held for the life of the tab.
|
|
42
|
+
*/
|
|
43
|
+
export declare function downloadText(text: string, filename: string, mime?: string): {
|
|
44
|
+
started: boolean;
|
|
45
|
+
name: string;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* A filename the reader will actually get, out of whatever the caller had.
|
|
49
|
+
*
|
|
50
|
+
* The `download` attribute is only a suggestion and each browser sanitises it
|
|
51
|
+
* its own way, so the name is decided here and every caller gets one
|
|
52
|
+
* predictable answer. A name composed from data (an id off the URL) that
|
|
53
|
+
* arrived as `../etc/passwd` or with a newline in it never reaches that guess.
|
|
54
|
+
*
|
|
55
|
+
* UNICODE-AWARE: letters, marks and numbers in every script are kept, and
|
|
56
|
+
* separators and invisibles (a slash, a colon, the fullwidth solidus, a
|
|
57
|
+
* right-to-left override) become a hyphen. An ASCII-only class turned
|
|
58
|
+
* `日本語.json` into a file called `json`. The EXTENSION is never what gets cut
|
|
59
|
+
* or stripped, because a name that loses it opens in the wrong application;
|
|
60
|
+
* leading dots, which make `..` a traversal and `.name` a hidden file, are
|
|
61
|
+
* stripped from the stem.
|
|
62
|
+
*/
|
|
63
|
+
export declare function safeFilename(name: string): string;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/** Where a hand-off stands: not tried, landed, or refused. */
|
|
2
|
+
export type OutcomeState = 'idle' | 'done' | 'failed';
|
|
3
|
+
export interface OutcomeOptions {
|
|
4
|
+
/** How long a success stands before the control settles back. */
|
|
5
|
+
resetMs?: number | undefined;
|
|
6
|
+
/**
|
|
7
|
+
* How long a REFUSAL stands. Unset it is `resetMs`; `null` holds it until
|
|
8
|
+
* the next attempt; a number gives it a clock of its own. See
|
|
9
|
+
* [ClipboardOptions.failedResetMs] for why a refusal wants its own.
|
|
10
|
+
*/
|
|
11
|
+
failedResetMs?: number | null | undefined;
|
|
12
|
+
}
|
|
13
|
+
export interface Outcome {
|
|
14
|
+
state: OutcomeState;
|
|
15
|
+
/**
|
|
16
|
+
* How many attempts have settled. A status region keyed on it is REPLACED
|
|
17
|
+
* on every attempt, so an identical outcome twice running is still a change
|
|
18
|
+
* a screen reader announces: a second refusal used to be silence.
|
|
19
|
+
*/
|
|
20
|
+
attempt: number;
|
|
21
|
+
/**
|
|
22
|
+
* Runs `task` and settles on its answer. The task returns whether it landed
|
|
23
|
+
* and must not throw: a refusal is `false`. The answer is returned to the
|
|
24
|
+
* caller even when the component is gone by the time it arrives.
|
|
25
|
+
*/
|
|
26
|
+
run: (task: () => boolean | Promise<boolean>) => Promise<boolean>;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* The state machine every hand-off control shares: do a thing that either
|
|
30
|
+
* lands or does not, say which, and settle back so the label is never a stale
|
|
31
|
+
* claim.
|
|
32
|
+
*
|
|
33
|
+
* ONE MACHINE, because the controls built on it sit side by side (a Copy and
|
|
34
|
+
* a Download over the same text), and any difference between them in how
|
|
35
|
+
* long a confirmation holds, or whether a repeat is announced, is a visible
|
|
36
|
+
* inconsistency rather than a private detail.
|
|
37
|
+
*
|
|
38
|
+
* THE TASK CAN OUTLIVE THE SCREEN. A clipboard write waits on a permission
|
|
39
|
+
* prompt the reader may never answer, so whether the component is still
|
|
40
|
+
* mounted is checked AFTER the await, and nothing is armed for one that is
|
|
41
|
+
* gone. The flag is set in the effect body as well as cleared in its cleanup,
|
|
42
|
+
* because StrictMode mounts, unmounts and mounts again.
|
|
43
|
+
*/
|
|
44
|
+
export declare function useOutcome({ resetMs, failedResetMs }?: OutcomeOptions): Outcome;
|