@opengeni/react 2.5.0-canary.1 → 3.0.0-canary.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 (70) hide show
  1. package/README.md +15 -0
  2. package/dist/accounts.d.ts +64 -0
  3. package/dist/accounts.js +746 -0
  4. package/dist/accounts.js.map +1 -0
  5. package/dist/{browser-viewer-GXUICIAG.js → browser-viewer-AEFHUYZK.js} +3 -3
  6. package/dist/{chunk-MXJGO7LE.js → chunk-D3UIAJKY.js} +52 -2
  7. package/dist/chunk-D3UIAJKY.js.map +1 -0
  8. package/dist/{chunk-QGBJ6GHG.js → chunk-ELIYWBZR.js} +4 -4
  9. package/dist/{chunk-6H6S5V4Z.js → chunk-HQVCKCLG.js} +758 -871
  10. package/dist/chunk-HQVCKCLG.js.map +1 -0
  11. package/dist/{chunk-T7VAYG2I.js → chunk-MZ2G2XBA.js} +54 -2
  12. package/dist/chunk-MZ2G2XBA.js.map +1 -0
  13. package/dist/{chunk-X4JAFD5R.js → chunk-OAM4WAAM.js} +4 -4
  14. package/dist/{chunk-KSDXER4X.js → chunk-RGALCTWO.js} +64 -15
  15. package/dist/chunk-RGALCTWO.js.map +1 -0
  16. package/dist/chunk-YFKJ7VZH.js +268 -0
  17. package/dist/chunk-YFKJ7VZH.js.map +1 -0
  18. package/dist/{chunk-ATQJEWCA.js → chunk-YJFGAFBD.js} +124 -50
  19. package/dist/chunk-YJFGAFBD.js.map +1 -0
  20. package/dist/components/composer.d.ts +8 -0
  21. package/dist/components/file-browser.d.ts +4 -1
  22. package/dist/components/sandbox-files.d.ts +4 -1
  23. package/dist/components/sandbox-workspace.d.ts +5 -0
  24. package/dist/composer.js +3 -3
  25. package/dist/{computer-viewer-ZOP4Q7A7.js → computer-viewer-FWEZISW4.js} +3 -3
  26. package/dist/embedded-session-client.d.ts +23 -0
  27. package/dist/file-node-visibility.d.ts +15 -0
  28. package/dist/hooks/use-file-attachments.d.ts +9 -2
  29. package/dist/human-input.d.ts +3 -1
  30. package/dist/index.d.ts +5 -1
  31. package/dist/index.js +139 -53
  32. package/dist/index.js.map +1 -1
  33. package/dist/interaction.js +3 -3
  34. package/dist/session-ui.js +4 -4
  35. package/dist/session.d.ts +2 -0
  36. package/dist/session.js +7 -5
  37. package/dist/timeline/index.d.ts +1 -0
  38. package/dist/timeline/screenshot-lightbox.d.ts +16 -1
  39. package/package.json +6 -2
  40. package/src/accounts.tsx +970 -0
  41. package/src/components/chat-composer.tsx +88 -84
  42. package/src/components/composer.tsx +61 -9
  43. package/src/components/file-browser.tsx +33 -20
  44. package/src/components/human-input-surface.tsx +10 -6
  45. package/src/components/message-timeline.tsx +37 -9
  46. package/src/components/sandbox-files.tsx +42 -2
  47. package/src/components/sandbox-workspace.tsx +10 -0
  48. package/src/embedded-session-client.ts +104 -0
  49. package/src/file-node-visibility.ts +66 -0
  50. package/src/hooks/use-composer.ts +64 -2
  51. package/src/hooks/use-file-attachments.ts +38 -6
  52. package/src/hooks/use-human-input.ts +31 -4
  53. package/src/human-input.ts +12 -1
  54. package/src/index.ts +12 -0
  55. package/src/session.ts +5 -0
  56. package/src/timeline/index.ts +1 -0
  57. package/src/timeline/screenshot-lightbox.tsx +93 -29
  58. package/styles/compiled.css +11 -1
  59. package/styles/tokens.css +3 -1
  60. package/dist/chunk-6H6S5V4Z.js.map +0 -1
  61. package/dist/chunk-ATQJEWCA.js.map +0 -1
  62. package/dist/chunk-FK6VG4LL.js +0 -90
  63. package/dist/chunk-FK6VG4LL.js.map +0 -1
  64. package/dist/chunk-KSDXER4X.js.map +0 -1
  65. package/dist/chunk-MXJGO7LE.js.map +0 -1
  66. package/dist/chunk-T7VAYG2I.js.map +0 -1
  67. /package/dist/{browser-viewer-GXUICIAG.js.map → browser-viewer-AEFHUYZK.js.map} +0 -0
  68. /package/dist/{chunk-QGBJ6GHG.js.map → chunk-ELIYWBZR.js.map} +0 -0
  69. /package/dist/{chunk-X4JAFD5R.js.map → chunk-OAM4WAAM.js.map} +0 -0
  70. /package/dist/{computer-viewer-ZOP4Q7A7.js.map → computer-viewer-FWEZISW4.js.map} +0 -0
@@ -1,6 +1,14 @@
1
1
  import { DownloadIcon, XIcon } from "lucide-react";
2
2
  import { AnimatePresence, motion } from "motion/react";
3
- import { createContext, useCallback, useContext, useMemo, useState, type ReactNode } from "react";
3
+ import {
4
+ createContext,
5
+ useCallback,
6
+ useContext,
7
+ useEffect,
8
+ useMemo,
9
+ useState,
10
+ type ReactNode,
11
+ } from "react";
4
12
  import { Dialog } from "radix-ui";
5
13
  import { cn } from "../lib/cn";
6
14
  import { usePortalTokenStyle } from "../lib/use-portal-token-style";
@@ -25,9 +33,16 @@ type LightboxController = {
25
33
  source?: HTMLElement | null,
26
34
  label?: string,
27
35
  downloadFilename?: string,
36
+ controlLabels?: LightboxControlLabels,
37
+ releaseSource?: () => void,
28
38
  ) => void;
29
39
  };
30
40
 
41
+ export type LightboxControlLabels = {
42
+ download?: string | undefined;
43
+ close?: string | undefined;
44
+ };
45
+
31
46
  const LightboxContext = createContext<LightboxController | null>(null);
32
47
 
33
48
  /** Open the app-level screenshot lightbox. No-op outside a `LightboxProvider`. */
@@ -46,6 +61,23 @@ export function useLightboxOptional(): LightboxController | null {
46
61
 
47
62
  const NOOP: LightboxController = { open: () => {} };
48
63
 
64
+ /** @internal Owns one optional retained lightbox source and releases it exactly once. */
65
+ export function createLightboxSourceOwner() {
66
+ let releaseCurrent: (() => void) | null = null;
67
+ return {
68
+ replace(release?: (() => void) | undefined) {
69
+ const previous = releaseCurrent;
70
+ releaseCurrent = release ?? null;
71
+ previous?.();
72
+ },
73
+ release() {
74
+ const release = releaseCurrent;
75
+ releaseCurrent = null;
76
+ release?.();
77
+ },
78
+ };
79
+ }
80
+
49
81
  /**
50
82
  * The app-level screenshot lightbox. Render once near the timeline; renderers
51
83
  * call `useLightbox().open(src)`.
@@ -70,10 +102,18 @@ function LightboxRoot({ children }: { children: ReactNode }) {
70
102
  caption?: string;
71
103
  label: string;
72
104
  downloadFilename?: string;
105
+ controlLabels?: LightboxControlLabels;
73
106
  } | null>(null);
74
107
  const [tokenSource, setTokenSource] = useState<HTMLElement | null>(null);
108
+ const sourceOwner = useMemo(() => createLightboxSourceOwner(), []);
75
109
  const portalStyle = usePortalTokenStyle(tokenSource);
76
110
 
111
+ const releaseCurrentSource = useCallback(() => {
112
+ sourceOwner.release();
113
+ }, [sourceOwner]);
114
+
115
+ useEffect(() => releaseCurrentSource, [releaseCurrentSource]);
116
+
77
117
  const open = useCallback(
78
118
  (
79
119
  src: string,
@@ -81,22 +121,27 @@ function LightboxRoot({ children }: { children: ReactNode }) {
81
121
  source?: HTMLElement | null,
82
122
  label = "Screenshot",
83
123
  downloadFilename?: string,
124
+ controlLabels?: LightboxControlLabels,
125
+ releaseSource?: () => void,
84
126
  ) => {
127
+ sourceOwner.replace(releaseSource);
85
128
  setTokenSource(source ?? null);
86
129
  setState({
87
130
  src,
88
131
  label,
89
132
  ...(caption ? { caption } : {}),
90
133
  ...(downloadFilename ? { downloadFilename } : {}),
134
+ ...(controlLabels ? { controlLabels } : {}),
91
135
  });
92
136
  },
93
- [],
137
+ [sourceOwner],
94
138
  );
95
139
 
96
140
  const close = useCallback(() => {
141
+ releaseCurrentSource();
97
142
  setState(null);
98
143
  setTokenSource(null);
99
- }, []);
144
+ }, [releaseCurrentSource]);
100
145
 
101
146
  const controller = useMemo<LightboxController>(() => ({ open }), [open]);
102
147
 
@@ -159,32 +204,11 @@ function LightboxRoot({ children }: { children: ReactNode }) {
159
204
  alt={state.caption ?? state.label}
160
205
  className="min-h-0 max-h-[82vh] w-auto max-w-full rounded-og-md border border-white/10 object-contain shadow-og-lg"
161
206
  />
162
- <div className="absolute -right-3 -top-3 flex items-center gap-2">
163
- {state.downloadFilename ? (
164
- <a
165
- href={state.src}
166
- download={state.downloadFilename}
167
- className={cn(
168
- "inline-flex size-9 items-center justify-center rounded-full",
169
- "border border-white/15 bg-black/60 text-white/70 backdrop-blur",
170
- "transition-colors hover:border-white/30 hover:text-white",
171
- )}
172
- aria-label={`Download ${state.downloadFilename}`}
173
- >
174
- <DownloadIcon className="size-4" />
175
- </a>
176
- ) : null}
177
- <Dialog.Close
178
- className={cn(
179
- "inline-flex size-9 items-center justify-center rounded-full",
180
- "border border-white/15 bg-black/60 text-white/70 backdrop-blur",
181
- "transition-colors hover:border-white/30 hover:text-white",
182
- )}
183
- aria-label="Close"
184
- >
185
- <XIcon className="size-4" />
186
- </Dialog.Close>
187
- </div>
207
+ <ScreenshotLightboxControls
208
+ src={state.src}
209
+ downloadFilename={state.downloadFilename}
210
+ controlLabels={state.controlLabels}
211
+ />
188
212
  </div>
189
213
  {state.caption ? (
190
214
  <figcaption className="max-w-2xl text-center font-og-mono text-og-xs text-white/55">
@@ -205,3 +229,43 @@ function LightboxRoot({ children }: { children: ReactNode }) {
205
229
  </LightboxContext.Provider>
206
230
  );
207
231
  }
232
+
233
+ /** @internal Exact controls rendered by an open screenshot lightbox. */
234
+ export function ScreenshotLightboxControls({
235
+ src,
236
+ downloadFilename,
237
+ controlLabels,
238
+ }: {
239
+ src: string;
240
+ downloadFilename?: string | undefined;
241
+ controlLabels?: LightboxControlLabels | undefined;
242
+ }) {
243
+ return (
244
+ <div className="absolute -right-3 -top-3 flex items-center gap-2">
245
+ {downloadFilename ? (
246
+ <a
247
+ href={src}
248
+ download={downloadFilename}
249
+ className={cn(
250
+ "inline-flex size-9 items-center justify-center rounded-full",
251
+ "border border-white/15 bg-black/60 text-white/70 backdrop-blur",
252
+ "transition-colors hover:border-white/30 hover:text-white",
253
+ )}
254
+ aria-label={controlLabels?.download ?? `Download ${downloadFilename}`}
255
+ >
256
+ <DownloadIcon className="size-4" />
257
+ </a>
258
+ ) : null}
259
+ <Dialog.Close
260
+ className={cn(
261
+ "inline-flex size-9 items-center justify-center rounded-full",
262
+ "border border-white/15 bg-black/60 text-white/70 backdrop-blur",
263
+ "transition-colors hover:border-white/30 hover:text-white",
264
+ )}
265
+ aria-label={controlLabels?.close ?? "Close"}
266
+ >
267
+ <XIcon className="size-4" />
268
+ </Dialog.Close>
269
+ </div>
270
+ );
271
+ }
@@ -3001,6 +3001,9 @@
3001
3001
  --tw-blur: blur(8px);
3002
3002
  filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
3003
3003
  }
3004
+ :where(.og-root).filter,:where(.og-root) .filter {
3005
+ filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
3006
+ }
3004
3007
  :where(.og-root).backdrop-blur,:where(.og-root) .backdrop-blur {
3005
3008
  --tw-backdrop-blur: blur(8px);
3006
3009
  -webkit-backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);
@@ -3873,6 +3876,13 @@
3873
3876
  }
3874
3877
  }
3875
3878
  }
3879
+ :where(.og-root).hover\:opacity-80,:where(.og-root) .hover\:opacity-80 {
3880
+ &:hover {
3881
+ @media (hover: hover) {
3882
+ opacity: 80%;
3883
+ }
3884
+ }
3885
+ }
3876
3886
  :where(.og-root).hover\:opacity-90,:where(.og-root) .hover\:opacity-90 {
3877
3887
  &:hover {
3878
3888
  @media (hover: hover) {
@@ -4937,7 +4947,7 @@
4937
4947
  --og-color-status-waiting: oklch(0.54 0.15 305);
4938
4948
  --og-color-status-failed: oklch(0.5 0.19 22);
4939
4949
  --og-color-status-cancelled: oklch(0.55 0.025 260);
4940
- --og-color-danger: oklch(0.55 0.2 22);
4950
+ --og-color-danger: oklch(0.54 0.2 22);
4941
4951
  --og-color-diff-add-bg: var(--og-color-status-idle);
4942
4952
  --og-color-diff-del-bg: var(--og-color-status-failed);
4943
4953
  --og-shadow-sm: 0 1px 2px oklch(0.2 0.02 260 / 0.07);
package/styles/tokens.css CHANGED
@@ -227,7 +227,9 @@
227
227
  --og-color-status-waiting: oklch(0.54 0.15 305);
228
228
  --og-color-status-failed: oklch(0.5 0.19 22);
229
229
  --og-color-status-cancelled: oklch(0.55 0.025 260);
230
- --og-color-danger: oklch(0.55 0.2 22);
230
+ /* Ordinary 14 px destructive menu text also appears on Surface 3. Keep
231
+ enough AA contrast headroom there, including browser color rounding. */
232
+ --og-color-danger: oklch(0.54 0.2 22);
231
233
  --og-color-diff-add-bg: var(--og-color-status-idle);
232
234
  --og-color-diff-del-bg: var(--og-color-status-failed);
233
235