@crewlethq/ui 0.17.0 → 0.18.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 +36 -1
- package/dist/AccessDeniedCard/AccessDeniedCard.d.ts +39 -0
- package/dist/AccessDeniedCard/index.d.ts +3 -0
- package/dist/AccessDeniedCard/index.js +8 -0
- package/dist/AccessDeniedCard-WXM5DBDZ.css +8 -0
- package/dist/ArtifactCard/ArtifactCard.d.ts +61 -0
- package/dist/ArtifactCard/index.d.ts +3 -0
- package/dist/ArtifactCard/index.js +12 -0
- package/dist/ArtifactCard-EXVAEBV6.css +109 -0
- package/dist/AvatarPicker/index.js +4 -4
- package/dist/ChangeMark/ChangeMark.d.ts +26 -0
- package/dist/ChangeMark/index.d.ts +3 -0
- package/dist/ChangeMark/index.js +8 -0
- package/dist/ChangeMark-3VMTW7MT.css +22 -0
- package/dist/Combobox/index.js +1 -1
- package/dist/CommandPalette/index.js +3 -3
- package/dist/CursorFlag/CursorFlag.d.ts +34 -0
- package/dist/CursorFlag/index.d.ts +3 -0
- package/dist/CursorFlag/index.js +3 -0
- package/dist/CursorFlag-AJQJBUGY.css +61 -0
- package/dist/DataTable/index.js +6 -6
- package/dist/DataView/index.js +12 -12
- package/dist/DateTimePicker/index.js +2 -2
- package/dist/FollowBanner/FollowBanner.d.ts +35 -0
- package/dist/FollowBanner/index.d.ts +2 -0
- package/dist/FollowBanner/index.js +7 -0
- package/dist/FrameProtocol/index.d.ts +2 -0
- package/dist/FrameProtocol/index.js +2 -0
- package/dist/FrameProtocol/protocol.d.ts +164 -0
- package/dist/HuePicker/index.js +2 -2
- package/dist/LinkInterstitial/LinkInterstitial.d.ts +41 -0
- package/dist/LinkInterstitial/index.d.ts +3 -0
- package/dist/LinkInterstitial/index.js +11 -0
- package/dist/LinkInterstitial-ET4MSVSV.css +34 -0
- package/dist/ListInput/index.js +1 -1
- package/dist/LiveCursor/LiveCursor.d.ts +34 -0
- package/dist/LiveCursor/index.d.ts +3 -0
- package/dist/LiveCursor/index.js +4 -0
- package/dist/LiveCursor-DZHGIYWE.css +47 -0
- package/dist/MarkdownEditor/index.js +2 -2
- package/dist/Modal/index.js +2 -2
- package/dist/OrgTable/index.js +2 -2
- package/dist/PresenceModel/index.d.ts +2 -0
- package/dist/PresenceModel/index.js +3 -0
- package/dist/PresenceModel/presence.d.ts +80 -0
- package/dist/PresenceRing/PresenceRing.d.ts +31 -0
- package/dist/PresenceRing/index.d.ts +3 -0
- package/dist/PresenceRing/index.js +2 -0
- package/dist/PresenceRing-M4C22Q6U.css +68 -0
- package/dist/PresenceStack/PresenceStack.d.ts +36 -0
- package/dist/PresenceStack/index.d.ts +3 -0
- package/dist/PresenceStack/index.js +9 -0
- package/dist/PresenceStack-QSXQJND5.css +59 -0
- package/dist/PricingCard/index.js +2 -2
- package/dist/Principal/Principal.d.ts +35 -0
- package/dist/Principal/index.d.ts +2 -0
- package/dist/Principal/index.js +4 -0
- package/dist/PrincipalPicker/PrincipalPicker.d.ts +45 -0
- package/dist/PrincipalPicker/index.d.ts +3 -0
- package/dist/PrincipalPicker/index.js +12 -0
- package/dist/PrincipalPicker-7NNZTGUP.css +41 -0
- package/dist/SandboxedFrame/SandboxedFrame.d.ts +142 -0
- package/dist/SandboxedFrame/index.d.ts +3 -0
- package/dist/SandboxedFrame/index.js +8 -0
- package/dist/SandboxedFrame-L6HBQZCD.css +50 -0
- package/dist/ShareDialog/ShareDialog.d.ts +101 -0
- package/dist/ShareDialog/index.d.ts +5 -0
- package/dist/ShareDialog/index.js +19 -0
- package/dist/ShareDialog/roles.d.ts +10 -0
- package/dist/ShareDialog-YZ4F37MW.css +146 -0
- package/dist/SheetGrid/SheetGrid.d.ts +78 -0
- package/dist/SheetGrid/cells.d.ts +117 -0
- package/dist/SheetGrid/index.d.ts +5 -0
- package/dist/SheetGrid/index.js +18 -0
- package/dist/SheetGrid-4HOXDVIB.css +595 -0
- package/dist/SheetModel/clipboard.d.ts +37 -0
- package/dist/SheetModel/edits.d.ts +68 -0
- package/dist/SheetModel/index.d.ts +14 -0
- package/dist/SheetModel/index.js +3 -0
- package/dist/SheetModel/labels.d.ts +71 -0
- package/dist/SheetModel/navigation.d.ts +79 -0
- package/dist/SheetModel/options.d.ts +28 -0
- package/dist/SheetModel/types.d.ts +126 -0
- package/dist/SheetModel/values.d.ts +76 -0
- package/dist/SheetModel/view.d.ts +32 -0
- package/dist/Switcher/index.js +5 -5
- package/dist/Tag/Tag.d.ts +13 -0
- package/dist/Tag/index.js +1 -1
- package/dist/{Tag-4BRQS6GN.css → Tag-SRGTK5KI.css} +42 -0
- package/dist/TagsInput/index.js +2 -2
- package/dist/ThemeSwitcher/apply.d.ts +43 -0
- package/dist/ThemeSwitcher/index.d.ts +4 -2
- package/dist/ThemeSwitcher/index.js +3 -2
- package/dist/ThemeSwitcher/preferences.d.ts +2 -19
- package/dist/ThemeToggle/index.js +3 -2
- package/dist/TimeWindowPicker/index.js +3 -3
- package/dist/Timeline/Timeline.d.ts +7 -2
- package/dist/Timeline/index.js +1 -1
- package/dist/VersionTimeline/VersionTimeline.d.ts +76 -0
- package/dist/VersionTimeline/index.d.ts +3 -0
- package/dist/VersionTimeline/index.js +10 -0
- package/dist/VersionTimeline-EBJ6MIPJ.css +108 -0
- package/dist/{chunk-SBRE7IML.js → chunk-2ONWEDQT.js} +1 -1
- package/dist/chunk-2YR5ZPQ3.js +216 -0
- package/dist/chunk-3BYIWOTV.js +29 -0
- package/dist/chunk-3UAA4IWJ.js +98 -0
- package/dist/chunk-4KP4RC3O.js +25 -0
- package/dist/chunk-4U3GQ7D2.js +99 -0
- package/dist/chunk-5XACKNYR.js +53 -0
- package/dist/{chunk-RF5O4FYL.js → chunk-76FXDZAZ.js} +2 -2
- package/dist/chunk-A7EBCHEG.js +49 -0
- package/dist/{chunk-JCO3SIST.js → chunk-AQCV62K6.js} +1 -1
- package/dist/{chunk-O67VF5MS.js → chunk-AUQPBL4O.js} +2 -2
- package/dist/{chunk-HENOTGUV.js → chunk-BOW2VUCH.js} +2 -2
- package/dist/{chunk-UCYIRDND.js → chunk-DQSXWQMJ.js} +1 -1
- package/dist/chunk-ESKP3TXM.js +1 -0
- package/dist/chunk-F6V2PTN6.js +142 -0
- package/dist/chunk-FW7HN6AP.js +40 -0
- package/dist/chunk-FYXRWBJJ.js +1235 -0
- package/dist/{chunk-LOECRMHA.js → chunk-GFV4LJHH.js} +4 -3
- package/dist/chunk-I6POAB4V.js +20 -0
- package/dist/{chunk-PQ63NLFC.js → chunk-IFKBDRNJ.js} +1 -1
- package/dist/{chunk-XU4H6JQB.js → chunk-KVT3TJVG.js} +4 -4
- package/dist/chunk-LFZ45HV2.js +46 -0
- package/dist/{chunk-6TSZCBID.js → chunk-NP2C4Y4E.js} +1 -1
- package/dist/{chunk-FA2V2VT6.js → chunk-NZY77ZDU.js} +3 -3
- package/dist/chunk-PPAQFGS2.js +12 -0
- package/dist/chunk-S35G6PNC.js +80 -0
- package/dist/chunk-VYDFB6PJ.js +243 -0
- package/dist/chunk-WXAULPBH.js +135 -0
- package/dist/chunk-YM3GJHGW.js +69 -0
- package/dist/chunk-YYZRLLLY.js +822 -0
- package/dist/{chunk-K3OWD7BJ.js → chunk-Z24ZUSTX.js} +4 -19
- package/dist/chunk-ZXXDZJQN.js +36 -0
- package/dist/generated/index.d.ts +18 -0
- package/dist/generated/index.js +82 -62
- package/dist/index.js +82 -62
- package/dist/styles.css +1578 -149
- package/dist/utils/index.js +1 -1
- package/package.json +6 -6
- package/dist/{chunk-DEEVA6TV.js → chunk-2TZATTIU.js} +1 -1
- package/dist/{chunk-2UU5IGZI.js → chunk-5NVKTB6E.js} +1 -1
- package/dist/{chunk-CRVETI5L.js → chunk-CENOOTAV.js} +0 -0
- package/dist/{chunk-JF7X673Z.js → chunk-ERV5BUS3.js} +1 -1
- package/dist/{chunk-NXDEPUVG.js → chunk-PA4CYTBY.js} +1 -1
- package/dist/{chunk-77IEHFY4.js → chunk-QQGWES46.js} +1 -1
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
export { DEFAULT_TIME_WINDOW_LABELS, TIME_WINDOW_SPANS, TimeWindowPicker, describeTimeWindow, isTimeWindowSet, parseTimeWindowDuration, resolveTimeWindow, timeWindowMatchesPreset } from '../chunk-
|
|
1
|
+
export { DEFAULT_TIME_WINDOW_LABELS, TIME_WINDOW_SPANS, TimeWindowPicker, describeTimeWindow, isTimeWindowSet, parseTimeWindowDuration, resolveTimeWindow, timeWindowMatchesPreset } from '../chunk-ERV5BUS3.js';
|
|
2
2
|
import '../chunk-FC4YTTFJ.js';
|
|
3
3
|
import '../chunk-F73MC7EZ.js';
|
|
4
4
|
import '../chunk-4GB57WIT.js';
|
|
5
|
+
import '../chunk-BWRGFKJP.js';
|
|
5
6
|
import '../chunk-GXQ3B46I.js';
|
|
6
7
|
import '../chunk-OG6CL3EB.js';
|
|
7
8
|
import '../chunk-4FQT6ZAY.js';
|
|
8
|
-
import '../chunk-PQADV6P6.js';
|
|
9
|
-
import '../chunk-BWRGFKJP.js';
|
|
10
9
|
import '../chunk-HMPFGIWM.js';
|
|
11
10
|
import '../chunk-R25RGPUB.js';
|
|
11
|
+
import '../chunk-PQADV6P6.js';
|
|
12
12
|
import '../chunk-BZFWDIV6.js';
|
|
13
13
|
import '../chunk-ODEQTPFM.js';
|
|
@@ -38,8 +38,13 @@ export interface TimelineItemProps extends LiHTMLAttributes<HTMLLIElement> {
|
|
|
38
38
|
* numbered ledger wants; a glyph where the step has an identity of its own.
|
|
39
39
|
*/
|
|
40
40
|
marker?: ReactNode;
|
|
41
|
-
/**
|
|
42
|
-
|
|
41
|
+
/**
|
|
42
|
+
* Overrides the hidden label, for a step whose name is not its number.
|
|
43
|
+
* `false` draws no hidden label at all, for an item whose own content
|
|
44
|
+
* already says what it is: a hidden "Version 12" in front of a visible
|
|
45
|
+
* "Version 12" is read twice.
|
|
46
|
+
*/
|
|
47
|
+
label?: string | false | undefined;
|
|
43
48
|
}
|
|
44
49
|
/**
|
|
45
50
|
* One step.
|
package/dist/Timeline/index.js
CHANGED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
import { type Principal } from '../Principal/index.js';
|
|
3
|
+
import { type TimeValue } from '../RelativeTime/index.js';
|
|
4
|
+
/**
|
|
5
|
+
* What made a version.
|
|
6
|
+
*
|
|
7
|
+
* A schema or a capability change has a row of its own, because it changes
|
|
8
|
+
* what the page CAN DO rather than what it shows. A restore is a publish of an
|
|
9
|
+
* old version as a new one, never a rewrite of history, so it names the
|
|
10
|
+
* version it brought back.
|
|
11
|
+
*/
|
|
12
|
+
export type VersionKind = 'publish' | 'restore' | 'schema' | 'capabilities';
|
|
13
|
+
export interface VersionItem {
|
|
14
|
+
version: number;
|
|
15
|
+
kind?: VersionKind | undefined;
|
|
16
|
+
/** A name somebody gave this version ("Review draft"). */
|
|
17
|
+
label?: string | undefined;
|
|
18
|
+
/** What changed, in the author's words or the engine's ("Added totals row"). */
|
|
19
|
+
summary?: string | undefined;
|
|
20
|
+
author: Principal;
|
|
21
|
+
at: TimeValue;
|
|
22
|
+
/** Where it came from: a task and a turn, as a link or as words. */
|
|
23
|
+
source?: ReactNode;
|
|
24
|
+
/** For a restore: the version it brought back. */
|
|
25
|
+
restoredFrom?: number | undefined;
|
|
26
|
+
}
|
|
27
|
+
export interface VersionTimelineLabels {
|
|
28
|
+
list: string;
|
|
29
|
+
version: (version: number) => string;
|
|
30
|
+
latest: string;
|
|
31
|
+
publish: string;
|
|
32
|
+
restore: (from: number | undefined) => string;
|
|
33
|
+
schema: string;
|
|
34
|
+
capabilities: string;
|
|
35
|
+
compare: string;
|
|
36
|
+
/** The compare control's accessible name; it is a toggle, pressed while this version is compared. */
|
|
37
|
+
compareWith: (version: number) => string;
|
|
38
|
+
restoreAction: string;
|
|
39
|
+
restoreVersion: (version: number) => string;
|
|
40
|
+
labelAction: string;
|
|
41
|
+
labelVersion: (version: number) => string;
|
|
42
|
+
/** The line for versions the engine no longer keeps, given the oldest it does. */
|
|
43
|
+
retention: (oldestKept: number) => string;
|
|
44
|
+
}
|
|
45
|
+
export interface VersionTimelineProps extends Omit<HTMLAttributes<HTMLElement>, 'onSelect'> {
|
|
46
|
+
/** Newest first. */
|
|
47
|
+
versions: readonly VersionItem[];
|
|
48
|
+
/** The newest version. The highest one listed when left out. */
|
|
49
|
+
latest?: number | undefined;
|
|
50
|
+
/** The version on show. */
|
|
51
|
+
selected: number;
|
|
52
|
+
/** The version the one on show is compared with, if any. */
|
|
53
|
+
against?: number | undefined;
|
|
54
|
+
onSelect: (version: number) => void;
|
|
55
|
+
/** Compares the version on show with this one; `null` stops comparing. Without it there is no compare control. */
|
|
56
|
+
onCompare?: ((version: number | null) => void) | undefined;
|
|
57
|
+
/** Publishes this version again as a new one. Without it there is no restore control. */
|
|
58
|
+
onRestore?: ((version: number) => void) | undefined;
|
|
59
|
+
/** Names this version. Without it there is no name control. */
|
|
60
|
+
onLabel?: ((version: number) => void) | undefined;
|
|
61
|
+
/** The oldest version the engine still keeps; anything below it is said to be past retention. */
|
|
62
|
+
oldestKept?: number | undefined;
|
|
63
|
+
/** Overrides the shared clock, for a story or a suite. */
|
|
64
|
+
now?: number | undefined;
|
|
65
|
+
labels?: Partial<VersionTimelineLabels> | undefined;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* An artifact's versions, newest first, with the one on show and the one it is
|
|
69
|
+
* compared with marked.
|
|
70
|
+
*
|
|
71
|
+
* SELECTING IS NOT RESTORING. Choosing a row shows that version; Restore is a
|
|
72
|
+
* separate control, and it publishes the old version as a new one, so nothing
|
|
73
|
+
* a reader does here rewrites history. The newest version offers no Restore,
|
|
74
|
+
* because it is already what everybody sees.
|
|
75
|
+
*/
|
|
76
|
+
export declare function VersionTimeline({ versions, latest, selected, against, onSelect, onCompare, onRestore, onLabel, oldestKept, now, labels, className, ...rest }: VersionTimelineProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { VersionTimeline } from '../chunk-WXAULPBH.js';
|
|
2
|
+
import '../chunk-AUQPBL4O.js';
|
|
3
|
+
import '../chunk-OG6CL3EB.js';
|
|
4
|
+
import '../chunk-4KP4RC3O.js';
|
|
5
|
+
import '../chunk-3CZ7XAVY.js';
|
|
6
|
+
import '../chunk-EUCC37WY.js';
|
|
7
|
+
import '../chunk-UAN5NE7M.js';
|
|
8
|
+
import '../chunk-5OM447RW.js';
|
|
9
|
+
import '../chunk-BZFWDIV6.js';
|
|
10
|
+
import '../chunk-ODEQTPFM.js';
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* A version list beside the version on show. The row's main line is the
|
|
3
|
+
* button that shows it; the controls sit under the facts, so a reader scanning
|
|
4
|
+
* the list reads numbers and names rather than a column of buttons.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
.crewlet-version-timeline {
|
|
8
|
+
display: flex;
|
|
9
|
+
flex-direction: column;
|
|
10
|
+
gap: var(--spacing-2);
|
|
11
|
+
min-width: 0;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.crewlet-version-timeline__select {
|
|
15
|
+
display: flex;
|
|
16
|
+
flex-direction: column;
|
|
17
|
+
align-items: flex-start;
|
|
18
|
+
gap: var(--spacing-1);
|
|
19
|
+
width: 100%;
|
|
20
|
+
margin: 0;
|
|
21
|
+
padding: var(--spacing-1) var(--spacing-2);
|
|
22
|
+
border: 0;
|
|
23
|
+
border-radius: var(--radius-sm);
|
|
24
|
+
background: transparent;
|
|
25
|
+
color: var(--color-text-primary);
|
|
26
|
+
font: inherit;
|
|
27
|
+
text-align: start;
|
|
28
|
+
cursor: pointer;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.crewlet-version-timeline__select:hover {
|
|
32
|
+
background: var(--color-surface-hover);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/* The version on show. The accent means "where the reader is", which is
|
|
36
|
+
exactly what this row is. */
|
|
37
|
+
.crewlet-version-timeline__select[aria-current='true'] {
|
|
38
|
+
background: var(--color-brand-accent-soft);
|
|
39
|
+
box-shadow: inset 2px 0 0 var(--color-brand-accent);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.crewlet-version-timeline__head {
|
|
43
|
+
display: flex;
|
|
44
|
+
flex-wrap: wrap;
|
|
45
|
+
align-items: baseline;
|
|
46
|
+
gap: var(--spacing-2);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.crewlet-version-timeline__number {
|
|
50
|
+
font-weight: var(--font-weight-semibold);
|
|
51
|
+
font-variant-numeric: tabular-nums;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.crewlet-version-timeline__latest,
|
|
55
|
+
.crewlet-version-timeline__label {
|
|
56
|
+
padding: 0 var(--spacing-1);
|
|
57
|
+
border-radius: var(--radius-xs);
|
|
58
|
+
font-size: var(--font-size-xs);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.crewlet-version-timeline__latest {
|
|
62
|
+
background: var(--color-surface-inset);
|
|
63
|
+
color: var(--color-text-secondary);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.crewlet-version-timeline__label {
|
|
67
|
+
border: 1px solid var(--color-border-default);
|
|
68
|
+
color: var(--color-text-primary);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.crewlet-version-timeline__summary {
|
|
72
|
+
color: var(--color-text-secondary);
|
|
73
|
+
overflow-wrap: anywhere;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.crewlet-version-timeline__meta,
|
|
77
|
+
.crewlet-version-timeline__source {
|
|
78
|
+
display: flex;
|
|
79
|
+
flex-wrap: wrap;
|
|
80
|
+
align-items: center;
|
|
81
|
+
gap: var(--spacing-1);
|
|
82
|
+
padding-inline: var(--spacing-2);
|
|
83
|
+
color: var(--color-text-tertiary);
|
|
84
|
+
font-size: var(--font-size-xs);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.crewlet-version-timeline__actions {
|
|
88
|
+
display: flex;
|
|
89
|
+
flex-wrap: wrap;
|
|
90
|
+
gap: var(--spacing-1);
|
|
91
|
+
padding-inline: var(--spacing-1);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/* The version compared against carries the same edge in the strong neutral:
|
|
95
|
+
it is the other side of the comparison, not where the reader is, so it does
|
|
96
|
+
not take the accent. */
|
|
97
|
+
.is-compared > .crewlet-timeline__body > .crewlet-version-timeline__select {
|
|
98
|
+
box-shadow: inset 2px 0 0 var(--color-border-strong);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.crewlet-version-timeline__gap {
|
|
102
|
+
margin: 0;
|
|
103
|
+
padding: var(--spacing-2) var(--spacing-3);
|
|
104
|
+
border: 1px dashed var(--color-border-default);
|
|
105
|
+
border-radius: var(--radius-md);
|
|
106
|
+
color: var(--color-text-tertiary);
|
|
107
|
+
font-size: var(--font-size-xs);
|
|
108
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useThemePreference, useDensityPreference } from './chunk-
|
|
1
|
+
import { useThemePreference, useDensityPreference } from './chunk-Z24ZUSTX.js';
|
|
2
2
|
import { SegmentedControl } from './chunk-26PEPONN.js';
|
|
3
3
|
import { SunGlyph, MonitorGlyph, MoonGlyph } from '@crewlethq/icons/glyphs';
|
|
4
4
|
import { jsx } from 'react/jsx-runtime';
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { Select } from './chunk-FC4YTTFJ.js';
|
|
2
|
+
import { Modal } from './chunk-2TZATTIU.js';
|
|
3
|
+
import { CopyButton } from './chunk-W46LPU4R.js';
|
|
4
|
+
import { Callout } from './chunk-SVSCLHHI.js';
|
|
5
|
+
import { Button } from './chunk-OG6CL3EB.js';
|
|
6
|
+
import { useMediaMatch } from './chunk-IG75YMUN.js';
|
|
7
|
+
import { IconButton } from './chunk-4FQT6ZAY.js';
|
|
8
|
+
import { PrincipalAvatar } from './chunk-4KP4RC3O.js';
|
|
9
|
+
import { useHeadingLevel, headingTag } from './chunk-PQADV6P6.js';
|
|
10
|
+
import { cx } from './chunk-ODEQTPFM.js';
|
|
11
|
+
import './ShareDialog-YZ4F37MW.css';
|
|
12
|
+
import { useState, useId } from 'react';
|
|
13
|
+
import { breakpoint } from '@crewlethq/tokens';
|
|
14
|
+
import { XGlyph } from '@crewlethq/icons/glyphs';
|
|
15
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
16
|
+
|
|
17
|
+
// src/ShareDialog/roles.ts
|
|
18
|
+
var ARTIFACT_ROLES = ["viewer", "commenter", "contributor", "editor", "owner"];
|
|
19
|
+
var SHAREABLE_ROLES = ["viewer", "commenter", "contributor", "editor"];
|
|
20
|
+
function roleAtLeast(role, floor) {
|
|
21
|
+
return ARTIFACT_ROLES.indexOf(role) >= ARTIFACT_ROLES.indexOf(floor);
|
|
22
|
+
}
|
|
23
|
+
var AGENT_CAN = {
|
|
24
|
+
viewer: "read this artifact in its turns",
|
|
25
|
+
commenter: "read this artifact and comment on it in its turns",
|
|
26
|
+
contributor: "read this artifact in its turns and edit its data",
|
|
27
|
+
editor: "read this artifact, edit its data and publish versions in its turns",
|
|
28
|
+
owner: "read, edit, publish and share this artifact in its turns"
|
|
29
|
+
};
|
|
30
|
+
var LABELS = {
|
|
31
|
+
title: (artifact) => `Share "${artifact}"`,
|
|
32
|
+
addRole: "Role for people you add",
|
|
33
|
+
audience: "Who has access",
|
|
34
|
+
you: "(you)",
|
|
35
|
+
roles: { viewer: "Viewer", commenter: "Commenter", contributor: "Contributor", editor: "Editor", owner: "Owner" },
|
|
36
|
+
roleDescriptions: {
|
|
37
|
+
viewer: "Reads the artifact, its versions and its history",
|
|
38
|
+
commenter: "Also comments",
|
|
39
|
+
contributor: "Also edits its data",
|
|
40
|
+
editor: "Also publishes versions and changes the schema",
|
|
41
|
+
owner: "Also shares, trashes and transfers it"
|
|
42
|
+
},
|
|
43
|
+
roleFor: (name) => `Role for ${name}`,
|
|
44
|
+
remove: (name) => `Remove ${name}`,
|
|
45
|
+
saving: "Saving",
|
|
46
|
+
busy: "Wait for the change to finish.",
|
|
47
|
+
agentNote: (name, role) => `${name} can ${AGENT_CAN[role]}.`,
|
|
48
|
+
companyAccess: "Company access",
|
|
49
|
+
company: (company, access) => {
|
|
50
|
+
switch (access) {
|
|
51
|
+
case "none":
|
|
52
|
+
return "Only people with access above";
|
|
53
|
+
case "viewer":
|
|
54
|
+
return `Everyone in ${company} can view`;
|
|
55
|
+
case "commenter":
|
|
56
|
+
return `Everyone in ${company} can comment`;
|
|
57
|
+
case "contributor":
|
|
58
|
+
return `Everyone in ${company} can edit its data`;
|
|
59
|
+
case "editor":
|
|
60
|
+
return `Everyone in ${company} can edit`;
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
copyLink: "Copy link",
|
|
64
|
+
linkCopied: "Link copied",
|
|
65
|
+
linkNote: "Only people with access can open the link.",
|
|
66
|
+
done: "Done"
|
|
67
|
+
};
|
|
68
|
+
function ShareDialog({
|
|
69
|
+
open,
|
|
70
|
+
onClose,
|
|
71
|
+
title,
|
|
72
|
+
picker,
|
|
73
|
+
defaultAddRole = "viewer",
|
|
74
|
+
grantableRoles = SHAREABLE_ROLES,
|
|
75
|
+
audience,
|
|
76
|
+
onRoleChange,
|
|
77
|
+
onRemove,
|
|
78
|
+
companyName,
|
|
79
|
+
companyAccess,
|
|
80
|
+
onCompanyAccessChange,
|
|
81
|
+
companyPending = false,
|
|
82
|
+
companyRefusal,
|
|
83
|
+
link,
|
|
84
|
+
readOnly,
|
|
85
|
+
note,
|
|
86
|
+
labels
|
|
87
|
+
}) {
|
|
88
|
+
const text = {
|
|
89
|
+
...LABELS,
|
|
90
|
+
...labels,
|
|
91
|
+
roles: { ...LABELS.roles, ...labels?.roles },
|
|
92
|
+
roleDescriptions: { ...LABELS.roleDescriptions, ...labels?.roleDescriptions }
|
|
93
|
+
};
|
|
94
|
+
const phone = useMediaMatch(`(width < ${breakpoint.phone})`);
|
|
95
|
+
const [addRole, setAddRole] = useState(defaultAddRole);
|
|
96
|
+
const level = useHeadingLevel();
|
|
97
|
+
const Heading = headingTag(level);
|
|
98
|
+
const audienceId = useId();
|
|
99
|
+
const companyId = useId();
|
|
100
|
+
const roleOptions = grantableRoles.map((role) => ({
|
|
101
|
+
value: role,
|
|
102
|
+
label: text.roles[role],
|
|
103
|
+
description: text.roleDescriptions[role]
|
|
104
|
+
}));
|
|
105
|
+
const companyOptions = ["none", ...grantableRoles].map((access) => ({
|
|
106
|
+
value: access,
|
|
107
|
+
label: text.company(companyName, access)
|
|
108
|
+
}));
|
|
109
|
+
return /* @__PURE__ */ jsxs(
|
|
110
|
+
Modal,
|
|
111
|
+
{
|
|
112
|
+
open,
|
|
113
|
+
onClose,
|
|
114
|
+
title: text.title(title),
|
|
115
|
+
placement: phone ? "bottom" : "top",
|
|
116
|
+
size: "md",
|
|
117
|
+
stackBody: true,
|
|
118
|
+
footerStart: link ? /* @__PURE__ */ jsxs("span", { className: "crewlet-share-dialog__link", children: [
|
|
119
|
+
/* @__PURE__ */ jsx(CopyButton, { text: link, label: text.copyLink, copiedLabel: text.linkCopied, copiedMessage: text.linkCopied, size: "small", variant: "outline" }),
|
|
120
|
+
/* @__PURE__ */ jsx("span", { className: "crewlet-share-dialog__link-note", children: text.linkNote })
|
|
121
|
+
] }) : void 0,
|
|
122
|
+
footer: /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: onClose, children: text.done }),
|
|
123
|
+
children: [
|
|
124
|
+
note ? /* @__PURE__ */ jsx(Callout, { variant: "info", children: note }) : null,
|
|
125
|
+
readOnly ? /* @__PURE__ */ jsx(Callout, { variant: "neutral", children: readOnly.reason }) : null,
|
|
126
|
+
!readOnly && picker ? /* @__PURE__ */ jsxs("div", { className: "crewlet-share-dialog__add", children: [
|
|
127
|
+
picker({ role: addRole }),
|
|
128
|
+
/* @__PURE__ */ jsx(
|
|
129
|
+
Select,
|
|
130
|
+
{
|
|
131
|
+
value: addRole,
|
|
132
|
+
options: roleOptions,
|
|
133
|
+
onChange: (value) => setAddRole(value),
|
|
134
|
+
ariaLabel: text.addRole,
|
|
135
|
+
size: "md",
|
|
136
|
+
width: "auto",
|
|
137
|
+
align: "right"
|
|
138
|
+
}
|
|
139
|
+
)
|
|
140
|
+
] }) : null,
|
|
141
|
+
/* @__PURE__ */ jsxs("section", { className: "crewlet-share-dialog__section", "aria-labelledby": audienceId, children: [
|
|
142
|
+
/* @__PURE__ */ jsx(Heading, { id: audienceId, className: "crewlet-share-dialog__heading", children: text.audience }),
|
|
143
|
+
/* @__PURE__ */ jsx("ul", { className: "crewlet-share-dialog__audience", children: audience.map((row) => {
|
|
144
|
+
const direct = row.via === void 0 && row.role !== "owner";
|
|
145
|
+
const editable = !readOnly && onRoleChange !== void 0 && (row.editable ?? direct);
|
|
146
|
+
const removable = !readOnly && onRemove !== void 0 && (row.removable ?? (row.editable ?? direct));
|
|
147
|
+
const rowNote = row.note ?? (row.principal.kind === "agent" ? text.agentNote(row.principal.name, row.role) : void 0);
|
|
148
|
+
const detail = row.via ?? row.principal.detail;
|
|
149
|
+
return /* @__PURE__ */ jsxs("li", { className: cx("crewlet-share-dialog__row", row.pending && "is-pending"), "aria-busy": row.pending || void 0, children: [
|
|
150
|
+
/* @__PURE__ */ jsx(PrincipalAvatar, { principal: row.principal, size: "md" }),
|
|
151
|
+
/* @__PURE__ */ jsxs("span", { className: "crewlet-share-dialog__who", children: [
|
|
152
|
+
/* @__PURE__ */ jsxs("span", { className: "crewlet-share-dialog__name", children: [
|
|
153
|
+
row.principal.name,
|
|
154
|
+
row.self ? /* @__PURE__ */ jsxs("span", { className: "crewlet-share-dialog__you", children: [
|
|
155
|
+
" ",
|
|
156
|
+
text.you
|
|
157
|
+
] }) : null
|
|
158
|
+
] }),
|
|
159
|
+
detail ? /* @__PURE__ */ jsx("span", { className: "crewlet-share-dialog__detail", children: detail }) : null
|
|
160
|
+
] }),
|
|
161
|
+
/* @__PURE__ */ jsxs("span", { className: "crewlet-share-dialog__controls", children: [
|
|
162
|
+
row.pending ? /* @__PURE__ */ jsx("span", { className: "crewlet-share-dialog__saving", children: text.saving }) : null,
|
|
163
|
+
editable && row.role !== "owner" ? /* @__PURE__ */ jsx(
|
|
164
|
+
Select,
|
|
165
|
+
{
|
|
166
|
+
value: row.role,
|
|
167
|
+
options: roleOptions,
|
|
168
|
+
onChange: (value) => onRoleChange(row, value),
|
|
169
|
+
ariaLabel: text.roleFor(row.principal.name),
|
|
170
|
+
disabled: row.pending ?? false,
|
|
171
|
+
size: "sm",
|
|
172
|
+
width: "auto",
|
|
173
|
+
align: "right"
|
|
174
|
+
}
|
|
175
|
+
) : /* @__PURE__ */ jsx("span", { className: "crewlet-share-dialog__role", children: text.roles[row.role] }),
|
|
176
|
+
removable ? /* @__PURE__ */ jsx(
|
|
177
|
+
IconButton,
|
|
178
|
+
{
|
|
179
|
+
label: text.remove(row.principal.name),
|
|
180
|
+
icon: /* @__PURE__ */ jsx(XGlyph, {}),
|
|
181
|
+
size: "sm",
|
|
182
|
+
variant: "ghost",
|
|
183
|
+
disabledReason: row.pending ? text.busy : void 0,
|
|
184
|
+
onClick: () => onRemove(row)
|
|
185
|
+
}
|
|
186
|
+
) : null
|
|
187
|
+
] }),
|
|
188
|
+
rowNote ? /* @__PURE__ */ jsx("span", { className: "crewlet-share-dialog__note", children: rowNote }) : null,
|
|
189
|
+
/* @__PURE__ */ jsx("span", { className: "crewlet-share-dialog__refusal", "aria-live": "polite", children: row.refusal ?? "" })
|
|
190
|
+
] }, row.id);
|
|
191
|
+
}) })
|
|
192
|
+
] }),
|
|
193
|
+
/* @__PURE__ */ jsxs("section", { className: "crewlet-share-dialog__section", "aria-labelledby": companyId, "aria-busy": companyPending || void 0, children: [
|
|
194
|
+
/* @__PURE__ */ jsx(Heading, { id: companyId, className: "crewlet-share-dialog__heading", children: text.companyAccess }),
|
|
195
|
+
readOnly || !onCompanyAccessChange ? /* @__PURE__ */ jsx("p", { className: "crewlet-share-dialog__company-text", children: text.company(companyName, companyAccess) }) : /* @__PURE__ */ jsxs("span", { className: "crewlet-share-dialog__company", children: [
|
|
196
|
+
/* @__PURE__ */ jsx(
|
|
197
|
+
Select,
|
|
198
|
+
{
|
|
199
|
+
value: companyAccess,
|
|
200
|
+
options: companyOptions,
|
|
201
|
+
onChange: (value) => onCompanyAccessChange(value),
|
|
202
|
+
ariaLabel: text.companyAccess,
|
|
203
|
+
disabled: companyPending,
|
|
204
|
+
size: "md"
|
|
205
|
+
}
|
|
206
|
+
),
|
|
207
|
+
companyPending ? /* @__PURE__ */ jsx("span", { className: "crewlet-share-dialog__saving", children: text.saving }) : null
|
|
208
|
+
] }),
|
|
209
|
+
/* @__PURE__ */ jsx("span", { className: "crewlet-share-dialog__refusal", "aria-live": "polite", children: companyRefusal ?? "" })
|
|
210
|
+
] })
|
|
211
|
+
]
|
|
212
|
+
}
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export { ARTIFACT_ROLES, SHAREABLE_ROLES, ShareDialog, roleAtLeast };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { presenceHueClass } from './chunk-I6POAB4V.js';
|
|
2
|
+
import { cx } from './chunk-ODEQTPFM.js';
|
|
3
|
+
import './CursorFlag-AJQJBUGY.css';
|
|
4
|
+
import { PencilGlyph } from '@crewlethq/icons/glyphs';
|
|
5
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
6
|
+
|
|
7
|
+
function CursorFlag({ name, hue, kind = "human", editing = false, placement = "top-end", className, ...rest }) {
|
|
8
|
+
const text = typeof name === "string" ? name : name.join(", ");
|
|
9
|
+
return /* @__PURE__ */ jsxs(
|
|
10
|
+
"span",
|
|
11
|
+
{
|
|
12
|
+
...rest,
|
|
13
|
+
"aria-hidden": "true",
|
|
14
|
+
className: cx(
|
|
15
|
+
"crewlet-cursor-flag",
|
|
16
|
+
presenceHueClass(hue),
|
|
17
|
+
`crewlet-cursor-flag--${kind}`,
|
|
18
|
+
`crewlet-cursor-flag--${placement}`,
|
|
19
|
+
className
|
|
20
|
+
),
|
|
21
|
+
children: [
|
|
22
|
+
editing ? /* @__PURE__ */ jsx(PencilGlyph, { size: "xs", className: "crewlet-cursor-flag__glyph" }) : null,
|
|
23
|
+
/* @__PURE__ */ jsx("span", { className: "crewlet-cursor-flag__name", children: text })
|
|
24
|
+
]
|
|
25
|
+
}
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export { CursorFlag };
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { Combobox } from './chunk-ZFH7H7GS.js';
|
|
2
|
+
import { PRINCIPAL_KINDS, PrincipalAvatar } from './chunk-4KP4RC3O.js';
|
|
3
|
+
import { cx } from './chunk-ODEQTPFM.js';
|
|
4
|
+
import './PrincipalPicker-7NNZTGUP.css';
|
|
5
|
+
import { useState, useId, useMemo } from 'react';
|
|
6
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
7
|
+
|
|
8
|
+
var LABELS = {
|
|
9
|
+
groups: { person: "People", agent: "Agents", team: "Teams" },
|
|
10
|
+
empty: "Nobody matches. Try a name, a handle or a team.",
|
|
11
|
+
loading: "Searching"
|
|
12
|
+
};
|
|
13
|
+
var key = (principal) => `${principal.kind}:${principal.id}`;
|
|
14
|
+
function PrincipalPicker({
|
|
15
|
+
query,
|
|
16
|
+
onQueryChange,
|
|
17
|
+
options,
|
|
18
|
+
onPick,
|
|
19
|
+
label,
|
|
20
|
+
placeholder,
|
|
21
|
+
loading = false,
|
|
22
|
+
disabled = false,
|
|
23
|
+
className,
|
|
24
|
+
labels
|
|
25
|
+
}) {
|
|
26
|
+
const text = { ...LABELS, ...labels, groups: { ...LABELS.groups, ...labels?.groups } };
|
|
27
|
+
const [open, setOpen] = useState(false);
|
|
28
|
+
const groupId = useId();
|
|
29
|
+
const ordered = useMemo(
|
|
30
|
+
() => PRINCIPAL_KINDS.flatMap((kind) => options.filter((option) => option.kind === kind)),
|
|
31
|
+
[options]
|
|
32
|
+
);
|
|
33
|
+
const offered = useMemo(
|
|
34
|
+
() => ordered.map((option) => ({ value: key(option), label: option.name, disabled: option.disabled ?? false })),
|
|
35
|
+
[ordered]
|
|
36
|
+
);
|
|
37
|
+
return /* @__PURE__ */ jsx(
|
|
38
|
+
Combobox,
|
|
39
|
+
{
|
|
40
|
+
value: query,
|
|
41
|
+
onValueChange: (next) => {
|
|
42
|
+
onQueryChange(next);
|
|
43
|
+
setOpen(true);
|
|
44
|
+
},
|
|
45
|
+
options: offered,
|
|
46
|
+
open: open && !disabled,
|
|
47
|
+
onOpenChange: setOpen,
|
|
48
|
+
label,
|
|
49
|
+
"aria-label": label,
|
|
50
|
+
placeholder,
|
|
51
|
+
disabled,
|
|
52
|
+
containerClassName: cx("crewlet-principal-picker", className),
|
|
53
|
+
onFocus: () => setOpen(true),
|
|
54
|
+
onBlur: () => setOpen(false),
|
|
55
|
+
emptyMessage: loading ? text.loading : query.trim() ? text.empty : void 0,
|
|
56
|
+
onCommit: (_option, index) => {
|
|
57
|
+
const picked = ordered[index];
|
|
58
|
+
if (!picked || picked.disabled) return;
|
|
59
|
+
onPick(picked);
|
|
60
|
+
onQueryChange("");
|
|
61
|
+
},
|
|
62
|
+
renderList: ordered.length > 0 ? ({ active, optionId, optionHandlers }) => PRINCIPAL_KINDS.map((kind) => {
|
|
63
|
+
const rows = ordered.map((option, index) => ({ option, index })).filter(({ option }) => option.kind === kind);
|
|
64
|
+
if (rows.length === 0) return null;
|
|
65
|
+
const headingId = `${groupId}-${kind}`;
|
|
66
|
+
return /* @__PURE__ */ jsxs("div", { role: "group", "aria-labelledby": headingId, className: "crewlet-principal-picker__group", children: [
|
|
67
|
+
/* @__PURE__ */ jsx("div", { id: headingId, role: "presentation", className: "crewlet-principal-picker__heading", children: text.groups[kind] }),
|
|
68
|
+
rows.map(({ option, index }) => /* @__PURE__ */ jsxs(
|
|
69
|
+
"div",
|
|
70
|
+
{
|
|
71
|
+
id: optionId(index),
|
|
72
|
+
role: "option",
|
|
73
|
+
"aria-selected": index === active,
|
|
74
|
+
"aria-disabled": option.disabled || void 0,
|
|
75
|
+
className: cx(
|
|
76
|
+
"crewlet-listbox__option",
|
|
77
|
+
"crewlet-principal-picker__option",
|
|
78
|
+
index === active && "is-highlight",
|
|
79
|
+
option.disabled && "is-disabled"
|
|
80
|
+
),
|
|
81
|
+
...option.disabled ? {} : optionHandlers(index),
|
|
82
|
+
children: [
|
|
83
|
+
/* @__PURE__ */ jsx(PrincipalAvatar, { principal: option, size: "sm" }),
|
|
84
|
+
/* @__PURE__ */ jsxs("span", { className: "crewlet-principal-picker__text", children: [
|
|
85
|
+
/* @__PURE__ */ jsx("span", { className: "crewlet-principal-picker__name", children: option.name }),
|
|
86
|
+
option.disabledReason ?? option.detail ? /* @__PURE__ */ jsx("span", { className: "crewlet-listbox__hint", children: option.disabledReason ?? option.detail }) : null
|
|
87
|
+
] })
|
|
88
|
+
]
|
|
89
|
+
},
|
|
90
|
+
key(option)
|
|
91
|
+
))
|
|
92
|
+
] }, kind);
|
|
93
|
+
}) : void 0
|
|
94
|
+
}
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export { PrincipalPicker };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Avatar } from './chunk-5OM447RW.js';
|
|
2
|
+
import { UsersGlyph } from '@crewlethq/icons/glyphs';
|
|
3
|
+
import { jsx } from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
var PRINCIPAL_KINDS = ["person", "agent", "team"];
|
|
6
|
+
function PrincipalAvatar({ principal, size = "sm", decorative = true }) {
|
|
7
|
+
const { kind, name, character, hue, src } = principal;
|
|
8
|
+
if (kind === "team") {
|
|
9
|
+
return /* @__PURE__ */ jsx(Avatar, { name, size, kind: "agent", icon: /* @__PURE__ */ jsx(UsersGlyph, {}), decorative });
|
|
10
|
+
}
|
|
11
|
+
return /* @__PURE__ */ jsx(
|
|
12
|
+
Avatar,
|
|
13
|
+
{
|
|
14
|
+
name,
|
|
15
|
+
size,
|
|
16
|
+
kind: kind === "person" ? "human" : "agent",
|
|
17
|
+
character: kind === "agent" ? character : void 0,
|
|
18
|
+
hue: kind === "agent" ? hue : void 0,
|
|
19
|
+
src,
|
|
20
|
+
decorative
|
|
21
|
+
}
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export { PRINCIPAL_KINDS, PrincipalAvatar };
|