@opengeni/react 7.4.0 → 7.5.0-canary.36919050519001

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 (210) hide show
  1. package/README.md +124 -27
  2. package/dist/artifacts-document.js +3 -2
  3. package/dist/artifacts-presentation.js +3 -2
  4. package/dist/artifacts-spreadsheet.js +2 -2
  5. package/dist/artifacts.d.ts +1 -0
  6. package/dist/artifacts.js +516 -1413
  7. package/dist/artifacts.js.map +1 -1
  8. package/dist/{browser-viewer-2E6R2Y4W.js → browser-viewer-Z7S7QEJL.js} +6 -5
  9. package/dist/chat-interactive-block-UGBTNB3L.js +11 -0
  10. package/dist/{chunk-Y3QTZN2F.js → chunk-2VFNCX4E.js} +6 -6
  11. package/dist/{chunk-UDD6DLLT.js → chunk-3IJJEYW4.js} +15 -3
  12. package/dist/chunk-3IJJEYW4.js.map +1 -0
  13. package/dist/chunk-4RVYOY4O.js +379 -0
  14. package/dist/chunk-4RVYOY4O.js.map +1 -0
  15. package/dist/chunk-5CVXZA3Y.js +292 -0
  16. package/dist/chunk-5CVXZA3Y.js.map +1 -0
  17. package/dist/{chunk-5YK2ZDIG.js → chunk-5J4FOW6Q.js} +2 -10
  18. package/dist/chunk-5J4FOW6Q.js.map +1 -0
  19. package/dist/{chunk-KVERXCFY.js → chunk-5KYZIQFY.js} +40 -3
  20. package/dist/chunk-5KYZIQFY.js.map +1 -0
  21. package/dist/{chunk-KNDIXZN6.js → chunk-7UAMYXJY.js} +25 -18
  22. package/dist/{chunk-KNDIXZN6.js.map → chunk-7UAMYXJY.js.map} +1 -1
  23. package/dist/{chunk-SEEVCT36.js → chunk-A4UJB2MM.js} +2 -2
  24. package/dist/{chunk-X4HIN6TV.js → chunk-AFLPWUQ7.js} +71 -162
  25. package/dist/chunk-AFLPWUQ7.js.map +1 -0
  26. package/dist/chunk-B3V6TG77.js +41 -0
  27. package/dist/chunk-B3V6TG77.js.map +1 -0
  28. package/dist/{chunk-XEJEOAOV.js → chunk-B7WMS3CS.js} +51 -40
  29. package/dist/chunk-B7WMS3CS.js.map +1 -0
  30. package/dist/{chunk-S5JQ4R22.js → chunk-BDKR6BAR.js} +54 -24
  31. package/dist/chunk-BDKR6BAR.js.map +1 -0
  32. package/dist/{chunk-4MDLEHXL.js → chunk-DYWBUX5Q.js} +24 -12
  33. package/dist/chunk-DYWBUX5Q.js.map +1 -0
  34. package/dist/{chunk-YZ3YYMOM.js → chunk-E3G7SAYZ.js} +252 -624
  35. package/dist/chunk-E3G7SAYZ.js.map +1 -0
  36. package/dist/chunk-JT4JW7BC.js +54 -0
  37. package/dist/chunk-JT4JW7BC.js.map +1 -0
  38. package/dist/{chunk-5AZSK6MV.js → chunk-LWNLETQT.js} +5 -5
  39. package/dist/{chunk-USXVQACU.js → chunk-M7LBYP63.js} +5 -4
  40. package/dist/{chunk-USXVQACU.js.map → chunk-M7LBYP63.js.map} +1 -1
  41. package/dist/{chunk-L4OSXQ6H.js → chunk-NBOHNRLJ.js} +1289 -1060
  42. package/dist/chunk-NBOHNRLJ.js.map +1 -0
  43. package/dist/chunk-RHREZ7BO.js +11 -0
  44. package/dist/chunk-RHREZ7BO.js.map +1 -0
  45. package/dist/chunk-SCOTPE2I.js +589 -0
  46. package/dist/chunk-SCOTPE2I.js.map +1 -0
  47. package/dist/chunk-WEHMPOXK.js +39 -0
  48. package/dist/chunk-WEHMPOXK.js.map +1 -0
  49. package/dist/chunk-WRHIZYZF.js +988 -0
  50. package/dist/chunk-WRHIZYZF.js.map +1 -0
  51. package/dist/{chunk-3E2AITTZ.js → chunk-WUISZ3WU.js} +32 -28
  52. package/dist/{chunk-3E2AITTZ.js.map → chunk-WUISZ3WU.js.map} +1 -1
  53. package/dist/chunk-XCHWDJ22.js +107 -0
  54. package/dist/chunk-XCHWDJ22.js.map +1 -0
  55. package/dist/{chunk-DUEBTL3N.js → chunk-Y2PRMYLC.js} +4 -3
  56. package/dist/{chunk-DUEBTL3N.js.map → chunk-Y2PRMYLC.js.map} +1 -1
  57. package/dist/chunk-YBXQDQFX.js +1772 -0
  58. package/dist/chunk-YBXQDQFX.js.map +1 -0
  59. package/dist/chunk-YV4L3ILF.js +9 -0
  60. package/dist/chunk-YV4L3ILF.js.map +1 -0
  61. package/dist/{chunk-V2ABIVYJ.js → chunk-ZXSEDZP7.js} +70 -6
  62. package/dist/chunk-ZXSEDZP7.js.map +1 -0
  63. package/dist/components/artifacts/artifact-chrome.d.ts +120 -0
  64. package/dist/components/artifacts/artifact-sandbox.d.ts +27 -0
  65. package/dist/components/artifacts/chat-interactive-block.d.ts +29 -0
  66. package/dist/components/artifacts/deferred-chat-media.d.ts +15 -0
  67. package/dist/components/artifacts/editable-artifact-ui.d.ts +2 -1
  68. package/dist/components/artifacts/editable-artifact-view.d.ts +46 -0
  69. package/dist/components/artifacts/index.d.ts +7 -0
  70. package/dist/components/artifacts/latest-task-runner.d.ts +15 -0
  71. package/dist/components/artifacts/session-artifact-viewer.d.ts +39 -0
  72. package/dist/components/artifacts/site-view.d.ts +23 -0
  73. package/dist/components/browser-select-control.d.ts +3 -1
  74. package/dist/components/code-editor.d.ts +1 -4
  75. package/dist/components/desktop-viewer.d.ts +1 -1
  76. package/dist/components/message-timeline.d.ts +20 -3
  77. package/dist/components/open-geni-links.d.ts +16 -0
  78. package/dist/components/session-conversation.d.ts +20 -1
  79. package/dist/components/timeline-pill-geometry.d.ts +8 -0
  80. package/dist/components/timeline-pill-placement.d.ts +24 -0
  81. package/dist/components/usage-limit-notice.d.ts +49 -0
  82. package/dist/components/usage-member-list.d.ts +91 -0
  83. package/dist/components/usage-meter.d.ts +73 -0
  84. package/dist/composer.js +5 -5
  85. package/dist/{computer-viewer-WMJE6OA3.js → computer-viewer-KJWLH3GI.js} +7 -5
  86. package/dist/connect.js +7 -6
  87. package/dist/connect.js.map +1 -1
  88. package/dist/conversation-timeline.d.ts +1 -1
  89. package/dist/desktop.d.ts +7 -0
  90. package/dist/desktop.js +26 -0
  91. package/dist/desktop.js.map +1 -0
  92. package/dist/editor.d.ts +7 -0
  93. package/dist/editor.js +21 -0
  94. package/dist/editor.js.map +1 -0
  95. package/dist/hooks/latest-question.d.ts +1 -1
  96. package/dist/hooks/use-composer.d.ts +4 -0
  97. package/dist/hooks/use-desktop-stream.d.ts +1 -1
  98. package/dist/hooks/use-usage.d.ts +40 -0
  99. package/dist/index.d.ts +7 -2
  100. package/dist/index.js +460 -1386
  101. package/dist/index.js.map +1 -1
  102. package/dist/interaction.js +8 -6
  103. package/dist/interaction.js.map +1 -1
  104. package/dist/{latest-question-QB4EUCW5.js → latest-question-IS445HOW.js} +3 -3
  105. package/dist/lib/format.d.ts +6 -1
  106. package/dist/lib/workbench-peers.d.ts +36 -0
  107. package/dist/machines.js +2 -2
  108. package/dist/{markdown-table-layout-PFUEZ2U4.js → markdown-table-layout-QXSLK4BY.js} +37 -5
  109. package/dist/markdown-table-layout-QXSLK4BY.js.map +1 -0
  110. package/dist/{queue-surface-implementation-IM2HD3SK.js → queue-surface-implementation-2CAQAIHM.js} +2 -2
  111. package/dist/realtime.js +3 -3
  112. package/dist/{sandbox-files-PXPIZAFG.js → sandbox-files-AEJTWGT4.js} +8 -5
  113. package/dist/sandbox-files-AEJTWGT4.js.map +1 -0
  114. package/dist/session-ui.d.ts +9 -2
  115. package/dist/session-ui.js +39 -20
  116. package/dist/session-ui.js.map +1 -1
  117. package/dist/session.js +4 -4
  118. package/dist/sites.js +4 -289
  119. package/dist/sites.js.map +1 -1
  120. package/dist/terminal.d.ts +8 -0
  121. package/dist/terminal.js +31 -0
  122. package/dist/terminal.js.map +1 -0
  123. package/dist/timeline/allowance-exhausted-row.d.ts +24 -0
  124. package/dist/timeline/genie-loading.d.ts +3 -1
  125. package/dist/timeline/types.d.ts +8 -1
  126. package/dist/{timeline-annotation-selection-ODLVF4OI.js → timeline-annotation-selection-DMLMM2TX.js} +6 -1
  127. package/dist/timeline-annotation-selection-DMLMM2TX.js.map +1 -0
  128. package/dist/timeline-pill-geometry-Z23V243M.js +110 -0
  129. package/dist/timeline-pill-geometry-Z23V243M.js.map +1 -0
  130. package/dist/usage/allowance-copy.d.ts +25 -0
  131. package/dist/usage/summary.d.ts +35 -0
  132. package/dist/usage.d.ts +13 -0
  133. package/dist/usage.js +1073 -0
  134. package/dist/usage.js.map +1 -0
  135. package/package.json +19 -3
  136. package/src/artifacts.ts +37 -0
  137. package/src/components/artifacts/artifact-chrome.tsx +413 -0
  138. package/src/components/artifacts/artifact-sandbox.tsx +185 -0
  139. package/src/components/artifacts/chat-interactive-block.tsx +260 -0
  140. package/src/components/artifacts/deferred-chat-media.tsx +67 -0
  141. package/src/components/artifacts/editable-artifact-ui.tsx +3 -1
  142. package/src/components/artifacts/editable-artifact-view.tsx +187 -0
  143. package/src/components/artifacts/editable-artifact-workbench.tsx +5 -2
  144. package/src/components/artifacts/editable-document.tsx +34 -36
  145. package/src/components/artifacts/editable-presentation.tsx +21 -16
  146. package/src/components/artifacts/index.ts +41 -0
  147. package/src/components/artifacts/latest-task-runner.ts +49 -0
  148. package/src/components/artifacts/session-artifact-viewer.tsx +376 -0
  149. package/src/components/artifacts/site-view.tsx +116 -0
  150. package/src/components/browser-select-control.tsx +4 -1
  151. package/src/components/browser-viewer.tsx +81 -22
  152. package/src/components/code-editor.tsx +13 -16
  153. package/src/components/computer-viewer.tsx +51 -23
  154. package/src/components/desktop-viewer.tsx +1 -1
  155. package/src/components/markdown-table-layout.ts +49 -5
  156. package/src/components/markdown.tsx +5 -2
  157. package/src/components/message-timeline.tsx +557 -516
  158. package/src/components/open-geni-links.tsx +24 -0
  159. package/src/components/sandbox-terminal.tsx +48 -11
  160. package/src/components/session-chrome.tsx +22 -3
  161. package/src/components/session-conversation.tsx +195 -102
  162. package/src/components/timeline-annotation-selection.tsx +7 -0
  163. package/src/components/timeline-pill-geometry.ts +169 -0
  164. package/src/components/timeline-pill-placement.ts +99 -0
  165. package/src/components/usage-limit-notice.tsx +179 -0
  166. package/src/components/usage-member-list.tsx +792 -0
  167. package/src/components/usage-meter.tsx +382 -0
  168. package/src/conversation-timeline.ts +10 -2
  169. package/src/desktop.ts +24 -0
  170. package/src/editor.ts +13 -0
  171. package/src/hooks/use-available-models.ts +1 -1
  172. package/src/hooks/use-composer.ts +57 -2
  173. package/src/hooks/use-desktop-stream.ts +19 -28
  174. package/src/hooks/use-usage.ts +100 -0
  175. package/src/index.ts +22 -0
  176. package/src/lib/format.ts +32 -6
  177. package/src/lib/workbench-peers.ts +62 -0
  178. package/src/session-ui.ts +22 -0
  179. package/src/terminal.ts +26 -0
  180. package/src/timeline/activity-rail.tsx +5 -3
  181. package/src/timeline/allowance-exhausted-row.tsx +86 -0
  182. package/src/timeline/genie-loading.tsx +16 -6
  183. package/src/timeline/projection.ts +78 -4
  184. package/src/timeline/types.ts +8 -0
  185. package/src/usage/allowance-copy.ts +64 -0
  186. package/src/usage/summary.ts +93 -0
  187. package/src/usage.ts +50 -0
  188. package/styles/compiled.css +325 -0
  189. package/dist/chunk-4MDLEHXL.js.map +0 -1
  190. package/dist/chunk-5YK2ZDIG.js.map +0 -1
  191. package/dist/chunk-KVERXCFY.js.map +0 -1
  192. package/dist/chunk-L4OSXQ6H.js.map +0 -1
  193. package/dist/chunk-S5JQ4R22.js.map +0 -1
  194. package/dist/chunk-UDD6DLLT.js.map +0 -1
  195. package/dist/chunk-UGMKPUEM.js +0 -299
  196. package/dist/chunk-UGMKPUEM.js.map +0 -1
  197. package/dist/chunk-V2ABIVYJ.js.map +0 -1
  198. package/dist/chunk-X4HIN6TV.js.map +0 -1
  199. package/dist/chunk-XEJEOAOV.js.map +0 -1
  200. package/dist/chunk-YZ3YYMOM.js.map +0 -1
  201. package/dist/markdown-table-layout-PFUEZ2U4.js.map +0 -1
  202. package/dist/timeline-annotation-selection-ODLVF4OI.js.map +0 -1
  203. /package/dist/{browser-viewer-2E6R2Y4W.js.map → browser-viewer-Z7S7QEJL.js.map} +0 -0
  204. /package/dist/{computer-viewer-WMJE6OA3.js.map → chat-interactive-block-UGBTNB3L.js.map} +0 -0
  205. /package/dist/{chunk-Y3QTZN2F.js.map → chunk-2VFNCX4E.js.map} +0 -0
  206. /package/dist/{chunk-SEEVCT36.js.map → chunk-A4UJB2MM.js.map} +0 -0
  207. /package/dist/{chunk-5AZSK6MV.js.map → chunk-LWNLETQT.js.map} +0 -0
  208. /package/dist/{sandbox-files-PXPIZAFG.js.map → computer-viewer-KJWLH3GI.js.map} +0 -0
  209. /package/dist/{latest-question-QB4EUCW5.js.map → latest-question-IS445HOW.js.map} +0 -0
  210. /package/dist/{queue-surface-implementation-IM2HD3SK.js.map → queue-surface-implementation-2CAQAIHM.js.map} +0 -0
package/dist/artifacts.js CHANGED
@@ -1,1431 +1,163 @@
1
+ import {
2
+ ArtifactSandbox,
3
+ ChatInteractiveBlock,
4
+ DeferredChatMedia,
5
+ inlineHtmlDocument
6
+ } from "./chunk-YBXQDQFX.js";
1
7
  import {
2
8
  EditableSpreadsheetArtifactSurface,
3
9
  EditableSpreadsheetGrid,
4
10
  SpreadsheetArtifactSurface,
5
11
  SpreadsheetGrid,
6
12
  SpreadsheetProjectionGrid
7
- } from "./chunk-SEEVCT36.js";
13
+ } from "./chunk-A4UJB2MM.js";
14
+ import {
15
+ DocumentArtifactSurface,
16
+ DocumentEditor,
17
+ DocumentProjectionArtifactSurface,
18
+ DocumentProjectionEditor,
19
+ EditableDocumentArtifactSurface
20
+ } from "./chunk-WUISZ3WU.js";
21
+ import {
22
+ isRetainedImageContentType,
23
+ useRetainedImageObjectUrl
24
+ } from "./chunk-FZCP527Y.js";
25
+ import {
26
+ ArtifactBadge,
27
+ ArtifactButton,
28
+ ArtifactLabelsProvider,
29
+ ArtifactLoading,
30
+ ArtifactProblem,
31
+ ArtifactSelect,
32
+ ArtifactViewerHeader,
33
+ DEFAULT_ARTIFACT_LABELS,
34
+ artifactKindIcon,
35
+ artifactKindSubtitle,
36
+ artifactLoadErrorMessage,
37
+ artifactLoadErrorView,
38
+ useArtifactLabels
39
+ } from "./chunk-5CVXZA3Y.js";
40
+ import "./chunk-ERGYJIBB.js";
41
+ import "./chunk-XCHWDJ22.js";
8
42
  import {
9
43
  PUBLISHED_HTML_ARTIFACT_IFRAME_SANDBOX,
10
44
  PublishedHtmlArtifactFrame,
45
+ loadSiteSnapshot,
11
46
  openGeniSiteBridgePortFromBootstrap,
12
47
  publishedHtmlArtifactDocument
13
- } from "./chunk-UGMKPUEM.js";
48
+ } from "./chunk-SCOTPE2I.js";
49
+ import {
50
+ useOpenGeni
51
+ } from "./chunk-NEXLLTP4.js";
14
52
  import {
15
53
  EditablePresentationArtifactSurface,
16
54
  PresentationArtifactSurface,
17
55
  PresentationEditor,
18
56
  PresentationProjectionArtifactSurface,
19
57
  PresentationProjectionEditor
20
- } from "./chunk-KNDIXZN6.js";
21
- import {
22
- isRetainedImageContentType,
23
- useRetainedImageObjectUrl
24
- } from "./chunk-FZCP527Y.js";
25
- import "./chunk-ERGYJIBB.js";
26
- import {
27
- DocumentArtifactSurface,
28
- DocumentEditor,
29
- DocumentProjectionArtifactSurface,
30
- DocumentProjectionEditor,
31
- EditableDocumentArtifactSurface
32
- } from "./chunk-3E2AITTZ.js";
58
+ } from "./chunk-7UAMYXJY.js";
59
+ import "./chunk-WEHMPOXK.js";
33
60
  import {
34
61
  ArtifactSurface,
35
62
  EditableArtifactMessage
36
- } from "./chunk-DUEBTL3N.js";
37
- import "./chunk-22KP6LR5.js";
38
-
39
- // src/components/artifacts/visualization-assets.gen.ts
40
- var VISUALIZATION_CSS = `/* Adapted from Codex visualize 1.0.32; shared with the OpenGeni visualization skill. */
41
- :root {
42
- color-scheme: light dark;
43
- background-color: var(
44
- --background,
45
- var(--color-background-primary, light-dark(rgb(255 255 255), rgb(24 24 24)))
46
- ) !important;
47
-
48
- /* Agent-facing contract; keep in sync with SKILL.md. */
49
- --background: var(
50
- --color-background-primary,
51
- light-dark(rgb(255 255 255), rgb(24 24 24))
52
- );
53
- --foreground: var(
54
- --color-text-primary,
55
- light-dark(rgb(26 28 31), rgb(255 255 255))
56
- );
57
- --card: color-mix(in oklab, var(--foreground) 5%, var(--background));
58
- --card-foreground: var(
59
- --color-text-primary,
60
- light-dark(rgb(26 28 31), rgb(255 255 255))
61
- );
62
- --popover: var(
63
- --color-background-secondary,
64
- light-dark(rgb(255 255 255), rgb(45 45 45))
65
- );
66
- --popover-foreground: var(
67
- --color-text-primary,
68
- light-dark(rgb(26 28 31), rgb(255 255 255))
69
- );
70
- --primary: var(
71
- --color-text-info,
72
- light-dark(rgb(51 156 255), rgb(131 195 255))
73
- );
74
- --primary-foreground: var(
75
- --color-text-inverse,
76
- light-dark(rgb(255 255 255), rgb(13 13 13))
77
- );
78
- --secondary: var(
79
- --color-background-secondary,
80
- light-dark(rgb(255 255 255 / 96%), rgb(54 54 54 / 96%))
81
- );
82
- --secondary-foreground: var(
83
- --color-text-primary,
84
- light-dark(rgb(26 28 31), rgb(255 255 255))
85
- );
86
- --muted: color-mix(in srgb, var(--foreground) 10%, transparent);
87
- --muted-foreground: var(
88
- --color-text-secondary,
89
- light-dark(rgb(26 28 31 / 49.4%), rgb(255 255 255 / 49.8%))
90
- );
91
- --accent: var(
92
- --color-background-info,
93
- light-dark(rgb(229 242 255), rgb(13 39 63))
94
- );
95
- --accent-foreground: var(
96
- --color-text-info,
97
- light-dark(rgb(51 156 255), rgb(131 195 255))
98
- );
99
- --destructive: var(
100
- --color-text-warning,
101
- light-dark(rgb(226 85 7), rgb(255 133 73))
102
- );
103
- --border: var(
104
- --color-border-secondary,
105
- light-dark(rgb(26 28 31 / 8%), rgb(255 255 255 / 8.2%))
106
- );
107
- --input: var(
108
- --color-border-primary,
109
- light-dark(
110
- rgb(26 28 31 / 11.8%),
111
- color-mix(in oklab, rgb(0 0 0) 10%, transparent)
112
- )
113
- );
114
- --ring: var(
115
- --color-ring-primary,
116
- light-dark(rgb(51 156 255), rgb(131 195 255 / 76%))
117
- );
118
- --font-size-base: var(--font-text-md-size, 14px);
119
- --blue: light-dark(rgb(51 156 255), rgb(51 156 255));
120
- --orange: light-dark(rgb(226 85 7), rgb(251 106 34));
121
- --green: light-dark(rgb(0 162 64), rgb(64 201 119));
122
- --red: light-dark(rgb(224 46 42), rgb(255 103 100));
123
- --purple: light-dark(rgb(146 79 247), rgb(173 123 249));
124
- --yellow: light-dark(rgb(255 195 0), rgb(255 210 64));
125
- --viz-series-1: var(--primary);
126
- --viz-series-2: light-dark(rgb(243 136 59), rgb(245 154 86));
127
- --viz-series-3: light-dark(rgb(93 201 119), rgb(116 213 139));
128
- --viz-series-4: light-dark(rgb(235 119 177), rgb(240 143 192));
129
- --viz-series-5: light-dark(rgb(155 121 236), rgb(170 145 239));
130
- --viz-series-6: light-dark(rgb(58 185 177), rgb(90 203 194));
131
-
132
- /* Internal implementation variables; not part of the agent contract. */
133
- --font-sans: -apple-system, system-ui, "Segoe UI", sans-serif;
134
- --font-mono:
135
- ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono",
136
- monospace;
137
- --font-size-normal: max(11px, var(--font-size-base));
138
- --font-size-tooltip: calc(var(--font-size-base) - 1px);
139
- --font-size-small: max(11px, calc(var(--font-size-base) - 2px));
140
- --font-size-h1: calc(var(--font-size-normal) * 1.7142857143);
141
- --font-size-h2: calc(var(--font-size-normal) * 1.4285714286);
142
- --font-size-h3: calc(var(--font-size-normal) * 1.2857142857);
143
- --font-weight-normal: 430;
144
- --font-weight-medium: 500;
145
- --icon-size: 16px;
146
- --line-height-normal: calc(var(--font-size-normal) * 1.5);
147
- --line-height-tooltip: calc(var(--font-size-tooltip) * 1.4285714286);
148
- --line-height-small: calc(var(--font-size-small) + 4px);
149
- --corner-shape: round;
150
- --radius: var(--border-radius-lg, 10px);
151
- --radius-sm: calc(var(--radius) * 0.6);
152
- --radius-md: calc(var(--radius) * 0.8);
153
- --radius-lg: var(--radius);
154
- --radius-2xl: calc(var(--radius) * 1.6);
155
- --radius-full: 9999px;
156
- --shadow-sm: 0 1px 2px -1px rgb(0 0 0 / 8%);
157
- --checkmark-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 17 17'%3E%3Cpath d='M 12.8961 3.64101C13.1297 3.41418 13.4984 3.37523 13.7779 3.56581C14.0571 3.75635 14.1554 4.11331 14.0299 4.41347L13.9615 4.53847L7.71151 13.7045C7.59411 13.8767 7.4063 13.9877 7.19881 14.0072C6.99136 14.0267 6.78564 13.9533 6.63826 13.806L2.88826 10.056L2.79842 9.9457C2.6192 9.67407 2.64927 9.30496 2.88826 9.06581C3.12738 8.82669 3.49647 8.79676 3.76815 8.97597L3.8785 9.06581L7.03084 12.2182L12.8053 3.74941L12.8961 3.64101Z'/%3E%3C/svg%3E");
158
-
159
- /* Legacy aliases; not part of the current agent contract. */
160
- --viz-bg: transparent;
161
- --viz-panel: var(--card);
162
- --viz-border: var(--border);
163
- --viz-text: var(--foreground);
164
- --viz-muted: var(--muted-foreground);
165
- --viz-accent: var(--primary);
166
- --viz-accent-text: var(--primary-foreground);
167
- --viz-accent-bg: var(--accent);
168
- --viz-font-size: var(--font-size-base);
169
- --viz-warning: var(--destructive);
170
- }
171
-
172
- :root[data-theme="light"] {
173
- color-scheme: light;
174
- }
175
-
176
- :root[data-theme="dark"] {
177
- color-scheme: dark;
178
- }
179
-
180
- * {
181
- box-sizing: border-box;
182
- }
183
-
184
- html > body {
185
- /* Preserve MCP aliases for older inline renderers without creating :root cycles. */
186
- --color-background-primary: var(
187
- --background,
188
- light-dark(rgb(255 255 255), rgb(24 24 24))
189
- );
190
- --color-text-primary: var(
191
- --foreground,
192
- light-dark(rgb(26 28 31), rgb(255 255 255))
193
- );
194
- --color-border-secondary: var(
195
- --border,
196
- light-dark(rgb(26 28 31 / 8%), rgb(255 255 255 / 8.2%))
197
- );
198
-
199
- margin: 0;
200
- padding: var(--visualize-paint-gutter, 16px);
201
- color: var(--foreground);
202
- background: transparent !important;
203
- font-family: var(--font-sans) !important;
204
- font-size: var(--font-size-normal);
205
- font-weight: var(--font-weight-normal);
206
- line-height: var(--line-height-normal);
207
- }
208
-
209
- a {
210
- color: color-mix(in srgb, var(--viz-accent) 80%, var(--viz-text) 20%);
211
- cursor: pointer;
212
- font-weight: var(--font-weight-medium, 500);
213
- text-decoration: none;
214
- text-underline-offset: 2px;
215
- }
216
-
217
- a:is(:hover, :focus-visible) {
218
- text-decoration-line: underline;
219
- text-decoration-style: dashed;
220
- text-decoration-thickness: 0.5px;
221
- }
222
-
223
- h1,
224
- h2,
225
- h3,
226
- h4,
227
- h5,
228
- h6,
229
- p {
230
- margin-block: 0;
231
- }
232
-
233
- h1 {
234
- font-size: var(--font-size-h1);
235
- font-weight: var(--font-weight-medium);
236
- line-height: 1.25;
237
- }
238
-
239
- h2 {
240
- font-size: var(--font-size-h2);
241
- font-weight: var(--font-weight-medium);
242
- line-height: 1.25;
243
- }
244
-
245
- h3,
246
- h4,
247
- h5,
248
- h6 {
249
- font-size: var(--font-size-h3);
250
- font-weight: var(--font-weight-medium);
251
- line-height: 1.3;
252
- }
253
-
254
- b,
255
- strong,
256
- th {
257
- font-weight: var(--font-weight-medium);
258
- }
259
-
260
- code:not(pre code) {
261
- display: inline;
262
- padding: 1px 6px;
263
- border-radius: var(--radius-sm);
264
- corner-shape: var(--corner-shape);
265
- background: var(--muted);
266
- font-family: var(--font-mono);
267
- font-size: 0.92em;
268
- overflow-wrap: anywhere;
269
- -webkit-box-decoration-break: clone;
270
- box-decoration-break: clone;
271
- word-break: break-word;
272
- }
273
-
274
- .table-responsive {
275
- width: 100%;
276
- overflow-x: auto;
277
- scrollbar-width: thin;
278
- }
279
-
280
- .table {
281
- width: 100%;
282
- border-collapse: collapse;
283
- color: var(--foreground);
284
- font: inherit;
285
- text-align: start;
286
- }
287
-
288
- .table :is(th, td) {
289
- padding-block: 10px;
290
- padding-inline: 0 24px;
291
- overflow-wrap: anywhere;
292
- border-bottom: 1px solid var(--border);
293
- text-align: start;
294
- vertical-align: top;
295
- }
296
-
297
- .table-responsive > .table :is(th, td) {
298
- overflow-wrap: break-word;
299
- }
300
-
301
- .table :is(th, td):last-child {
302
- padding-inline-end: 0;
303
- }
304
-
305
- .table :is(caption, thead th) {
306
- font-weight: 600;
307
- }
308
-
309
- .table thead th {
310
- padding-block: 8px;
311
- border-bottom-color: color-mix(in srgb, var(--foreground) 16%, transparent);
312
- }
313
-
314
- .table tbody tr:last-child :is(th, td) {
315
- border-bottom: 0;
316
- }
317
-
318
- .table.table-sm :is(th, td) {
319
- padding-block: 6px;
320
- }
321
-
322
- .table.table-sm :is(th, td):not(:last-child) {
323
- padding-inline-end: 16px;
324
- }
325
-
326
- .table :is(.text-end, [align="right"]) {
327
- text-align: end;
328
- font-variant-numeric: tabular-nums;
329
- }
330
-
331
- .table :is(.text-center, [align="center"]) {
332
- text-align: center;
333
- }
334
-
335
- .table .text-nowrap {
336
- white-space: nowrap;
337
- }
338
-
339
- #widget {
340
- display: flex;
341
- flex-direction: column;
342
- gap: 12px;
343
- width: 100%;
344
- padding: 0;
345
- background: transparent !important;
346
- }
347
-
348
- .card {
349
- min-width: 0;
350
- padding: 12px;
351
- overflow: hidden;
352
- overflow-wrap: break-word;
353
- border-radius: var(--radius-2xl);
354
- corner-shape: var(--corner-shape);
355
- color: var(--card-foreground);
356
- background: var(--card);
357
- }
358
-
359
- #widget > :not(.card, .progress) {
360
- width: 100% !important;
361
- max-width: none !important;
362
- margin: 0 !important;
363
- padding: 0 !important;
364
- border: 0 !important;
365
- border-radius: 0 !important;
366
- background: transparent !important;
367
- box-shadow: none !important;
368
- }
369
-
370
- .tooltip {
371
- position: fixed;
372
- z-index: 50;
373
- top: 0;
374
- left: 0;
375
- width: max-content;
376
- max-width: min(
377
- 20rem,
378
- var(--tooltip-available-width, calc(100vw - 10px)),
379
- calc(100vw - 10px)
380
- );
381
- max-height: min(
382
- var(--tooltip-available-height, calc(100vh - 10px)),
383
- calc(100vh - 10px)
384
- );
385
- padding: 4px 8px;
386
- border: 1px solid var(--border);
387
- border-radius: var(--radius-lg);
388
- corner-shape: var(--corner-shape);
389
- color: var(--popover-foreground);
390
- background: var(--popover);
391
- box-shadow: none;
392
- font-size: var(--font-size-tooltip);
393
- line-height: var(--line-height-tooltip);
394
- overflow-wrap: break-word;
395
- white-space: normal;
396
- pointer-events: none;
397
- user-select: none;
398
- }
399
-
400
- .viz-grid {
401
- display: grid;
402
- grid-template-columns: repeat(auto-fit, minmax(max(180px, 24%), 1fr));
403
- gap: 10px;
404
- }
405
-
406
- .viz-stat {
407
- display: flex;
408
- flex-direction: column;
409
- gap: 2px;
410
- }
411
-
412
- .viz-stat-value {
413
- font-size: var(--font-size-h2);
414
- font-weight: var(--font-weight-medium);
415
- line-height: 1.25;
416
- }
417
-
418
- .viz-row {
419
- display: flex;
420
- flex-wrap: wrap;
421
- align-items: center;
422
- gap: 10px;
423
- }
424
-
425
- hr {
426
- width: 100%;
427
- height: 1px;
428
- margin-block: 6px;
429
- border: 0;
430
- background: var(--border);
431
- }
432
-
433
- .nav {
434
- display: flex;
435
- min-width: 0;
436
- align-items: center;
437
- gap: 4px;
438
- }
439
-
440
- .progress {
441
- display: flex;
442
- height: 8px;
443
- margin-block: calc((var(--line-height-normal, 1.5em) - 8px) / 2);
444
- overflow: hidden;
445
- border: 0;
446
- border-radius: var(--radius-full);
447
- background: var(--muted);
448
- }
449
-
450
- .progress-bar:only-child {
451
- border-radius: var(--radius-full);
452
- }
453
-
454
- .progress-bar {
455
- height: 100%;
456
- flex-shrink: 0;
457
- border: 0;
458
- background: var(--viz-series-1);
459
- }
460
-
461
- .viz-badge {
462
- padding: 3px 8px;
463
- border-radius: var(--radius-full);
464
- color: var(--accent-foreground);
465
- background: var(--accent);
466
- font-weight: var(--font-weight-medium);
467
- }
468
-
469
- small,
470
- .text-small,
471
- .viz-badge {
472
- font-size: var(--font-size-small);
473
- line-height: var(--line-height-small);
474
- }
475
-
476
- .text-muted {
477
- color: var(--muted-foreground);
478
- }
479
-
480
- .tabular-nums {
481
- font-variant-numeric: tabular-nums;
482
- }
483
-
484
- .sr-only {
485
- position: absolute;
486
- width: 1px;
487
- height: 1px;
488
- padding: 0;
489
- overflow: hidden;
490
- clip: rect(0, 0, 0, 0);
491
- white-space: nowrap;
492
- border: 0;
493
- }
494
-
495
- .viz-controls {
496
- display: flex;
497
- flex-wrap: wrap;
498
- align-items: center;
499
- gap: 8px;
500
- }
501
-
502
- .viz-controls > .form-label {
503
- display: grid;
504
- min-width: min(100%, 260px);
505
- flex: 1 1 280px;
506
- grid-template-columns: minmax(0, 1fr) auto;
507
- align-items: baseline;
508
- gap: 2px 12px;
509
- margin-bottom: 0;
510
- }
511
-
512
- .viz-controls > .form-label > :is(.form-control, .form-range, .form-select) {
513
- grid-column: 1 / -1;
514
- }
515
-
516
- .btn,
517
- .nav-link,
518
- .form-check-input,
519
- .form-control,
520
- .form-range,
521
- .form-select {
522
- font: inherit;
523
- }
524
-
525
- .btn,
526
- .nav-link {
527
- appearance: button;
528
- display: inline-flex;
529
- inline-size: fit-content;
530
- max-inline-size: 100%;
531
- min-height: 28px;
532
- align-items: center;
533
- justify-content: center;
534
- gap: 4px;
535
- margin: 0;
536
- padding: 0 8px;
537
- -webkit-app-region: no-drag;
538
- border: 1px solid var(--input);
539
- border-radius: var(--radius-lg);
540
- corner-shape: var(--corner-shape);
541
- color: var(--secondary-foreground);
542
- background: var(--secondary);
543
- cursor: var(--cursor-interaction, pointer);
544
- text-align: center;
545
- text-decoration: none;
546
- white-space: nowrap;
547
- user-select: none;
548
- -webkit-font-smoothing: antialiased;
549
- }
550
-
551
- .btn:is(.btn-block, .viz-tile) {
552
- inline-size: 100%;
553
- }
554
-
555
- .btn.viz-tile {
556
- min-width: 0;
557
- overflow-wrap: anywhere;
558
- white-space: normal;
559
- }
560
-
561
- a.btn {
562
- cursor: pointer;
563
- text-decoration: none;
564
- }
565
-
566
- .btn:not(:disabled):hover,
567
- .nav-link:not(:disabled):not([aria-disabled="true"]):hover {
568
- background: color-mix(in srgb, var(--foreground) 6%, var(--secondary));
569
- }
570
-
571
- .btn-primary {
572
- border-color: transparent;
573
- color: var(--primary-foreground);
574
- background: var(--foreground);
575
- background-clip: padding-box;
576
- }
577
-
578
- .btn-primary .text-muted {
579
- color: color-mix(in srgb, var(--primary-foreground) 50%, transparent);
580
- }
581
-
582
- .btn-primary:not(:disabled):hover {
583
- background: color-mix(in srgb, var(--foreground) 80%, transparent);
584
- background-clip: padding-box;
585
- }
586
-
587
- .btn-ghost {
588
- border-color: transparent;
589
- color: var(--muted-foreground);
590
- background: transparent;
591
- }
592
-
593
- .btn-ghost:not(:disabled):hover {
594
- color: var(--foreground);
595
- background: color-mix(in srgb, var(--foreground) 6%, var(--secondary));
596
- }
597
-
598
- .nav-pills .nav-link {
599
- min-width: 0;
600
- border-color: transparent;
601
- color: var(--muted-foreground);
602
- background: transparent;
603
- }
604
-
605
- .nav-justified .nav-link {
606
- flex: 1 1 0;
607
- overflow-wrap: anywhere;
608
- white-space: normal;
609
- }
610
-
611
- .nav-pills .nav-link.active {
612
- color: var(--foreground);
613
- background: var(--muted);
614
- }
615
-
616
- .btn:disabled,
617
- .nav-link:disabled,
618
- .nav-link[aria-disabled="true"] {
619
- cursor: not-allowed;
620
- opacity: 0.4;
621
- }
622
-
623
- [data-lucide] {
624
- stroke-width: 1.6;
625
- }
626
-
627
- .form-label {
628
- display: block;
629
- margin-bottom: 6px;
630
- color: var(--foreground);
631
- }
632
-
633
- .form-control {
634
- display: block;
635
- width: 100%;
636
- min-height: 28px;
637
- padding: 0 8px;
638
- outline: none;
639
- border: 1px solid var(--input);
640
- border-radius: var(--radius-lg);
641
- corner-shape: var(--corner-shape);
642
- color: var(--foreground);
643
- background: var(--secondary);
644
- }
645
-
646
- .form-control::placeholder {
647
- color: var(--muted-foreground);
648
- }
649
-
650
- .form-control[type="file"] {
651
- padding: 0;
652
- overflow: hidden;
653
- cursor: var(--cursor-interaction, pointer);
654
- }
655
-
656
- .form-control[type="file"]::file-selector-button {
657
- min-height: 26px;
658
- margin-right: 8px;
659
- padding: 0 8px;
660
- border: 0;
661
- border-right: 1px solid var(--input);
662
- color: var(--secondary-foreground);
663
- background: var(--secondary);
664
- cursor: inherit;
665
- font: inherit;
666
- }
667
-
668
- .form-control[type="file"]:not(:disabled):hover::file-selector-button {
669
- background: color-mix(in srgb, var(--foreground) 6%, var(--secondary));
670
- }
671
-
672
- .form-control-color[type="color"] {
673
- width: 40px;
674
- height: 28px;
675
- padding: 3px;
676
- cursor: var(--cursor-interaction, pointer);
677
- }
678
-
679
- .form-control-color[type="color"]::-webkit-color-swatch-wrapper {
680
- padding: 0;
681
- }
682
-
683
- .form-control-color[type="color"]::-webkit-color-swatch {
684
- border: 0;
685
- border-radius: calc(var(--radius-lg) - 4px);
686
- corner-shape: var(--corner-shape);
687
- }
688
-
689
- textarea.form-control {
690
- height: auto;
691
- min-height: 72px;
692
- padding: 8px 10px;
693
- resize: vertical;
694
- }
695
-
696
- .form-control:focus-visible {
697
- border-color: var(--ring);
698
- box-shadow: inset 0 0 0 1px var(--ring);
699
- }
700
-
701
- .form-control:disabled,
702
- .form-select:disabled {
703
- cursor: not-allowed;
704
- opacity: 0.4;
705
- }
706
-
707
- .form-select {
708
- appearance: none;
709
- display: block;
710
- width: 100%;
711
- min-height: 28px;
712
- margin: 0;
713
- padding: 0 32px 0 8px;
714
- outline: none;
715
- border: 1px solid var(--input);
716
- border-radius: var(--radius-lg);
717
- corner-shape: var(--corner-shape);
718
- color: var(--foreground);
719
- background-color: var(--secondary);
720
- background-image:
721
- linear-gradient(45deg, transparent 50%, var(--muted-foreground) 50%),
722
- linear-gradient(135deg, var(--muted-foreground) 50%, transparent 50%);
723
- background-position:
724
- calc(100% - 14px) 50%,
725
- calc(100% - 10px) 50%;
726
- background-repeat: no-repeat;
727
- background-size: 4px 4px;
728
- cursor: var(--cursor-interaction, default);
729
- }
730
-
731
- .form-select:not(:disabled):hover {
732
- background-color: color-mix(in srgb, var(--foreground) 6%, var(--secondary));
733
- }
734
-
735
- .form-select:focus-visible {
736
- border-color: var(--ring);
737
- box-shadow: inset 0 0 0 1px var(--ring);
738
- }
739
-
740
- .form-check {
741
- display: flex;
742
- min-height: 20px;
743
- align-items: center;
744
- gap: 6px;
745
- }
746
-
747
- .form-check-input {
748
- appearance: none;
749
- width: 14px;
750
- height: 14px;
751
- flex: 0 0 auto;
752
- margin: 0;
753
- border: 1px solid var(--input);
754
- color: var(--primary-foreground);
755
- background-color: transparent;
756
- cursor: var(--cursor-interaction, default);
757
- transition:
758
- background-color 150ms,
759
- border-color 150ms,
760
- box-shadow 150ms;
761
- }
762
-
763
- .form-check:not(.form-switch) .form-check-input[type="checkbox"] {
764
- border-color: var(--input);
765
- border-radius: var(--radius-sm);
766
- corner-shape: var(--corner-shape);
767
- background-color: var(--secondary);
768
- box-shadow: var(--shadow-sm);
769
- }
770
-
771
- .form-check:not(.form-switch)
772
- .form-check-input:not(:disabled):not(:checked):hover {
773
- background-color: var(--card);
774
- }
775
-
776
- .form-check:not(.form-switch) .form-check-input[type="checkbox"]:checked {
777
- border-color: var(--primary);
778
- background-color: var(--primary);
779
- }
780
-
781
- .form-check:not(.form-switch)
782
- .form-check-input[type="checkbox"]:checked::before {
783
- display: block;
784
- width: 100%;
785
- height: 100%;
786
- background: var(--primary-foreground);
787
- content: "";
788
- mask: var(--checkmark-image) center / 12px 12px no-repeat;
789
- }
790
-
791
- .form-check-input[type="radio"] {
792
- width: 14px;
793
- height: 14px;
794
- border-radius: var(--radius-full);
795
- }
796
-
797
- .form-check-input[type="radio"]:checked {
798
- border: 2px solid var(--primary);
799
- background:
800
- radial-gradient(circle, var(--primary-foreground) 0 2.5px, transparent 3px),
801
- var(--primary);
802
- }
803
-
804
- .form-check:not(.form-switch) .form-check-input:focus-visible {
805
- outline: 2px solid var(--ring);
806
- outline-offset: 2px;
807
- }
808
-
809
- .form-check:not(.form-switch) .form-check-input:disabled {
810
- cursor: not-allowed;
811
- pointer-events: none;
812
- }
813
-
814
- .form-check:not(.form-switch) .form-check-input:disabled + .form-check-label {
815
- cursor: not-allowed;
816
- }
817
-
818
- .form-switch .form-check-input:disabled,
819
- .form-switch .form-check-input:disabled + .form-check-label {
820
- cursor: not-allowed;
821
- opacity: 0.6;
822
- }
823
-
824
- .form-check-label {
825
- color: var(--foreground);
826
- cursor: var(--cursor-interaction, default);
827
- }
828
-
829
- .form-switch .form-check-input {
830
- position: relative;
831
- width: 32px;
832
- height: 20px;
833
- border: 0;
834
- border-radius: var(--radius-full);
835
- background: var(--muted);
836
- box-shadow: none;
837
- transition: background-color 200ms cubic-bezier(0, 0, 0.2, 1);
838
- }
839
-
840
- .form-switch .form-check-input::before {
841
- position: absolute;
842
- top: 50%;
843
- left: 0;
844
- width: 16px;
845
- height: 16px;
846
- box-sizing: border-box;
847
- border: 1px solid light-dark(var(--primary-foreground), var(--foreground));
848
- border-radius: var(--radius-full);
849
- background: light-dark(var(--primary-foreground), var(--foreground));
850
- box-shadow: var(--shadow-sm);
851
- content: "";
852
- transform: translate(2px, -50%);
853
- transition: transform 200ms cubic-bezier(0, 0, 0.2, 1);
854
- }
855
-
856
- .form-switch .form-check-input:checked {
857
- background: var(--primary);
858
- }
859
-
860
- .form-switch .form-check-input:checked::before {
861
- transform: translate(14px, -50%);
862
- }
863
-
864
- .form-switch .form-check-input:focus-visible {
865
- box-shadow: 0 0 0 2px var(--ring);
866
- }
867
-
868
- .form-range {
869
- appearance: none;
870
- display: block;
871
- width: 100%;
872
- height: 28px;
873
- flex: 1;
874
- margin: 0;
875
- padding: 0;
876
- outline: none;
877
- border: 0;
878
- accent-color: var(--primary);
879
- background: linear-gradient(
880
- color-mix(in srgb, var(--foreground) 7%, transparent),
881
- color-mix(in srgb, var(--foreground) 7%, transparent)
882
- )
883
- center / 100% 2px no-repeat;
884
- }
885
-
886
- .form-range::-webkit-slider-runnable-track {
887
- height: 28px;
888
- background: transparent;
889
- }
890
-
891
- .form-range::-webkit-slider-thumb {
892
- appearance: none;
893
- width: 20px;
894
- height: 20px;
895
- margin-top: 4px;
896
- border: 1px solid var(--border);
897
- border-radius: var(--radius-full);
898
- background: light-dark(var(--primary-foreground), var(--foreground));
899
- }
900
-
901
- .form-range:focus-visible::-webkit-slider-thumb {
902
- border-color: var(--ring);
903
- box-shadow: inset 0 0 0 1px var(--ring);
904
- }
905
-
906
- .form-range::-moz-range-track {
907
- height: 28px;
908
- background: transparent;
909
- }
910
-
911
- .form-range::-moz-range-thumb {
912
- width: 20px;
913
- height: 20px;
914
- border: 1px solid var(--border);
915
- border-radius: var(--radius-full);
916
- background: light-dark(var(--primary-foreground), var(--foreground));
917
- }
918
-
919
- .form-range:focus-visible::-moz-range-thumb {
920
- border-color: var(--ring);
921
- box-shadow: inset 0 0 0 1px var(--ring);
922
- }
923
-
924
- .form-range:disabled {
925
- cursor: not-allowed;
926
- opacity: 0.4;
927
- }
928
-
929
- .btn:not(.btn-primary, .viz-tile):is(
930
- [aria-pressed="true"],
931
- [aria-selected="true"],
932
- .is-selected
933
- ) {
934
- border-color: var(--primary);
935
- color: var(--primary-foreground);
936
- background: var(--primary);
937
- }
938
-
939
- .btn.viz-tile:is([aria-pressed="true"], [aria-selected="true"], .is-selected) {
940
- border-color: var(--primary);
941
- box-shadow: inset 0 0 0 1px var(--primary);
942
- }
943
-
944
- .btn:focus-visible,
945
- .nav-link:focus-visible {
946
- outline: 2px solid var(--ring);
947
- outline-offset: 2px;
948
- }
949
-
950
- @media (pointer: coarse) {
951
- .btn,
952
- .nav-link,
953
- .form-control,
954
- .form-select {
955
- min-width: 44px;
956
- min-height: 44px;
957
- }
958
-
959
- /* Keep small-screen WebKit from zooming when a text field receives focus. */
960
- .form-control,
961
- .form-select {
962
- font-size: max(16px, var(--font-size-normal));
963
- }
964
-
965
- .form-control[type="file"]::file-selector-button {
966
- min-width: 44px;
967
- min-height: 44px;
968
- }
969
-
970
- .form-control-color[type="color"] {
971
- width: 44px;
972
- height: 44px;
973
- }
974
-
975
- .form-control:is(
976
- [type="date"],
977
- [type="datetime-local"],
978
- [type="month"],
979
- [type="time"],
980
- [type="week"]
981
- ) {
982
- min-width: 0;
983
- max-width: 100%;
984
- padding-block: 8px;
985
- }
986
-
987
- .form-check {
988
- min-height: 44px;
989
- padding-inline: 15px;
990
- }
991
-
992
- .form-check-input {
993
- position: relative;
994
- }
995
-
996
- .form-check-input::after {
997
- position: absolute;
998
- top: 50%;
999
- left: 50%;
1000
- width: 44px;
1001
- height: 44px;
1002
- content: "";
1003
- transform: translate(-50%, -50%);
1004
- }
1005
-
1006
- .form-check-label {
1007
- display: inline-flex;
1008
- min-width: 44px;
1009
- min-height: 44px;
1010
- align-items: center;
1011
- }
1012
-
1013
- .form-range {
1014
- height: 44px;
1015
- touch-action: pan-y;
1016
- }
1017
-
1018
- .form-range::-webkit-slider-runnable-track {
1019
- height: 44px;
1020
- }
1021
-
1022
- .form-range::-moz-range-track {
1023
- height: 44px;
1024
- }
1025
-
1026
- .form-range::-webkit-slider-thumb {
1027
- margin-top: 12px;
1028
- }
1029
- }
1030
-
1031
- svg {
1032
- display: block;
1033
- max-width: 100%;
1034
- height: auto;
1035
- }
1036
-
1037
- #widget > svg {
1038
- width: 100%;
1039
- }
1040
-
1041
- /* Model-authored chart rules can otherwise stretch icons after these styles load. */
1042
- svg.lucide {
1043
- display: block;
1044
- width: var(--icon-size) !important;
1045
- height: var(--icon-size) !important;
1046
- flex: none;
1047
- margin: 0 !important;
1048
- stroke-width: 1.6;
1049
- }
1050
-
1051
- .text-warning,
1052
- .text-destructive {
1053
- color: var(--destructive);
1054
- }
1055
- `;
1056
- var VISUALIZATION_HELPERS = `
1057
- <script src="https://unpkg.com/@floating-ui/core@1.7.3/dist/floating-ui.core.umd.min.js"></script>
1058
- <script src="https://unpkg.com/@floating-ui/dom@1.7.4/dist/floating-ui.dom.umd.min.js"></script>
1059
- <script>
1060
- (() => {
1061
- if (window.FloatingUIDOM == null) {
1062
- return;
1063
- }
1064
- const { autoUpdate, computePosition, flip, offset, shift, size } = window.FloatingUIDOM;
1065
- const tooltipPlacements = new Set(["top", "right", "bottom", "left"]);
1066
- const tooltipId = \`codex-visualization-tooltip-\${
1067
- window.crypto?.randomUUID?.() ?? Date.now().toString(36)
1068
- }\`;
1069
- const tooltipGap = 5;
1070
- const hoverDelay = 700;
1071
- const skipDelay = 300;
1072
- let activeTrigger = null;
1073
- let pendingTrigger = null;
1074
- let tooltip = null;
1075
- let openTimeout = null;
1076
- let autoUpdateCleanup = null;
1077
- let positionRequest = 0;
1078
- let skipDelayUntil = 0;
1079
- let lastPointerWasTouch = false;
1080
- let pinnedByTouch = false;
63
+ } from "./chunk-Y2PRMYLC.js";
64
+ import {
65
+ cn
66
+ } from "./chunk-22KP6LR5.js";
1081
67
 
1082
- const getTrigger = (target) =>
1083
- target?.nodeType === Node.ELEMENT_NODE ? target.closest("[data-tooltip]") : null;
1084
- const containsTarget = (trigger, target) =>
1085
- target?.nodeType != null && trigger.contains(target);
1086
- const getContent = (trigger) => trigger.getAttribute("data-tooltip")?.trim() ?? "";
1087
- const getPlacement = (trigger) => {
1088
- const placement = trigger.getAttribute("data-tooltip-placement");
1089
- return tooltipPlacements.has(placement) ? placement : "top";
1090
- };
1091
- const getTooltip = () => {
1092
- if (tooltip == null) {
1093
- tooltip = document.createElement("div");
1094
- tooltip.id = tooltipId;
1095
- tooltip.className = "tooltip";
1096
- tooltip.setAttribute("role", "tooltip");
1097
- }
1098
- return tooltip;
1099
- };
1100
- const setDescribedBy = (trigger, described) => {
1101
- const ids = new Set(
1102
- (trigger.getAttribute("aria-describedby") ?? "").split(/\\s+/).filter(Boolean),
1103
- );
1104
- if (described) {
1105
- ids.add(tooltipId);
1106
- } else {
1107
- ids.delete(tooltipId);
1108
- }
1109
- if (ids.size === 0) {
1110
- trigger.removeAttribute("aria-describedby");
1111
- } else {
1112
- trigger.setAttribute("aria-describedby", [...ids].join(" "));
1113
- }
1114
- };
1115
- const clearOpenTimeout = () => {
1116
- if (openTimeout != null) {
1117
- window.clearTimeout(openTimeout);
1118
- openTimeout = null;
1119
- }
1120
- pendingTrigger = null;
1121
- };
1122
- const closeTooltip = (activateSkipDelay = true) => {
1123
- clearOpenTimeout();
1124
- pinnedByTouch = false;
1125
- positionRequest += 1;
1126
- autoUpdateCleanup?.();
1127
- autoUpdateCleanup = null;
1128
- if (activeTrigger == null) {
1129
- return;
1130
- }
1131
- setDescribedBy(activeTrigger, false);
1132
- activeTrigger = null;
1133
- tooltip?.remove();
1134
- if (activateSkipDelay) {
1135
- skipDelayUntil = Date.now() + skipDelay;
1136
- }
1137
- };
1138
- const updatePosition = (trigger, floating) => {
1139
- const request = ++positionRequest;
1140
- void computePosition(trigger, floating, {
1141
- middleware: [
1142
- offset(tooltipGap),
1143
- flip({ padding: tooltipGap }),
1144
- shift({ padding: tooltipGap }),
1145
- size({
1146
- padding: tooltipGap,
1147
- apply({ availableHeight, availableWidth, elements }) {
1148
- elements.floating.style.setProperty(
1149
- "--tooltip-available-width",
1150
- \`\${Math.max(0, availableWidth)}px\`,
1151
- );
1152
- elements.floating.style.setProperty(
1153
- "--tooltip-available-height",
1154
- \`\${Math.max(0, availableHeight)}px\`,
1155
- );
1156
- },
1157
- }),
1158
- ],
1159
- placement: getPlacement(trigger),
1160
- strategy: "fixed",
1161
- })
1162
- .then(({ x, y }) => {
1163
- if (activeTrigger !== trigger || request !== positionRequest) {
1164
- return;
1165
- }
1166
- const scale = window.devicePixelRatio || 1;
1167
- floating.style.transform = \`translate(\${Math.round(x * scale) / scale}px, \${Math.round(y * scale) / scale}px)\`;
1168
- floating.style.visibility = "visible";
1169
- })
1170
- .catch(() => {
1171
- if (activeTrigger === trigger && request === positionRequest) {
1172
- closeTooltip(false);
1173
- }
1174
- });
1175
- };
1176
- const openTooltip = (trigger) => {
1177
- const content = getContent(trigger);
1178
- if (!trigger.isConnected || content.length === 0) {
1179
- return;
1180
- }
1181
- clearOpenTimeout();
1182
- if (activeTrigger === trigger) {
1183
- return;
1184
- }
1185
- closeTooltip();
1186
- const floating = getTooltip();
1187
- floating.textContent = content;
1188
- floating.style.visibility = "hidden";
1189
- floating.style.transform = "translate(0, 0)";
1190
- document.body.appendChild(floating);
1191
- activeTrigger = trigger;
1192
- setDescribedBy(trigger, true);
1193
- autoUpdateCleanup = autoUpdate(trigger, floating, () => {
1194
- updatePosition(trigger, floating);
68
+ // src/components/artifacts/site-view.tsx
69
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
70
+ import { jsx } from "react/jsx-runtime";
71
+ function SiteView({
72
+ client,
73
+ workspaceId,
74
+ siteId,
75
+ toolBridge,
76
+ theme,
77
+ archivedMessage,
78
+ showTitle = true,
79
+ loadingLabel,
80
+ onTitle,
81
+ className
82
+ }) {
83
+ const labels = useArtifactLabels();
84
+ const [snapshot, setSnapshot] = useState(null);
85
+ const [error, setError] = useState(null);
86
+ const readAbort = useRef(null);
87
+ const onTitleRef = useRef(onTitle);
88
+ onTitleRef.current = onTitle;
89
+ const load = useCallback(async () => {
90
+ readAbort.current?.abort();
91
+ const abort = new AbortController();
92
+ readAbort.current = abort;
93
+ try {
94
+ setError(null);
95
+ const next = await loadSiteSnapshot(client, workspaceId, siteId, {
96
+ signal: abort.signal,
97
+ includeArchivedContent: true
1195
98
  });
1196
- };
1197
- const requestOpen = (trigger, immediate = false) => {
1198
- if (
1199
- getContent(trigger).length === 0 ||
1200
- activeTrigger === trigger ||
1201
- pendingTrigger === trigger
1202
- ) {
1203
- return;
1204
- }
1205
- clearOpenTimeout();
1206
- pendingTrigger = trigger;
1207
- const delay =
1208
- immediate || activeTrigger != null || Date.now() < skipDelayUntil ? 0 : hoverDelay;
1209
- if (delay === 0) {
1210
- openTooltip(trigger);
1211
- return;
1212
- }
1213
- openTimeout = window.setTimeout(() => {
1214
- openTimeout = null;
1215
- pendingTrigger = null;
1216
- openTooltip(trigger);
1217
- }, delay);
1218
- };
1219
- const handlePointerOpen = (event) => {
1220
- if (event.pointerType === "touch") {
1221
- return;
1222
- }
1223
- const trigger = getTrigger(event.target);
1224
- if (trigger == null || containsTarget(trigger, event.relatedTarget)) {
1225
- return;
1226
- }
1227
- requestOpen(trigger);
1228
- };
1229
- const handlePointer = (event) => {
1230
- lastPointerWasTouch = event.type === "pointerdown" && event.pointerType === "touch";
1231
- };
1232
- const handleTouchClick = (event) => {
1233
- const isTouch = event.pointerType === "touch" || lastPointerWasTouch;
1234
- lastPointerWasTouch = false;
1235
- if (!isTouch || event.detail === 0) {
1236
- return;
1237
- }
1238
- const trigger = getTrigger(event.target);
1239
- if (
1240
- trigger == null ||
1241
- !trigger.isConnected ||
1242
- getContent(trigger).length === 0 ||
1243
- (pinnedByTouch && activeTrigger === trigger)
1244
- ) {
1245
- if (pinnedByTouch) {
1246
- closeTooltip();
1247
- }
1248
- return;
1249
- }
1250
- openTooltip(trigger);
1251
- pinnedByTouch = activeTrigger === trigger;
1252
- window.setTimeout(() => {
1253
- if (activeTrigger === trigger && !trigger.isConnected) {
1254
- closeTooltip(false);
1255
- }
1256
- }, 0);
1257
- };
1258
- const handleLeave = (event) => {
1259
- if (pinnedByTouch) {
1260
- return;
1261
- }
1262
- const trigger = getTrigger(event.target);
1263
- if (trigger == null || containsTarget(trigger, event.relatedTarget)) {
1264
- return;
1265
- }
1266
- if (activeTrigger === trigger || pendingTrigger === trigger) {
1267
- closeTooltip();
1268
- }
1269
- };
1270
- const handleFocusIn = (event) => {
1271
- const trigger = getTrigger(event.target);
1272
- if (trigger?.matches(":focus-visible")) {
1273
- requestOpen(trigger, true);
1274
- }
1275
- };
1276
- const handleKeyDown = (event) => {
1277
- if (event.key === "Escape") {
1278
- closeTooltip();
1279
- }
1280
- };
1281
- const handleContextMenu = (event) => {
1282
- lastPointerWasTouch = false;
1283
- const trigger = getTrigger(event.target);
1284
- if (activeTrigger === trigger || pendingTrigger === trigger) {
1285
- closeTooltip();
1286
- }
1287
- };
1288
- const destroy = () => {
1289
- closeTooltip(false);
1290
- lastPointerWasTouch = false;
1291
- document.removeEventListener("pointerover", handlePointerOpen);
1292
- document.removeEventListener("pointerdown", handlePointer);
1293
- document.removeEventListener("pointercancel", handlePointer);
1294
- document.removeEventListener("click", handleTouchClick);
1295
- document.removeEventListener("pointerout", handleLeave);
1296
- document.removeEventListener("focusin", handleFocusIn);
1297
- document.removeEventListener("focusout", handleLeave);
1298
- document.removeEventListener("keydown", handleKeyDown);
1299
- document.removeEventListener("contextmenu", handleContextMenu);
1300
- tooltip = null;
1301
- };
1302
-
1303
- document.addEventListener("pointerover", handlePointerOpen);
1304
- document.addEventListener("pointerdown", handlePointer);
1305
- document.addEventListener("pointercancel", handlePointer);
1306
- document.addEventListener("click", handleTouchClick);
1307
- document.addEventListener("pointerout", handleLeave);
1308
- document.addEventListener("focusin", handleFocusIn);
1309
- document.addEventListener("focusout", handleLeave);
1310
- document.addEventListener("keydown", handleKeyDown);
1311
- document.addEventListener("contextmenu", handleContextMenu);
1312
- window.addEventListener("pagehide", destroy, { once: true });
1313
- })();
1314
- </script>
1315
- <script id="codex-visualization-tabs">
1316
- (() => {
1317
- const selector = '.nav[role="tablist"] [role="tab"]';
1318
- const disabled = ':disabled,[aria-disabled="true"]';
1319
- const selectTab = (selected) => {
1320
- const panelId = selected.getAttribute("aria-controls");
1321
- for (const tab of selected.closest('[role="tablist"]').querySelectorAll('[role="tab"]')) {
1322
- const active = tab === selected;
1323
- tab.classList.toggle("active", active);
1324
- tab.setAttribute("aria-selected", String(active));
1325
- const id = tab.getAttribute("aria-controls");
1326
- const panel = id && document.getElementById(id);
1327
- if (panel != null) {
1328
- panel.hidden = id !== panelId;
1329
- if (!panel.hidden && selected.id) {
1330
- panel.setAttribute("aria-labelledby", selected.id);
1331
- }
1332
- }
1333
- }
1334
- };
1335
- const interact = (event) => {
1336
- const tab = event.target?.closest?.(selector);
1337
- if (event.defaultPrevented || tab == null || tab.matches(disabled)) {
1338
- return;
1339
- }
1340
- if (event.type === "click") {
1341
- selectTab(tab);
1342
- return;
1343
- }
1344
- const tabs = Array.from(
1345
- tab.closest('[role="tablist"]').querySelectorAll('[role="tab"]'),
1346
- ).filter((candidate) => !candidate.matches(disabled));
1347
- const current = tabs.indexOf(tab);
1348
- let next;
1349
- if (event.key === "ArrowRight" || event.key === "ArrowDown") {
1350
- next = (current + 1) % tabs.length;
1351
- } else if (event.key === "ArrowLeft" || event.key === "ArrowUp") {
1352
- next = (current + tabs.length - 1) % tabs.length;
1353
- } else if (event.key === "Home") {
1354
- next = 0;
1355
- } else if (event.key === "End") {
1356
- next = tabs.length - 1;
1357
- } else {
1358
- return;
1359
- }
1360
- event.preventDefault();
1361
- tabs[next].focus();
1362
- selectTab(tabs[next]);
1363
- };
1364
-
1365
- for (const list of document.querySelectorAll('.nav[role="tablist"]')) {
1366
- const selected =
1367
- list.querySelector('[role="tab"][aria-selected="true"]') ??
1368
- list.querySelector('[role="tab"].active') ??
1369
- list.querySelector('[role="tab"]');
1370
- if (selected != null) {
1371
- selectTab(selected);
1372
- }
99
+ if (abort.signal.aborted) return;
100
+ setSnapshot(next);
101
+ onTitleRef.current?.(next.detail.artifact.title);
102
+ } catch (nextError) {
103
+ if (abort.signal.aborted) return;
104
+ setSnapshot(null);
105
+ setError(nextError);
1373
106
  }
1374
- document.addEventListener("click", interact);
1375
- document.addEventListener("keydown", interact);
1376
- window.addEventListener(
1377
- "pagehide",
1378
- () => {
1379
- document.removeEventListener("click", interact);
1380
- document.removeEventListener("keydown", interact);
1381
- },
1382
- { once: true },
107
+ }, [client, siteId, workspaceId]);
108
+ useEffect(() => {
109
+ setSnapshot(null);
110
+ void load();
111
+ return () => readAbort.current?.abort();
112
+ }, [load]);
113
+ const content = snapshot?.content;
114
+ const bridge = useMemo(
115
+ () => content ? toolBridge?.({
116
+ artifactId: siteId,
117
+ siteVersionId: content.versionId,
118
+ requestedTools: content.requestedTools
119
+ }) : void 0,
120
+ [content, siteId, toolBridge]
121
+ );
122
+ if (error)
123
+ return /* @__PURE__ */ jsx(
124
+ ArtifactProblem,
125
+ {
126
+ view: artifactLoadErrorView(error, "site", labels),
127
+ onRetry: () => void load()
128
+ }
1383
129
  );
1384
- })();
1385
- </script>
1386
- <script
1387
- id="codex-visualization-lucide"
1388
- async
1389
- src="https://unpkg.com/lucide@1.17.0/dist/umd/lucide.js"
1390
- ></script>
1391
- <script>
1392
- (() => {
1393
- const initialize = () => {
1394
- globalThis.lucide?.createIcons({ attrs: { width: 16, height: 16 } });
1395
- };
1396
- if (globalThis.lucide != null) {
1397
- initialize();
1398
- return;
130
+ if (!snapshot || !content) return /* @__PURE__ */ jsx(ArtifactLoading, { label: loadingLabel ?? labels.loadingSite });
131
+ if (snapshot.detail.artifact.status === "archived")
132
+ return /* @__PURE__ */ jsx("div", { className: "p-4 text-sm text-fg-muted", children: archivedMessage ?? labels.siteArchived });
133
+ return /* @__PURE__ */ jsx(
134
+ ArtifactSandbox,
135
+ {
136
+ html: content.html,
137
+ title: snapshot.detail.artifact.title,
138
+ showTitle,
139
+ versionLabel: `v${snapshot.detail.artifact.currentVersion?.revision}`,
140
+ toolBridge: bridge,
141
+ connectedToolCount: content.requestedTools.length,
142
+ theme,
143
+ fill: true,
144
+ className: className ?? "h-full rounded-none border-0"
1399
145
  }
1400
- document
1401
- .getElementById("codex-visualization-lucide")
1402
- ?.addEventListener("load", initialize, { once: true });
1403
- })();
1404
- </script>
1405
- `;
1406
-
1407
- // src/components/artifacts/inline-html-document.ts
1408
- function inlineHtmlDocument(fragment) {
1409
- return '<!doctype html><html><head><meta name="viewport" content="width=device-width,initial-scale=1"><style>' + VISUALIZATION_CSS + "</style><style>html,body{margin:0;min-height:0}body{padding:16px;box-sizing:border-box}</style></head><body>" + fragment + VISUALIZATION_HELPERS + `<script>
1410
- (()=>{
1411
- window.addEventListener('message',event=>{
1412
- if(event.source!==parent||event.data?.type!=='opengeni.preview.theme')return;
1413
- if(event.data.theme==='light'||event.data.theme==='dark')document.documentElement.style.colorScheme=event.data.theme;
1414
- previous=0;resize();
1415
- });
1416
- let previous=0;
1417
- const resize=()=>{const height=Math.ceil(document.body.getBoundingClientRect().height);if(height!==previous){previous=height;parent.postMessage({type:'opengeni.preview.height',height},'*')}};
1418
- new ResizeObserver(resize).observe(document.body);resize();
1419
- })();
1420
- </script></body></html>`;
146
+ );
1421
147
  }
1422
148
 
149
+ // src/components/artifacts/editable-artifact-view.tsx
150
+ import {
151
+ createBrowserEditableArtifactSession as createBrowserEditableArtifactSession2
152
+ } from "@opengeni/sdk/editable-artifacts";
153
+ import { useCallback as useCallback3, useEffect as useEffect3, useMemo as useMemo2, useRef as useRef3, useState as useState3 } from "react";
154
+
1423
155
  // src/components/artifacts/editable-artifact-workbench.tsx
1424
156
  import {
1425
157
  createBrowserEditableArtifactSession
1426
158
  } from "@opengeni/sdk/editable-artifacts";
1427
- import { useCallback, useEffect, useRef, useState } from "react";
1428
- import { jsx } from "react/jsx-runtime";
159
+ import { useCallback as useCallback2, useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
160
+ import { jsx as jsx2 } from "react/jsx-runtime";
1429
161
  function EditableArtifactWorkbench({
1430
162
  session,
1431
163
  document,
@@ -1434,7 +166,7 @@ function EditableArtifactWorkbench({
1434
166
  }) {
1435
167
  switch (session.modality) {
1436
168
  case "document":
1437
- return /* @__PURE__ */ jsx(
169
+ return /* @__PURE__ */ jsx2(
1438
170
  EditableDocumentArtifactSurface,
1439
171
  {
1440
172
  ...document,
@@ -1443,9 +175,9 @@ function EditableArtifactWorkbench({
1443
175
  }
1444
176
  );
1445
177
  case "spreadsheet":
1446
- return /* @__PURE__ */ jsx(EditableSpreadsheetArtifactSurface, { ...spreadsheet, session });
178
+ return /* @__PURE__ */ jsx2(EditableSpreadsheetArtifactSurface, { ...spreadsheet, session });
1447
179
  case "presentation":
1448
- return /* @__PURE__ */ jsx(EditablePresentationArtifactSurface, { ...presentation, session });
180
+ return /* @__PURE__ */ jsx2(EditablePresentationArtifactSurface, { ...presentation, session });
1449
181
  }
1450
182
  }
1451
183
  function EditableArtifactWorkbenchHost({
@@ -1455,13 +187,13 @@ function EditableArtifactWorkbenchHost({
1455
187
  spreadsheet,
1456
188
  presentation
1457
189
  }) {
1458
- const createSessionRef = useRef(createSession);
1459
- const [retryEpoch, setRetryEpoch] = useState(0);
1460
- const [state, setState] = useState({ key: null, session: null, error: null });
1461
- useEffect(() => {
190
+ const createSessionRef = useRef2(createSession);
191
+ const [retryEpoch, setRetryEpoch] = useState2(0);
192
+ const [state, setState] = useState2({ key: null, session: null, error: null });
193
+ useEffect2(() => {
1462
194
  createSessionRef.current = createSession;
1463
195
  }, [createSession]);
1464
- useEffect(() => {
196
+ useEffect2(() => {
1465
197
  let owned = null;
1466
198
  setState({ key: sessionKey, session: null, error: null });
1467
199
  try {
@@ -1480,10 +212,11 @@ function EditableArtifactWorkbenchHost({
1480
212
  if (closing) void closing.close().catch(() => void 0);
1481
213
  };
1482
214
  }, [retryEpoch, sessionKey]);
1483
- const retry = useCallback(() => setRetryEpoch((value) => value + 1), []);
215
+ const retry = useCallback2(() => setRetryEpoch((value) => value + 1), []);
216
+ const labels = useArtifactLabels();
1484
217
  const currentError = state.key === sessionKey ? state.error : null;
1485
218
  if (state.key === sessionKey && state.session) {
1486
- return /* @__PURE__ */ jsx(
219
+ return /* @__PURE__ */ jsx2(
1487
220
  EditableArtifactWorkbench,
1488
221
  {
1489
222
  session: state.session,
@@ -1493,12 +226,13 @@ function EditableArtifactWorkbenchHost({
1493
226
  }
1494
227
  );
1495
228
  }
1496
- return /* @__PURE__ */ jsx(
229
+ return /* @__PURE__ */ jsx2(
1497
230
  EditableArtifactMessage,
1498
231
  {
1499
- title: currentError ? "Could not open this artifact" : "Opening artifact",
1500
- detail: currentError?.message ?? "Starting the secure editing session\u2026",
1501
- retry: currentError ? retry : void 0
232
+ title: currentError ? labels.editableErrors.transient.title : labels.opening,
233
+ detail: currentError?.message ?? labels.startingEditor,
234
+ retry: currentError ? retry : void 0,
235
+ retryLabel: labels.retry
1502
236
  }
1503
237
  );
1504
238
  }
@@ -1509,8 +243,8 @@ function BrowserEditableArtifactWorkbench({
1509
243
  presentation
1510
244
  }) {
1511
245
  const sessionKey = browserSessionKey(options);
1512
- const createSession = useCallback(() => createBrowserEditableArtifactSession(options), [options]);
1513
- return /* @__PURE__ */ jsx(
246
+ const createSession = useCallback2(() => createBrowserEditableArtifactSession(options), [options]);
247
+ return /* @__PURE__ */ jsx2(
1514
248
  EditableArtifactWorkbenchHost,
1515
249
  {
1516
250
  sessionKey,
@@ -1541,13 +275,375 @@ function browserSessionKey(options) {
1541
275
  (_key, value) => value instanceof URL ? value.href : value
1542
276
  );
1543
277
  }
278
+
279
+ // src/components/artifacts/editable-artifact-view.tsx
280
+ import { jsx as jsx3 } from "react/jsx-runtime";
281
+ function EditableArtifactView({
282
+ baseUrl,
283
+ workspaceId,
284
+ artifactId,
285
+ open,
286
+ runtimes,
287
+ transport,
288
+ showHeader = true,
289
+ authorityKey,
290
+ describeError,
291
+ onTitle,
292
+ loadingLabel
293
+ }) {
294
+ const [loadEpoch, setLoadEpoch] = useState3(0);
295
+ const labels = useArtifactLabels();
296
+ const loadKey = JSON.stringify([artifactId, authorityKey, baseUrl.href, workspaceId, loadEpoch]);
297
+ const [state, setState] = useState3({ key: null, kind: "loading" });
298
+ const current = state.key === loadKey ? state : null;
299
+ const openRef = useRef3(open);
300
+ openRef.current = open;
301
+ const onTitleRef = useRef3(onTitle);
302
+ onTitleRef.current = onTitle;
303
+ useEffect3(() => {
304
+ const abort = new AbortController();
305
+ setState({ key: loadKey, kind: "loading" });
306
+ void openRef.current(abort.signal).then((value) => {
307
+ if (abort.signal.aborted) return;
308
+ setState({ key: loadKey, kind: "ready", value });
309
+ onTitleRef.current?.(value.artifact.title);
310
+ }).catch((error) => {
311
+ if (!abort.signal.aborted) setState({ key: loadKey, kind: "error", error });
312
+ });
313
+ return () => abort.abort();
314
+ }, [loadKey]);
315
+ const ready = current?.kind === "ready" ? current.value : null;
316
+ const transportRef = useRef3(transport);
317
+ transportRef.current = transport;
318
+ const sessionKey = useMemo2(
319
+ () => ready ? JSON.stringify({
320
+ baseUrl: baseUrl.href,
321
+ authorityKey,
322
+ workspaceId,
323
+ artifact: { id: ready.artifact.id, modality: ready.artifact.modality },
324
+ authority: ready.authority,
325
+ replicaId: ready.replicaId,
326
+ workerUrl: runtimes.workerUrl
327
+ }) : "",
328
+ [authorityKey, baseUrl.href, ready, runtimes.workerUrl, workspaceId]
329
+ );
330
+ const createSession = useCallback3(() => {
331
+ if (!ready) throw new Error("Artifact is not open");
332
+ return createBrowserEditableArtifactSession2({
333
+ baseUrl,
334
+ workspaceId,
335
+ artifact: ready.artifact,
336
+ storageAuthority: ready.authority,
337
+ replicaId: ready.replicaId,
338
+ runtime: {
339
+ ...runtimeFor(runtimes, ready.artifact.modality),
340
+ workerUrl: runtimes.workerUrl,
341
+ ...runtimes.applicationOrigin ? { applicationOrigin: runtimes.applicationOrigin } : {},
342
+ ...runtimes.allowInsecureDevelopmentAssets ? { allowInsecureDevelopmentAssets: true } : {}
343
+ },
344
+ ...transportRef.current ? { transport: transportRef.current } : {}
345
+ });
346
+ }, [baseUrl, ready, runtimes, workspaceId]);
347
+ if (!current || current.kind === "loading")
348
+ return /* @__PURE__ */ jsx3(ArtifactLoading, { label: loadingLabel ?? labels.opening });
349
+ if (current.kind === "error") {
350
+ return /* @__PURE__ */ jsx3(
351
+ ArtifactProblem,
352
+ {
353
+ view: describeError ? describeError(current.error) : artifactLoadErrorView(current.error, "editable", labels),
354
+ onRetry: () => setLoadEpoch((value) => value + 1)
355
+ }
356
+ );
357
+ }
358
+ const { artifact } = current.value;
359
+ const surface = { title: artifact.title, showHeader };
360
+ return /* @__PURE__ */ jsx3("div", { className: "h-full min-h-0 bg-og-bg text-og-fg", children: /* @__PURE__ */ jsx3(
361
+ EditableArtifactWorkbenchHost,
362
+ {
363
+ sessionKey,
364
+ createSession,
365
+ document: surface,
366
+ spreadsheet: surface,
367
+ presentation: surface
368
+ }
369
+ ) });
370
+ }
371
+ function runtimeFor(runtimes, modality) {
372
+ switch (modality) {
373
+ case "document":
374
+ return runtimes.document;
375
+ case "spreadsheet":
376
+ return runtimes.spreadsheet;
377
+ case "presentation":
378
+ return runtimes.presentation;
379
+ }
380
+ }
381
+
382
+ // src/components/artifacts/session-artifact-viewer.tsx
383
+ import { SESSION_SCOPE_HEADER } from "@opengeni/sdk";
384
+ import { createEditableArtifactReplicaId } from "@opengeni/sdk/editable-artifacts";
385
+ import { useCallback as useCallback4, useEffect as useEffect4, useMemo as useMemo3, useRef as useRef4, useState as useState4 } from "react";
386
+ import { jsx as jsx4, jsxs } from "react/jsx-runtime";
387
+ var viewerClientKeys = /* @__PURE__ */ new WeakMap();
388
+ function viewerClientKey(client) {
389
+ let key = viewerClientKeys.get(client);
390
+ if (!key) {
391
+ key = crypto.randomUUID();
392
+ viewerClientKeys.set(client, key);
393
+ }
394
+ return key;
395
+ }
396
+ function SessionArtifactViewer({ labels, ...props }) {
397
+ return /* @__PURE__ */ jsx4(ArtifactLabelsProvider, { labels, children: /* @__PURE__ */ jsx4(Viewer, { ...props }) });
398
+ }
399
+ function Viewer({
400
+ client: clientOverride,
401
+ workspaceId: workspaceOverride,
402
+ sessionId,
403
+ target,
404
+ onClose,
405
+ onBack,
406
+ editableRuntimes,
407
+ theme,
408
+ siteToolBridge,
409
+ className
410
+ }) {
411
+ const labels = useArtifactLabels();
412
+ const context = useOpenGeni({ client: clientOverride, workspaceId: workspaceOverride });
413
+ const base = context.client;
414
+ const workspaceId = context.workspaceId;
415
+ const client = useMemo3(
416
+ () => base.withHeaders({ [SESSION_SCOPE_HEADER]: sessionId }),
417
+ [base, sessionId]
418
+ );
419
+ const [loaded, setLoaded] = useState4(null);
420
+ const targetKey = `${target.kind}:${target.artifactId}`;
421
+ const current = loaded?.key === targetKey && loaded.client === client && loaded.workspaceId === workspaceId ? loaded : null;
422
+ const kind = target.kind === "site" ? "site" : current?.kind ?? null;
423
+ const [unavailable, setUnavailable] = useState4(null);
424
+ const markUnavailable = useCallback4(
425
+ () => setUnavailable({ key: targetKey, client, workspaceId }),
426
+ [client, targetKey, workspaceId]
427
+ );
428
+ const title = current?.title ?? target.title ?? (unavailable?.key === targetKey && unavailable.client === client && unavailable.workspaceId === workspaceId ? labels.artifact : labels.opening);
429
+ return /* @__PURE__ */ jsxs(
430
+ "section",
431
+ {
432
+ "aria-label": title,
433
+ "data-og-artifact-viewer": target.kind,
434
+ className: cn("og-root flex h-full min-h-0 w-full min-w-0 flex-col bg-bg text-fg", className),
435
+ children: [
436
+ /* @__PURE__ */ jsx4(
437
+ ArtifactViewerHeader,
438
+ {
439
+ kind,
440
+ title,
441
+ onBack,
442
+ backLabel: labels.back,
443
+ onClose,
444
+ closeLabel: labels.close
445
+ }
446
+ ),
447
+ /* @__PURE__ */ jsx4("div", { className: "flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden", children: target.kind === "site" ? /* @__PURE__ */ jsx4(
448
+ SiteView,
449
+ {
450
+ client,
451
+ workspaceId,
452
+ siteId: target.artifactId,
453
+ theme,
454
+ toolBridge: siteToolBridge,
455
+ showTitle: false,
456
+ onTitle: (next) => setLoaded({ key: targetKey, client, workspaceId, title: next, kind: "site" })
457
+ },
458
+ targetKey
459
+ ) : /* @__PURE__ */ jsx4(
460
+ EditableBody,
461
+ {
462
+ client,
463
+ workspaceId,
464
+ sessionId,
465
+ artifactId: target.artifactId,
466
+ runtimes: editableRuntimes,
467
+ onOpened: (next, modality) => setLoaded({ key: targetKey, client, workspaceId, title: next, kind: modality }),
468
+ onUnavailable: markUnavailable
469
+ },
470
+ targetKey
471
+ ) })
472
+ ]
473
+ }
474
+ );
475
+ }
476
+ function EditableBody({
477
+ client,
478
+ workspaceId,
479
+ sessionId,
480
+ artifactId,
481
+ runtimes,
482
+ onOpened,
483
+ onUnavailable
484
+ }) {
485
+ const labels = useArtifactLabels();
486
+ const clientKey = viewerClientKey(client);
487
+ const [retryEpoch, setRetryEpoch] = useState4(0);
488
+ const [configState, setConfigState] = useState4(null);
489
+ const current = configState?.client === client && configState.workspaceId === workspaceId && configState.sessionId === sessionId ? configState.result : null;
490
+ const config = current?.kind === "ready" ? current.config : null;
491
+ const scopeRef = useRef4({ client, workspaceId, sessionId });
492
+ scopeRef.current = { client, workspaceId, sessionId };
493
+ useEffect4(() => {
494
+ let live = true;
495
+ setConfigState(null);
496
+ client.getClientConfig().then(
497
+ (value) => live && setConfigState({
498
+ client,
499
+ workspaceId,
500
+ sessionId,
501
+ result: value.artifacts ? { kind: "ready", config: value.artifacts } : { kind: "unavailable" }
502
+ }),
503
+ (error) => live && setConfigState({ client, workspaceId, sessionId, result: { kind: "error", error } })
504
+ );
505
+ return () => {
506
+ live = false;
507
+ };
508
+ }, [client, retryEpoch, sessionId, workspaceId]);
509
+ const baseUrl = useMemo3(
510
+ () => new URL(client.apiUrl("/"), globalThis.location?.href ?? "http://localhost/"),
511
+ [client]
512
+ );
513
+ const transport = useMemo3(() => {
514
+ if (!config) return void 0;
515
+ const socket = new URL(config.editableLiveUrl);
516
+ let scope = new AbortController();
517
+ const checkCurrent = (signal) => {
518
+ signal.throwIfAborted();
519
+ if (scopeRef.current.client !== client || scopeRef.current.workspaceId !== workspaceId || scopeRef.current.sessionId !== sessionId) {
520
+ throw new DOMException("Artifact viewer scope changed", "AbortError");
521
+ }
522
+ };
523
+ return {
524
+ activate: () => {
525
+ if (scope.signal.aborted) scope = new AbortController();
526
+ },
527
+ abort: () => scope.abort(),
528
+ fetch: async (input, init) => {
529
+ const signal = AbortSignal.any([scope.signal, ...init?.signal ? [init.signal] : []]);
530
+ checkCurrent(signal);
531
+ const url = new URL(input instanceof Request ? input.url : input, baseUrl);
532
+ if (init?.method === "POST" && url.pathname === new URL(
533
+ `v1/workspaces/${encodeURIComponent(workspaceId)}/editable-artifacts/${encodeURIComponent(artifactId)}/live-ticket`,
534
+ baseUrl
535
+ ).pathname) {
536
+ const next = (await client.getClientConfig({ signal })).artifacts;
537
+ checkCurrent(signal);
538
+ if (!next || artifactCapabilityKey(next) !== artifactCapabilityKey(config)) {
539
+ setConfigState({
540
+ client,
541
+ workspaceId,
542
+ sessionId,
543
+ result: next ? { kind: "ready", config: next } : { kind: "unavailable" }
544
+ });
545
+ scope.abort();
546
+ signal.throwIfAborted();
547
+ }
548
+ const { replicaId } = await new Request(input, init).json();
549
+ if (typeof replicaId !== "string") throw new TypeError("Artifact replica is required");
550
+ await client.getEditableArtifact(workspaceId, artifactId, { replicaId, signal });
551
+ checkCurrent(signal);
552
+ }
553
+ return client.fetchApi(url, { ...init, signal });
554
+ },
555
+ webSocketUrl: socket,
556
+ ...isLoopback(baseUrl) && isLoopback(socket) ? { allowInsecureDevelopmentTransport: true } : {}
557
+ };
558
+ }, [artifactId, baseUrl, client, config, sessionId, workspaceId]);
559
+ useEffect4(() => {
560
+ transport?.activate();
561
+ return () => transport?.abort();
562
+ }, [transport]);
563
+ const blocked = current !== null && (current.kind !== "ready" || !runtimes);
564
+ useEffect4(() => {
565
+ if (blocked) onUnavailable();
566
+ }, [blocked, onUnavailable]);
567
+ if (!current) return /* @__PURE__ */ jsx4(ArtifactLoading, { label: labels.opening });
568
+ if (current.kind === "error") {
569
+ return /* @__PURE__ */ jsx4(
570
+ ArtifactProblem,
571
+ {
572
+ view: artifactLoadErrorView(current.error, "editable", labels),
573
+ onRetry: () => setRetryEpoch((value) => value + 1)
574
+ }
575
+ );
576
+ }
577
+ if (!config || !transport) {
578
+ return /* @__PURE__ */ jsx4(ArtifactProblem, { view: { ...labels.viewingDisabled, retryable: false } });
579
+ }
580
+ if (!runtimes) {
581
+ return /* @__PURE__ */ jsx4(ArtifactProblem, { view: { ...labels.editorsMissing, retryable: false } });
582
+ }
583
+ return /* @__PURE__ */ jsx4(
584
+ EditableArtifactView,
585
+ {
586
+ baseUrl,
587
+ workspaceId,
588
+ artifactId,
589
+ authorityKey: JSON.stringify([clientKey, sessionId, artifactCapabilityKey(config)]),
590
+ runtimes: {
591
+ ...runtimes,
592
+ ...isLoopback(baseUrl) ? { allowInsecureDevelopmentAssets: true } : {}
593
+ },
594
+ transport,
595
+ showHeader: false,
596
+ open: async (signal) => {
597
+ const replicaId = createEditableArtifactReplicaId();
598
+ const artifact = await client.getEditableArtifact(workspaceId, artifactId, {
599
+ replicaId,
600
+ signal
601
+ });
602
+ signal.throwIfAborted();
603
+ onOpened(artifact.title, artifact.modality);
604
+ return {
605
+ artifact,
606
+ replicaId,
607
+ authority: {
608
+ deploymentOrigin: baseUrl.origin,
609
+ workspaceId,
610
+ ...config.cachePartition
611
+ }
612
+ };
613
+ }
614
+ }
615
+ );
616
+ }
617
+ function artifactCapabilityKey(config) {
618
+ return JSON.stringify([
619
+ config.editableLiveUrl,
620
+ config.cachePartition.accountId,
621
+ config.cachePartition.principalId,
622
+ config.cachePartition.authorizationEpoch
623
+ ]);
624
+ }
625
+ function isLoopback(url) {
626
+ return (url.protocol === "http:" || url.protocol === "ws:") && (url.hostname === "localhost" || url.hostname === "127.0.0.1" || url.hostname === "[::1]");
627
+ }
1544
628
  export {
629
+ ArtifactBadge,
630
+ ArtifactButton,
631
+ ArtifactLabelsProvider,
632
+ ArtifactLoading,
633
+ ArtifactProblem,
634
+ ArtifactSandbox,
635
+ ArtifactSelect,
1545
636
  ArtifactSurface,
637
+ ArtifactViewerHeader,
1546
638
  BrowserEditableArtifactWorkbench,
639
+ ChatInteractiveBlock,
640
+ DEFAULT_ARTIFACT_LABELS,
641
+ DeferredChatMedia,
1547
642
  DocumentArtifactSurface,
1548
643
  DocumentEditor,
1549
644
  DocumentProjectionArtifactSurface,
1550
645
  DocumentProjectionEditor,
646
+ EditableArtifactView,
1551
647
  EditableArtifactWorkbench,
1552
648
  EditableArtifactWorkbenchHost,
1553
649
  EditableDocumentArtifactSurface,
@@ -1560,13 +656,20 @@ export {
1560
656
  PresentationProjectionArtifactSurface,
1561
657
  PresentationProjectionEditor,
1562
658
  PublishedHtmlArtifactFrame,
659
+ SessionArtifactViewer,
660
+ SiteView,
1563
661
  SpreadsheetArtifactSurface,
1564
662
  SpreadsheetGrid,
1565
663
  SpreadsheetProjectionGrid,
664
+ artifactKindIcon,
665
+ artifactKindSubtitle,
666
+ artifactLoadErrorMessage,
667
+ artifactLoadErrorView,
1566
668
  inlineHtmlDocument,
1567
669
  isRetainedImageContentType,
1568
670
  openGeniSiteBridgePortFromBootstrap,
1569
671
  publishedHtmlArtifactDocument,
672
+ useArtifactLabels,
1570
673
  useRetainedImageObjectUrl
1571
674
  };
1572
675
  //# sourceMappingURL=artifacts.js.map