@crewlethq/ui 0.61.0 → 0.63.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 +8 -0
- package/dist/AgentHandoffPanel/index.js +1 -1
- package/dist/AppShell/index.js +1 -1
- package/dist/ArtifactBar/index.js +5 -5
- package/dist/ArtifactCard/index.js +3 -3
- package/dist/AttachmentChip/AttachmentChip.d.ts +37 -0
- package/dist/AttachmentChip/index.d.ts +3 -0
- package/dist/AttachmentChip/index.js +6 -0
- package/dist/AttachmentChip-XF4KPQ3G.css +16 -0
- package/dist/AvatarPicker/index.js +6 -6
- package/dist/Canvas/index.js +1 -1
- package/dist/CanvasBoard/index.js +1 -1
- package/dist/CanvasToolbar/index.js +1 -1
- package/dist/Combobox/index.js +1 -1
- package/dist/CommandPalette/index.js +1 -1
- package/dist/CommentThread/index.js +1 -1
- package/dist/ContrastBadge/index.js +2 -2
- package/dist/ContrastHelp/index.js +3 -3
- package/dist/DataTable/index.js +1 -1
- package/dist/DataView/index.js +1 -1
- package/dist/DateTimePicker/index.js +1 -1
- package/dist/DeepWorkCard/DeepWorkCard.d.ts +85 -0
- package/dist/DeepWorkCard/index.d.ts +3 -0
- package/dist/DeepWorkCard/index.js +17 -0
- package/dist/DeepWorkCard-DGHRIQDM.css +80 -0
- package/dist/DocTabsEditor/index.js +1 -1
- package/dist/DownloadButton/DownloadButton.d.ts +7 -1
- package/dist/DownloadButton/index.js +1 -1
- package/dist/FileList/FileList.d.ts +42 -0
- package/dist/FileList/index.d.ts +3 -0
- package/dist/FileList/index.js +3 -0
- package/dist/FileList-TGDNV2QS.css +89 -0
- package/dist/FollowBanner/index.js +1 -1
- package/dist/HuePicker/index.js +5 -5
- package/dist/InlineEditor/index.js +1 -1
- package/dist/LinkInterstitial/index.js +1 -1
- package/dist/ListInput/index.js +1 -1
- package/dist/LogoSlot/index.js +3 -3
- package/dist/MarkdownEditor/index.js +5 -5
- package/dist/Menu/index.js +1 -1
- package/dist/MergeConflicts/index.js +5 -5
- package/dist/Modal/index.js +1 -1
- package/dist/OpenInAppCard/index.js +2 -2
- package/dist/PeekRail/index.js +1 -1
- package/dist/PresenterView/index.js +1 -1
- package/dist/PrincipalPicker/index.js +2 -2
- package/dist/ResultTableCard/index.js +3 -3
- package/dist/RichEditor/index.js +1 -1
- package/dist/SegmentedControl/index.js +4 -4
- package/dist/SelectionBar/index.js +1 -1
- package/dist/SetupWizard/index.js +2 -2
- package/dist/ShareDialog/index.js +1 -1
- package/dist/SheetColumnEditor/index.js +6 -6
- package/dist/SheetGrid/index.js +3 -3
- package/dist/SlideCompare/index.js +1 -1
- package/dist/SlideFilmstrip/index.js +1 -1
- package/dist/Switcher/index.js +1 -1
- package/dist/Tabs/index.js +3 -3
- package/dist/ThemeGallery/index.js +1 -1
- package/dist/ThemeSwitcher/index.js +5 -5
- package/dist/TimeRangePicker/index.js +5 -5
- package/dist/TimeWindowPicker/index.js +1 -1
- package/dist/TreeCanvas/index.js +1 -1
- package/dist/ValueField/ValueField.d.ts +117 -0
- package/dist/ValueField/index.d.ts +10 -0
- package/dist/ValueField/index.js +15 -0
- package/dist/ValueField/references.d.ts +66 -0
- package/dist/ValueField-EIBD6RYS.css +13 -0
- package/dist/VersionCompare/index.js +5 -5
- package/dist/{chunk-53NTMTRM.js → chunk-6IGIYOTV.js} +1 -1
- package/dist/chunk-CZXF6EFK.js +52 -0
- package/dist/{chunk-5ZGJ22CO.js → chunk-DHIO6Q75.js} +1 -1
- package/dist/{chunk-3BQWARG2.js → chunk-F7VBYCW2.js} +1 -1
- package/dist/{chunk-5G76O23M.js → chunk-IJIC4COR.js} +1 -1
- package/dist/{chunk-RPHQNXE5.js → chunk-IOZFPFQS.js} +1 -1
- package/dist/{chunk-NL72YZWF.js → chunk-ISHLFPNN.js} +1 -1
- package/dist/{chunk-5KW63GZ3.js → chunk-JAOJLEYB.js} +1 -1
- package/dist/{chunk-MOW65OIJ.js → chunk-JPVORBWC.js} +1 -1
- package/dist/chunk-KYTOEWJD.js +56 -0
- package/dist/chunk-LA4PX7Z6.js +118 -0
- package/dist/{chunk-LG6TUGET.js → chunk-NSCYGUDG.js} +2 -0
- package/dist/chunk-OD3Z6QKN.js +237 -0
- package/dist/{chunk-OM6CPZB7.js → chunk-OIMWGV2N.js} +1 -1
- package/dist/{chunk-5PMFRAGL.js → chunk-OU4FLGOZ.js} +1 -1
- package/dist/{chunk-5MN2HISF.js → chunk-PHQPQZUX.js} +1 -1
- package/dist/{chunk-VC2M2E7N.js → chunk-PK2P2QH6.js} +4 -3
- package/dist/{chunk-NRMXUNLR.js → chunk-QCVAVAF6.js} +1 -1
- package/dist/{chunk-LND6XSXN.js → chunk-S2VMOITT.js} +1 -1
- package/dist/{chunk-VRPDQSXZ.js → chunk-SELUJSTZ.js} +2 -2
- package/dist/{chunk-3633T7EJ.js → chunk-WSV3MBOE.js} +1 -1
- package/dist/generated/index.d.ts +4 -0
- package/dist/generated/index.js +88 -84
- package/dist/index.js +88 -84
- package/dist/styles.css +210 -0
- package/package.json +3 -3
- package/dist/{Editor-DM7X24B7.js → Editor-GHHWWXXL.js} +1 -1
- package/dist/{chunk-VN3DCUED.js → chunk-27JCHL64.js} +1 -1
- package/dist/{chunk-T4THNJ6E.js → chunk-5DCY2QUY.js} +1 -1
- package/dist/{chunk-WDRYUMN6.js → chunk-BSAQE7PO.js} +1 -1
- package/dist/{chunk-I43D5K6A.js → chunk-CT6I36FH.js} +1 -1
- package/dist/{chunk-MHFTG2LO.js → chunk-EBCH3MRX.js} +1 -1
- package/dist/{chunk-OXZKRUGM.js → chunk-TXQNWGUD.js} +0 -0
- package/dist/{chunk-WXSGCYZO.js → chunk-VVVB3OBW.js} +1 -1
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* What a value field holds, which decides its control and what it does to a
|
|
4
|
+
* value on its way through.
|
|
5
|
+
*
|
|
6
|
+
* - `text`: free text, spaces kept.
|
|
7
|
+
* - `multiline`: prose in a textarea, every space and newline kept, spell check on.
|
|
8
|
+
* - `secret`: a credential, masked unless the value is a whole reference.
|
|
9
|
+
* - `url`: an address, wearing an `https://` affix, whitespace dropped.
|
|
10
|
+
* - `id` and `email`: one token, whitespace dropped.
|
|
11
|
+
* - `choice` and `handle`: one of `choices`, picked from a listbox.
|
|
12
|
+
*/
|
|
13
|
+
export type ValueFieldKind = 'text' | 'multiline' | 'secret' | 'url' | 'id' | 'choice' | 'handle' | 'email';
|
|
14
|
+
/** One option of a `choice` or `handle` field. */
|
|
15
|
+
export interface ValueFieldChoice {
|
|
16
|
+
value: string;
|
|
17
|
+
label: string;
|
|
18
|
+
/** A sentence saying what picking this one does: drawn under the option, and on the help line once chosen. */
|
|
19
|
+
hint?: string | undefined;
|
|
20
|
+
}
|
|
21
|
+
/** The words a value field draws itself. */
|
|
22
|
+
export interface ValueFieldLabels {
|
|
23
|
+
/** Names the completion list. "Secrets" by default. */
|
|
24
|
+
references: string;
|
|
25
|
+
/** The choice placeholder while nothing is chosen. "Choose one" by default. */
|
|
26
|
+
choose: string;
|
|
27
|
+
}
|
|
28
|
+
export interface ValueFieldProps {
|
|
29
|
+
label: string;
|
|
30
|
+
/** A mark drawn before the label, such as a third party's own logo. */
|
|
31
|
+
mark?: ReactNode;
|
|
32
|
+
kind?: ValueFieldKind | undefined;
|
|
33
|
+
value: string;
|
|
34
|
+
onChange: (value: string) => void;
|
|
35
|
+
/** Where the value comes from, or what shape it takes. */
|
|
36
|
+
help?: ReactNode;
|
|
37
|
+
/** Why the last value was refused. */
|
|
38
|
+
error?: ReactNode;
|
|
39
|
+
placeholder?: string | undefined;
|
|
40
|
+
/** What a `choice` or `handle` field offers; ignored by every other kind. */
|
|
41
|
+
choices?: readonly ValueFieldChoice[] | undefined;
|
|
42
|
+
disabled?: boolean | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* Whether an answer is required. REQUIRED IS THE UNMARKED DEFAULT: `false`
|
|
45
|
+
* says "(optional)" beside the label, `true` sets `aria-required` and draws
|
|
46
|
+
* nothing unless `markRequired` says the requiredness is news. Most fields
|
|
47
|
+
* on a form are required, and marking them all is noise that teaches a
|
|
48
|
+
* reader to skip the note.
|
|
49
|
+
*/
|
|
50
|
+
required?: boolean | undefined;
|
|
51
|
+
/**
|
|
52
|
+
* Says "(required)" beside the label, for a field whose requiredness is
|
|
53
|
+
* NEWS: one that appeared because of an answer above it. Read only with
|
|
54
|
+
* `required`.
|
|
55
|
+
*/
|
|
56
|
+
markRequired?: boolean | undefined;
|
|
57
|
+
autoFocus?: boolean | undefined;
|
|
58
|
+
/**
|
|
59
|
+
* The stored entry names offered when somebody types `$`, completed into a
|
|
60
|
+
* whole `${NAME}`. NAMES ONLY: a value never reaches the field, so a list
|
|
61
|
+
* that could not be assembled leaves the field exactly as it was.
|
|
62
|
+
*/
|
|
63
|
+
references?: readonly string[] | undefined;
|
|
64
|
+
/**
|
|
65
|
+
* Called as the completion list is about to open, so the caller can make
|
|
66
|
+
* sure the names are current. On the way in only, never per keystroke.
|
|
67
|
+
*/
|
|
68
|
+
onReferencesNeeded?: (() => void) | undefined;
|
|
69
|
+
/**
|
|
70
|
+
* Whether a value is exactly one reference, which keeps a `secret` field
|
|
71
|
+
* readable and lets a `url` field's affix step aside. [isWholeReference]
|
|
72
|
+
* by default; a product with its own reference grammar passes it here.
|
|
73
|
+
*/
|
|
74
|
+
isReference?: ((value: string) => boolean) | undefined;
|
|
75
|
+
/** How many lines a `multiline` field shows before it scrolls. Three by default. */
|
|
76
|
+
rows?: number | undefined;
|
|
77
|
+
/** Show the help line only while the field has focus. See [FormField]. */
|
|
78
|
+
helperOnFocus?: boolean | undefined;
|
|
79
|
+
labels?: Partial<ValueFieldLabels> | undefined;
|
|
80
|
+
className?: string | undefined;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* A labelled value: [FormField] with the control a kind of value needs, and
|
|
84
|
+
* the rules every form holding such values otherwise rewrites.
|
|
85
|
+
*
|
|
86
|
+
* A SECRET FIELD IS A PASSWORD FIELD, and that is not decoration: `type` is
|
|
87
|
+
* what keeps the value out of an autofill store, out of a screenshot and out
|
|
88
|
+
* of the accessibility tree as text.
|
|
89
|
+
*
|
|
90
|
+
* A REFERENCE IS NOT A CREDENTIAL, so it is not masked. A secret whose value
|
|
91
|
+
* is wholly a `${NAME}` holds the NAME of a stored entry, and the reader has
|
|
92
|
+
* to be able to see which entry it points at. Typing over it masks again the
|
|
93
|
+
* moment it stops being a whole reference, so a credential is never on screen.
|
|
94
|
+
*
|
|
95
|
+
* TYPING `$` OFFERS THE STORED ENTRIES, from `references`, ranked closest
|
|
96
|
+
* first and written in as a whole `${NAME}` with the caret after it. Tab and
|
|
97
|
+
* Enter take the highlighted name, Escape closes the list and keeps what was
|
|
98
|
+
* typed, and a press outside closes only the list.
|
|
99
|
+
*
|
|
100
|
+
* A URL FIELD WEARS ITS SCHEME. An `https://` affix sits inside the box, is
|
|
101
|
+
* read once as part of the value, and is written into it. It steps aside for
|
|
102
|
+
* a value that carries `http://` and for one starting with `$` (a reference
|
|
103
|
+
* carries its own scheme once it resolves), and a pasted `https://` is not
|
|
104
|
+
* doubled onto it.
|
|
105
|
+
*
|
|
106
|
+
* A SINGLE TOKEN TAKES NO WHITESPACE. A `url`, `id` or `email` drops it as it
|
|
107
|
+
* is typed or pasted: a space around one is invisible in the box and fatal
|
|
108
|
+
* wherever it is used. No field asserts `type="email"`, because the browser
|
|
109
|
+
* would refuse a reference for having no "@" in it; `inputMode` still offers
|
|
110
|
+
* the right keyboard.
|
|
111
|
+
*
|
|
112
|
+
* A CHOICE IS THE LISTBOX, which can draw each choice's hint under it. The
|
|
113
|
+
* chosen one's hint also joins the help line, and a stored answer the list
|
|
114
|
+
* no longer offers keeps a row of its own rather than vanishing into a
|
|
115
|
+
* different selection.
|
|
116
|
+
*/
|
|
117
|
+
export declare function ValueField({ label, mark, kind, value, onChange, help, error, placeholder, choices, disabled, required, markRequired, autoFocus, references, onReferencesNeeded, isReference, rows, helperOnFocus, labels, className, }: ValueFieldProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import '../Input/Input.css';
|
|
2
|
+
import '../VisuallyHidden/VisuallyHidden.css';
|
|
3
|
+
import '../HitArea/HitArea.css';
|
|
4
|
+
import '../Combobox/Combobox.css';
|
|
5
|
+
import '../Select/Select.css';
|
|
6
|
+
import './ValueField.css';
|
|
7
|
+
export { ValueField } from './ValueField.js';
|
|
8
|
+
export type { ValueFieldChoice, ValueFieldKind, ValueFieldLabels, ValueFieldProps } from './ValueField.js';
|
|
9
|
+
export { REFERENCE_NAME_PATTERN, completeReference, isWholeReference, rankReferences, referenceAt, urlSchemeOf, } from './references.js';
|
|
10
|
+
export type { ReferenceQuery } from './references.js';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export { REFERENCE_NAME_PATTERN, ValueField, completeReference, isWholeReference, rankReferences, referenceAt, urlSchemeOf } from '../chunk-OD3Z6QKN.js';
|
|
2
|
+
import '../chunk-XQZ6EWOE.js';
|
|
3
|
+
import '../chunk-PK2P2QH6.js';
|
|
4
|
+
import '../chunk-7KHM2FZH.js';
|
|
5
|
+
import '../chunk-TLIJG4TP.js';
|
|
6
|
+
import '../chunk-PGCLHYVP.js';
|
|
7
|
+
import '../chunk-PQADV6P6.js';
|
|
8
|
+
import '../chunk-2G355KDJ.js';
|
|
9
|
+
import '../chunk-OMV5W53A.js';
|
|
10
|
+
import '../chunk-2YTOOH3A.js';
|
|
11
|
+
import '../chunk-H5XTJ7GJ.js';
|
|
12
|
+
import '../chunk-2XWFWNDT.js';
|
|
13
|
+
import '../chunk-NUZHC6MM.js';
|
|
14
|
+
import '../chunk-UT6CW3C7.js';
|
|
15
|
+
import '../chunk-ODEQTPFM.js';
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Completing a `${NAME}` reference from a list of stored entry names.
|
|
3
|
+
*
|
|
4
|
+
* A value field takes either a value or a reference to one, and the reference
|
|
5
|
+
* has to be typed exactly: a name off by a character resolves to nothing,
|
|
6
|
+
* which reads as configured on every surface while whatever it feeds refuses
|
|
7
|
+
* every use. These helpers are what lets a field offer the names it knows
|
|
8
|
+
* rather than leaving the reader to copy one across from another screen.
|
|
9
|
+
*/
|
|
10
|
+
/** The shape of a reference's name: a letter or underscore, then letters, digits and underscores. */
|
|
11
|
+
export declare const REFERENCE_NAME_PATTERN = "[A-Za-z_][A-Za-z0-9_]*";
|
|
12
|
+
/**
|
|
13
|
+
* Whether a value is exactly one `${NAME}` reference, trimmed first.
|
|
14
|
+
*
|
|
15
|
+
* This is the default a [ValueField] asks when deciding whether a secret's
|
|
16
|
+
* value is a name (readable) or a credential (masked). A product whose
|
|
17
|
+
* reference grammar is stricter passes its own predicate as `isReference`.
|
|
18
|
+
*/
|
|
19
|
+
export declare function isWholeReference(value: string): boolean;
|
|
20
|
+
/** Where a reference is being typed, and what has been typed of it. */
|
|
21
|
+
export interface ReferenceQuery {
|
|
22
|
+
/** Index of the `$` that opens it. */
|
|
23
|
+
start: number;
|
|
24
|
+
/** What follows the `$`, with any `{` stripped. */
|
|
25
|
+
query: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The `${...}` under the caret, or null.
|
|
29
|
+
*
|
|
30
|
+
* IT SCANS BACK FROM THE CARET rather than matching the whole value, because
|
|
31
|
+
* a field can hold a reference among other text and the one being edited is
|
|
32
|
+
* the one being completed. The scan stops at whitespace and at a `}`: the
|
|
33
|
+
* first because no name contains one, the second because a reference that is
|
|
34
|
+
* already closed is finished, and offering to complete it again would replace
|
|
35
|
+
* a name somebody had chosen.
|
|
36
|
+
*/
|
|
37
|
+
export declare function referenceAt(value: string, caret: number): ReferenceQuery | null;
|
|
38
|
+
/**
|
|
39
|
+
* The names ordered by how closely they match what has been typed.
|
|
40
|
+
*
|
|
41
|
+
* Three tiers, in the order somebody means them: a name that STARTS with the
|
|
42
|
+
* query, then one that CONTAINS it, then one whose letters appear in order.
|
|
43
|
+
* Case is ignored, because a name is upper snake case and nobody holds shift
|
|
44
|
+
* to filter a list. An empty query keeps every name in the order given: the
|
|
45
|
+
* point of typing `$` alone is to see what there is.
|
|
46
|
+
*/
|
|
47
|
+
export declare function rankReferences(names: readonly string[], query: string): string[];
|
|
48
|
+
/**
|
|
49
|
+
* The value with the chosen name written in as a whole `${NAME}`, and where
|
|
50
|
+
* the caret goes.
|
|
51
|
+
*
|
|
52
|
+
* CLOSED BRACES, always, and the caret lands after them: a reference resolves
|
|
53
|
+
* only when it is whole, and a half-written one is a literal that reaches its
|
|
54
|
+
* destination as the characters somebody typed.
|
|
55
|
+
*/
|
|
56
|
+
export declare function completeReference(value: string, caret: number, at: ReferenceQuery, name: string): {
|
|
57
|
+
value: string;
|
|
58
|
+
caret: number;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* The scheme a value already carries, `https://`, `http://` or empty.
|
|
62
|
+
*
|
|
63
|
+
* Matched without regard to case, because a pasted address is whatever the
|
|
64
|
+
* address bar had.
|
|
65
|
+
*/
|
|
66
|
+
export declare function urlSchemeOf(value: string): '' | 'https://' | 'http://';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* ValueField: a labelled value with the control its kind needs.
|
|
3
|
+
*
|
|
4
|
+
* The row is FormField's and every control is the package's own; what is
|
|
5
|
+
* drawn here is the mark a label may carry, such as a third party's logo,
|
|
6
|
+
* set on the label's line ahead of its words.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
.crewlet-value-field__label {
|
|
10
|
+
display: inline-flex;
|
|
11
|
+
align-items: center;
|
|
12
|
+
gap: var(--spacing-1);
|
|
13
|
+
}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
export { VERSION_COMPARE_LABELS, VERSION_COMPARE_LENSES, VersionCompare } from '../chunk-
|
|
1
|
+
export { VERSION_COMPARE_LABELS, VERSION_COMPARE_LENSES, VersionCompare } from '../chunk-ISHLFPNN.js';
|
|
2
2
|
import '../chunk-AOFVXE6V.js';
|
|
3
3
|
import '../chunk-OOC7Q67K.js';
|
|
4
|
-
import '../chunk-
|
|
5
|
-
import '../chunk-
|
|
6
|
-
import '../chunk-WIATRXEJ.js';
|
|
4
|
+
import '../chunk-F7VBYCW2.js';
|
|
5
|
+
import '../chunk-27JCHL64.js';
|
|
7
6
|
import '../chunk-EGMQURBR.js';
|
|
7
|
+
import '../chunk-WIATRXEJ.js';
|
|
8
8
|
import '../chunk-PPUR46MK.js';
|
|
9
9
|
import '../chunk-5KRRJNQO.js';
|
|
10
10
|
import '../chunk-PQADV6P6.js';
|
|
11
11
|
import '../chunk-LODRX4FU.js';
|
|
12
12
|
import '../chunk-7QTPJDRF.js';
|
|
13
|
-
import '../chunk-XSPCITPN.js';
|
|
14
13
|
import '../chunk-OMV5W53A.js';
|
|
15
14
|
import '../chunk-2YTOOH3A.js';
|
|
15
|
+
import '../chunk-XSPCITPN.js';
|
|
16
16
|
import '../chunk-H5XTJ7GJ.js';
|
|
17
17
|
import '../chunk-2XWFWNDT.js';
|
|
18
18
|
import '../chunk-NUZHC6MM.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useThemePreference, useDensityPreference } from './chunk-Z24ZUSTX.js';
|
|
2
|
-
import { SegmentedControl } from './chunk-
|
|
2
|
+
import { SegmentedControl } from './chunk-F7VBYCW2.js';
|
|
3
3
|
import { SunGlyph, MonitorGlyph, MoonGlyph } from '@crewlethq/icons/glyphs';
|
|
4
4
|
import { jsx } from 'react/jsx-runtime';
|
|
5
5
|
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { VisuallyHidden } from './chunk-UT6CW3C7.js';
|
|
2
|
+
import { cx } from './chunk-ODEQTPFM.js';
|
|
3
|
+
import './FileList-TGDNV2QS.css';
|
|
4
|
+
import { useState } from 'react';
|
|
5
|
+
import { FileTextGlyph, ImageGlyph } from '@crewlethq/icons/glyphs';
|
|
6
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
7
|
+
|
|
8
|
+
function FileRow({ file }) {
|
|
9
|
+
const [broken, setBroken] = useState(false);
|
|
10
|
+
const preview = file.preview !== void 0 && file.preview !== "" && !broken ? file.preview : void 0;
|
|
11
|
+
return /* @__PURE__ */ jsxs("li", { className: "crewlet-file-list__file", children: [
|
|
12
|
+
/* @__PURE__ */ jsxs("div", { className: "crewlet-file-list__row", children: [
|
|
13
|
+
/* @__PURE__ */ jsx("span", { className: "crewlet-file-list__mark", "aria-hidden": "true", children: file.preview === void 0 ? /* @__PURE__ */ jsx(FileTextGlyph, { size: "sm" }) : /* @__PURE__ */ jsx(ImageGlyph, { size: "sm" }) }),
|
|
14
|
+
/* @__PURE__ */ jsxs("span", { className: "crewlet-file-list__text", children: [
|
|
15
|
+
/* @__PURE__ */ jsx("span", { className: "crewlet-file-list__name", title: file.name, children: file.name }),
|
|
16
|
+
/* @__PURE__ */ jsxs("span", { className: "crewlet-file-list__meta", children: [
|
|
17
|
+
file.type,
|
|
18
|
+
/* @__PURE__ */ jsx(VisuallyHidden, { children: "," }),
|
|
19
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: " \xB7 " }),
|
|
20
|
+
file.size
|
|
21
|
+
] })
|
|
22
|
+
] }),
|
|
23
|
+
file.action === void 0 || file.action === null ? null : /* @__PURE__ */ jsx("span", { className: "crewlet-file-list__action", children: file.action })
|
|
24
|
+
] }),
|
|
25
|
+
preview === void 0 ? null : /* @__PURE__ */ jsx("div", { className: "crewlet-file-list__preview", children: /* @__PURE__ */ jsx(
|
|
26
|
+
"img",
|
|
27
|
+
{
|
|
28
|
+
src: preview,
|
|
29
|
+
alt: "",
|
|
30
|
+
loading: "lazy",
|
|
31
|
+
decoding: "async",
|
|
32
|
+
referrerPolicy: "no-referrer",
|
|
33
|
+
draggable: false,
|
|
34
|
+
onError: () => setBroken(true)
|
|
35
|
+
}
|
|
36
|
+
) })
|
|
37
|
+
] });
|
|
38
|
+
}
|
|
39
|
+
function FileList({ files, label, className, ...rest }) {
|
|
40
|
+
const seen = /* @__PURE__ */ new Set();
|
|
41
|
+
for (const file of files) {
|
|
42
|
+
if (seen.has(file.id)) throw new RangeError(`FileList file ids must be unique; "${file.id}" is used twice`);
|
|
43
|
+
seen.add(file.id);
|
|
44
|
+
}
|
|
45
|
+
return (
|
|
46
|
+
/* The role is restated for WebKit, which drops it from a list with no markers. */
|
|
47
|
+
/* eslint-disable-next-line jsx-a11y/no-redundant-roles */
|
|
48
|
+
/* @__PURE__ */ jsx("ul", { ...rest, role: "list", "aria-label": label, className: cx("crewlet-file-list", className), children: files.map((file) => /* @__PURE__ */ jsx(FileRow, { file }, file.id)) })
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export { FileList };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { diffLines, diffStat, collapseDiff, DiffSummary, DiffView } from './chunk-AOFVXE6V.js';
|
|
2
|
-
import { SegmentedControl } from './chunk-
|
|
2
|
+
import { SegmentedControl } from './chunk-F7VBYCW2.js';
|
|
3
3
|
import { EmptyState } from './chunk-PPUR46MK.js';
|
|
4
4
|
import { useHeadingLevel, headingTag, nextHeadingLevel, HeadingLevelProvider } from './chunk-PQADV6P6.js';
|
|
5
5
|
import { cx } from './chunk-ODEQTPFM.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Tooltip } from './chunk-I33UIUZD.js';
|
|
2
|
-
import { SegmentedControl } from './chunk-
|
|
2
|
+
import { SegmentedControl } from './chunk-F7VBYCW2.js';
|
|
3
3
|
import { ArtifactIcon } from './chunk-AVL52EME.js';
|
|
4
4
|
import { isApplePlatform, Kbd } from './chunk-ACRRRPWT.js';
|
|
5
5
|
import { Menu } from './chunk-LODRX4FU.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FileDrop, FilePickButton } from './chunk-2JHGPXYG.js';
|
|
2
|
-
import { contrastRatio } from './chunk-
|
|
2
|
+
import { contrastRatio } from './chunk-BSAQE7PO.js';
|
|
3
3
|
import { normalizeHex } from './chunk-7W3LYIOC.js';
|
|
4
4
|
import { Button } from './chunk-7QTPJDRF.js';
|
|
5
5
|
import { VisuallyHidden } from './chunk-UT6CW3C7.js';
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { Tag } from './chunk-KYIAFNU7.js';
|
|
2
|
+
import { Spinner } from './chunk-XSPCITPN.js';
|
|
3
|
+
import { VisuallyHidden } from './chunk-UT6CW3C7.js';
|
|
4
|
+
import { cx } from './chunk-ODEQTPFM.js';
|
|
5
|
+
import './AttachmentChip-XF4KPQ3G.css';
|
|
6
|
+
import { useState } from 'react';
|
|
7
|
+
import { CircleAlertGlyph, ImageGlyph } from '@crewlethq/icons/glyphs';
|
|
8
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
9
|
+
|
|
10
|
+
var ATTACHMENT_CHIP_LABELS = {
|
|
11
|
+
uploading: "Uploading",
|
|
12
|
+
failed: "Not attached",
|
|
13
|
+
remove: (name) => `Remove ${name}`
|
|
14
|
+
};
|
|
15
|
+
function AttachmentChip({
|
|
16
|
+
name,
|
|
17
|
+
preview,
|
|
18
|
+
state = "ready",
|
|
19
|
+
onRemove,
|
|
20
|
+
labels: overrides,
|
|
21
|
+
className,
|
|
22
|
+
...rest
|
|
23
|
+
}) {
|
|
24
|
+
const labels = overrides ? { ...ATTACHMENT_CHIP_LABELS, ...overrides } : ATTACHMENT_CHIP_LABELS;
|
|
25
|
+
const [broken, setBroken] = useState(false);
|
|
26
|
+
const picture = preview !== void 0 && preview !== "" && !broken;
|
|
27
|
+
const mark = state === "uploading" ? /* @__PURE__ */ jsx(Spinner, { size: "xs" }) : state === "failed" ? /* @__PURE__ */ jsx(CircleAlertGlyph, { size: "xs" }) : picture ? /* @__PURE__ */ jsx(
|
|
28
|
+
"img",
|
|
29
|
+
{
|
|
30
|
+
className: "crewlet-attachment-chip__thumb",
|
|
31
|
+
src: preview,
|
|
32
|
+
alt: "",
|
|
33
|
+
decoding: "async",
|
|
34
|
+
referrerPolicy: "no-referrer",
|
|
35
|
+
draggable: false,
|
|
36
|
+
onError: () => setBroken(true)
|
|
37
|
+
}
|
|
38
|
+
) : /* @__PURE__ */ jsx(ImageGlyph, { size: "xs" });
|
|
39
|
+
const said = state === "ready" ? "" : `, ${labels[state]}`;
|
|
40
|
+
const common = {
|
|
41
|
+
...rest,
|
|
42
|
+
className: cx("crewlet-attachment-chip", `crewlet-attachment-chip--${state}`, className),
|
|
43
|
+
size: "sm",
|
|
44
|
+
appearance: "outline",
|
|
45
|
+
variant: state === "failed" ? "danger" : "neutral",
|
|
46
|
+
leadingIcon: mark,
|
|
47
|
+
title: name
|
|
48
|
+
};
|
|
49
|
+
const words = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
50
|
+
name,
|
|
51
|
+
said === "" ? null : /* @__PURE__ */ jsx(VisuallyHidden, { children: said })
|
|
52
|
+
] });
|
|
53
|
+
return onRemove === void 0 ? /* @__PURE__ */ jsx(Tag, { ...common, children: words }) : /* @__PURE__ */ jsx(Tag, { ...common, onRemove, removeAriaLabel: labels.remove(name), children: words });
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export { ATTACHMENT_CHIP_LABELS, AttachmentChip };
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { StepList } from './chunk-Z4EKUMZW.js';
|
|
2
|
+
import { Meter } from './chunk-RQFRRPV6.js';
|
|
3
|
+
import { ReceiptStrip } from './chunk-NLI7OVO2.js';
|
|
4
|
+
import { StatusCard } from './chunk-WW4E5EUS.js';
|
|
5
|
+
import { Disclosure } from './chunk-P4YORMRZ.js';
|
|
6
|
+
import { Spinner } from './chunk-XSPCITPN.js';
|
|
7
|
+
import { cx } from './chunk-ODEQTPFM.js';
|
|
8
|
+
import './DeepWorkCard-DGHRIQDM.css';
|
|
9
|
+
import { useId } from 'react';
|
|
10
|
+
import { TelescopeGlyph, CircleAlertGlyph, CircleStopGlyph, CircleCheckGlyph, ClockGlyph } from '@crewlethq/icons/glyphs';
|
|
11
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
12
|
+
|
|
13
|
+
var DEEP_WORK_STATES = [
|
|
14
|
+
"starting",
|
|
15
|
+
"running",
|
|
16
|
+
"waiting",
|
|
17
|
+
"finished",
|
|
18
|
+
"stopped",
|
|
19
|
+
"failed"
|
|
20
|
+
];
|
|
21
|
+
var DEEP_WORK_STATE_LABELS = {
|
|
22
|
+
starting: "Starting",
|
|
23
|
+
running: "Working",
|
|
24
|
+
waiting: "Waiting for your approval",
|
|
25
|
+
finished: "Finished",
|
|
26
|
+
stopped: "Stopped",
|
|
27
|
+
failed: "Failed"
|
|
28
|
+
};
|
|
29
|
+
var STATUS = {
|
|
30
|
+
starting: { tone: "info", icon: /* @__PURE__ */ jsx(Spinner, { size: "xs" }) },
|
|
31
|
+
running: { tone: "info", icon: /* @__PURE__ */ jsx(Spinner, { size: "xs" }) },
|
|
32
|
+
waiting: { tone: "warning", icon: /* @__PURE__ */ jsx(ClockGlyph, { size: "xs" }) },
|
|
33
|
+
finished: { tone: "success", icon: /* @__PURE__ */ jsx(CircleCheckGlyph, { size: "xs" }) },
|
|
34
|
+
stopped: { tone: "neutral", icon: /* @__PURE__ */ jsx(CircleStopGlyph, { size: "xs" }) },
|
|
35
|
+
failed: { tone: "danger", icon: /* @__PURE__ */ jsx(CircleAlertGlyph, { size: "xs" }) }
|
|
36
|
+
};
|
|
37
|
+
var NOTE_TONE = {
|
|
38
|
+
starting: "info",
|
|
39
|
+
running: "info",
|
|
40
|
+
waiting: "warning",
|
|
41
|
+
finished: "success",
|
|
42
|
+
stopped: "neutral",
|
|
43
|
+
failed: "danger"
|
|
44
|
+
};
|
|
45
|
+
var SETTLED = /* @__PURE__ */ new Set(["finished", "stopped", "failed"]);
|
|
46
|
+
var DEEP_WORK_CARD_LABELS = {
|
|
47
|
+
title: "Deep work",
|
|
48
|
+
activity: "Latest activity",
|
|
49
|
+
steps: "Steps",
|
|
50
|
+
stepCount: (count) => count === 1 ? "1 step" : `${count} steps`
|
|
51
|
+
};
|
|
52
|
+
function DeepWorkCard({
|
|
53
|
+
state,
|
|
54
|
+
goal,
|
|
55
|
+
measures = [],
|
|
56
|
+
activity = [],
|
|
57
|
+
steps = [],
|
|
58
|
+
stepsOpenAt = 3,
|
|
59
|
+
note,
|
|
60
|
+
stateLabels,
|
|
61
|
+
labels: labelOverrides,
|
|
62
|
+
className,
|
|
63
|
+
...rest
|
|
64
|
+
}) {
|
|
65
|
+
const id = useId();
|
|
66
|
+
const labels = labelOverrides ? { ...DEEP_WORK_CARD_LABELS, ...labelOverrides } : DEEP_WORK_CARD_LABELS;
|
|
67
|
+
const words = stateLabels ? { ...DEEP_WORK_STATE_LABELS, ...stateLabels } : DEEP_WORK_STATE_LABELS;
|
|
68
|
+
const hasNote = !(note === void 0 || note === null || note === false || note === "");
|
|
69
|
+
const list = steps.length > 0 ? /* @__PURE__ */ jsx(StepList, { label: labels.steps, steps }) : null;
|
|
70
|
+
return /* @__PURE__ */ jsxs(
|
|
71
|
+
StatusCard,
|
|
72
|
+
{
|
|
73
|
+
...rest,
|
|
74
|
+
className: cx("crewlet-deep-work-card", `crewlet-deep-work-card--${state}`, className),
|
|
75
|
+
title: labels.title,
|
|
76
|
+
status: { label: words[state], ...STATUS[state] },
|
|
77
|
+
settled: SETTLED.has(state),
|
|
78
|
+
strip: hasNote ? /* @__PURE__ */ jsx(ReceiptStrip, { tone: NOTE_TONE[state], children: note }) : void 0,
|
|
79
|
+
children: [
|
|
80
|
+
/* @__PURE__ */ jsxs("div", { className: "crewlet-deep-work-card__goal", children: [
|
|
81
|
+
/* @__PURE__ */ jsx(TelescopeGlyph, { size: "sm", className: "crewlet-deep-work-card__goal-mark" }),
|
|
82
|
+
/* @__PURE__ */ jsx("p", { className: "crewlet-deep-work-card__goal-text", children: goal })
|
|
83
|
+
] }),
|
|
84
|
+
measures.length > 0 ? /* @__PURE__ */ jsx("div", { className: "crewlet-deep-work-card__measures", children: measures.map((measure) => /* @__PURE__ */ jsx(
|
|
85
|
+
Meter,
|
|
86
|
+
{
|
|
87
|
+
size: "compact",
|
|
88
|
+
label: measure.label,
|
|
89
|
+
value: measure.value,
|
|
90
|
+
max: measure.max,
|
|
91
|
+
hint: measure.hint,
|
|
92
|
+
valueText: measure.valueText ?? measure.hint
|
|
93
|
+
},
|
|
94
|
+
measure.key
|
|
95
|
+
)) }) : null,
|
|
96
|
+
activity.length > 0 ? (
|
|
97
|
+
/* The role is restated for WebKit, which drops it from a list with no markers. */
|
|
98
|
+
/* eslint-disable-next-line jsx-a11y/no-redundant-roles */
|
|
99
|
+
/* @__PURE__ */ jsx("ol", { role: "list", "aria-label": labels.activity, className: "crewlet-deep-work-card__activity", children: activity.map((line, index) => /* @__PURE__ */ jsx("li", { className: "crewlet-deep-work-card__line", title: line, children: /* @__PURE__ */ jsx("code", { children: line }) }, `${index}:${line}`)) })
|
|
100
|
+
) : null,
|
|
101
|
+
list === null ? null : steps.length > stepsOpenAt ? /* @__PURE__ */ jsx(
|
|
102
|
+
Disclosure,
|
|
103
|
+
{
|
|
104
|
+
id: `${id}-steps`,
|
|
105
|
+
className: "crewlet-deep-work-card__steps",
|
|
106
|
+
size: "compact",
|
|
107
|
+
headingLevel: "none",
|
|
108
|
+
title: labels.stepCount(steps.length),
|
|
109
|
+
defaultOpen: false,
|
|
110
|
+
children: list
|
|
111
|
+
}
|
|
112
|
+
) : /* @__PURE__ */ jsx("div", { className: "crewlet-deep-work-card__steps", children: list })
|
|
113
|
+
]
|
|
114
|
+
}
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export { DEEP_WORK_CARD_LABELS, DEEP_WORK_STATES, DEEP_WORK_STATE_LABELS, DeepWorkCard };
|
|
@@ -23,6 +23,7 @@ function DownloadButton({
|
|
|
23
23
|
size = "small",
|
|
24
24
|
variant = "ghost",
|
|
25
25
|
title,
|
|
26
|
+
"aria-label": ariaLabel,
|
|
26
27
|
disabled,
|
|
27
28
|
resetMs,
|
|
28
29
|
failedResetMs = null,
|
|
@@ -61,6 +62,7 @@ function DownloadButton({
|
|
|
61
62
|
loading: fetching,
|
|
62
63
|
disabled,
|
|
63
64
|
title: state === "failed" ? failedMessage : title,
|
|
65
|
+
"aria-label": ariaLabel,
|
|
64
66
|
children: state === "started" ? startedLabel : state === "failed" ? failedLabel : label
|
|
65
67
|
}
|
|
66
68
|
),
|