@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.
Files changed (146) hide show
  1. package/README.md +36 -1
  2. package/dist/AccessDeniedCard/AccessDeniedCard.d.ts +39 -0
  3. package/dist/AccessDeniedCard/index.d.ts +3 -0
  4. package/dist/AccessDeniedCard/index.js +8 -0
  5. package/dist/AccessDeniedCard-WXM5DBDZ.css +8 -0
  6. package/dist/ArtifactCard/ArtifactCard.d.ts +61 -0
  7. package/dist/ArtifactCard/index.d.ts +3 -0
  8. package/dist/ArtifactCard/index.js +12 -0
  9. package/dist/ArtifactCard-EXVAEBV6.css +109 -0
  10. package/dist/AvatarPicker/index.js +4 -4
  11. package/dist/ChangeMark/ChangeMark.d.ts +26 -0
  12. package/dist/ChangeMark/index.d.ts +3 -0
  13. package/dist/ChangeMark/index.js +8 -0
  14. package/dist/ChangeMark-3VMTW7MT.css +22 -0
  15. package/dist/Combobox/index.js +1 -1
  16. package/dist/CommandPalette/index.js +3 -3
  17. package/dist/CursorFlag/CursorFlag.d.ts +34 -0
  18. package/dist/CursorFlag/index.d.ts +3 -0
  19. package/dist/CursorFlag/index.js +3 -0
  20. package/dist/CursorFlag-AJQJBUGY.css +61 -0
  21. package/dist/DataTable/index.js +6 -6
  22. package/dist/DataView/index.js +12 -12
  23. package/dist/DateTimePicker/index.js +2 -2
  24. package/dist/FollowBanner/FollowBanner.d.ts +35 -0
  25. package/dist/FollowBanner/index.d.ts +2 -0
  26. package/dist/FollowBanner/index.js +7 -0
  27. package/dist/FrameProtocol/index.d.ts +2 -0
  28. package/dist/FrameProtocol/index.js +2 -0
  29. package/dist/FrameProtocol/protocol.d.ts +164 -0
  30. package/dist/HuePicker/index.js +2 -2
  31. package/dist/LinkInterstitial/LinkInterstitial.d.ts +41 -0
  32. package/dist/LinkInterstitial/index.d.ts +3 -0
  33. package/dist/LinkInterstitial/index.js +11 -0
  34. package/dist/LinkInterstitial-ET4MSVSV.css +34 -0
  35. package/dist/ListInput/index.js +1 -1
  36. package/dist/LiveCursor/LiveCursor.d.ts +34 -0
  37. package/dist/LiveCursor/index.d.ts +3 -0
  38. package/dist/LiveCursor/index.js +4 -0
  39. package/dist/LiveCursor-DZHGIYWE.css +47 -0
  40. package/dist/MarkdownEditor/index.js +2 -2
  41. package/dist/Modal/index.js +2 -2
  42. package/dist/OrgTable/index.js +2 -2
  43. package/dist/PresenceModel/index.d.ts +2 -0
  44. package/dist/PresenceModel/index.js +3 -0
  45. package/dist/PresenceModel/presence.d.ts +80 -0
  46. package/dist/PresenceRing/PresenceRing.d.ts +31 -0
  47. package/dist/PresenceRing/index.d.ts +3 -0
  48. package/dist/PresenceRing/index.js +2 -0
  49. package/dist/PresenceRing-M4C22Q6U.css +68 -0
  50. package/dist/PresenceStack/PresenceStack.d.ts +36 -0
  51. package/dist/PresenceStack/index.d.ts +3 -0
  52. package/dist/PresenceStack/index.js +9 -0
  53. package/dist/PresenceStack-QSXQJND5.css +59 -0
  54. package/dist/PricingCard/index.js +2 -2
  55. package/dist/Principal/Principal.d.ts +35 -0
  56. package/dist/Principal/index.d.ts +2 -0
  57. package/dist/Principal/index.js +4 -0
  58. package/dist/PrincipalPicker/PrincipalPicker.d.ts +45 -0
  59. package/dist/PrincipalPicker/index.d.ts +3 -0
  60. package/dist/PrincipalPicker/index.js +12 -0
  61. package/dist/PrincipalPicker-7NNZTGUP.css +41 -0
  62. package/dist/SandboxedFrame/SandboxedFrame.d.ts +142 -0
  63. package/dist/SandboxedFrame/index.d.ts +3 -0
  64. package/dist/SandboxedFrame/index.js +8 -0
  65. package/dist/SandboxedFrame-L6HBQZCD.css +50 -0
  66. package/dist/ShareDialog/ShareDialog.d.ts +101 -0
  67. package/dist/ShareDialog/index.d.ts +5 -0
  68. package/dist/ShareDialog/index.js +19 -0
  69. package/dist/ShareDialog/roles.d.ts +10 -0
  70. package/dist/ShareDialog-YZ4F37MW.css +146 -0
  71. package/dist/SheetGrid/SheetGrid.d.ts +78 -0
  72. package/dist/SheetGrid/cells.d.ts +117 -0
  73. package/dist/SheetGrid/index.d.ts +5 -0
  74. package/dist/SheetGrid/index.js +18 -0
  75. package/dist/SheetGrid-4HOXDVIB.css +595 -0
  76. package/dist/SheetModel/clipboard.d.ts +37 -0
  77. package/dist/SheetModel/edits.d.ts +68 -0
  78. package/dist/SheetModel/index.d.ts +14 -0
  79. package/dist/SheetModel/index.js +3 -0
  80. package/dist/SheetModel/labels.d.ts +71 -0
  81. package/dist/SheetModel/navigation.d.ts +79 -0
  82. package/dist/SheetModel/options.d.ts +28 -0
  83. package/dist/SheetModel/types.d.ts +126 -0
  84. package/dist/SheetModel/values.d.ts +76 -0
  85. package/dist/SheetModel/view.d.ts +32 -0
  86. package/dist/Switcher/index.js +5 -5
  87. package/dist/Tag/Tag.d.ts +13 -0
  88. package/dist/Tag/index.js +1 -1
  89. package/dist/{Tag-4BRQS6GN.css → Tag-SRGTK5KI.css} +42 -0
  90. package/dist/TagsInput/index.js +2 -2
  91. package/dist/ThemeSwitcher/apply.d.ts +43 -0
  92. package/dist/ThemeSwitcher/index.d.ts +4 -2
  93. package/dist/ThemeSwitcher/index.js +3 -2
  94. package/dist/ThemeSwitcher/preferences.d.ts +2 -19
  95. package/dist/ThemeToggle/index.js +3 -2
  96. package/dist/TimeWindowPicker/index.js +3 -3
  97. package/dist/Timeline/Timeline.d.ts +7 -2
  98. package/dist/Timeline/index.js +1 -1
  99. package/dist/VersionTimeline/VersionTimeline.d.ts +76 -0
  100. package/dist/VersionTimeline/index.d.ts +3 -0
  101. package/dist/VersionTimeline/index.js +10 -0
  102. package/dist/VersionTimeline-EBJ6MIPJ.css +108 -0
  103. package/dist/{chunk-SBRE7IML.js → chunk-2ONWEDQT.js} +1 -1
  104. package/dist/chunk-2YR5ZPQ3.js +216 -0
  105. package/dist/chunk-3BYIWOTV.js +29 -0
  106. package/dist/chunk-3UAA4IWJ.js +98 -0
  107. package/dist/chunk-4KP4RC3O.js +25 -0
  108. package/dist/chunk-4U3GQ7D2.js +99 -0
  109. package/dist/chunk-5XACKNYR.js +53 -0
  110. package/dist/{chunk-RF5O4FYL.js → chunk-76FXDZAZ.js} +2 -2
  111. package/dist/chunk-A7EBCHEG.js +49 -0
  112. package/dist/{chunk-JCO3SIST.js → chunk-AQCV62K6.js} +1 -1
  113. package/dist/{chunk-O67VF5MS.js → chunk-AUQPBL4O.js} +2 -2
  114. package/dist/{chunk-HENOTGUV.js → chunk-BOW2VUCH.js} +2 -2
  115. package/dist/{chunk-UCYIRDND.js → chunk-DQSXWQMJ.js} +1 -1
  116. package/dist/chunk-ESKP3TXM.js +1 -0
  117. package/dist/chunk-F6V2PTN6.js +142 -0
  118. package/dist/chunk-FW7HN6AP.js +40 -0
  119. package/dist/chunk-FYXRWBJJ.js +1235 -0
  120. package/dist/{chunk-LOECRMHA.js → chunk-GFV4LJHH.js} +4 -3
  121. package/dist/chunk-I6POAB4V.js +20 -0
  122. package/dist/{chunk-PQ63NLFC.js → chunk-IFKBDRNJ.js} +1 -1
  123. package/dist/{chunk-XU4H6JQB.js → chunk-KVT3TJVG.js} +4 -4
  124. package/dist/chunk-LFZ45HV2.js +46 -0
  125. package/dist/{chunk-6TSZCBID.js → chunk-NP2C4Y4E.js} +1 -1
  126. package/dist/{chunk-FA2V2VT6.js → chunk-NZY77ZDU.js} +3 -3
  127. package/dist/chunk-PPAQFGS2.js +12 -0
  128. package/dist/chunk-S35G6PNC.js +80 -0
  129. package/dist/chunk-VYDFB6PJ.js +243 -0
  130. package/dist/chunk-WXAULPBH.js +135 -0
  131. package/dist/chunk-YM3GJHGW.js +69 -0
  132. package/dist/chunk-YYZRLLLY.js +822 -0
  133. package/dist/{chunk-K3OWD7BJ.js → chunk-Z24ZUSTX.js} +4 -19
  134. package/dist/chunk-ZXXDZJQN.js +36 -0
  135. package/dist/generated/index.d.ts +18 -0
  136. package/dist/generated/index.js +82 -62
  137. package/dist/index.js +82 -62
  138. package/dist/styles.css +1578 -149
  139. package/dist/utils/index.js +1 -1
  140. package/package.json +6 -6
  141. package/dist/{chunk-DEEVA6TV.js → chunk-2TZATTIU.js} +1 -1
  142. package/dist/{chunk-2UU5IGZI.js → chunk-5NVKTB6E.js} +1 -1
  143. package/dist/{chunk-CRVETI5L.js → chunk-CENOOTAV.js} +0 -0
  144. package/dist/{chunk-JF7X673Z.js → chunk-ERV5BUS3.js} +1 -1
  145. package/dist/{chunk-NXDEPUVG.js → chunk-PA4CYTBY.js} +1 -1
  146. package/dist/{chunk-77IEHFY4.js → chunk-QQGWES46.js} +1 -1
@@ -0,0 +1,36 @@
1
+ import { type AvatarSizeStep } from '../Avatar/index.js';
2
+ import { type PresenceLabels, type PresenceMember } from '../PresenceModel/index.js';
3
+ export interface PresenceStackProps {
4
+ /** Everybody present but the reader, in the order they joined. The stack orders them by activity. */
5
+ members: readonly PresenceMember[];
6
+ /** Whether the reader is present too, which is what the accessible name counts from: "You and 3 others are here". */
7
+ self?: boolean | undefined;
8
+ /** How many badges are drawn before the rest are counted in a chip. Four by default. */
9
+ max?: number | undefined;
10
+ size?: AvatarSizeStep | undefined;
11
+ /**
12
+ * Makes each badge a button: a host opens its own menu from it ("Follow
13
+ * Maya", "Open turn"). Without it the stack is one image with one name.
14
+ */
15
+ onSelect?: ((member: PresenceMember) => void) | undefined;
16
+ /** The stack's accessible name, where the derived one is not what it means where it stands. */
17
+ label?: string | undefined;
18
+ labels?: Partial<PresenceLabels> | undefined;
19
+ className?: string | undefined;
20
+ }
21
+ /**
22
+ * Who is here, at a glance: the badges of everybody present in an artifact,
23
+ * people editing first, then agents editing, people viewing, agents reading,
24
+ * and anybody idle last.
25
+ *
26
+ * A PRESENT BADGE WEARS A RING IN THE COLLABORATOR'S HUE, the same hue their
27
+ * cursor and cell outline are drawn in, which is how a reader matches a ring
28
+ * on a cell to a face in the stack. It is the presence colour exception (D22):
29
+ * the badge carries the name, and the ring is never the only carrier. An idle
30
+ * collaborator's badge loses its ring and fades, and says "Idle" in words.
31
+ *
32
+ * Built on the avatar stack's own geometry (the overlap, the cut-out ring in
33
+ * the ground's colour, the counted chip), so a presence stack and a stack of
34
+ * watchers beside it are one mark.
35
+ */
36
+ export declare function PresenceStack({ members, self, max, size, onSelect, label, labels, className }: PresenceStackProps): import("react").JSX.Element | null;
@@ -0,0 +1,3 @@
1
+ import './PresenceStack.css';
2
+ export { PresenceStack } from './PresenceStack.js';
3
+ export type { PresenceStackProps } from './PresenceStack.js';
@@ -0,0 +1,9 @@
1
+ export { PresenceStack } from '../chunk-YM3GJHGW.js';
2
+ import '../chunk-CENOOTAV.js';
3
+ import '../chunk-I6POAB4V.js';
4
+ import '../chunk-S35G6PNC.js';
5
+ import '../chunk-AYKXMIOR.js';
6
+ import '../chunk-UAN5NE7M.js';
7
+ import '../chunk-5OM447RW.js';
8
+ import '../chunk-BZFWDIV6.js';
9
+ import '../chunk-ODEQTPFM.js';
@@ -0,0 +1,59 @@
1
+ /*
2
+ * Who is here (PresenceStack.tsx), on the avatar stack's own geometry: the
3
+ * overlap and the counted chip are the stack's. What this adds is the ring in
4
+ * each present collaborator's hue, outside the cut-out, and the idle fade.
5
+ */
6
+
7
+ /* The wrapper (a span, or a button when badges select) carries no edge of its
8
+ own: the cut-out and the hue ring are drawn on the badge inside it, which
9
+ has the badge's own outline to follow. */
10
+ .crewlet-presence-stack > .crewlet-presence-stack__member {
11
+ display: inline-flex;
12
+ flex: none;
13
+ padding: 0;
14
+ border: 0;
15
+ background: none;
16
+ box-shadow: none;
17
+ color: inherit;
18
+ font: inherit;
19
+ }
20
+
21
+ .crewlet-presence-stack > .crewlet-presence-stack__member--human {
22
+ border-radius: var(--radius-circle);
23
+ }
24
+
25
+ .crewlet-presence-stack > .crewlet-presence-stack__member--agent {
26
+ border-radius: var(--radius-sm);
27
+ }
28
+
29
+ button.crewlet-presence-stack__member {
30
+ cursor: pointer;
31
+ }
32
+
33
+ button.crewlet-presence-stack__member:focus-visible {
34
+ outline: 2px solid var(--color-focus);
35
+ outline-offset: var(--size-focus-ring-inset-offset);
36
+ }
37
+
38
+ .crewlet-presence-stack .crewlet-presence-stack__badge {
39
+ box-shadow: 0 0 0 2px var(--crewlet-avatar-stack-ground);
40
+ }
41
+
42
+ /* The hue ring sits outside the cut-out, so it reads as a ring round the
43
+ badge rather than a stroke on it. */
44
+ .crewlet-presence-stack .crewlet-presence-stack__badge--present {
45
+ box-shadow:
46
+ 0 0 0 2px var(--crewlet-avatar-stack-ground),
47
+ 0 0 0 4px var(--crewlet-presence-hue);
48
+ }
49
+
50
+ .crewlet-presence-stack .crewlet-presence-stack__badge--idle {
51
+ opacity: 0.5;
52
+ }
53
+
54
+ @media (forced-colors: active) {
55
+ .crewlet-presence-stack .crewlet-presence-stack__badge--present {
56
+ outline: 2px solid Highlight;
57
+ outline-offset: 2px;
58
+ }
59
+ }
@@ -1,4 +1,4 @@
1
- export { PricingCard } from '../chunk-UCYIRDND.js';
2
- import '../chunk-LOECRMHA.js';
1
+ export { PricingCard } from '../chunk-DQSXWQMJ.js';
2
+ import '../chunk-GFV4LJHH.js';
3
3
  import '../chunk-WIATRXEJ.js';
4
4
  import '../chunk-ODEQTPFM.js';
@@ -0,0 +1,35 @@
1
+ import type { CrewletCharacterId } from '@crewlethq/icons/characters';
2
+ import { type AvatarSize } from '../Avatar/index.js';
3
+ import type { NodeHue } from '../utils/nodeHue.js';
4
+ /**
5
+ * Who something is shared with, made by or owned by.
6
+ *
7
+ * `person` and `agent` are seats (a person holds a human seat), drawn as the
8
+ * circle and the squircle `Avatar` already draws them as. A `team` is an org
9
+ * unit: everyone in it and below it, people and agents alike, so it is drawn
10
+ * with the people glyph rather than anybody's initials.
11
+ */
12
+ export type PrincipalKind = 'person' | 'agent' | 'team';
13
+ export declare const PRINCIPAL_KINDS: readonly ["person", "agent", "team"];
14
+ export interface Principal {
15
+ /** Stable across renames: a seat handle or a unit key. */
16
+ id: string;
17
+ kind: PrincipalKind;
18
+ name: string;
19
+ /** A short second line: a unit, a handle, "6 people, 4 agents". */
20
+ detail?: string | undefined;
21
+ /** The Crewlet character an agent is drawn as. */
22
+ character?: CrewletCharacterId | undefined;
23
+ /** The hue an agent's character is drawn in. */
24
+ hue?: NodeHue | undefined;
25
+ /** A person's picture. */
26
+ src?: string | undefined;
27
+ }
28
+ export interface PrincipalAvatarProps {
29
+ principal: Principal;
30
+ size?: AvatarSize | undefined;
31
+ /** The name is printed beside the badge, so the badge says nothing itself. Defaults to true. */
32
+ decorative?: boolean | undefined;
33
+ }
34
+ /** A principal's badge, drawn the one way every surface draws it. */
35
+ export declare function PrincipalAvatar({ principal, size, decorative }: PrincipalAvatarProps): import("react").JSX.Element;
@@ -0,0 +1,2 @@
1
+ export { PRINCIPAL_KINDS, PrincipalAvatar } from './Principal.js';
2
+ export type { Principal, PrincipalAvatarProps, PrincipalKind } from './Principal.js';
@@ -0,0 +1,4 @@
1
+ export { PRINCIPAL_KINDS, PrincipalAvatar } from '../chunk-4KP4RC3O.js';
2
+ import '../chunk-UAN5NE7M.js';
3
+ import '../chunk-5OM447RW.js';
4
+ import '../chunk-ODEQTPFM.js';
@@ -0,0 +1,45 @@
1
+ import { type Principal, type PrincipalKind } from '../Principal/index.js';
2
+ /** A principal that may be offered but not taken, with the reason in words. */
3
+ export interface PrincipalOption extends Principal {
4
+ disabled?: boolean | undefined;
5
+ /** Why it cannot be picked: "Already has access", "Only a person can add the whole company". */
6
+ disabledReason?: string | undefined;
7
+ }
8
+ export interface PrincipalPickerLabels {
9
+ /** The heading over each kind's group of suggestions. */
10
+ groups: Record<PrincipalKind, string>;
11
+ empty: string;
12
+ loading: string;
13
+ }
14
+ export interface PrincipalPickerProps {
15
+ /** What the field holds. The caller owns it, and searches with it. */
16
+ query: string;
17
+ onQueryChange: (query: string) => void;
18
+ /**
19
+ * The matches for `query`, in any order: they are grouped people, then
20
+ * agents, then teams. The caller filters, because who matches is the
21
+ * engine's answer, not a substring of a list the browser happens to hold.
22
+ */
23
+ options: readonly PrincipalOption[];
24
+ onPick: (principal: Principal) => void;
25
+ /** Names the field and its list. */
26
+ label: string;
27
+ placeholder?: string | undefined;
28
+ /** A search is in flight; the list says so instead of saying nobody matches. */
29
+ loading?: boolean | undefined;
30
+ disabled?: boolean | undefined;
31
+ className?: string | undefined;
32
+ labels?: Partial<PrincipalPickerLabels> | undefined;
33
+ }
34
+ /**
35
+ * A search over people, agents and teams, with each match drawn as itself.
36
+ *
37
+ * THE LIST IS GROUPED BY KIND, because "Operations" the team and "Operations
38
+ * Lead" the agent are different answers to "who should see this", and a flat
39
+ * list of names makes a reader stop on every row to find out which is which.
40
+ * The groups are real ARIA groups named by their headings, and the highlight
41
+ * still moves through every option in order, across the groups.
42
+ *
43
+ * Picking clears the field, ready for the next name.
44
+ */
45
+ export declare function PrincipalPicker({ query, onQueryChange, options, onPick, label, placeholder, loading, disabled, className, labels, }: PrincipalPickerProps): import("react").JSX.Element;
@@ -0,0 +1,3 @@
1
+ import './PrincipalPicker.css';
2
+ export { PrincipalPicker } from './PrincipalPicker.js';
3
+ export type { PrincipalOption, PrincipalPickerLabels, PrincipalPickerProps } from './PrincipalPicker.js';
@@ -0,0 +1,12 @@
1
+ export { PrincipalPicker } from '../chunk-3UAA4IWJ.js';
2
+ import '../chunk-ZFH7H7GS.js';
3
+ import '../chunk-F73MC7EZ.js';
4
+ import '../chunk-4GB57WIT.js';
5
+ import '../chunk-4FQT6ZAY.js';
6
+ import '../chunk-R25RGPUB.js';
7
+ import '../chunk-4KP4RC3O.js';
8
+ import '../chunk-UAN5NE7M.js';
9
+ import '../chunk-5OM447RW.js';
10
+ import '../chunk-PQADV6P6.js';
11
+ import '../chunk-BZFWDIV6.js';
12
+ import '../chunk-ODEQTPFM.js';
@@ -0,0 +1,41 @@
1
+ /*
2
+ * The suggestions under the field, grouped by kind. A row is the badge and the
3
+ * name with its second line, the shape every list of principals in the
4
+ * product draws.
5
+ */
6
+
7
+ .crewlet-principal-picker {
8
+ flex: 1 1 auto;
9
+ min-width: 0;
10
+ }
11
+
12
+ .crewlet-principal-picker__group + .crewlet-principal-picker__group {
13
+ margin-top: var(--spacing-1);
14
+ padding-top: var(--spacing-1);
15
+ border-top: 1px solid var(--color-border-default);
16
+ }
17
+
18
+ .crewlet-principal-picker__heading {
19
+ padding: var(--spacing-1) var(--spacing-2);
20
+ color: var(--color-text-tertiary);
21
+ font-size: var(--font-size-xs);
22
+ font-weight: var(--font-weight-medium);
23
+ }
24
+
25
+ .crewlet-principal-picker__option {
26
+ display: flex;
27
+ align-items: center;
28
+ gap: var(--spacing-2);
29
+ }
30
+
31
+ .crewlet-principal-picker__text {
32
+ display: flex;
33
+ flex-direction: column;
34
+ min-width: 0;
35
+ }
36
+
37
+ .crewlet-principal-picker__name {
38
+ overflow: hidden;
39
+ text-overflow: ellipsis;
40
+ white-space: nowrap;
41
+ }
@@ -0,0 +1,142 @@
1
+ import { type HTMLAttributes } from 'react';
2
+ import { type FrameBridgeRange, type FrameHello, type FrameOriginMode, type FrameTheme } from '../FrameProtocol/index.js';
3
+ /**
4
+ * Where the frame is in its life.
5
+ *
6
+ * `loading` until the document has said hello, `ready` once it holds a port,
7
+ * and four ends, each torn down rather than left showing a document nobody
8
+ * vouched for: `failed` (it never said hello), `navigated` (a document that did
9
+ * not say hello replaced one that had), `refused` (the policy it arrived with
10
+ * is not one this host embeds) and `outdated` (it speaks no bridge version
11
+ * this host does).
12
+ */
13
+ export type SandboxedFrameState = 'loading' | 'ready' | 'failed' | 'navigated' | 'refused' | 'outdated';
14
+ /**
15
+ * Something the host turned away, reported so the page around the frame can
16
+ * record it. None of these is shown to the reader as more than the frame's
17
+ * own state: they are evidence for whoever reads the logs.
18
+ */
19
+ export type FrameRefusal =
20
+ /** The engine's sandbox attribute carried tokens this host never sets. */
21
+ {
22
+ kind: 'sandbox';
23
+ tokens: string[];
24
+ }
25
+ /** The frame URL is not http or https, or is not served from the origin it was given. */
26
+ | {
27
+ kind: 'src';
28
+ }
29
+ /** The nonce handed to the frame is not the shape the engine mints. */
30
+ | {
31
+ kind: 'nonce';
32
+ }
33
+ /** The embedded window said hello from the wrong origin. */
34
+ | {
35
+ kind: 'origin';
36
+ origin: string;
37
+ }
38
+ /** The embedded window said hello with a nonce that is not this frame's. */
39
+ | {
40
+ kind: 'hello-nonce';
41
+ }
42
+ /** A second hello without a document load between, or any second hello on the shared host. */
43
+ | {
44
+ kind: 'rehello';
45
+ }
46
+ /** The runtime speaks no bridge version this host does. */
47
+ | {
48
+ kind: 'bridge';
49
+ offered: FrameBridgeRange;
50
+ }
51
+ /** The page asked to open something that is not an external http, https or mailto link. */
52
+ | {
53
+ kind: 'link';
54
+ url: string;
55
+ };
56
+ export interface SandboxedFrameLabels {
57
+ /** The loading line, said once to a screen reader and drawn under the placeholder. */
58
+ loading: (title: string) => string;
59
+ failed: string;
60
+ failedDetail: string;
61
+ navigated: string;
62
+ navigatedDetail: string;
63
+ refused: string;
64
+ refusedDetail: string;
65
+ outdated: string;
66
+ outdatedDetail: string;
67
+ reload: string;
68
+ }
69
+ /** How long a document has to say hello after the frame mounts, or after a load, before it is torn down. */
70
+ export declare const FRAME_HELLO_TIMEOUT_MS = 10000;
71
+ type FrameDivAttributes = Omit<HTMLAttributes<HTMLDivElement>, 'title' | 'onMessage' | 'children' | 'role' | 'aria-label'>;
72
+ export interface SandboxedFrameProps extends FrameDivAttributes {
73
+ /** The engine's ticketed frame URL (`Frame.frame_url`). The host appends the fragment. */
74
+ src: string;
75
+ /**
76
+ * The origin the document is served from (`Frame.origin`). Per artifact, the
77
+ * hello must come from exactly this origin. On the shared host the document
78
+ * is opaque, its hello comes from `"null"`, and this may be that host's
79
+ * origin or `"null"` itself.
80
+ */
81
+ origin: string;
82
+ /** How the engine isolated the artifact (`Frame.mode`). */
83
+ mode: FrameOriginMode;
84
+ /** The engine's sandbox attribute (`Frame.sandbox`), set verbatim once it passes the host's own check. */
85
+ sandbox: string;
86
+ /** The engine's permissions attribute (`Frame.allow`), set verbatim. */
87
+ allow?: string | undefined;
88
+ /** The artifact's title. It names the frame, and the region around it, to assistive technology. */
89
+ title: string;
90
+ /**
91
+ * The reader's appearance. The value at mount goes in the fragment, so the
92
+ * first paint is already right; later values are posted on the port.
93
+ */
94
+ theme: FrameTheme;
95
+ /** The handshake nonce minted with the ticket (`Frame.nonce`). */
96
+ nonce: string;
97
+ /** The document said hello and holds its port. Called again for each document that does. */
98
+ onReady?: ((port: MessagePort, hello: FrameHello) => void) | undefined;
99
+ /** Every port message the frame does not handle itself. UNTRUSTED input: decide every call. */
100
+ onMessage?: ((data: unknown, port: MessagePort) => void) | undefined;
101
+ /**
102
+ * The page asked to open an external link. The frame never opens a window
103
+ * itself: the page around it shows the destination first (`LinkInterstitial`).
104
+ */
105
+ onOpenLink?: ((url: URL) => void) | undefined;
106
+ /**
107
+ * The page asked to give focus back, which is how a reader leaves a page
108
+ * that traps Tab. Without a handler, focus moves to the frame's region.
109
+ */
110
+ onFocusExit?: (() => void) | undefined;
111
+ onStateChange?: ((state: SandboxedFrameState) => void) | undefined;
112
+ onRefusal?: ((refusal: FrameRefusal) => void) | undefined;
113
+ /** Offered on every end state as the Reload action. Mint a fresh frame, then re-render with it. */
114
+ onReload?: (() => void) | undefined;
115
+ helloTimeoutMs?: number | undefined;
116
+ labels?: Partial<SandboxedFrameLabels> | undefined;
117
+ }
118
+ /**
119
+ * An artifact's document, embedded in a sandboxed frame and spoken to over one
120
+ * transferred `MessagePort`.
121
+ *
122
+ * THE HANDSHAKE IS THE WHOLE SECURITY OF THE BRIDGE. A hello is accepted only
123
+ * from this iframe's own window, carrying the nonce minted with its ticket,
124
+ * and, per artifact, from the artifact's own origin. Only then is a fresh
125
+ * port transferred, in the same task, to the window that was checked. Every
126
+ * later call travels on that port, which no other window can address, and a
127
+ * document that navigates away loses it.
128
+ *
129
+ * A DOCUMENT THAT DOES NOT ANNOUNCE ITSELF IS TORN DOWN. The engine's runtime
130
+ * says hello on every load, so a load with no hello means the frame now holds
131
+ * a document the engine did not serve, and the frame is removed rather than
132
+ * left on screen. On the shared host, where origins are opaque, a document
133
+ * gets one handshake per ticket; a second document needs a fresh ticket.
134
+ *
135
+ * The frame never opens a window: an external link reaches `onOpenLink`, and
136
+ * the page around the frame decides.
137
+ *
138
+ * A new `src` or `nonce` is a new frame: everything is torn down and started
139
+ * again, as if the component had been remounted.
140
+ */
141
+ export declare function SandboxedFrame(props: SandboxedFrameProps): import("react").JSX.Element;
142
+ export {};
@@ -0,0 +1,3 @@
1
+ import './SandboxedFrame.css';
2
+ export { FRAME_HELLO_TIMEOUT_MS, SandboxedFrame } from './SandboxedFrame.js';
3
+ export type { FrameRefusal, SandboxedFrameLabels, SandboxedFrameProps, SandboxedFrameState } from './SandboxedFrame.js';
@@ -0,0 +1,8 @@
1
+ export { FRAME_HELLO_TIMEOUT_MS, SandboxedFrame } from '../chunk-VYDFB6PJ.js';
2
+ import '../chunk-W5J7R5EB.js';
3
+ import '../chunk-F6V2PTN6.js';
4
+ import '../chunk-ZXXDZJQN.js';
5
+ import '../chunk-SVSCLHHI.js';
6
+ import '../chunk-OG6CL3EB.js';
7
+ import '../chunk-BZFWDIV6.js';
8
+ import '../chunk-ODEQTPFM.js';
@@ -0,0 +1,50 @@
1
+ /*
2
+ * The frame fills the box it is given. The page around it does not scroll
3
+ * round the artifact: the artifact scrolls inside its own document, which is
4
+ * what a viewer body that holds one wants.
5
+ *
6
+ * The region takes focus when the frame hands it back, and keeps the
7
+ * document's own focus treatment then: a reader who just left a page by
8
+ * keyboard needs to see where they landed.
9
+ */
10
+
11
+ .crewlet-sandboxed-frame {
12
+ position: relative;
13
+ display: flex;
14
+ flex-direction: column;
15
+ width: 100%;
16
+ height: 100%;
17
+ min-height: 0;
18
+ overflow: hidden;
19
+ border-radius: var(--radius-md);
20
+ background: var(--color-surface-background);
21
+ }
22
+
23
+ .crewlet-sandboxed-frame__frame {
24
+ flex: 1 1 auto;
25
+ display: block;
26
+ width: 100%;
27
+ height: 100%;
28
+ border: 0;
29
+ background: transparent;
30
+ }
31
+
32
+ /* Kept out of sight while it starts, so a document that has not painted in
33
+ the reader's palette yet is never what they see. It still loads. */
34
+ .crewlet-sandboxed-frame[data-state='loading'] .crewlet-sandboxed-frame__frame {
35
+ visibility: hidden;
36
+ }
37
+
38
+ .crewlet-sandboxed-frame__loading {
39
+ position: absolute;
40
+ inset: 0;
41
+ display: flex;
42
+ padding: var(--spacing-3);
43
+ }
44
+
45
+ .crewlet-sandboxed-frame__end {
46
+ display: flex;
47
+ flex-direction: column;
48
+ justify-content: flex-start;
49
+ padding: var(--spacing-4);
50
+ }
@@ -0,0 +1,101 @@
1
+ import { type ReactNode } from 'react';
2
+ import { type Principal } from '../Principal/index.js';
3
+ import { type ArtifactRole, type CompanyAccess, type ShareableRole } from './roles.js';
4
+ /** One line of "Who has access". */
5
+ export interface ShareAudienceRow {
6
+ /** Stable for the row: the share's id, or the principal's key for an effective row. */
7
+ id: string;
8
+ principal: Principal;
9
+ role: ArtifactRole;
10
+ /** The reader's own row, drawn with "(you)". */
11
+ self?: boolean | undefined;
12
+ /**
13
+ * Access this principal holds THROUGH something else ("Through Operations",
14
+ * "Everyone in Acme"). An effective row is not a share: it carries no role
15
+ * control and no remove, because changing it means changing what it is
16
+ * through.
17
+ */
18
+ via?: string | undefined;
19
+ /** A change to this row is in flight; the row says so until the engine answers. */
20
+ pending?: boolean | undefined;
21
+ /** The engine refused the last change to this row, in words ("Only a person can share with the whole company."). */
22
+ refusal?: string | undefined;
23
+ /** The role can be changed here. Defaults to true for a direct share that is not the owner. */
24
+ editable?: boolean | undefined;
25
+ /** The row can be removed here. Defaults to `editable`. */
26
+ removable?: boolean | undefined;
27
+ /** A line under the row. An agent's row says what the agent may do with its role when this is left out. */
28
+ note?: string | undefined;
29
+ }
30
+ export interface ShareDialogLabels {
31
+ title: (artifact: string) => string;
32
+ addRole: string;
33
+ audience: string;
34
+ you: string;
35
+ roles: Record<ArtifactRole, string>;
36
+ roleDescriptions: Record<ArtifactRole, string>;
37
+ roleFor: (name: string) => string;
38
+ remove: (name: string) => string;
39
+ saving: string;
40
+ /** Why a row's controls wait while its change is in flight. */
41
+ busy: string;
42
+ /** What an agent may do in its turns with each role. */
43
+ agentNote: (name: string, role: ArtifactRole) => string;
44
+ companyAccess: string;
45
+ company: (company: string, access: CompanyAccess) => string;
46
+ copyLink: string;
47
+ linkCopied: string;
48
+ linkNote: string;
49
+ done: string;
50
+ }
51
+ export interface ShareDialogProps {
52
+ open: boolean;
53
+ onClose: () => void;
54
+ /** The artifact's title, named in the dialog's own. */
55
+ title: string;
56
+ /**
57
+ * The grantee search, given the role the reader chose for whoever they add.
58
+ * A `PrincipalPicker` wired to the engine's search, as a rule: picking
59
+ * somebody there is the add, at that role.
60
+ */
61
+ picker?: ((context: {
62
+ role: ShareableRole;
63
+ }) => ReactNode) | undefined;
64
+ /** The role a new grantee starts at. The least by default. */
65
+ defaultAddRole?: ShareableRole | undefined;
66
+ /** The roles this reader may grant, in ladder order. Every shareable role by default. */
67
+ grantableRoles?: readonly ShareableRole[] | undefined;
68
+ audience: readonly ShareAudienceRow[];
69
+ onRoleChange?: ((row: ShareAudienceRow, role: ShareableRole) => void) | undefined;
70
+ onRemove?: ((row: ShareAudienceRow) => void) | undefined;
71
+ companyName: string;
72
+ companyAccess: CompanyAccess;
73
+ onCompanyAccessChange?: ((access: CompanyAccess) => void) | undefined;
74
+ companyPending?: boolean | undefined;
75
+ companyRefusal?: string | undefined;
76
+ /** The artifact's address inside the dashboard. Access is still the engine's decision on every open. */
77
+ link?: string | undefined;
78
+ /** The reader may see who has access but not change it. The reason is said in place of every control. */
79
+ readOnly?: {
80
+ reason: string;
81
+ } | undefined;
82
+ /** A line above everything else: "You can manage this because you are an administrator." */
83
+ note?: ReactNode;
84
+ labels?: Partial<ShareDialogLabels> | undefined;
85
+ }
86
+ /**
87
+ * Who can open an artifact, and at what role, with the controls to change it.
88
+ *
89
+ * CHANGES ARE CONFIRMED, NOT OPTIMISTIC. A role change or a removal is asked
90
+ * of the engine and the row shows it is saving until the engine answers; a
91
+ * refusal is said on the row it belongs to, in the engine's words. Nothing
92
+ * here pretends a share happened before it did.
93
+ *
94
+ * A READER WHO CANNOT SHARE STILL SEES WHO CAN OPEN IT. The dialog opens in
95
+ * read mode with the reason, every role as words, and no control: a write is
96
+ * never hidden, and neither is the audience.
97
+ *
98
+ * Owner is not offered by any control: it moves only by transfer, in the
99
+ * artifact's settings.
100
+ */
101
+ export declare function ShareDialog({ open, onClose, title, picker, defaultAddRole, grantableRoles, audience, onRoleChange, onRemove, companyName, companyAccess, onCompanyAccessChange, companyPending, companyRefusal, link, readOnly, note, labels, }: ShareDialogProps): import("react").JSX.Element;
@@ -0,0 +1,5 @@
1
+ import './ShareDialog.css';
2
+ export { ShareDialog } from './ShareDialog.js';
3
+ export type { ShareAudienceRow, ShareDialogLabels, ShareDialogProps } from './ShareDialog.js';
4
+ export { ARTIFACT_ROLES, roleAtLeast, SHAREABLE_ROLES } from './roles.js';
5
+ export type { ArtifactRole, CompanyAccess, ShareableRole } from './roles.js';
@@ -0,0 +1,19 @@
1
+ export { ARTIFACT_ROLES, SHAREABLE_ROLES, ShareDialog, roleAtLeast } from '../chunk-2YR5ZPQ3.js';
2
+ import '../chunk-FC4YTTFJ.js';
3
+ import '../chunk-2TZATTIU.js';
4
+ import '../chunk-F73MC7EZ.js';
5
+ import '../chunk-W46LPU4R.js';
6
+ import '../chunk-STJ7QBC3.js';
7
+ import '../chunk-DTIW4CHZ.js';
8
+ import '../chunk-SVSCLHHI.js';
9
+ import '../chunk-OG6CL3EB.js';
10
+ import '../chunk-IG75YMUN.js';
11
+ import '../chunk-4FQT6ZAY.js';
12
+ import '../chunk-HMPFGIWM.js';
13
+ import '../chunk-R25RGPUB.js';
14
+ import '../chunk-4KP4RC3O.js';
15
+ import '../chunk-UAN5NE7M.js';
16
+ import '../chunk-5OM447RW.js';
17
+ import '../chunk-PQADV6P6.js';
18
+ import '../chunk-BZFWDIV6.js';
19
+ import '../chunk-ODEQTPFM.js';
@@ -0,0 +1,10 @@
1
+ export type ArtifactRole = 'viewer' | 'commenter' | 'contributor' | 'editor' | 'owner';
2
+ /** The roles a share may grant: every role but owner. */
3
+ export type ShareableRole = Exclude<ArtifactRole, 'owner'>;
4
+ /** The ladder in ascending order. */
5
+ export declare const ARTIFACT_ROLES: readonly ["viewer", "commenter", "contributor", "editor", "owner"];
6
+ export declare const SHAREABLE_ROLES: readonly ["viewer", "commenter", "contributor", "editor"];
7
+ /** Whether `role` includes `floor`: an editor can do everything a viewer can. */
8
+ export declare function roleAtLeast(role: ArtifactRole, floor: ArtifactRole): boolean;
9
+ /** What the whole company may do: nothing beyond the people added, or one shareable role. */
10
+ export type CompanyAccess = 'none' | ShareableRole;