@parallelworks/ui 0.77.0 → 0.78.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 +30 -5
- package/dist/access/AccessDrawer.d.ts +28 -7
- package/dist/access/AccessDrawer.js +216 -35
- package/dist/access/AccessList.d.ts +19 -1
- package/dist/access/AccessList.js +220 -9
- package/dist/access/GrantView.d.ts +3 -1
- package/dist/access/GrantView.js +17 -4
- package/dist/access/PrincipalPicker.js +5 -5
- package/dist/access/focus.js +1 -1
- package/dist/access/index.d.ts +2 -2
- package/dist/access/index.js +2 -2
- package/dist/access/strings.d.ts +18 -0
- package/dist/access/strings.js +20 -2
- package/dist/access/types.d.ts +26 -0
- package/dist/ai/components/AllocationSelector.js +1 -1
- package/dist/ai/components/AttachmentManager.js +5 -5
- package/dist/ai/components/AttachmentUpload.js +2 -2
- package/dist/ai/components/BranchNavigator.js +1 -1
- package/dist/ai/components/ChatActivity.js +1 -1
- package/dist/ai/components/ChatEmptyState.js +3 -3
- package/dist/ai/components/ChatInput.js +3 -5
- package/dist/ai/components/ChatLayout.js +1 -1
- package/dist/ai/components/ChatMessage.js +1 -1
- package/dist/ai/components/ChatMessageList.js +2 -2
- package/dist/ai/components/ChatSidebar.js +3 -3
- package/dist/ai/components/ChatThread.js +4 -4
- package/dist/ai/components/ComposerAddMenu.js +9 -20
- package/dist/ai/components/ModelSelector.js +3 -3
- package/dist/ai/components/PastedText.js +5 -5
- package/dist/ai/components/SessionView.js +1 -1
- package/dist/ai/components/ShareDialog.js +3 -3
- package/dist/ai/components/SlashMenu.d.ts +31 -4
- package/dist/ai/components/SlashMenu.js +36 -63
- package/dist/ai/components/agent/ActivityLine.js +1 -1
- package/dist/ai/components/agent/AgentMessageParts.js +13 -13
- package/dist/ai/components/conversationActions.js +3 -3
- package/dist/ai/core/ChatProvider.js +1 -1
- package/dist/ai/core/config.js +1 -1
- package/dist/ai/ui/ConversationSidebar.js +3 -3
- package/dist/ai/ui/sidebar.js +3 -3
- package/dist/assets/yaml.worker-DOBV2lND.js +884 -0
- package/dist/components/ActionMenu.d.ts +38 -9
- package/dist/components/ActionMenu.js +48 -22
- package/dist/components/Avatar.d.ts +66 -6
- package/dist/components/Avatar.js +130 -18
- package/dist/components/Breadcrumbs.d.ts +4 -0
- package/dist/components/Breadcrumbs.js +26 -10
- package/dist/components/Button.d.ts +3 -2
- package/dist/components/Button.js +11 -1
- package/dist/components/Callout.d.ts +3 -2
- package/dist/components/Callout.js +3 -2
- package/dist/components/Card.d.ts +33 -9
- package/dist/components/Card.js +24 -8
- package/dist/components/Checkbox.d.ts +3 -1
- package/dist/components/Checkbox.js +4 -2
- package/dist/components/ColorInput.js +1 -1
- package/dist/components/Combobox.d.ts +23 -0
- package/dist/components/Combobox.js +252 -86
- package/dist/components/ConfirmModal.d.ts +26 -2
- package/dist/components/ConfirmModal.js +81 -15
- package/dist/components/ContextMenu.d.ts +29 -2
- package/dist/components/ContextMenu.js +60 -8
- package/dist/components/CopyButton.d.ts +21 -8
- package/dist/components/CopyButton.js +29 -9
- package/dist/components/CreateModal.d.ts +16 -4
- package/dist/components/CreateModal.js +27 -16
- package/dist/components/DatePicker.d.ts +31 -1
- package/dist/components/DatePicker.js +178 -47
- package/dist/components/DescriptionList.d.ts +13 -3
- package/dist/components/DescriptionList.js +43 -11
- package/dist/components/Disclosure.d.ts +10 -2
- package/dist/components/Disclosure.js +18 -7
- package/dist/components/Drawer.js +5 -5
- package/dist/components/EmptyState.d.ts +12 -4
- package/dist/components/EmptyState.js +18 -10
- package/dist/components/ErrorPage.d.ts +40 -0
- package/dist/components/ErrorPage.js +101 -0
- package/dist/components/ExternalLink.d.ts +4 -1
- package/dist/components/ExternalLink.js +4 -5
- package/dist/components/Field.d.ts +21 -6
- package/dist/components/Field.js +32 -16
- package/dist/components/FileButton.d.ts +19 -0
- package/dist/components/FileButton.js +32 -0
- package/dist/components/HoverCard.d.ts +26 -6
- package/dist/components/HoverCard.js +11 -5
- package/dist/components/IconButton.js +4 -2
- package/dist/components/InfoTip.js +3 -3
- package/dist/components/Input.d.ts +33 -3
- package/dist/components/Input.js +149 -14
- package/dist/components/Kbd.d.ts +40 -0
- package/dist/components/Kbd.js +168 -0
- package/dist/components/Listbox.d.ts +103 -0
- package/dist/components/Listbox.js +190 -0
- package/dist/components/Loader.d.ts +8 -2
- package/dist/components/Loader.js +16 -1
- package/dist/components/Markdown.js +1 -1
- package/dist/components/MarkdownImpl.js +1 -1
- package/dist/components/Menu.d.ts +20 -2
- package/dist/components/Menu.js +48 -19
- package/dist/components/MenuEntries.d.ts +38 -2
- package/dist/components/MenuEntries.js +266 -39
- package/dist/components/Meter.d.ts +50 -11
- package/dist/components/Meter.js +71 -21
- package/dist/components/Modal.d.ts +9 -3
- package/dist/components/Modal.js +68 -29
- package/dist/components/OneTimeCodeInput.js +1 -1
- package/dist/components/PageHeader.js +111 -7
- package/dist/components/PageHeaderAction.d.ts +8 -3
- package/dist/components/PageHeaderAction.js +122 -34
- package/dist/components/Pagination.d.ts +13 -1
- package/dist/components/Pagination.js +90 -19
- package/dist/components/Popover.d.ts +13 -2
- package/dist/components/Popover.js +20 -21
- package/dist/components/Provider.d.ts +140 -3
- package/dist/components/Provider.js +142 -12
- package/dist/components/RefreshButton.d.ts +13 -6
- package/dist/components/RefreshButton.js +17 -9
- package/dist/components/RunStatusIcon.d.ts +16 -7
- package/dist/components/RunStatusIcon.js +21 -8
- package/dist/components/Section.d.ts +11 -4
- package/dist/components/Section.js +33 -22
- package/dist/components/SegmentedControl.d.ts +16 -3
- package/dist/components/SegmentedControl.js +7 -3
- package/dist/components/Select.d.ts +19 -3
- package/dist/components/Select.js +114 -68
- package/dist/components/SelectionCopy.d.ts +10 -0
- package/dist/components/SelectionCopy.js +105 -0
- package/dist/components/SettingModeOption.js +1 -1
- package/dist/components/SettingsCard.js +1 -1
- package/dist/components/Skeleton.js +1 -1
- package/dist/components/StatusBadge.d.ts +55 -10
- package/dist/components/StatusBadge.js +91 -15
- package/dist/components/StickyBar.js +1 -1
- package/dist/components/Table.d.ts +22 -4
- package/dist/components/Table.js +46 -24
- package/dist/components/Tabs.d.ts +9 -4
- package/dist/components/Tabs.js +9 -4
- package/dist/components/Tag.d.ts +49 -0
- package/dist/components/Tag.js +199 -0
- package/dist/components/ThemeEditor.js +1 -1
- package/dist/components/Toast.js +1 -1
- package/dist/components/ToggleGroup.d.ts +4 -1
- package/dist/components/ToggleGroup.js +30 -13
- package/dist/components/Tooltip.d.ts +9 -3
- package/dist/components/Tooltip.js +55 -39
- package/dist/components/buttonClasses.d.ts +5 -2
- package/dist/components/buttonClasses.js +11 -10
- package/dist/components/chart.d.ts +69 -0
- package/dist/components/chart.js +145 -0
- package/dist/components/comboboxItems.d.ts +7 -1
- package/dist/components/comboboxItems.js +6 -2
- package/dist/components/dismiss.d.ts +5 -1
- package/dist/components/dismiss.js +6 -2
- package/dist/components/floating.d.ts +4 -4
- package/dist/components/floating.js +5 -5
- package/dist/components/headerActionsFit.d.ts +37 -0
- package/dist/components/headerActionsFit.js +81 -0
- package/dist/components/pageHeaderStore.d.ts +3 -0
- package/dist/components/pageHeaderStore.js +3 -0
- package/dist/components/pathBreaks.js +2 -2
- package/dist/components/popupContainer.d.ts +17 -0
- package/dist/components/popupContainer.js +69 -0
- package/dist/components/relativeTime.d.ts +21 -10
- package/dist/components/relativeTime.js +50 -22
- package/dist/components/segmented.d.ts +18 -4
- package/dist/components/segmented.js +48 -6
- package/dist/components/typedDate.d.ts +5 -0
- package/dist/components/typedDate.js +50 -0
- package/dist/components/useClosingValue.d.ts +4 -0
- package/dist/components/useClosingValue.js +12 -0
- package/dist/components/useCopy.d.ts +6 -0
- package/dist/components/useCopy.js +3 -3
- package/dist/components/useNarrow.d.ts +2 -0
- package/dist/components/useNarrow.js +16 -0
- package/dist/editor/Editor.js +1 -1
- package/dist/editor/FormCodePanel.js +1 -1
- package/dist/editor/Monaco.js +1 -1
- package/dist/editor/workers.js +1 -1
- package/dist/file-explorer/FileExplorer.js +16 -15
- package/dist/file-explorer/FileExplorerContext.js +2 -2
- package/dist/file-explorer/FilePreview/Viewer.js +3 -3
- package/dist/file-explorer/FilePreview/index.js +2 -2
- package/dist/file-explorer/FileRowsWindow.js +3 -3
- package/dist/file-explorer/FileTable.js +1 -1
- package/dist/file-explorer/LoadMoreRow.js +1 -1
- package/dist/file-explorer/TreeView.js +5 -5
- package/dist/file-explorer/helpers.js +2 -2
- package/dist/file-explorer/toasts.js +2 -2
- package/dist/form/Fields/CheckboxGroupField.js +1 -1
- package/dist/form/Fields/DropdownField.js +1 -1
- package/dist/form/Fields/DurationField.js +2 -2
- package/dist/form/Fields/MultiDropdownField.js +1 -1
- package/dist/form/Fields/NumberField.js +1 -1
- package/dist/form/Fields/ObjectField.js +1 -1
- package/dist/form/Fields/RangeField.js +1 -1
- package/dist/form/Fields/StringField.js +1 -1
- package/dist/form/Form.js +3 -3
- package/dist/form/FormLayout.js +1 -1
- package/dist/form/Wizard/WizardContainer.js +1 -1
- package/dist/form/Wizard/WizardNavigation.js +1 -1
- package/dist/form/Wizard/WizardStepContent.js +1 -1
- package/dist/form/fieldRegistry.js +1 -1
- package/dist/form/formEditing.js +1 -1
- package/dist/format.d.ts +17 -7
- package/dist/format.js +39 -16
- package/dist/graph/AnnotationBanner.js +2 -2
- package/dist/graph/Connectors.js +5 -5
- package/dist/graph/DependencyGraph.js +10 -9
- package/dist/graph/GraphEditor.js +4 -4
- package/dist/graph/GraphEditorDialogs.js +13 -12
- package/dist/graph/GraphNode.js +1 -1
- package/dist/graph/InputDialog.js +5 -5
- package/dist/graph/InputsEditor.js +7 -7
- package/dist/graph/MatrixGroup.js +2 -2
- package/dist/graph/ProblemsButton.js +3 -3
- package/dist/graph/Reveal.js +1 -1
- package/dist/graph/RunWarningsList.js +1 -1
- package/dist/graph/ShortcutsButton.js +25 -8
- package/dist/graph/StepSummaries.js +1 -1
- package/dist/graph/TreeView.js +2 -2
- package/dist/graph/WorkflowSettingsDialog.js +3 -3
- package/dist/graph/editorFields.js +3 -3
- package/dist/graph/editorPrimitives.js +1 -1
- package/dist/graph/editorRows.js +5 -5
- package/dist/graph/fieldProblems.js +2 -2
- package/dist/graph/inputRefs.js +7 -6
- package/dist/graph/stepWith.js +2 -2
- package/dist/index.d.ts +30 -21
- package/dist/index.js +20 -12
- package/dist/list/ActionToolbar.d.ts +4 -0
- package/dist/list/ActionToolbar.js +35 -12
- package/dist/list/ListFilterBar.d.ts +42 -0
- package/dist/list/ListFilterBar.js +789 -0
- package/dist/list/ListPage.d.ts +42 -4
- package/dist/list/ListPage.js +56 -22
- package/dist/list/ListTable.d.ts +27 -3
- package/dist/list/ListTable.js +48 -23
- package/dist/list/ListToolbar.d.ts +31 -0
- package/dist/list/ListToolbar.js +43 -0
- package/dist/list/ListViewControls.d.ts +8 -4
- package/dist/list/ListViewControls.js +22 -14
- package/dist/list/UserHoverCard.d.ts +8 -2
- package/dist/list/UserHoverCard.js +26 -13
- package/dist/list/filterModel.d.ts +122 -0
- package/dist/list/filterModel.js +308 -0
- package/dist/list/index.d.ts +6 -2
- package/dist/list/index.js +6 -2
- package/dist/list/listSearch.d.ts +1 -1
- package/dist/list/listSearch.js +8 -4
- package/dist/list/listView.d.ts +24 -2
- package/dist/list/listView.js +47 -45
- package/dist/list/rowMenu.d.ts +10 -5
- package/dist/list/rowMenu.js +17 -7
- package/dist/list/useListFilters.d.ts +68 -0
- package/dist/list/useListFilters.js +252 -0
- package/dist/logviewer/LogViewer.js +4 -4
- package/dist/styles/theme.css +94 -0
- package/dist/styles.css +1 -1
- package/package.json +11 -11
- package/dist/assets/yaml.worker-k9AdOqzf.js +0 -1441
- package/dist/components/fullscreen.d.ts +0 -4
- package/dist/components/fullscreen.js +0 -18
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import { cx } from "../cx.js";
|
|
2
|
-
import { AddIcon, ChevronRightIcon, LockIcon, OrganizationIcon, TrashIcon } from "../icons.js";
|
|
2
|
+
import { AddIcon, ChevronRightIcon, KeyIcon, LockIcon, OrganizationIcon, TrashIcon } from "../icons.js";
|
|
3
3
|
import { Loader } from "../components/Loader.js";
|
|
4
|
+
import { menuDivider } from "../components/MenuEntries.js";
|
|
5
|
+
import { Avatar } from "../components/Avatar.js";
|
|
4
6
|
import { Button } from "../components/Button.js";
|
|
5
7
|
import { IconButton } from "../components/IconButton.js";
|
|
6
8
|
import { Callout } from "../components/Callout.js";
|
|
7
9
|
import { collapsePanelClassName } from "../components/Disclosure.js";
|
|
10
|
+
import { Select } from "../components/Select.js";
|
|
8
11
|
import { StatusBadge } from "../components/StatusBadge.js";
|
|
9
12
|
import { alsoHas, firstOfEach, isOwner, key, overlapOf, removalOf } from "./model.js";
|
|
10
13
|
import { PrincipalTile } from "./PrincipalPicker.js";
|
|
11
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
12
14
|
import { useEffect, useId, useRef } from "react";
|
|
15
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
13
16
|
import { Collapsible } from "@base-ui/react/collapsible";
|
|
14
17
|
//#region src/access/AccessList.tsx
|
|
15
18
|
/** The id the owner's section has among the roles' sections. */
|
|
@@ -20,6 +23,21 @@ var aboutOf = (principal, t) => principal.kind === "user" ? principal.detail : p
|
|
|
20
23
|
/** Where a role someone has elsewhere comes from, as "through" reads it. */
|
|
21
24
|
var sourceOf = (holding) => holding.through?.name ?? holding.from ?? "";
|
|
22
25
|
/** Stands where a remove button would, on a row that can't be removed here. */
|
|
26
|
+
/** A role named where a row's role select would sit, so read-only rows line up with
|
|
27
|
+
* editable ones: the select's width, border and padding, without the box. */
|
|
28
|
+
function RoleText({ children }) {
|
|
29
|
+
return /* @__PURE__ */ jsx("span", {
|
|
30
|
+
className: "w-36 shrink-0 wrap-anywhere border border-transparent px-2 text-xs text-(--theme-muted-text-color)",
|
|
31
|
+
children
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
/** Holds the remove button's place on a row that has none. */
|
|
35
|
+
function NoAction() {
|
|
36
|
+
return /* @__PURE__ */ jsx("span", {
|
|
37
|
+
"aria-hidden": "true",
|
|
38
|
+
className: "size-7 shrink-0"
|
|
39
|
+
});
|
|
40
|
+
}
|
|
23
41
|
function Locked() {
|
|
24
42
|
return /* @__PURE__ */ jsx("span", {
|
|
25
43
|
className: "flex size-7 items-center justify-center text-(--theme-muted-text-color)",
|
|
@@ -30,12 +48,13 @@ function Locked() {
|
|
|
30
48
|
});
|
|
31
49
|
}
|
|
32
50
|
/** A role or principal whose rows fold under it. */
|
|
33
|
-
function Section({ id, open, onOpenChange, disabled, lead, title, description, aside, narrowAside, notice, children }) {
|
|
51
|
+
function Section({ id, open, onOpenChange, disabled, lead, title, description, aside, narrowAside, notice, onContextMenu, children }) {
|
|
34
52
|
return /* @__PURE__ */ jsxs(Collapsible.Root, {
|
|
35
53
|
open: open && !disabled,
|
|
36
54
|
onOpenChange,
|
|
37
55
|
disabled,
|
|
38
56
|
className: "border-b border-(--theme-border)",
|
|
57
|
+
onContextMenu,
|
|
39
58
|
children: [
|
|
40
59
|
/* @__PURE__ */ jsxs(Collapsible.Trigger, {
|
|
41
60
|
id,
|
|
@@ -87,9 +106,10 @@ function Section({ id, open, onOpenChange, disabled, lead, title, description, a
|
|
|
87
106
|
});
|
|
88
107
|
}
|
|
89
108
|
/** A line under a section: a principal under a role, or a role under a principal. */
|
|
90
|
-
function Row({ lead, title, meta, action, muted }) {
|
|
109
|
+
function Row({ lead, title, meta, action, muted, onContextMenu }) {
|
|
91
110
|
return /* @__PURE__ */ jsxs("div", {
|
|
92
111
|
className: "flex items-center gap-3 py-1.5 ps-11 pe-4 @min-[30rem]/access:ps-11",
|
|
112
|
+
onContextMenu,
|
|
93
113
|
children: [
|
|
94
114
|
lead,
|
|
95
115
|
/* @__PURE__ */ jsxs("div", {
|
|
@@ -173,7 +193,7 @@ function RemoveConfirm({ model, removal, saving, onCancel, onConfirm, t }) {
|
|
|
173
193
|
children: impact.owner ? /* @__PURE__ */ jsx("p", {
|
|
174
194
|
className: "m-0 text-(--theme-muted-text-color)",
|
|
175
195
|
children: t.ownerLosesNothing
|
|
176
|
-
}) : impact.lost.length > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
196
|
+
}) : impact.lost.length > 0 ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
177
197
|
/* @__PURE__ */ jsx("p", {
|
|
178
198
|
className: "m-0 text-(--theme-muted-text-color)",
|
|
179
199
|
children: t.losesIntro(principal.kind, principal.memberCount)
|
|
@@ -277,7 +297,7 @@ function ByRole({ model, shown, order, expanded, onExpandedChange, filtering, ac
|
|
|
277
297
|
notice: failure,
|
|
278
298
|
title: role.name,
|
|
279
299
|
description: role.description,
|
|
280
|
-
aside: /* @__PURE__ */ jsxs(Fragment, { children: [everyoneTag, count] }),
|
|
300
|
+
aside: /* @__PURE__ */ jsxs(Fragment$1, { children: [everyoneTag, count] }),
|
|
281
301
|
narrowAside: everyoneTag && !count ? /* @__PURE__ */ jsx("span", {
|
|
282
302
|
className: "mt-1 inline-flex",
|
|
283
303
|
children: everyoneTag
|
|
@@ -310,6 +330,11 @@ function ByRole({ model, shown, order, expanded, onExpandedChange, filtering, ac
|
|
|
310
330
|
const hint = overlapHint(overlapOf(model, principalId, role), t);
|
|
311
331
|
const label = t.removeRole(principalLabel(principal, t), role.name);
|
|
312
332
|
return /* @__PURE__ */ jsx(Row, {
|
|
333
|
+
onContextMenu: rowMenu(actions, () => rowEntries(model, principal, actions, t, {
|
|
334
|
+
principalId,
|
|
335
|
+
roleIds: [roleId],
|
|
336
|
+
all: false
|
|
337
|
+
})),
|
|
313
338
|
lead,
|
|
314
339
|
title: principalLabel(principal, t),
|
|
315
340
|
meta: [aboutOf(principal, t), hint].filter(Boolean).join(" · "),
|
|
@@ -349,7 +374,7 @@ function ByPrincipal({ model, shown, order, expanded, onExpandedChange, actions,
|
|
|
349
374
|
const room = owner ? 1 : 2;
|
|
350
375
|
const badges = badgeRoles.length <= room ? badgeRoles : badgeRoles.slice(0, room - 1);
|
|
351
376
|
const hidden = badgeRoles.slice(badges.length);
|
|
352
|
-
const roleBadges = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
377
|
+
const roleBadges = /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
353
378
|
owner && /* @__PURE__ */ jsx(StatusBadge, {
|
|
354
379
|
size: "md",
|
|
355
380
|
variant: "info",
|
|
@@ -378,6 +403,11 @@ function ByPrincipal({ model, shown, order, expanded, onExpandedChange, actions,
|
|
|
378
403
|
principal,
|
|
379
404
|
className: "hidden @min-[30rem]/access:flex"
|
|
380
405
|
}),
|
|
406
|
+
onContextMenu: held.length > 0 ? rowMenu(actions, () => rowEntries(model, principal, actions, t, {
|
|
407
|
+
principalId,
|
|
408
|
+
roleIds: held.map((role) => role.id),
|
|
409
|
+
all: true
|
|
410
|
+
})) : void 0,
|
|
381
411
|
notice: failure,
|
|
382
412
|
title: principalLabel(principal, t),
|
|
383
413
|
description: everyone ? t.everyoneJoinLater : aboutOf(principal, t),
|
|
@@ -393,7 +423,7 @@ function ByPrincipal({ model, shown, order, expanded, onExpandedChange, actions,
|
|
|
393
423
|
onCancel: actions.onCancelRemove,
|
|
394
424
|
onConfirm: () => actions.removal && actions.onRemove(actions.removal),
|
|
395
425
|
t
|
|
396
|
-
}) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
426
|
+
}) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
397
427
|
owner && /* @__PURE__ */ jsx(Row, {
|
|
398
428
|
title: /* @__PURE__ */ jsx("span", {
|
|
399
429
|
className: "font-medium",
|
|
@@ -482,5 +512,186 @@ function RoleRow({ model, principal, role, actions, t }) {
|
|
|
482
512
|
})
|
|
483
513
|
});
|
|
484
514
|
}
|
|
515
|
+
/** A row's right-click menu, which repeats what its buttons do; none while read-only. */
|
|
516
|
+
function rowMenu(actions, entries) {
|
|
517
|
+
if (actions.readOnly) return;
|
|
518
|
+
return (e) => {
|
|
519
|
+
e.stopPropagation();
|
|
520
|
+
actions.openMenu(e, entries());
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
/** A principal's row menu: its role, where each holds one, more roles otherwise, then removal. */
|
|
524
|
+
function rowEntries(model, principal, actions, t, removal) {
|
|
525
|
+
const held = new Set((model.held.get(principal.id) ?? []).map((role) => role.id));
|
|
526
|
+
const lead = actions.singleRole ? [{
|
|
527
|
+
label: t.roleMenu,
|
|
528
|
+
icon: /* @__PURE__ */ jsx(KeyIcon, {}),
|
|
529
|
+
items: model.grantable.map((role) => ({
|
|
530
|
+
label: role.name,
|
|
531
|
+
description: role.description,
|
|
532
|
+
checked: held.has(role.id),
|
|
533
|
+
onClick: () => {
|
|
534
|
+
if (!held.has(role.id) || held.size > 1) actions.onChangeRole(principal.id, role.id);
|
|
535
|
+
}
|
|
536
|
+
}))
|
|
537
|
+
}] : isOwner(model, principal.id) ? [] : [{
|
|
538
|
+
label: t.grantMoreRoles,
|
|
539
|
+
icon: /* @__PURE__ */ jsx(AddIcon, {}),
|
|
540
|
+
onClick: () => actions.onGrantMore(principal.id)
|
|
541
|
+
}];
|
|
542
|
+
return [
|
|
543
|
+
...lead,
|
|
544
|
+
...lead.length > 0 ? [menuDivider] : [],
|
|
545
|
+
{
|
|
546
|
+
label: removal.all || actions.singleRole ? t.removeAccess : t.confirmRemove(removal.roleIds.map((id) => model.roleById.get(id)?.name ?? id)),
|
|
547
|
+
icon: /* @__PURE__ */ jsx(TrashIcon, {}),
|
|
548
|
+
destructive: true,
|
|
549
|
+
onClick: () => actions.onAskRemove(removal)
|
|
550
|
+
}
|
|
551
|
+
];
|
|
552
|
+
}
|
|
553
|
+
/** A reason someone has access that no grant here changes, locked ahead of the grants. */
|
|
554
|
+
function RuleRow({ rule, roleName, lead, t }) {
|
|
555
|
+
const people = rule.people ?? [];
|
|
556
|
+
const shown = people.slice(0, 4);
|
|
557
|
+
const more = people.length - shown.length;
|
|
558
|
+
const icon = rule.icon ?? /* @__PURE__ */ jsx(LockIcon, {});
|
|
559
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
560
|
+
className: "flex items-center gap-3 border-b border-(--theme-border) px-4 py-2.5",
|
|
561
|
+
children: [
|
|
562
|
+
lead === "chevron" ? /* @__PURE__ */ jsx("span", {
|
|
563
|
+
"aria-hidden": "true",
|
|
564
|
+
className: "flex size-4 shrink-0 items-center justify-center text-(--theme-muted-text-color) [&_svg]:size-4",
|
|
565
|
+
children: icon
|
|
566
|
+
}) : /* @__PURE__ */ jsxs(Fragment$1, { children: [lead === "both" && /* @__PURE__ */ jsx("span", {
|
|
567
|
+
"aria-hidden": "true",
|
|
568
|
+
className: "size-4 shrink-0"
|
|
569
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
570
|
+
"aria-hidden": "true",
|
|
571
|
+
className: "hidden size-8 shrink-0 items-center justify-center rounded-md bg-(--theme-muted-panel-bg) text-(--theme-muted-text-color) @min-[30rem]/access:flex [&_svg]:size-4",
|
|
572
|
+
children: icon
|
|
573
|
+
})] }),
|
|
574
|
+
/* @__PURE__ */ jsxs("span", {
|
|
575
|
+
className: "flex min-w-0 flex-1 flex-col",
|
|
576
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
577
|
+
className: "text-sm font-medium wrap-anywhere",
|
|
578
|
+
children: rule.title
|
|
579
|
+
}), rule.detail && /* @__PURE__ */ jsx("span", {
|
|
580
|
+
className: "text-xs wrap-anywhere text-(--theme-muted-text-color)",
|
|
581
|
+
children: rule.detail
|
|
582
|
+
})]
|
|
583
|
+
}),
|
|
584
|
+
shown.length > 0 && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
|
|
585
|
+
className: "sr-only",
|
|
586
|
+
children: t.ruleMembers(shown.map((person) => person.name), more)
|
|
587
|
+
}), /* @__PURE__ */ jsxs("span", {
|
|
588
|
+
"aria-hidden": "true",
|
|
589
|
+
className: "hidden shrink-0 items-center gap-1 @min-[30rem]/access:flex",
|
|
590
|
+
children: [shown.map((person, index) => /* @__PURE__ */ jsx(Avatar, {
|
|
591
|
+
name: person.name,
|
|
592
|
+
src: person.avatarUrl,
|
|
593
|
+
size: "md",
|
|
594
|
+
decorative: true
|
|
595
|
+
}, `${person.name}-${index.toString()}`)), more > 0 && /* @__PURE__ */ jsx("span", {
|
|
596
|
+
className: "inline-flex size-7 items-center justify-center rounded-full bg-(--theme-muted-panel-bg) text-[11px] font-medium tabular-nums text-(--theme-muted-text-color)",
|
|
597
|
+
children: t.moreMembers(more)
|
|
598
|
+
})]
|
|
599
|
+
})] }),
|
|
600
|
+
roleName && (lead === "tile" ? /* @__PURE__ */ jsx(RoleText, { children: roleName }) : /* @__PURE__ */ jsx("span", {
|
|
601
|
+
className: "shrink-0 text-xs text-(--theme-muted-text-color)",
|
|
602
|
+
children: roleName
|
|
603
|
+
})),
|
|
604
|
+
/* @__PURE__ */ jsx(Locked, {})
|
|
605
|
+
]
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
/** Person and group one by one where each holds one role: a flat row each, its role picked
|
|
609
|
+
* from a list on the row. */
|
|
610
|
+
function ByPrincipalSingle({ model, order, actions, t, sectionId }) {
|
|
611
|
+
return order.map((principalId) => {
|
|
612
|
+
const principal = model.principalById.get(principalId);
|
|
613
|
+
if (!principal) return null;
|
|
614
|
+
const owner = isOwner(model, principalId);
|
|
615
|
+
const held = model.held.get(principalId) ?? [];
|
|
616
|
+
const inheritedRoles = (model.inherited.get(principalId) ?? []).map((holding) => holding.role);
|
|
617
|
+
const role = held[0];
|
|
618
|
+
const name = principalLabel(principal, t);
|
|
619
|
+
const failure = actions.failure?.principalId === principalId ? actions.failure.node : void 0;
|
|
620
|
+
const removal = {
|
|
621
|
+
principalId,
|
|
622
|
+
roleIds: held.map((r) => r.id),
|
|
623
|
+
all: held.length > 1
|
|
624
|
+
};
|
|
625
|
+
if (actions.removal?.principalId === principalId) return /* @__PURE__ */ jsx("div", {
|
|
626
|
+
className: "border-b border-(--theme-border)",
|
|
627
|
+
children: /* @__PURE__ */ jsx(RemoveConfirm, {
|
|
628
|
+
model,
|
|
629
|
+
removal: actions.removal,
|
|
630
|
+
saving: actions.saving.size > 0,
|
|
631
|
+
onCancel: actions.onCancelRemove,
|
|
632
|
+
onConfirm: () => actions.removal && actions.onRemove(actions.removal),
|
|
633
|
+
t
|
|
634
|
+
})
|
|
635
|
+
}, principalId);
|
|
636
|
+
const saving = held.some((r) => actions.saving.has(key({
|
|
637
|
+
principalId,
|
|
638
|
+
roleId: r.id
|
|
639
|
+
})));
|
|
640
|
+
const options = [...model.grantable, ...role && !model.grantable.includes(role) ? [role] : []].map((r) => ({
|
|
641
|
+
value: r.id,
|
|
642
|
+
label: r.name
|
|
643
|
+
}));
|
|
644
|
+
const control = owner ? /* @__PURE__ */ jsx(StatusBadge, {
|
|
645
|
+
size: "md",
|
|
646
|
+
variant: "info",
|
|
647
|
+
children: t.owner
|
|
648
|
+
}) : !role ? /* @__PURE__ */ jsx(RoleText, { children: inheritedRoles.map((r) => r.name).join(", ") }) : actions.readOnly ? /* @__PURE__ */ jsx(RoleText, { children: role.name }) : /* @__PURE__ */ jsx(Select, {
|
|
649
|
+
size: "sm",
|
|
650
|
+
"aria-label": t.roleFor(name),
|
|
651
|
+
items: options,
|
|
652
|
+
value: role.id,
|
|
653
|
+
disabled: saving,
|
|
654
|
+
onValueChange: (next) => {
|
|
655
|
+
if (next !== null && (next !== role.id || held.length > 1)) actions.onChangeRole(principalId, next);
|
|
656
|
+
},
|
|
657
|
+
className: "w-36 shrink-0"
|
|
658
|
+
});
|
|
659
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
660
|
+
id: sectionId(principalId),
|
|
661
|
+
tabIndex: -1,
|
|
662
|
+
className: "border-b border-(--theme-border) outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-(--theme-focus)",
|
|
663
|
+
onContextMenu: role && !owner ? rowMenu(actions, () => rowEntries(model, principal, actions, t, removal)) : void 0,
|
|
664
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
665
|
+
className: "flex items-center gap-3 px-4 py-2.5",
|
|
666
|
+
children: [
|
|
667
|
+
/* @__PURE__ */ jsx(PrincipalTile, {
|
|
668
|
+
principal,
|
|
669
|
+
className: "hidden @min-[30rem]/access:flex"
|
|
670
|
+
}),
|
|
671
|
+
/* @__PURE__ */ jsxs("span", {
|
|
672
|
+
className: "flex min-w-0 flex-1 flex-col",
|
|
673
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
674
|
+
className: "text-sm font-medium wrap-anywhere",
|
|
675
|
+
children: name
|
|
676
|
+
}), aboutOf(principal, t) && /* @__PURE__ */ jsx("span", {
|
|
677
|
+
className: "text-xs wrap-anywhere text-(--theme-muted-text-color)",
|
|
678
|
+
children: aboutOf(principal, t)
|
|
679
|
+
})]
|
|
680
|
+
}),
|
|
681
|
+
control,
|
|
682
|
+
owner || !role ? /* @__PURE__ */ jsx(Locked, {}) : actions.readOnly ? /* @__PURE__ */ jsx(NoAction, {}) : /* @__PURE__ */ jsx(RemoveButton, {
|
|
683
|
+
label: t.removeRole(name, role.name),
|
|
684
|
+
saving,
|
|
685
|
+
removal,
|
|
686
|
+
onAsk: actions.onAskRemove
|
|
687
|
+
})
|
|
688
|
+
]
|
|
689
|
+
}), failure && /* @__PURE__ */ jsx("div", {
|
|
690
|
+
className: "px-4 pb-3",
|
|
691
|
+
children: failure
|
|
692
|
+
})]
|
|
693
|
+
}, principalId);
|
|
694
|
+
});
|
|
695
|
+
}
|
|
485
696
|
//#endregion
|
|
486
|
-
export { ByPrincipal, ByRole, OWNER_SECTION, RemoveConfirm, principalLabel, removeKey };
|
|
697
|
+
export { ByPrincipal, ByPrincipalSingle, ByRole, OWNER_SECTION, RemoveConfirm, RuleRow, principalLabel, removeKey };
|
|
@@ -8,7 +8,7 @@ export interface GrantSelection {
|
|
|
8
8
|
roleIds: string[];
|
|
9
9
|
}
|
|
10
10
|
/** The grant form's body and footer, which the drawer lays out in its own body and footer. */
|
|
11
|
-
export declare function useGrantView({ model, selection, onSelectionChange, resourceName, describeGroup, searchPrincipals, groupCount, peopleCount, recentPrincipalIds, cache, seen, saving, failure, onGrant, onCancel, focusLater, boundary, t, }: {
|
|
11
|
+
export declare function useGrantView({ model, selection, onSelectionChange, resourceName, describeGroup, searchPrincipals, groupCount, peopleCount, recentPrincipalIds, cache, seen, saving, failure, onGrant, onCancel, focusLater, boundary, singleRole, t, }: {
|
|
12
12
|
model: AccessModel;
|
|
13
13
|
selection: GrantSelection;
|
|
14
14
|
onSelectionChange: (next: GrantSelection) => void;
|
|
@@ -29,6 +29,8 @@ export declare function useGrantView({ model, selection, onSelectionChange, reso
|
|
|
29
29
|
focusLater: (find: () => HTMLElement | null | undefined) => void;
|
|
30
30
|
/** The drawer's body, above its footer, which the open list fills. */
|
|
31
31
|
boundary: Element | null;
|
|
32
|
+
/** One role each: the form picks one, and granting it takes the role each already holds. */
|
|
33
|
+
singleRole?: boolean;
|
|
32
34
|
t: AccessStrings;
|
|
33
35
|
}): {
|
|
34
36
|
body: ReactNode;
|
package/dist/access/GrantView.js
CHANGED
|
@@ -4,11 +4,11 @@ import { Combobox } from "../components/Combobox.js";
|
|
|
4
4
|
import { StatusBadge } from "../components/StatusBadge.js";
|
|
5
5
|
import { covers, grantPlan, isOwner } from "./model.js";
|
|
6
6
|
import { PrincipalPicker } from "./PrincipalPicker.js";
|
|
7
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
7
|
import { useId, useRef, useState } from "react";
|
|
8
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
9
|
//#region src/access/GrantView.tsx
|
|
10
10
|
/** The grant form's body and footer, which the drawer lays out in its own body and footer. */
|
|
11
|
-
function useGrantView({ model, selection, onSelectionChange, resourceName, describeGroup, searchPrincipals, groupCount, peopleCount, recentPrincipalIds, cache, seen, saving, failure, onGrant, onCancel, focusLater, boundary, t }) {
|
|
11
|
+
function useGrantView({ model, selection, onSelectionChange, resourceName, describeGroup, searchPrincipals, groupCount, peopleCount, recentPrincipalIds, cache, seen, saving, failure, onGrant, onCancel, focusLater, boundary, singleRole = false, t }) {
|
|
12
12
|
const uid = useId();
|
|
13
13
|
const [confirming, setConfirming] = useState(false);
|
|
14
14
|
const keepButton = useRef(null);
|
|
@@ -61,9 +61,13 @@ function useGrantView({ model, selection, onSelectionChange, resourceName, descr
|
|
|
61
61
|
};
|
|
62
62
|
const grant = () => {
|
|
63
63
|
setConfirming(false);
|
|
64
|
+
const revoke = singleRole ? [...new Set(plan.grant.map((granted) => granted.principalId))].flatMap((principalId) => (model.held.get(principalId) ?? []).filter((held) => !roleIds.includes(held.id)).map((held) => ({
|
|
65
|
+
principalId,
|
|
66
|
+
roleId: held.id
|
|
67
|
+
}))) : [];
|
|
64
68
|
onGrant({
|
|
65
69
|
grant: plan.grant,
|
|
66
|
-
revoke
|
|
70
|
+
revoke
|
|
67
71
|
});
|
|
68
72
|
};
|
|
69
73
|
const statusId = `${uid}status`;
|
|
@@ -98,7 +102,16 @@ function useGrantView({ model, selection, onSelectionChange, resourceName, descr
|
|
|
98
102
|
htmlFor: `${uid}roles`,
|
|
99
103
|
className: "mb-1.5 block text-sm font-medium",
|
|
100
104
|
children: t.rolesLabel
|
|
101
|
-
}), /* @__PURE__ */ jsx(Combobox, {
|
|
105
|
+
}), singleRole ? /* @__PURE__ */ jsx(Combobox, {
|
|
106
|
+
id: `${uid}roles`,
|
|
107
|
+
items: roleItems,
|
|
108
|
+
value: roleIds[0] ?? null,
|
|
109
|
+
onValueChange: (next) => onSelectionChange({
|
|
110
|
+
principalIds,
|
|
111
|
+
roleIds: next === null ? [] : [next]
|
|
112
|
+
}),
|
|
113
|
+
placeholder: t.searchRoles
|
|
114
|
+
}) : /* @__PURE__ */ jsx(Combobox, {
|
|
102
115
|
multiple: true,
|
|
103
116
|
id: `${uid}roles`,
|
|
104
117
|
items: roleItems,
|
|
@@ -9,8 +9,8 @@ import { Combobox } from "../components/Combobox.js";
|
|
|
9
9
|
import { useRelativeTime } from "../components/relativeTime.js";
|
|
10
10
|
import { StatusBadge } from "../components/StatusBadge.js";
|
|
11
11
|
import { covers, isOwner } from "./model.js";
|
|
12
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
13
12
|
import { useEffect, useMemo, useState } from "react";
|
|
13
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
14
14
|
//#region src/access/PrincipalPicker.tsx
|
|
15
15
|
/** Waits this long on a highlighted group before asking for its details, so arrowing past
|
|
16
16
|
* groups doesn't ask for each one. */
|
|
@@ -124,7 +124,7 @@ function PrincipalPicker({ model, value, onValueChange, granting, describeGroup,
|
|
|
124
124
|
return principal?.kind === "everyone" ? t.everyoneInOrganization : principal?.name ?? principalId;
|
|
125
125
|
};
|
|
126
126
|
const highlightedPrincipal = highlighted === void 0 ? void 0 : seen.get(highlighted);
|
|
127
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Combobox, {
|
|
127
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Combobox, {
|
|
128
128
|
multiple: true,
|
|
129
129
|
id,
|
|
130
130
|
"aria-describedby": describedBy,
|
|
@@ -261,7 +261,7 @@ function Updated({ value, t }) {
|
|
|
261
261
|
});
|
|
262
262
|
}
|
|
263
263
|
function DetailsLine({ details, t }) {
|
|
264
|
-
return /* @__PURE__ */ jsx(Fragment, { children: [details.source === "synced" && t.syncedShort, memberLine(details, 2, t)].filter(Boolean).join(" · ") });
|
|
264
|
+
return /* @__PURE__ */ jsx(Fragment$1, { children: [details.source === "synced" && t.syncedShort, memberLine(details, 2, t)].filter(Boolean).join(" · ") });
|
|
265
265
|
}
|
|
266
266
|
/** What the highlighted one holds here, and what granting the picked roles would change. */
|
|
267
267
|
function OnResource({ principalId, model, granting, t }) {
|
|
@@ -383,7 +383,7 @@ function GroupDetailsPane({ group, state, model, granting, t }) {
|
|
|
383
383
|
className: "rounded-full"
|
|
384
384
|
})
|
|
385
385
|
]
|
|
386
|
-
}) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
386
|
+
}) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
387
387
|
state.failed && /* @__PURE__ */ jsx("p", {
|
|
388
388
|
className: "m-0 text-xs text-(--theme-error-text)",
|
|
389
389
|
children: t.detailsFailed
|
|
@@ -394,7 +394,7 @@ function GroupDetailsPane({ group, state, model, granting, t }) {
|
|
|
394
394
|
}),
|
|
395
395
|
count !== void 0 && /* @__PURE__ */ jsxs("div", { children: [
|
|
396
396
|
/* @__PURE__ */ jsx(PaneHeading, { children: everyone ? t.people(count) : t.members(count) }),
|
|
397
|
-
details && details.members.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Faces, {
|
|
397
|
+
details && details.members.length > 0 && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Faces, {
|
|
398
398
|
details,
|
|
399
399
|
t
|
|
400
400
|
}), /* @__PURE__ */ jsx("p", {
|
package/dist/access/focus.js
CHANGED
|
@@ -5,7 +5,7 @@ import { useCallback, useEffect, useRef } from "react";
|
|
|
5
5
|
* later, which would undo wherever focus is sent next; parked, nothing is lost and it doesn't. */
|
|
6
6
|
function holdFocus() {
|
|
7
7
|
const active = document.activeElement;
|
|
8
|
-
const dialog = active instanceof HTMLElement ? active.closest("[role=\"dialog\"]") : null;
|
|
8
|
+
const dialog = active instanceof HTMLElement ? active.closest("[role=\"dialog\"], [data-access-panel]") : null;
|
|
9
9
|
if (dialog && dialog !== active) dialog.focus({ preventScroll: true });
|
|
10
10
|
}
|
|
11
11
|
/** Returns a function that sends focus to what `find` returns once the change it goes with
|
package/dist/access/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { type AccessArrangement, AccessDrawer, type AccessDrawerProps } from './AccessDrawer.js';
|
|
1
|
+
export { type AccessArrangement, AccessDrawer, type AccessDrawerProps, type AccessEditorProps, AccessPanel, type AccessPanelProps, } from './AccessDrawer.js';
|
|
2
2
|
export { ACCESS_STRINGS, type AccessStrings, type AccessText, useAccessStrings, } from './strings.js';
|
|
3
|
-
export type { AccessChange, AccessGrant, AccessGroupDetails, AccessInheritedGrant, AccessMember, AccessPermission, AccessPrincipal, AccessRole, } from './types.js';
|
|
3
|
+
export type { AccessChange, AccessGrant, AccessGroupDetails, AccessInheritedGrant, AccessMember, AccessPermission, AccessPrincipal, AccessRole, AccessRule, AccessVisibility, } from './types.js';
|
package/dist/access/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { ACCESS_STRINGS, useAccessStrings } from "./strings.js";
|
|
2
|
-
import { AccessDrawer } from "./AccessDrawer.js";
|
|
3
|
-
export { ACCESS_STRINGS, AccessDrawer, useAccessStrings };
|
|
2
|
+
import { AccessDrawer, AccessPanel } from "./AccessDrawer.js";
|
|
3
|
+
export { ACCESS_STRINGS, AccessDrawer, AccessPanel, useAccessStrings };
|
package/dist/access/strings.d.ts
CHANGED
|
@@ -76,6 +76,24 @@ export declare const ACCESS_STRINGS: {
|
|
|
76
76
|
readOnly: string;
|
|
77
77
|
/** After `readOnly` when the host gives no reason. */
|
|
78
78
|
readOnlyReason: string;
|
|
79
|
+
/** Names the switch between open to everyone and only those listed. */
|
|
80
|
+
visibility: string;
|
|
81
|
+
/** The switch's choice that limits it to the people and groups listed. */
|
|
82
|
+
restrictedLabel: string;
|
|
83
|
+
/** The toast after the switch saves; `choice` is the label now chosen. */
|
|
84
|
+
visibilityChanged: (choice: string) => string;
|
|
85
|
+
visibilityFailed: (choice: string) => string;
|
|
86
|
+
/** Names the role picker on a row where each person or group holds one role. */
|
|
87
|
+
roleFor: (principal: string) => string;
|
|
88
|
+
/** A row menu's submenu of roles. */
|
|
89
|
+
roleMenu: string;
|
|
90
|
+
/** A row menu's action that takes every role the row holds here. */
|
|
91
|
+
removeAccess: string;
|
|
92
|
+
/** The toast after a row's one role is swapped for another. */
|
|
93
|
+
roleChanged: (principal: string, role: string) => string;
|
|
94
|
+
roleChangeFailed: (principal: string, role: string) => string;
|
|
95
|
+
/** Read with a rule's faces: the first few by name, and how many more. */
|
|
96
|
+
ruleMembers: (names: readonly string[], more: number) => string;
|
|
79
97
|
emptyTitle: string;
|
|
80
98
|
emptyDescription: (resource: string) => string;
|
|
81
99
|
noMatches: string;
|
package/dist/access/strings.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useStrings } from "../components/Provider.js";
|
|
2
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
2
|
import { useMemo } from "react";
|
|
3
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
4
4
|
//#region src/access/strings.tsx
|
|
5
5
|
var plural = new Intl.PluralRules("en");
|
|
6
6
|
var list = new Intl.ListFormat("en", { type: "conjunction" });
|
|
@@ -101,6 +101,24 @@ var ACCESS_STRINGS = {
|
|
|
101
101
|
readOnly: "View only.",
|
|
102
102
|
/** After `readOnly` when the host gives no reason. */
|
|
103
103
|
readOnlyReason: "Only people who manage access can make changes.",
|
|
104
|
+
/** Names the switch between open to everyone and only those listed. */
|
|
105
|
+
visibility: "Who can see it",
|
|
106
|
+
/** The switch's choice that limits it to the people and groups listed. */
|
|
107
|
+
restrictedLabel: "Only people with access",
|
|
108
|
+
/** The toast after the switch saves; `choice` is the label now chosen. */
|
|
109
|
+
visibilityChanged: (choice) => `Changed to ${choice}`,
|
|
110
|
+
visibilityFailed: (choice) => `Couldn’t change to ${choice}`,
|
|
111
|
+
/** Names the role picker on a row where each person or group holds one role. */
|
|
112
|
+
roleFor: (principal) => `Role for ${principal}`,
|
|
113
|
+
/** A row menu's submenu of roles. */
|
|
114
|
+
roleMenu: "Role",
|
|
115
|
+
/** A row menu's action that takes every role the row holds here. */
|
|
116
|
+
removeAccess: "Remove access",
|
|
117
|
+
/** The toast after a row's one role is swapped for another. */
|
|
118
|
+
roleChanged: (principal, role) => `Changed ${principal} to ${role}`,
|
|
119
|
+
roleChangeFailed: (principal, role) => `Couldn’t change ${principal} to ${role}`,
|
|
120
|
+
/** Read with a rule's faces: the first few by name, and how many more. */
|
|
121
|
+
ruleMembers: (names, more) => more > 0 ? `Includes ${and([...names, `${more.toLocaleString()} more`])}` : `Includes ${and(names)}`,
|
|
104
122
|
emptyTitle: "No access granted",
|
|
105
123
|
emptyDescription: (resource) => `Grant a role to a person or group to give them access to ${resource}.`,
|
|
106
124
|
noMatches: "No matches",
|
|
@@ -132,7 +150,7 @@ var ACCESS_STRINGS = {
|
|
|
132
150
|
alreadyCovered: (roles) => `Included in ${and(roles)}`,
|
|
133
151
|
everyoneHasIt: "Already granted to Everyone",
|
|
134
152
|
/** The footer's account of what pressing Grant does. */
|
|
135
|
-
grantSummary: (principals, roles) => /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("strong", {
|
|
153
|
+
grantSummary: (principals, roles) => /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("strong", {
|
|
136
154
|
className: "font-medium text-(--theme-app)",
|
|
137
155
|
children: and(roles)
|
|
138
156
|
}), ` for ${and(principals)}`] }),
|
package/dist/access/types.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
1
2
|
import type { TimeValue } from '../format.js';
|
|
2
3
|
/** A named set of permissions. People and groups are granted roles, never permissions one by
|
|
3
4
|
* one. */
|
|
@@ -72,3 +73,28 @@ export interface AccessGroupDetails {
|
|
|
72
73
|
/** When its membership last changed. */
|
|
73
74
|
updatedAt?: TimeValue;
|
|
74
75
|
}
|
|
76
|
+
/** A reason someone has access that no grant here changes, such as "Workspace admins always
|
|
77
|
+
* have access". It shows, locked, ahead of the grants. */
|
|
78
|
+
export interface AccessRule {
|
|
79
|
+
id: string;
|
|
80
|
+
/** In the leading column, in place of a section's chevron. */
|
|
81
|
+
icon?: ReactNode;
|
|
82
|
+
title: string;
|
|
83
|
+
/** A line under the title, such as who sets it. */
|
|
84
|
+
detail?: string | undefined;
|
|
85
|
+
/** A few of the people it covers, shown as overlapping faces: four, then how many more. */
|
|
86
|
+
people?: readonly AccessMember[] | undefined;
|
|
87
|
+
/** The role it gives, when it gives everyone it covers the same one. */
|
|
88
|
+
roleId?: string | undefined;
|
|
89
|
+
}
|
|
90
|
+
/** Whether a resource is open to everyone who can see what it is in, or only to those listed. */
|
|
91
|
+
export interface AccessVisibility {
|
|
92
|
+
restricted: boolean;
|
|
93
|
+
/** Saves the switch, as `onChange` saves a grant: until the promise settles the switch shows
|
|
94
|
+
* it is saving, and when it rejects the panel says nothing changed and offers to retry. */
|
|
95
|
+
onChange: (restricted: boolean) => void | Promise<unknown>;
|
|
96
|
+
/** The open choice, which names what it is open to: "Everyone in the workspace". */
|
|
97
|
+
openLabel: string;
|
|
98
|
+
/** The restricted choice; defaults to the strings' "Only people with access". */
|
|
99
|
+
restrictedLabel?: string | undefined;
|
|
100
|
+
}
|
|
@@ -4,8 +4,8 @@ import { useChatConfig } from "../core/config.js";
|
|
|
4
4
|
import { useChat } from "../core/ChatProvider.js";
|
|
5
5
|
import { chipClassName } from "../ui/chip.js";
|
|
6
6
|
import { isOrgModel } from "../utils.js";
|
|
7
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
7
|
import { useEffect } from "react";
|
|
8
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
9
|
import useSWR from "swr";
|
|
10
10
|
//#region src/ai/components/AllocationSelector.tsx
|
|
11
11
|
var dollars = new Intl.NumberFormat(void 0, {
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { cx } from "../../cx.js";
|
|
2
|
+
import { EmptyState } from "../../components/EmptyState.js";
|
|
2
3
|
import { DownloadIcon, FileIcon, TrashIcon } from "../../icons.js";
|
|
3
4
|
import { safeUrl } from "../../safeUrl.js";
|
|
4
5
|
import { Loader } from "../../components/Loader.js";
|
|
5
6
|
import { toast } from "../../components/Toast.js";
|
|
6
7
|
import { Tooltip } from "../../components/Tooltip.js";
|
|
7
8
|
import { useStrings } from "../../components/Provider.js";
|
|
8
|
-
import { EmptyState } from "../../components/EmptyState.js";
|
|
9
9
|
import { formatBytes } from "../../format.js";
|
|
10
10
|
import { RelativeTime } from "../../components/relativeTime.js";
|
|
11
11
|
import { useChatConfig } from "../core/config.js";
|
|
12
12
|
import { useChat } from "../core/ChatProvider.js";
|
|
13
13
|
import { attachmentsPageKey } from "./attachmentKeys.js";
|
|
14
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
15
14
|
import { useCallback, useMemo, useState } from "react";
|
|
15
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
16
16
|
import useSWRInfinite from "swr/infinite";
|
|
17
17
|
//#region src/ai/components/AttachmentManager.tsx
|
|
18
18
|
function AttachmentManager() {
|
|
@@ -64,7 +64,7 @@ function AttachmentManager() {
|
|
|
64
64
|
}) : attachments.length === 0 ? /* @__PURE__ */ jsx(EmptyState, {
|
|
65
65
|
variant: "bare",
|
|
66
66
|
title: t.empty
|
|
67
|
-
}) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
|
|
67
|
+
}) : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("div", {
|
|
68
68
|
className: "grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4",
|
|
69
69
|
children: attachments.map((att) => {
|
|
70
70
|
const downloadUrl = safeUrl(attachmentsAdapter.downloadUrl(att.id));
|
|
@@ -72,7 +72,7 @@ function AttachmentManager() {
|
|
|
72
72
|
const isDeleting = deleting === att.id;
|
|
73
73
|
const thumbnail = thumbnails[att.id];
|
|
74
74
|
const showThumbnail = att.contentType?.startsWith("image/") && thumbnail !== "broken";
|
|
75
|
-
const preview = /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(FileIcon, {
|
|
75
|
+
const preview = /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(FileIcon, {
|
|
76
76
|
"aria-hidden": "true",
|
|
77
77
|
className: "w-8 h-8 theme-muted-text"
|
|
78
78
|
}), showThumbnail && /* @__PURE__ */ jsx("img", {
|
|
@@ -104,7 +104,7 @@ function AttachmentManager() {
|
|
|
104
104
|
children: name
|
|
105
105
|
}), /* @__PURE__ */ jsxs("p", {
|
|
106
106
|
className: "truncate theme-muted-text",
|
|
107
|
-
children: [att.size ? formatBytes(att.size) : "", att.uploadedAt && /* @__PURE__ */ jsxs(Fragment, { children: [att.size ? " · " : "", /* @__PURE__ */ jsx(RelativeTime, { value: att.uploadedAt })] })]
|
|
107
|
+
children: [att.size ? formatBytes(att.size) : "", att.uploadedAt && /* @__PURE__ */ jsxs(Fragment$1, { children: [att.size ? " · " : "", /* @__PURE__ */ jsx(RelativeTime, { value: att.uploadedAt })] })]
|
|
108
108
|
})]
|
|
109
109
|
}), /* @__PURE__ */ jsxs("div", {
|
|
110
110
|
className: "flex items-center gap-0.5 flex-shrink-0",
|
|
@@ -6,8 +6,8 @@ import { formatBytes } from "../../format.js";
|
|
|
6
6
|
import { useChatConfig } from "../core/config.js";
|
|
7
7
|
import { useChat } from "../core/ChatProvider.js";
|
|
8
8
|
import { ATTACHMENTS_INFINITE_KEY } from "./attachmentKeys.js";
|
|
9
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
10
9
|
import { useCallback, useImperativeHandle, useLayoutEffect, useRef, useState } from "react";
|
|
10
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
11
11
|
import { mutate } from "swr";
|
|
12
12
|
//#region src/ai/components/AttachmentUpload.tsx
|
|
13
13
|
var DEFAULT_MAX_FILE_SIZE = 26214400;
|
|
@@ -118,7 +118,7 @@ function AttachmentUpload({ conversationId, attachments, onAttachmentsChange, di
|
|
|
118
118
|
const handleClick = () => {
|
|
119
119
|
fileInputRef.current?.click();
|
|
120
120
|
};
|
|
121
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("input", {
|
|
121
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("input", {
|
|
122
122
|
ref: fileInputRef,
|
|
123
123
|
type: "file",
|
|
124
124
|
multiple: true,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { ChevronLeftIcon, ChevronRightIcon } from "../../icons.js";
|
|
2
2
|
import { IconButton } from "../../components/IconButton.js";
|
|
3
3
|
import { useChatConfig } from "../core/config.js";
|
|
4
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
4
|
import { useMemo } from "react";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
//#region src/ai/components/BranchNavigator.tsx
|
|
7
7
|
function findSiblings(messages, messageId) {
|
|
8
8
|
const message = messages.find((m) => m.id === messageId);
|
|
@@ -2,8 +2,8 @@ import { toolHeaderFor } from "../agent/toolfmt.js";
|
|
|
2
2
|
import { useChatConfig } from "../core/config.js";
|
|
3
3
|
import { useChat, useChatStream } from "../core/ChatProvider.js";
|
|
4
4
|
import ActivityLine from "./agent/ActivityLine.js";
|
|
5
|
-
import { jsx } from "react/jsx-runtime";
|
|
6
5
|
import { useEffect, useState } from "react";
|
|
6
|
+
import { jsx } from "react/jsx-runtime";
|
|
7
7
|
import { DateTime } from "luxon";
|
|
8
8
|
//#region src/ai/components/ChatActivity.tsx
|
|
9
9
|
/** An agent session's working line for the provider's reply, naming its current step. */
|