@crewlethq/ui 0.83.0 → 0.84.1
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 +38 -0
- package/dist/ActionCard/ActionCard.d.ts +7 -7
- package/dist/ActionCard/index.js +1 -1
- package/dist/ActionCard-YZKL3CKR.css +130 -0
- package/dist/AppShell/AppShell.d.ts +14 -11
- package/dist/AppShell/index.js +1 -1
- package/dist/{AppShell-U7D2MUUF.css → AppShell-NX5HCD4O.css} +84 -44
- package/dist/ArtifactBar/index.js +1 -1
- package/dist/ArtifactCard/index.js +3 -3
- package/dist/ArtifactKindIllustration/index.js +1 -1
- package/dist/{ArtifactKinds-3EH4KR3F.css → ArtifactKinds-27TE3KJL.css} +7 -7
- package/dist/ArtifactMakeRow/index.js +1 -1
- package/dist/ArtifactNameCell/index.js +1 -1
- package/dist/Avatar/index.js +1 -1
- package/dist/{Avatar-MNE3WBZO.css → Avatar-CRSLRUVT.css} +11 -10
- package/dist/BriefCard/index.js +2 -1
- package/dist/CatalogTile/CatalogTile.d.ts +23 -5
- package/dist/CatalogTile/index.d.ts +1 -1
- package/dist/CatalogTile/index.js +2 -1
- package/dist/{CatalogTile-6VF36JWA.css → CatalogTile-TMOSGSV3.css} +4 -3
- package/dist/CommentThread/index.js +1 -1
- package/dist/CompactNav/CompactNav.d.ts +10 -6
- package/dist/CompactNav/index.js +1 -1
- package/dist/DeepWorkCard/index.js +2 -2
- package/dist/DirectoryList/index.js +1 -1
- package/dist/{DirectoryList-XZOWYOA3.css → DirectoryList-IXQIMNFS.css} +8 -1
- package/dist/EntityChip/index.js +1 -1
- package/dist/ImageUpload/index.js +1 -1
- package/dist/InboxList/InboxList.d.ts +28 -2
- package/dist/InboxList/index.d.ts +1 -1
- package/dist/InboxList/index.js +6 -1
- package/dist/{InboxList-OFGSX5IH.css → InboxList-X5Q5WWAI.css} +63 -2
- package/dist/ListDetail/ListDetail.d.ts +6 -0
- package/dist/ListDetail/index.js +1 -1
- package/dist/{ListDetail-N3L7PB46.css → ListDetail-JGESKTR7.css} +38 -0
- package/dist/OrgLabel/index.js +1 -1
- package/dist/OrgNode/index.js +1 -1
- package/dist/OrgTable/index.js +1 -1
- package/dist/PeopleRail/index.js +1 -1
- package/dist/PresenceStack/index.js +1 -1
- package/dist/Principal/index.js +1 -1
- package/dist/PrincipalPicker/index.js +1 -1
- package/dist/ReadingPane/ReadingPane.d.ts +17 -1
- package/dist/ReadingPane/index.d.ts +1 -1
- package/dist/ReadingPane/index.js +2 -1
- package/dist/{ReadingPane-VLYOWMCM.css → ReadingPane-VFTRDPC5.css} +19 -0
- package/dist/SectionFrame/index.js +2 -2
- package/dist/ShareDialog/index.js +1 -1
- package/dist/SheetGrid/index.js +1 -1
- package/dist/SidebarNav/SidebarNav.d.ts +18 -2
- package/dist/SidebarNav/index.d.ts +1 -1
- package/dist/SidebarNav/index.js +1 -1
- package/dist/{SidebarNav-E7PZGGA6.css → SidebarNav-IKBKGXW4.css} +20 -0
- package/dist/TableCells/index.js +1 -1
- package/dist/ThreadSummary/index.js +2 -2
- package/dist/VersionTimeline/index.js +1 -1
- package/dist/{chunk-Q7N2ATMC.js → chunk-64JNKLLP.js} +57 -9
- package/dist/chunk-6C7GQOBV.js +10 -0
- package/dist/{chunk-YRNNUCQP.js → chunk-7BDBO2NP.js} +1 -1
- package/dist/{chunk-QM3432PH.js → chunk-7IWZN5Q2.js} +3 -3
- package/dist/{chunk-25JQNHTC.js → chunk-BRK3HXGZ.js} +8 -2
- package/dist/{chunk-QE4OIE3Q.js → chunk-DJIWCW5Z.js} +6 -4
- package/dist/{chunk-QPHD4UUG.js → chunk-F6ZUM66S.js} +160 -25
- package/dist/{chunk-MVMVMHYI.js → chunk-HDEKHP65.js} +1 -1
- package/dist/{chunk-BXGBGYKH.js → chunk-HKUZ2GYX.js} +1 -1
- package/dist/{chunk-ZB3E2Z4Y.js → chunk-J5T5TDM2.js} +1 -1
- package/dist/{chunk-C46DDVTK.js → chunk-LTD7KLOU.js} +1 -1
- package/dist/{chunk-YBC2CYPD.js → chunk-O4VTQMEF.js} +1 -1
- package/dist/{chunk-HTBTAIH6.js → chunk-OM2LABPS.js} +2 -2
- package/dist/{chunk-PGBKZSSQ.js → chunk-ORONAXSF.js} +10 -7
- package/dist/{chunk-YP2FS6SH.js → chunk-QPYGJ7R7.js} +1 -1
- package/dist/{chunk-ICE3D63E.js → chunk-QWRAWKB2.js} +50 -9
- package/dist/{chunk-SRDNGGZE.js → chunk-RKIJAXQA.js} +1 -1
- package/dist/{chunk-CF4M6N6A.js → chunk-XYSSFI5C.js} +1 -7
- package/dist/{chunk-IRONPJB4.js → chunk-YTLWOHOY.js} +1 -1
- package/dist/generated/index.js +33 -32
- package/dist/index.js +33 -32
- package/dist/styles.css +306 -99
- package/dist/utils/developing.d.ts +10 -0
- package/package.json +3 -3
- package/dist/ActionCard-47WSZ2O5.css +0 -110
- package/dist/{chunk-CV2LU2T2.js → chunk-IYI6HWKN.js} +1 -1
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
* own prop types, so one list of places feeds both shapes.
|
|
37
37
|
*/
|
|
38
38
|
import { type MouseEventHandler, type ReactNode } from 'react';
|
|
39
|
+
import type { CountTone } from '../Count/index.js';
|
|
39
40
|
export interface SidebarNavProps {
|
|
40
41
|
/**
|
|
41
42
|
* Names the navigation region. A page with two of them ("Sections" and
|
|
@@ -148,6 +149,20 @@ export interface NavFigure {
|
|
|
148
149
|
*/
|
|
149
150
|
label: string;
|
|
150
151
|
}
|
|
152
|
+
/**
|
|
153
|
+
* A figure of what waits on the reader, and how loudly it asks.
|
|
154
|
+
*
|
|
155
|
+
* `attention` (the default) is the accent's filled pill, the one hue in the
|
|
156
|
+
* chrome: what the reader is asked to act on, the unread in an inbox.
|
|
157
|
+
* `quiet` keeps the pill's round shape and its place at the row's end, in
|
|
158
|
+
* the quiet count's grey: work that is the reader's own and is waiting, but
|
|
159
|
+
* not calling (the open tasks assigned to them). The vocabulary is `Count`'s
|
|
160
|
+
* own (`CountTone`), so a figure is quiet or calling in the same words
|
|
161
|
+
* wherever it stands.
|
|
162
|
+
*/
|
|
163
|
+
export interface NavBadge extends NavFigure {
|
|
164
|
+
tone?: CountTone | undefined;
|
|
165
|
+
}
|
|
151
166
|
/** A quiet figure: how many of something the destination holds. */
|
|
152
167
|
export interface NavCount extends NavFigure {
|
|
153
168
|
/**
|
|
@@ -180,9 +195,10 @@ export interface NavItemProps {
|
|
|
180
195
|
* of what is waiting on the reader is the one thing in the rail that asks
|
|
181
196
|
* them to act, which is what the accent means; it is a FILL carrying a
|
|
182
197
|
* figure rather than a figure in a hue, so it still reads to somebody who
|
|
183
|
-
* cannot separate the hue. Anything else is a `count`.
|
|
198
|
+
* cannot separate the hue. Anything else is a `count`. `tone: 'quiet'`
|
|
199
|
+
* keeps the pill and draws it in the quiet count's grey (`NavBadge`).
|
|
184
200
|
*/
|
|
185
|
-
badge?:
|
|
201
|
+
badge?: NavBadge | undefined;
|
|
186
202
|
href?: string | undefined;
|
|
187
203
|
/** Whether this row is the screen the reader is on. */
|
|
188
204
|
current?: boolean | undefined;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import '../HitArea/HitArea.css';
|
|
2
2
|
import './SidebarNav.css';
|
|
3
3
|
export { NavGroup, NavItem, SidebarNav } from './SidebarNav.js';
|
|
4
|
-
export type { NavCount, NavFigure, NavGroupAction, NavGroupProps, NavItemProps, NavLinkProps, SidebarNavProps, } from './SidebarNav.js';
|
|
4
|
+
export type { NavBadge, NavCount, NavFigure, NavGroupAction, NavGroupProps, NavItemProps, NavLinkProps, SidebarNavProps, } from './SidebarNav.js';
|
package/dist/SidebarNav/index.js
CHANGED
|
@@ -415,6 +415,26 @@
|
|
|
415
415
|
line-height: 1;
|
|
416
416
|
}
|
|
417
417
|
|
|
418
|
+
/*
|
|
419
|
+
* A QUIET BADGE keeps the pill, its size and its place at the row's end, and
|
|
420
|
+
* takes the quiet count's grey: a neutral wash (`--color-fill-soft`, the
|
|
421
|
+
* ground of a quiet label at rest) carrying the secondary ink, for work that
|
|
422
|
+
* is the reader's own and waiting, but not calling. The secondary ink rather
|
|
423
|
+
* than the count's tertiary, because on a wash over a hovered row the
|
|
424
|
+
* tertiary measured 4.41:1 in light; it is the ink the compact rail's quiet
|
|
425
|
+
* figure takes, so the two shapes draw the same grey. On the reader's own row
|
|
426
|
+
* its ink lifts to the row's, as the count's does; the suite measures the
|
|
427
|
+
* pair on every ground a row can have.
|
|
428
|
+
*/
|
|
429
|
+
.crewlet-nav-item__badge--quiet {
|
|
430
|
+
background: var(--color-fill-soft);
|
|
431
|
+
color: var(--color-text-secondary);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
.crewlet-nav-item__row[aria-current='page'] .crewlet-nav-item__badge--quiet {
|
|
435
|
+
color: inherit;
|
|
436
|
+
}
|
|
437
|
+
|
|
418
438
|
/* Beside a count the badge is the second figure, not a second push to the
|
|
419
439
|
end: two auto margins would split the room between them and float the
|
|
420
440
|
count into the middle of the row. */
|
package/dist/TableCells/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import '../chunk-QF5UNP4T.js';
|
|
|
3
3
|
import '../chunk-LBGKLYBY.js';
|
|
4
4
|
import '../chunk-EJNJMHQG.js';
|
|
5
5
|
import '../chunk-RE3FBGQQ.js';
|
|
6
|
-
import '../chunk-
|
|
6
|
+
import '../chunk-YTLWOHOY.js';
|
|
7
7
|
import '../chunk-XZY6S3UC.js';
|
|
8
8
|
import '../chunk-CYQBDZ6M.js';
|
|
9
9
|
import '../chunk-UT6CW3C7.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { THREAD_SUMMARY_LABELS, ThreadSummary } from '../chunk-
|
|
1
|
+
export { THREAD_SUMMARY_LABELS, ThreadSummary } from '../chunk-QPYGJ7R7.js';
|
|
2
2
|
import '../chunk-LBGKLYBY.js';
|
|
3
|
-
import '../chunk-
|
|
3
|
+
import '../chunk-YTLWOHOY.js';
|
|
4
4
|
import '../chunk-XZY6S3UC.js';
|
|
5
5
|
import '../chunk-CYQBDZ6M.js';
|
|
6
6
|
import '../chunk-ODEQTPFM.js';
|
|
@@ -2,7 +2,7 @@ export { VersionTimeline } from '../chunk-L5VU3LZT.js';
|
|
|
2
2
|
import '../chunk-HF5L56YQ.js';
|
|
3
3
|
import '../chunk-EJNJMHQG.js';
|
|
4
4
|
import '../chunk-RE3FBGQQ.js';
|
|
5
|
-
import '../chunk-
|
|
5
|
+
import '../chunk-YTLWOHOY.js';
|
|
6
6
|
import '../chunk-XZY6S3UC.js';
|
|
7
7
|
import '../chunk-4MJN2KN6.js';
|
|
8
8
|
import '../chunk-DGXZ635L.js';
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { Eyebrow } from './chunk-RK4XPHVG.js';
|
|
2
|
+
import { returnFocus } from './chunk-4ITETIGZ.js';
|
|
2
3
|
import { useHeadingLevel, HeadingLevelProvider, nextHeadingLevel, headingTag } from './chunk-PQADV6P6.js';
|
|
3
4
|
import { cx } from './chunk-ODEQTPFM.js';
|
|
4
|
-
import './ReadingPane-
|
|
5
|
-
import { createContext, useId, useContext } from 'react';
|
|
5
|
+
import './ReadingPane-VFTRDPC5.css';
|
|
6
|
+
import { createContext, useId, useRef, useState, useEffect, useLayoutEffect, createElement, useContext } from 'react';
|
|
6
7
|
import { ClockGlyph, CheckGlyph } from '@crewlethq/icons/glyphs';
|
|
7
8
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
8
9
|
|
|
@@ -12,19 +13,62 @@ function usePane(part) {
|
|
|
12
13
|
if (pane === null) throw new Error(`${part} must be drawn inside a ReadingPane.`);
|
|
13
14
|
return pane;
|
|
14
15
|
}
|
|
15
|
-
|
|
16
|
+
var READING_PANE_ENTER = { animations: ["crewlet-reading-pane-enter"] };
|
|
17
|
+
function ReadingPane({ headingLevel, contentKey, focusTarget, className, children, ...rest }) {
|
|
16
18
|
const titleId = useId();
|
|
17
19
|
const outer = useHeadingLevel();
|
|
18
20
|
const level = headingLevel ?? outer;
|
|
19
21
|
const named = rest["aria-label"] !== void 0 || rest["aria-labelledby"] !== void 0;
|
|
20
|
-
|
|
22
|
+
const pane = useRef(null);
|
|
23
|
+
const column = useRef(null);
|
|
24
|
+
const [drawnKey, setDrawnKey] = useState(contentKey);
|
|
25
|
+
const [moved, setMoved] = useState(false);
|
|
26
|
+
if (drawnKey !== contentKey) {
|
|
27
|
+
setDrawnKey(contentKey);
|
|
28
|
+
setMoved(true);
|
|
29
|
+
}
|
|
30
|
+
const owned = useRef(false);
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
const root = pane.current;
|
|
33
|
+
if (!root) return void 0;
|
|
34
|
+
const doc = root.ownerDocument;
|
|
35
|
+
const inside = (node) => node instanceof Node && root.contains(node);
|
|
36
|
+
const focusIn = () => {
|
|
37
|
+
owned.current = true;
|
|
38
|
+
};
|
|
39
|
+
const focusOut = (event) => {
|
|
40
|
+
if (event.relatedTarget !== null && !inside(event.relatedTarget)) owned.current = false;
|
|
41
|
+
};
|
|
42
|
+
const press = (event) => {
|
|
43
|
+
owned.current = inside(event.target);
|
|
44
|
+
};
|
|
45
|
+
root.addEventListener("focusin", focusIn);
|
|
46
|
+
root.addEventListener("focusout", focusOut);
|
|
47
|
+
doc.addEventListener("pointerdown", press, true);
|
|
48
|
+
return () => {
|
|
49
|
+
root.removeEventListener("focusin", focusIn);
|
|
50
|
+
root.removeEventListener("focusout", focusOut);
|
|
51
|
+
doc.removeEventListener("pointerdown", press, true);
|
|
52
|
+
};
|
|
53
|
+
}, []);
|
|
54
|
+
const settled = useRef(contentKey);
|
|
55
|
+
useLayoutEffect(() => {
|
|
56
|
+
if (contentKey === settled.current) return;
|
|
57
|
+
settled.current = contentKey;
|
|
58
|
+
if (!owned.current) return;
|
|
59
|
+
const target = focusTarget?.() ?? column.current?.querySelector(".crewlet-reading-pane__title");
|
|
60
|
+
returnFocus(target, { preventScroll: true });
|
|
61
|
+
}, [contentKey, focusTarget]);
|
|
62
|
+
return /* @__PURE__ */ jsx("div", { ref: pane, className: "crewlet-reading-pane", children: /* @__PURE__ */ createElement(
|
|
21
63
|
"article",
|
|
22
64
|
{
|
|
23
65
|
...rest,
|
|
66
|
+
key: contentKey,
|
|
67
|
+
ref: column,
|
|
24
68
|
"aria-labelledby": named ? rest["aria-labelledby"] : titleId,
|
|
25
|
-
className: cx("crewlet-reading-pane__column", className)
|
|
26
|
-
|
|
27
|
-
}
|
|
69
|
+
className: cx("crewlet-reading-pane__column", moved && "crewlet-reading-pane__column--entering", className)
|
|
70
|
+
},
|
|
71
|
+
/* @__PURE__ */ jsx(ReadingPaneContext.Provider, { value: { titleId, level }, children: /* @__PURE__ */ jsx(HeadingLevelProvider, { level: nextHeadingLevel(level), children }) })
|
|
28
72
|
) });
|
|
29
73
|
}
|
|
30
74
|
function ReadingPaneByline({ start, leading, note, className, children, ...rest }) {
|
|
@@ -46,7 +90,11 @@ function ReadingPaneByline({ start, leading, note, className, children, ...rest
|
|
|
46
90
|
function ReadingPaneTitle({ className, children, ...rest }) {
|
|
47
91
|
const { titleId, level } = usePane("ReadingPane.Title");
|
|
48
92
|
const Heading = headingTag(level);
|
|
49
|
-
return
|
|
93
|
+
return (
|
|
94
|
+
// Focusable from code alone, for the pane to hand focus to when its item
|
|
95
|
+
// changes; never a tab stop.
|
|
96
|
+
/* @__PURE__ */ jsx(Heading, { id: titleId, tabIndex: -1, ...rest, className: cx("crewlet-reading-pane__title", className), children })
|
|
97
|
+
);
|
|
50
98
|
}
|
|
51
99
|
function ReadingPaneLead({ className, children, ...rest }) {
|
|
52
100
|
return /* @__PURE__ */ jsx("div", { ...rest, className: cx("crewlet-reading-pane__lead", className), children });
|
|
@@ -109,4 +157,4 @@ ReadingPane.Reasoning = ReadingPaneReasoning;
|
|
|
109
157
|
ReadingPane.Outcome = ReadingPaneOutcome;
|
|
110
158
|
ReadingPane.Section = ReadingPaneSection;
|
|
111
159
|
|
|
112
|
-
export { ReadingPane, ReadingPaneByline, ReadingPaneLead, ReadingPaneOutcome, ReadingPaneQuote, ReadingPaneReasoning, ReadingPaneSection, ReadingPaneTitle };
|
|
160
|
+
export { READING_PANE_ENTER, ReadingPane, ReadingPaneByline, ReadingPaneLead, ReadingPaneOutcome, ReadingPaneQuote, ReadingPaneReasoning, ReadingPaneSection, ReadingPaneTitle };
|
|
@@ -2,14 +2,14 @@ import { Skeleton } from './chunk-I4IUX3JF.js';
|
|
|
2
2
|
import { PrincipalAvatar } from './chunk-HF5L56YQ.js';
|
|
3
3
|
import { RelativeTime } from './chunk-EJNJMHQG.js';
|
|
4
4
|
import { Card } from './chunk-U2IQNDDR.js';
|
|
5
|
-
import { AvatarStack } from './chunk-
|
|
6
|
-
import { ArtifactKindGround } from './chunk-
|
|
5
|
+
import { AvatarStack } from './chunk-YTLWOHOY.js';
|
|
6
|
+
import { ArtifactKindGround } from './chunk-J5T5TDM2.js';
|
|
7
7
|
import { Checkbox } from './chunk-YQ7Q52XU.js';
|
|
8
8
|
import { ArtifactAccessGlyph } from './chunk-DOY3KC6I.js';
|
|
9
9
|
import { ArtifactKindGlyph } from './chunk-RSKW25Y5.js';
|
|
10
10
|
import { VisuallyHidden } from './chunk-UT6CW3C7.js';
|
|
11
11
|
import { cx } from './chunk-ODEQTPFM.js';
|
|
12
|
-
import './ArtifactKinds-
|
|
12
|
+
import './ArtifactKinds-27TE3KJL.css';
|
|
13
13
|
import './ArtifactCard-B2QE5CVL.css';
|
|
14
14
|
import { useId } from 'react';
|
|
15
15
|
import { PinGlyph } from '@crewlethq/icons/glyphs';
|
|
@@ -4,7 +4,7 @@ import { HIT_AREA_CLASS } from './chunk-2YTOOH3A.js';
|
|
|
4
4
|
import { VisuallyHidden } from './chunk-UT6CW3C7.js';
|
|
5
5
|
import { cx } from './chunk-ODEQTPFM.js';
|
|
6
6
|
import './HitArea-QUOS6ZDJ.css';
|
|
7
|
-
import './SidebarNav-
|
|
7
|
+
import './SidebarNav-IKBKGXW4.css';
|
|
8
8
|
import { createContext, useId, useState, useContext } from 'react';
|
|
9
9
|
import { ChevronDownGlyph } from '@crewlethq/icons/glyphs';
|
|
10
10
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
@@ -136,7 +136,13 @@ function NavItem({
|
|
|
136
136
|
count || badge || state ? /* @__PURE__ */ jsx(VisuallyHidden, { children: `${spoken([count, badge])}${state}` }) : null
|
|
137
137
|
] }),
|
|
138
138
|
count ? /* @__PURE__ */ jsx(Figure, { figure: count, mark: count.mark, className: "crewlet-nav-item__count" }) : null,
|
|
139
|
-
badge ? /* @__PURE__ */ jsx(
|
|
139
|
+
badge ? /* @__PURE__ */ jsx(
|
|
140
|
+
Figure,
|
|
141
|
+
{
|
|
142
|
+
figure: badge,
|
|
143
|
+
className: cx("crewlet-nav-item__badge", badge.tone === "quiet" && "crewlet-nav-item__badge--quiet")
|
|
144
|
+
}
|
|
145
|
+
) : null
|
|
140
146
|
] });
|
|
141
147
|
const rowClass = cx("crewlet-nav-item__row", HIT_AREA_CLASS);
|
|
142
148
|
let row;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { StatusDot } from './chunk-CYQBDZ6M.js';
|
|
1
2
|
import { useHeadingLevel, headingTag } from './chunk-PQADV6P6.js';
|
|
2
3
|
import { cx } from './chunk-ODEQTPFM.js';
|
|
3
|
-
import './CatalogTile-
|
|
4
|
+
import './CatalogTile-TMOSGSV3.css';
|
|
4
5
|
import { useId } from 'react';
|
|
5
|
-
import {
|
|
6
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
6
7
|
|
|
7
8
|
function CatalogTile({
|
|
8
9
|
as: Element = "article",
|
|
@@ -22,6 +23,7 @@ function CatalogTile({
|
|
|
22
23
|
const Heading = headingTag(headingLevel ?? level);
|
|
23
24
|
const titleId = useId();
|
|
24
25
|
const foot = meta !== void 0 || action !== void 0;
|
|
26
|
+
const state = status ? /* @__PURE__ */ jsx("span", { className: "crewlet-catalog-tile__status", children: /* @__PURE__ */ jsx(StatusDot, { tone: status.tone, children: status.label }) }) : null;
|
|
25
27
|
if (density === "compact") {
|
|
26
28
|
return /* @__PURE__ */ jsxs(
|
|
27
29
|
Element,
|
|
@@ -39,7 +41,7 @@ function CatalogTile({
|
|
|
39
41
|
/* @__PURE__ */ jsx("span", { className: "crewlet-catalog-tile__mark", "aria-hidden": "true", children: mark }),
|
|
40
42
|
/* @__PURE__ */ jsxs("span", { className: "crewlet-catalog-tile__title", children: [
|
|
41
43
|
/* @__PURE__ */ jsx(Heading, { id: titleId, className: "crewlet-catalog-tile__name", children: title }),
|
|
42
|
-
|
|
44
|
+
state,
|
|
43
45
|
meta === void 0 || meta === null ? null : /* @__PURE__ */ jsx("span", { className: "crewlet-catalog-tile__meta", children: meta })
|
|
44
46
|
] }),
|
|
45
47
|
action === void 0 ? null : /* @__PURE__ */ jsx("span", { className: "crewlet-catalog-tile__action", children: action })
|
|
@@ -67,7 +69,7 @@ function CatalogTile({
|
|
|
67
69
|
/* @__PURE__ */ jsx("span", { className: "crewlet-catalog-tile__mark", "aria-hidden": "true", children: mark }),
|
|
68
70
|
/* @__PURE__ */ jsxs("span", { className: "crewlet-catalog-tile__title", children: [
|
|
69
71
|
/* @__PURE__ */ jsx(Heading, { id: titleId, className: "crewlet-catalog-tile__name", children: title }),
|
|
70
|
-
|
|
72
|
+
state
|
|
71
73
|
] })
|
|
72
74
|
] }),
|
|
73
75
|
description === void 0 ? null : /* @__PURE__ */ jsx("p", { className: "crewlet-catalog-tile__description", children: description }),
|
|
@@ -1,15 +1,108 @@
|
|
|
1
1
|
import { Eyebrow } from './chunk-RK4XPHVG.js';
|
|
2
|
+
import { developing } from './chunk-6C7GQOBV.js';
|
|
3
|
+
import { usePresence, releaseFocus } from './chunk-PCAT2EFB.js';
|
|
2
4
|
import { useHeadingLevel, headingTag } from './chunk-PQADV6P6.js';
|
|
3
5
|
import { VisuallyHidden } from './chunk-UT6CW3C7.js';
|
|
4
6
|
import { cx } from './chunk-ODEQTPFM.js';
|
|
5
|
-
import './InboxList-
|
|
6
|
-
import { useId, useState } from 'react';
|
|
7
|
+
import './InboxList-X5Q5WWAI.css';
|
|
8
|
+
import { useId, useState, useRef, useLayoutEffect, useEffect, useCallback, cloneElement, Children, isValidElement } from 'react';
|
|
7
9
|
import { ChevronDownGlyph } from '@crewlethq/icons/glyphs';
|
|
8
10
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
9
11
|
|
|
10
12
|
function InboxList({ label, className, children, ...rest }) {
|
|
11
13
|
return /* @__PURE__ */ jsx("nav", { ...rest, "aria-label": label, className: cx("crewlet-inbox-list", className), children });
|
|
12
14
|
}
|
|
15
|
+
var INBOX_ROW_LEAVE = { transitions: ["grid-template-rows"] };
|
|
16
|
+
function rowsOf(children) {
|
|
17
|
+
const given = [];
|
|
18
|
+
Children.forEach(children, (child) => {
|
|
19
|
+
if (isValidElement(child)) given.push(child.key !== null);
|
|
20
|
+
});
|
|
21
|
+
return Children.toArray(children).filter((child) => isValidElement(child)).map((element, index) => ({
|
|
22
|
+
key: String(element.key),
|
|
23
|
+
element,
|
|
24
|
+
keyed: given[index] === true,
|
|
25
|
+
component: typeof element.type !== "string"
|
|
26
|
+
}));
|
|
27
|
+
}
|
|
28
|
+
function sameKeys(a, b) {
|
|
29
|
+
return a.length === b.length && a.every((key, index) => key === b[index]);
|
|
30
|
+
}
|
|
31
|
+
function keepPlaces(previous, next, kept) {
|
|
32
|
+
const placed = new Set(next);
|
|
33
|
+
const order = [...next];
|
|
34
|
+
previous.forEach((key, index) => {
|
|
35
|
+
if (placed.has(key) || !kept.has(key)) return;
|
|
36
|
+
let at = 0;
|
|
37
|
+
for (let back = index - 1; back >= 0; back -= 1) {
|
|
38
|
+
if (placed.has(previous[back])) {
|
|
39
|
+
at = order.indexOf(previous[back]) + 1;
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
order.splice(at, 0, key);
|
|
44
|
+
placed.add(key);
|
|
45
|
+
});
|
|
46
|
+
return order;
|
|
47
|
+
}
|
|
48
|
+
function useLeavingRows(children) {
|
|
49
|
+
const rows = rowsOf(children);
|
|
50
|
+
const keys = rows.map((row) => row.key);
|
|
51
|
+
const [shown, setRows] = useState(() => ({
|
|
52
|
+
keys,
|
|
53
|
+
order: keys,
|
|
54
|
+
leaving: /* @__PURE__ */ new Map()
|
|
55
|
+
}));
|
|
56
|
+
const drawn = useRef(/* @__PURE__ */ new Map());
|
|
57
|
+
useLayoutEffect(() => {
|
|
58
|
+
drawn.current = new Map(rows.map((row) => [row.key, row]));
|
|
59
|
+
});
|
|
60
|
+
let now = shown;
|
|
61
|
+
if (!sameKeys(shown.keys, keys)) {
|
|
62
|
+
const present = new Set(keys);
|
|
63
|
+
const leaving = new Map([...shown.leaving].filter(([key]) => !present.has(key)));
|
|
64
|
+
for (const key of shown.keys) {
|
|
65
|
+
if (present.has(key)) continue;
|
|
66
|
+
const last = drawn.current.get(key);
|
|
67
|
+
if (last?.keyed && last.component) leaving.set(key, last.element);
|
|
68
|
+
}
|
|
69
|
+
now = { keys, order: keepPlaces(shown.order, keys, new Set(leaving.keys())), leaving };
|
|
70
|
+
setRows(now);
|
|
71
|
+
}
|
|
72
|
+
const warned = useRef(false);
|
|
73
|
+
useEffect(() => {
|
|
74
|
+
if (warned.current || !developing()) return;
|
|
75
|
+
if (rows.some((row) => row.component && !row.keyed)) {
|
|
76
|
+
warned.current = true;
|
|
77
|
+
console.warn(
|
|
78
|
+
"[crewlet] InboxGroup was handed a row without a key of its own. Give each row a stable key, such as its id: a row without one is told apart by its position, and is not kept while it leaves."
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
const drop = useCallback((key) => {
|
|
83
|
+
setRows((was) => {
|
|
84
|
+
if (!was.leaving.has(key)) return was;
|
|
85
|
+
const leaving = new Map(was.leaving);
|
|
86
|
+
leaving.delete(key);
|
|
87
|
+
return { ...was, leaving, order: was.order.filter((each) => each !== key) };
|
|
88
|
+
});
|
|
89
|
+
}, []);
|
|
90
|
+
if (now.leaving.size === 0) return rows.map((row) => row.element);
|
|
91
|
+
const live = new Map(rows.map((row) => [row.key, row.element]));
|
|
92
|
+
return now.order.map((key) => {
|
|
93
|
+
const row = live.get(key);
|
|
94
|
+
if (row) return row;
|
|
95
|
+
const last = now.leaving.get(key);
|
|
96
|
+
if (!last) return null;
|
|
97
|
+
return cloneElement(last, {
|
|
98
|
+
leaving: true,
|
|
99
|
+
onLeft: () => {
|
|
100
|
+
last.props.onLeft?.();
|
|
101
|
+
drop(key);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
}
|
|
13
106
|
function InboxGroup({
|
|
14
107
|
label,
|
|
15
108
|
hideLabel = false,
|
|
@@ -19,10 +112,12 @@ function InboxGroup({
|
|
|
19
112
|
open: controlledOpen,
|
|
20
113
|
defaultOpen = false,
|
|
21
114
|
onOpenChange,
|
|
115
|
+
arrived,
|
|
22
116
|
className,
|
|
23
117
|
children,
|
|
24
118
|
...rest
|
|
25
119
|
}) {
|
|
120
|
+
const rows = useLeavingRows(children);
|
|
26
121
|
const level = useHeadingLevel();
|
|
27
122
|
const Heading = headingTag(headingLevel ?? level);
|
|
28
123
|
const labelId = useId();
|
|
@@ -40,6 +135,7 @@ function InboxGroup({
|
|
|
40
135
|
" ",
|
|
41
136
|
/* @__PURE__ */ jsx("span", { className: "crewlet-inbox-list__count", children: count })
|
|
42
137
|
] });
|
|
138
|
+
const arrival = arrived === void 0 ? null : /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "crewlet-inbox-list__arrival" }, arrived);
|
|
43
139
|
return /* @__PURE__ */ jsxs(
|
|
44
140
|
"section",
|
|
45
141
|
{
|
|
@@ -54,27 +150,31 @@ function InboxGroup({
|
|
|
54
150
|
// A DISCLOSURE INSIDE THE HEADING, never a heading inside a button: a
|
|
55
151
|
// reader moving by heading still lands on the group, and the button
|
|
56
152
|
// in it says whether the rows are shown.
|
|
57
|
-
/* @__PURE__ */
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
153
|
+
/* @__PURE__ */ jsxs(Heading, { className: "crewlet-inbox-list__label", children: [
|
|
154
|
+
/* @__PURE__ */ jsxs(
|
|
155
|
+
"button",
|
|
156
|
+
{
|
|
157
|
+
type: "button",
|
|
158
|
+
id: labelId,
|
|
159
|
+
className: "crewlet-inbox-list__disclosure",
|
|
160
|
+
"aria-expanded": open,
|
|
161
|
+
"aria-controls": rowsId,
|
|
162
|
+
onClick: toggle,
|
|
163
|
+
children: [
|
|
164
|
+
/* @__PURE__ */ jsx(ChevronDownGlyph, { "aria-hidden": true, size: "sm", className: "crewlet-inbox-list__chevron" }),
|
|
165
|
+
/* @__PURE__ */ jsx(Eyebrow, { children: label }),
|
|
166
|
+
counted
|
|
167
|
+
]
|
|
168
|
+
}
|
|
169
|
+
),
|
|
170
|
+
arrival
|
|
171
|
+
] })
|
|
73
172
|
) : /* @__PURE__ */ jsxs(Heading, { id: labelId, className: "crewlet-inbox-list__label", children: [
|
|
74
173
|
/* @__PURE__ */ jsx(Eyebrow, { children: label }),
|
|
75
|
-
counted
|
|
174
|
+
counted,
|
|
175
|
+
arrival
|
|
76
176
|
] }),
|
|
77
|
-
/* @__PURE__ */ jsx("ul", { id: rowsId, className: "crewlet-inbox-list__rows", hidden: !open, children })
|
|
177
|
+
/* @__PURE__ */ jsx("ul", { id: rowsId, className: "crewlet-inbox-list__rows", hidden: !open, children: rows })
|
|
78
178
|
]
|
|
79
179
|
}
|
|
80
180
|
);
|
|
@@ -99,10 +199,29 @@ function InboxRow({
|
|
|
99
199
|
outcomeTone = "neutral",
|
|
100
200
|
href,
|
|
101
201
|
onClick,
|
|
202
|
+
leaving = false,
|
|
203
|
+
onLeft,
|
|
204
|
+
arrived = false,
|
|
102
205
|
className,
|
|
103
206
|
children,
|
|
104
207
|
...rest
|
|
105
208
|
}) {
|
|
209
|
+
const self = useRef(null);
|
|
210
|
+
const presence = usePresence(!leaving, self, INBOX_ROW_LEAVE);
|
|
211
|
+
const gone = !presence.present;
|
|
212
|
+
useLayoutEffect(() => {
|
|
213
|
+
if (presence.leaving) releaseFocus(self.current);
|
|
214
|
+
}, [presence.leaving]);
|
|
215
|
+
const told = useRef(false);
|
|
216
|
+
useEffect(() => {
|
|
217
|
+
if (!gone) {
|
|
218
|
+
told.current = false;
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
if (told.current) return;
|
|
222
|
+
told.current = true;
|
|
223
|
+
onLeft?.();
|
|
224
|
+
}, [gone, onLeft]);
|
|
106
225
|
const contents = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
107
226
|
leading === void 0 ? null : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
108
227
|
/* @__PURE__ */ jsx("span", { className: "crewlet-inbox-row__leading", children: leading }),
|
|
@@ -157,10 +276,26 @@ function InboxRow({
|
|
|
157
276
|
);
|
|
158
277
|
const current = selected ? "true" : void 0;
|
|
159
278
|
const control = href !== void 0 ? /* @__PURE__ */ jsx("a", { className: controlClass, href, "aria-current": current, onClick, children: contents }) : /* @__PURE__ */ jsx("button", { type: "button", className: controlClass, "aria-current": current, onClick, children: contents });
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
279
|
+
if (gone) return null;
|
|
280
|
+
return /* @__PURE__ */ jsx(
|
|
281
|
+
"li",
|
|
282
|
+
{
|
|
283
|
+
...rest,
|
|
284
|
+
ref: self,
|
|
285
|
+
inert: presence.leaving,
|
|
286
|
+
className: cx(
|
|
287
|
+
"crewlet-inbox-row",
|
|
288
|
+
selected && "crewlet-inbox-row--selected",
|
|
289
|
+
arrived && "crewlet-inbox-row--arrived",
|
|
290
|
+
presence.leaving && "crewlet-inbox-row--leaving",
|
|
291
|
+
className
|
|
292
|
+
),
|
|
293
|
+
children: /* @__PURE__ */ jsxs("div", { className: "crewlet-inbox-row__body", children: [
|
|
294
|
+
control,
|
|
295
|
+
aside === void 0 || aside === null || aside === false ? null : /* @__PURE__ */ jsx("div", { className: "crewlet-inbox-row__aside", children: aside })
|
|
296
|
+
] })
|
|
297
|
+
}
|
|
298
|
+
);
|
|
164
299
|
}
|
|
165
300
|
function InboxMore({ className, children, ...rest }) {
|
|
166
301
|
return /* @__PURE__ */ jsx("div", { ...rest, className: cx("crewlet-inbox-list__more", className), children });
|
|
@@ -173,4 +308,4 @@ InboxList.Row = InboxRow;
|
|
|
173
308
|
InboxList.More = InboxMore;
|
|
174
309
|
InboxList.Toggle = InboxToggle;
|
|
175
310
|
|
|
176
|
-
export { InboxGroup, InboxList, InboxMore, InboxRow, InboxToggle };
|
|
311
|
+
export { INBOX_ROW_LEAVE, InboxGroup, InboxList, InboxMore, InboxRow, InboxToggle };
|
|
@@ -3,7 +3,7 @@ import { HIT_AREA_CLASS } from './chunk-2YTOOH3A.js';
|
|
|
3
3
|
import { VisuallyHidden } from './chunk-UT6CW3C7.js';
|
|
4
4
|
import { cx } from './chunk-ODEQTPFM.js';
|
|
5
5
|
import './HitArea-QUOS6ZDJ.css';
|
|
6
|
-
import './ArtifactKinds-
|
|
6
|
+
import './ArtifactKinds-27TE3KJL.css';
|
|
7
7
|
import './ArtifactMakeRow-6UX2LTF7.css';
|
|
8
8
|
import { useId } from 'react';
|
|
9
9
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
@@ -7,7 +7,7 @@ import { Button } from './chunk-DGXZ635L.js';
|
|
|
7
7
|
import { returnFocus } from './chunk-4ITETIGZ.js';
|
|
8
8
|
import { IconButton } from './chunk-UAUP6XGK.js';
|
|
9
9
|
import { cx } from './chunk-ODEQTPFM.js';
|
|
10
|
-
import './ArtifactKinds-
|
|
10
|
+
import './ArtifactKinds-27TE3KJL.css';
|
|
11
11
|
import './ArtifactBar-X46WJNW7.css';
|
|
12
12
|
import { useId, useState, useRef, useEffect } from 'react';
|
|
13
13
|
import { ChevronLeftGlyph, EllipsisGlyph, ChevronDownGlyph } from '@crewlethq/icons/glyphs';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { VisuallyHidden } from './chunk-UT6CW3C7.js';
|
|
2
2
|
import { cx } from './chunk-ODEQTPFM.js';
|
|
3
|
-
import './ArtifactKinds-
|
|
3
|
+
import './ArtifactKinds-27TE3KJL.css';
|
|
4
4
|
import './ArtifactKindIllustration-D2J3HJMJ.css';
|
|
5
5
|
import { useId } from 'react';
|
|
6
6
|
import { CheckGlyph } from '@crewlethq/icons/glyphs';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ArtifactKindGlyph } from './chunk-RSKW25Y5.js';
|
|
2
2
|
import { VisuallyHidden } from './chunk-UT6CW3C7.js';
|
|
3
3
|
import { cx } from './chunk-ODEQTPFM.js';
|
|
4
|
-
import './ArtifactKinds-
|
|
4
|
+
import './ArtifactKinds-27TE3KJL.css';
|
|
5
5
|
import './ArtifactNameCell-3AHLUSE5.css';
|
|
6
6
|
import { FolderGlyph, PinGlyph } from '@crewlethq/icons/glyphs';
|
|
7
7
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { cx } from './chunk-ODEQTPFM.js';
|
|
2
|
-
import './ArtifactKinds-
|
|
3
|
-
import './ActionCard-
|
|
2
|
+
import './ArtifactKinds-27TE3KJL.css';
|
|
3
|
+
import './ActionCard-YZKL3CKR.css';
|
|
4
4
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
5
5
|
|
|
6
6
|
var ACTION_CARD_GROUND = {
|