@openviking/react 0.1.4 → 0.1.6

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 (139) hide show
  1. package/README.md +15 -11
  2. package/dist/28~0.js +15 -0
  3. package/dist/2~0.js +6 -3
  4. package/dist/37~0.js +27 -0
  5. package/dist/3c~0.js +17 -9
  6. package/dist/3~0.js +4 -2
  7. package/dist/ae~0.js +6 -2
  8. package/dist/a~0.js +79 -72
  9. package/dist/ck~0.js +4 -0
  10. package/dist/client/paths.d.ts +4 -0
  11. package/dist/client/provider.d.ts +10 -6
  12. package/dist/components/agent-connect/agent-connect-code-block.d.ts +14 -0
  13. package/dist/components/agent-connect/agent-connect-copy.d.ts +3 -0
  14. package/dist/components/agent-connect/agent-connect-design.d.ts +1 -1
  15. package/dist/components/agent-connect/agent-connect-installer.d.ts +1 -0
  16. package/dist/components/agent-connect/agent-connect-instructions-view.d.ts +4 -6
  17. package/dist/components/agent-connect/agent-connect-instructions.d.ts +13 -0
  18. package/dist/components/agent-connect/agent-connect-markdown.d.ts +8 -2
  19. package/dist/components/agent-connect/agent-connect-mask.d.ts +10 -0
  20. package/dist/components/agent-connect/agent-connect.d.ts +1 -1
  21. package/dist/components/agent-connect/locales/en-US.d.ts +3 -0
  22. package/dist/components/agent-connect/style.css +163 -5
  23. package/dist/components/agent-connect/types.d.ts +5 -3
  24. package/dist/components/agent-connect/use-agent-connect-copy.d.ts +6 -0
  25. package/dist/components/directory-tour/style.css +46 -2
  26. package/dist/components/directory-tour/types.d.ts +2 -1
  27. package/dist/components/experience-dashboard/dashboard-tabs.d.ts +11 -0
  28. package/dist/components/experience-dashboard/experience-dashboard.d.ts +2 -0
  29. package/dist/components/experience-dashboard/experience-impact.d.ts +11 -0
  30. package/dist/components/experience-dashboard/experience-list.d.ts +9 -0
  31. package/dist/components/experience-dashboard/experience-pagination.d.ts +8 -0
  32. package/dist/components/experience-dashboard/experience-tests.d.ts +6 -0
  33. package/dist/components/experience-dashboard/experience-trajectories.d.ts +6 -0
  34. package/dist/components/experience-dashboard/index.d.ts +2 -0
  35. package/dist/components/experience-dashboard/labels.d.ts +2 -0
  36. package/dist/components/experience-dashboard/style.css +699 -0
  37. package/dist/components/experience-dashboard/style.js +0 -0
  38. package/dist/components/experience-dashboard/types.d.ts +106 -0
  39. package/dist/components/experience-dashboard.js +1 -0
  40. package/dist/components/file-browser-entries/file-browser-entries.d.ts +1 -1
  41. package/dist/components/file-browser-entries/style.css +259 -13
  42. package/dist/components/file-browser-entries/types.d.ts +2 -2
  43. package/dist/components/file-preview/style.css +48 -4
  44. package/dist/components/file-preview/types.d.ts +2 -2
  45. package/dist/components/file-tree/style.css +63 -4
  46. package/dist/components/file-tree/types.d.ts +2 -2
  47. package/dist/components/scope-switcher/scope-switcher.d.ts +2 -2
  48. package/dist/components/scope-switcher/style.css +48 -4
  49. package/dist/components/scope-switcher/types.d.ts +5 -5
  50. package/dist/components/scope-switcher.js +1 -1
  51. package/dist/components/style.css +2451 -139
  52. package/dist/components/tui/style.css +122 -36
  53. package/dist/components/tui/tui.d.ts +1 -1
  54. package/dist/components/tui/types.d.ts +2 -2
  55. package/dist/components/viking-bot/ark-message-list-view.d.ts +4 -1
  56. package/dist/components/viking-bot/interaction/types.d.ts +2 -2
  57. package/dist/components/viking-bot/interaction/viking-bot-interaction.d.ts +1 -1
  58. package/dist/components/viking-bot/session-actions.d.ts +2 -2
  59. package/dist/components/viking-bot/style.css +159 -12
  60. package/dist/components/viking-bot/types.d.ts +7 -7
  61. package/dist/components/viking-bot/viking-bot.d.ts +1 -1
  62. package/dist/components/wiki-dashboard/index.d.ts +2 -0
  63. package/dist/components/wiki-dashboard/labels.d.ts +2 -0
  64. package/dist/components/wiki-dashboard/style.css +741 -0
  65. package/dist/components/wiki-dashboard/style.js +0 -0
  66. package/dist/components/wiki-dashboard/types.d.ts +92 -0
  67. package/dist/components/wiki-dashboard/wiki-action-button.d.ts +9 -0
  68. package/dist/components/wiki-dashboard/wiki-conflict-card.d.ts +15 -0
  69. package/dist/components/wiki-dashboard/wiki-dashboard.d.ts +2 -0
  70. package/dist/components/wiki-dashboard/wiki-file-icon.d.ts +3 -0
  71. package/dist/components/wiki-dashboard/wiki-severity-filter.d.ts +8 -0
  72. package/dist/components/wiki-dashboard.js +1 -0
  73. package/dist/c~0.js +169 -155
  74. package/dist/e~0.js +3 -1
  75. package/dist/fi~0.js +354 -0
  76. package/dist/fj~0.js +503 -0
  77. package/dist/f~0.js +661 -309
  78. package/dist/icons/index.d.ts +28 -0
  79. package/dist/icons.js +1 -1
  80. package/dist/index.d.ts +4 -0
  81. package/dist/index.js +3 -1
  82. package/dist/k~0.js +277 -1
  83. package/dist/lk~0.js +55 -13
  84. package/dist/l~0.js +1096 -187
  85. package/dist/modules/console/console.d.ts +1 -1
  86. package/dist/modules/console/index.d.ts +1 -2
  87. package/dist/modules/console/style.css +377 -56
  88. package/dist/modules/console/types.d.ts +2 -2
  89. package/dist/modules/console/use-console.d.ts +1 -1
  90. package/dist/modules/console.js +1 -1
  91. package/dist/modules/file-browser/dashboard-data.d.ts +9 -0
  92. package/dist/modules/file-browser/dashboard-indicator.d.ts +8 -0
  93. package/dist/modules/file-browser/dashboard-labels.d.ts +9 -0
  94. package/dist/modules/file-browser/dashboard-model.d.ts +14 -0
  95. package/dist/modules/file-browser/dashboard-resource.d.ts +12 -0
  96. package/dist/modules/file-browser/experience-dashboard-pane.d.ts +8 -0
  97. package/dist/modules/file-browser/experience-data.d.ts +31 -0
  98. package/dist/modules/file-browser/file-browser-labels.d.ts +1 -1
  99. package/dist/modules/file-browser/file-browser-tree-pane.d.ts +3 -2
  100. package/dist/modules/file-browser/file-browser.d.ts +1 -1
  101. package/dist/modules/file-browser/fs-directories.d.ts +8 -0
  102. package/dist/modules/file-browser/fs-lines.d.ts +36 -0
  103. package/dist/modules/file-browser/fs-memory-fields.d.ts +65 -0
  104. package/dist/modules/file-browser/fs-model.d.ts +12 -2
  105. package/dist/modules/file-browser/fs-read-file.d.ts +14 -0
  106. package/dist/modules/file-browser/fs-selection.d.ts +4 -0
  107. package/dist/modules/file-browser/index.d.ts +2 -2
  108. package/dist/modules/file-browser/style.css +1883 -25
  109. package/dist/modules/file-browser/types.d.ts +64 -2
  110. package/dist/modules/file-browser/use-browser-dashboards.d.ts +31 -0
  111. package/dist/modules/file-browser/use-dashboard-query.d.ts +9 -0
  112. package/dist/modules/file-browser/use-experience-dashboard.d.ts +27 -0
  113. package/dist/modules/file-browser/use-file-browser.d.ts +2 -45
  114. package/dist/modules/file-browser/use-fs-tree.d.ts +2 -0
  115. package/dist/modules/file-browser/use-wiki-dashboard.d.ts +17 -0
  116. package/dist/modules/file-browser/wiki-conflicts.d.ts +12 -0
  117. package/dist/modules/file-browser/wiki-dashboard-pane.d.ts +14 -0
  118. package/dist/modules/file-browser.js +1 -1
  119. package/dist/modules/scope-cascade/controller.d.ts +2 -2
  120. package/dist/modules/scope-cascade/index.d.ts +1 -2
  121. package/dist/modules/scope-cascade/scope-cascade.d.ts +2 -2
  122. package/dist/modules/scope-cascade/style.css +48 -4
  123. package/dist/modules/scope-cascade/types.d.ts +9 -4
  124. package/dist/modules/scope-cascade/use-scope-cascade.d.ts +2 -2
  125. package/dist/modules/scope-cascade.js +1 -1
  126. package/dist/modules/style.css +2459 -192
  127. package/dist/n~0.js +16 -130
  128. package/dist/rt~0.js +152 -0
  129. package/dist/r~0.js +17 -38
  130. package/dist/shared/components/popover/popover.d.ts +1 -1
  131. package/dist/shared/components/popover/types.d.ts +7 -1
  132. package/dist/shared/dashboard/dashboard-state.d.ts +12 -0
  133. package/dist/shared/locale-context.d.ts +8 -0
  134. package/dist/static/image/dashboard-background.png +0 -0
  135. package/dist/style.css +9445 -4822
  136. package/dist/u~0.js +324 -96
  137. package/dist/viking-bot-composer~0.js +4 -2
  138. package/dist/viking-bot-interaction~0.js +3 -1
  139. package/package.json +14 -2
package/dist/f~0.js CHANGED
@@ -1,348 +1,700 @@
1
1
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
- import { useCallback, useEffect, useId, useRef, useState } from "react";
3
- import { resolveLocale } from "./nx~0.js";
4
- import { checkreact } from "./0~0.js";
5
- import { searchreact } from "./p~0.js";
6
- const SvgChevronDown = (props)=>/*#__PURE__*/ jsx("svg", {
7
- xmlns: "http://www.w3.org/2000/svg",
8
- width: 14,
9
- height: 14,
10
- fill: "none",
11
- viewBox: "0 0 14 14",
12
- ...props,
13
- children: /*#__PURE__*/ jsx("path", {
14
- fill: "currentColor",
15
- d: "M9.607 5.232a.437.437 0 1 1 .619.619L7.309 8.768a.437.437 0 0 1-.618 0L3.774 5.85a.437.437 0 1 1 .619-.619L7 7.84z"
16
- })
2
+ import { useId, useState } from "react";
3
+ import { mergeLabels } from "./nx~0.js";
4
+ import { FileInputIcon, ScanSearchIcon, ActivityIcon } from "./k~0.js";
5
+ import { DashboardState } from "./37~0.js";
6
+ import { useLocale } from "./28~0.js";
7
+ function DashboardTabs({ tabs, active, label, onChange, children }) {
8
+ const id = useId();
9
+ return /*#__PURE__*/ jsxs(Fragment, {
10
+ children: [
11
+ /*#__PURE__*/ jsx("div", {
12
+ className: "ov-dashboard-tabs",
13
+ role: "tablist",
14
+ tabIndex: -1,
15
+ "aria-label": label,
16
+ onKeyDown: (event)=>{
17
+ const delta = 'ArrowRight' === event.key ? 1 : 'ArrowLeft' === event.key ? -1 : 0;
18
+ if (!delta && 'Home' !== event.key && 'End' !== event.key) return;
19
+ event.preventDefault();
20
+ const index = 'Home' === event.key ? 0 : 'End' === event.key ? tabs.length - 1 : (tabs.findIndex((tab)=>tab.key === active) + delta + tabs.length) % tabs.length;
21
+ onChange(tabs[index].key);
22
+ const buttons = event.currentTarget.querySelectorAll('[role="tab"]');
23
+ buttons[index]?.focus();
24
+ },
25
+ children: tabs.map((tab)=>/*#__PURE__*/ jsx("button", {
26
+ type: "button",
27
+ id: `${id}-${tab.key}`,
28
+ role: "tab",
29
+ "aria-selected": active === tab.key,
30
+ "aria-controls": `${id}-panel`,
31
+ tabIndex: active === tab.key ? 0 : -1,
32
+ onClick: ()=>onChange(tab.key),
33
+ children: tab.title
34
+ }, tab.key))
35
+ }),
36
+ /*#__PURE__*/ jsx("div", {
37
+ role: "tabpanel",
38
+ id: `${id}-panel`,
39
+ "aria-labelledby": `${id}-${active}`,
40
+ className: "ov-dashboard-tabpanel",
41
+ children: children
42
+ })
43
+ ]
17
44
  });
18
- const chevron_downreact = SvgChevronDown;
19
- const messages = {
45
+ }
46
+ const en = {
47
+ latest: 'Latest experience',
48
+ sourceCount: 'Generated from {count} trajectories',
49
+ sourceUri: 'Source Trajectory URI',
50
+ task: 'Task',
51
+ copy: 'Copy',
52
+ copied: 'Copied',
53
+ copyFailed: 'Copy failed',
54
+ title: 'Agent experiences',
55
+ allExperiences: 'All experiences',
56
+ index: 'No.',
57
+ impact: 'Application impact',
58
+ source: 'Source trace',
59
+ test: 'Test',
60
+ application: 'Experience application data',
61
+ notice: 'AI-generated data may contain errors',
62
+ injection: 'Context injections',
63
+ recall: 'Retrieval recalls',
64
+ listRecall: 'Experience recalls',
65
+ rate: 'Injection rate',
66
+ outcomes: 'Outcome distribution',
67
+ trajectories: 'Application trajectories',
68
+ empty: 'No experiences',
69
+ emptySource: 'No source records',
70
+ emptyTests: 'No test materials',
71
+ emptyOutcomes: 'No distribution data',
20
72
  loading: 'Loading…',
21
- searchPlaceholder: 'Search',
22
- empty: 'No options',
23
- noMatch: 'No matches',
24
- error: 'Unable to load options'
73
+ failed: 'Could not load data',
74
+ retry: 'Retry',
75
+ previous: 'Previous',
76
+ next: 'Next',
77
+ all: 'All time',
78
+ week: 'Last 7 days',
79
+ month: 'Last 30 days',
80
+ range: 'Statistics period',
81
+ updated: 'Updated',
82
+ name: 'Experience',
83
+ success: 'Task success',
84
+ partial: 'Partial success',
85
+ unfinished: 'Unfinished',
86
+ failure: 'Failure',
87
+ unknown: 'Unknown',
88
+ unsupportedMetric: 'Metric not provided',
89
+ open: 'Open'
25
90
  };
26
- const en_US = messages;
27
- const zh_CN_messages = {
91
+ const zh = {
92
+ latest: '最新经验',
93
+ sourceCount: '由 {count} 条轨迹生成',
94
+ sourceUri: '来源 Trajectory URI',
95
+ task: '任务描述',
96
+ copy: '复制',
97
+ copied: '已复制',
98
+ copyFailed: '复制失败',
99
+ title: 'Agent 经验',
100
+ allExperiences: '全部经验',
101
+ index: '序号',
102
+ impact: '应用效果',
103
+ source: '来源追溯',
104
+ test: '测试',
105
+ application: '经验应用数据',
106
+ notice: '数据由 AI 生成,可能有误',
107
+ injection: '注入上下文次数',
108
+ recall: '检索召回次数',
109
+ listRecall: '经验召回次数',
110
+ rate: '注入率',
111
+ outcomes: '任务结果分布',
112
+ trajectories: '应用轨迹记录',
113
+ empty: '暂无经验',
114
+ emptySource: '暂无来源记录',
115
+ emptyTests: '暂无测试材料',
116
+ emptyOutcomes: '暂无可用分布数据',
28
117
  loading: '加载中…',
29
- searchPlaceholder: '搜索',
30
- empty: '暂无选项',
31
- noMatch: '没有匹配项',
32
- error: '选项加载失败'
33
- };
34
- const zh_CN = zh_CN_messages;
35
- const LOCALES = {
36
- 'en-US': en_US,
37
- 'zh-CN': zh_CN
118
+ failed: '数据加载失败',
119
+ retry: '重试',
120
+ previous: '上一页',
121
+ next: '下一页',
122
+ all: '全部时间',
123
+ week: '最近 7 天',
124
+ month: '最近 30 天',
125
+ range: '选择统计时间范围',
126
+ updated: '更新于',
127
+ name: '经验文件',
128
+ success: '任务成功',
129
+ partial: '部分成功',
130
+ unfinished: '未完成',
131
+ failure: '失败',
132
+ unknown: '未知',
133
+ unsupportedMetric: '未提供此指标',
134
+ open: '打开'
38
135
  };
39
- function resolveScopeLabels(locale = 'en-US', labels) {
40
- const defaults = resolveLocale(LOCALES, locale, labels);
41
- return {
42
- ...defaults,
43
- noMatch: labels?.noMatch ?? labels?.empty ?? defaults.noMatch
44
- };
45
- }
46
- function moveScopeFocus(event) {
47
- if (![
48
- 'ArrowDown',
49
- 'ArrowUp',
50
- 'Home',
51
- 'End'
52
- ].includes(event.key)) return;
53
- const target = event.target;
54
- const isSearch = target.matches('input.ov-scope-switcher__search');
55
- if (event.defaultPrevented || !target.matches('[role="option"]') && !isSearch || isSearch && !event.key.startsWith('Arrow')) return;
56
- const options = Array.from(event.currentTarget.querySelectorAll('[role="option"]:not([aria-disabled="true"])'));
57
- if (!options.length) return;
58
- event.preventDefault();
59
- const current = options.indexOf(document.activeElement);
60
- const next = 'Home' === event.key ? 0 : 'End' === event.key ? options.length - 1 : 'ArrowDown' === event.key ? (current + 1) % options.length : current < 0 ? options.length - 1 : (current - 1 + options.length) % options.length;
61
- options[next]?.focus();
62
- }
63
- function Highlight({ text, keyword }) {
64
- const needle = keyword.trim().toLocaleLowerCase();
65
- if (!needle) return /*#__PURE__*/ jsx(Fragment, {
66
- children: text
67
- });
68
- const haystack = text.toLocaleLowerCase();
69
- const parts = [];
70
- let cursor = 0;
71
- let hit = haystack.indexOf(needle);
72
- while(hit >= 0){
73
- if (hit > cursor) parts.push(text.slice(cursor, hit));
74
- const end = hit + needle.length;
75
- parts.push(/*#__PURE__*/ jsx("mark", {
76
- children: text.slice(hit, end)
77
- }, `${hit}-${end}`));
78
- cursor = end;
79
- hit = haystack.indexOf(needle, cursor);
80
- }
81
- if (cursor < text.length) parts.push(text.slice(cursor));
82
- return /*#__PURE__*/ jsx(Fragment, {
83
- children: parts
84
- });
136
+ const experienceLabels = (locale, labels)=>mergeLabels('zh-CN' === locale ? zh : en, labels);
137
+ function updatedAt(value, locale) {
138
+ const time = Date.parse(value);
139
+ if (!Number.isFinite(time)) return value;
140
+ const seconds = (time - Date.now()) / 1000;
141
+ const absolute = Math.abs(seconds);
142
+ if (absolute >= 604800) return new Intl.DateTimeFormat(locale).format(time);
143
+ const [unit, size] = absolute < 3600 ? [
144
+ 'minute',
145
+ 60
146
+ ] : absolute < 86400 ? [
147
+ 'hour',
148
+ 3600
149
+ ] : [
150
+ 'day',
151
+ 86400
152
+ ];
153
+ return new Intl.RelativeTimeFormat(locale, {
154
+ numeric: 'always'
155
+ }).format(Math.round(seconds / size), unit);
85
156
  }
86
- function ScopePanel({ label, data, state, slots, actions, onSelect, labels }) {
87
- const focusPanel = useCallback((node)=>{
88
- const target = node?.querySelector('input') ?? node?.querySelector('[role="option"][aria-selected="true"]:not([aria-disabled="true"])') ?? node?.querySelector('[role="option"]:not([aria-disabled="true"])');
89
- (target ?? node)?.focus();
90
- }, []);
91
- const options = data.visibleOptions ?? data.options;
92
- const keyword = state?.searchKeyword ?? '';
93
- const hasKeyword = keyword.trim().length > 0;
94
- const searchVisible = actions?.onSearchKeywordChange && (hasKeyword || Math.max(options.length, data.options.length, data.total ?? 0) > 10);
95
- const search = searchVisible ? /*#__PURE__*/ jsxs("div", {
96
- className: "ov-scope-switcher__search-field",
157
+ function ExperienceList({ items, total, startIndex = 0, locale = 'en-US', labels: t, onOpenUri }) {
158
+ return /*#__PURE__*/ jsxs(Fragment, {
97
159
  children: [
98
- /*#__PURE__*/ jsx(searchreact, {
99
- className: "ov-scope-switcher__search-icon"
160
+ /*#__PURE__*/ jsxs("h2", {
161
+ className: "ov-experience-dashboard__list-title",
162
+ children: [
163
+ t.allExperiences,
164
+ void 0 === total ? '' : ` · ${total}`
165
+ ]
100
166
  }),
101
- /*#__PURE__*/ jsx("input", {
102
- type: "search",
103
- className: "ov-scope-switcher__search",
104
- value: keyword,
105
- "aria-label": labels.searchPlaceholder,
106
- placeholder: labels.searchPlaceholder,
107
- onChange: (event)=>actions?.onSearchKeywordChange?.(event.currentTarget.value)
167
+ /*#__PURE__*/ jsx("div", {
168
+ className: "ov-experience-dashboard__table-scroll",
169
+ tabIndex: 0,
170
+ role: "region",
171
+ "aria-label": t.title,
172
+ children: /*#__PURE__*/ jsxs("table", {
173
+ className: "ov-experience-dashboard__table",
174
+ children: [
175
+ /*#__PURE__*/ jsx("caption", {
176
+ children: t.title
177
+ }),
178
+ /*#__PURE__*/ jsx("thead", {
179
+ children: /*#__PURE__*/ jsxs("tr", {
180
+ children: [
181
+ /*#__PURE__*/ jsx("th", {
182
+ scope: "col",
183
+ children: t.index
184
+ }),
185
+ /*#__PURE__*/ jsx("th", {
186
+ scope: "col",
187
+ children: t.name
188
+ }),
189
+ /*#__PURE__*/ jsx("th", {
190
+ scope: "col",
191
+ children: t.injection
192
+ }),
193
+ /*#__PURE__*/ jsx("th", {
194
+ scope: "col",
195
+ children: t.listRecall
196
+ })
197
+ ]
198
+ })
199
+ }),
200
+ /*#__PURE__*/ jsx("tbody", {
201
+ children: items.map((item, index)=>/*#__PURE__*/ jsxs("tr", {
202
+ children: [
203
+ /*#__PURE__*/ jsxs("td", {
204
+ children: [
205
+ "# ",
206
+ startIndex + index + 1
207
+ ]
208
+ }),
209
+ /*#__PURE__*/ jsxs("th", {
210
+ scope: "row",
211
+ children: [
212
+ /*#__PURE__*/ jsx("button", {
213
+ type: "button",
214
+ disabled: !onOpenUri,
215
+ onClick: ()=>onOpenUri?.(item.uri),
216
+ children: item.name
217
+ }),
218
+ /*#__PURE__*/ jsxs("span", {
219
+ children: [
220
+ /*#__PURE__*/ jsx("code", {
221
+ title: item.uri,
222
+ children: item.uri
223
+ }),
224
+ item.modTime ? /*#__PURE__*/ jsxs("time", {
225
+ dateTime: item.modTime,
226
+ title: item.modTime,
227
+ children: [
228
+ "\xb7 ",
229
+ t.updated,
230
+ " ",
231
+ updatedAt(item.modTime, locale)
232
+ ]
233
+ }) : null
234
+ ]
235
+ })
236
+ ]
237
+ }),
238
+ /*#__PURE__*/ jsx("td", {
239
+ children: item.injectionCount ?? '—'
240
+ }),
241
+ /*#__PURE__*/ jsx("td", {
242
+ children: item.recallCount ?? '—'
243
+ })
244
+ ]
245
+ }, item.uri))
246
+ })
247
+ ]
248
+ })
108
249
  })
109
250
  ]
110
- }) : null;
111
- let list;
112
- list = state?.loading ? /*#__PURE__*/ jsx("div", {
113
- className: "ov-scope-switcher__state",
114
- role: "status",
115
- children: labels.loading
116
- }) : state?.error ? /*#__PURE__*/ jsx("div", {
117
- className: "ov-scope-switcher__state",
118
- role: "alert",
119
- children: slots?.errorFallback ?? labels.error
120
- }) : options.length ? /*#__PURE__*/ jsx("div", {
121
- className: "ov-scope-switcher__list",
122
- role: "listbox",
123
- "aria-label": label,
124
- "aria-busy": state?.busy,
125
- onScroll: (event)=>{
126
- const { scrollTop, scrollHeight, clientHeight } = event.currentTarget;
127
- actions?.onScroll?.({
128
- scrollTop,
129
- scrollHeight,
130
- clientHeight
131
- });
132
- },
133
- children: options.map((option)=>{
134
- const selected = option.id === data.selectedId;
135
- const content = /*#__PURE__*/ jsxs(Fragment, {
251
+ });
252
+ }
253
+ function ExperienceTrajectories({ items, onOpenUri, source = false }) {
254
+ return /*#__PURE__*/ jsx("ul", {
255
+ className: `ov-experience-dashboard__timeline${source ? ' ov-experience-dashboard__timeline--source' : ''}`,
256
+ children: items.map((item)=>/*#__PURE__*/ jsxs("li", {
136
257
  children: [
137
- option.icon && /*#__PURE__*/ jsx("span", {
138
- className: "ov-scope-switcher__icon",
139
- "aria-hidden": "true",
140
- children: option.icon
258
+ item.created_at ? /*#__PURE__*/ jsx("time", {
259
+ dateTime: item.created_at,
260
+ children: item.created_at
261
+ }) : null,
262
+ /*#__PURE__*/ jsx("button", {
263
+ type: "button",
264
+ disabled: !onOpenUri,
265
+ onClick: ()=>onOpenUri?.(item.uri),
266
+ children: item.name
267
+ }),
268
+ /*#__PURE__*/ jsx("code", {
269
+ children: item.uri
141
270
  }),
142
- /*#__PURE__*/ jsxs("span", {
143
- className: "ov-scope-switcher__option-text",
271
+ item.description ? /*#__PURE__*/ jsx("p", {
272
+ children: item.description
273
+ }) : null
274
+ ]
275
+ }, item.uri))
276
+ });
277
+ }
278
+ const ORDER = [
279
+ 'success',
280
+ 'partial',
281
+ 'unfinished',
282
+ 'failure',
283
+ 'unknown'
284
+ ];
285
+ function ExperienceImpact({ data, labels: t, days, onDaysChange, outcomesState, trajectoriesState, onOpenUri }) {
286
+ const total = data.outcomes?.reduce((sum, item)=>sum + item.count, 0) ?? 0;
287
+ const metrics = [
288
+ {
289
+ label: t.injection,
290
+ value: data.effect?.injectionCount,
291
+ icon: /*#__PURE__*/ jsx(FileInputIcon, {
292
+ width: 14,
293
+ height: 14
294
+ })
295
+ },
296
+ {
297
+ label: t.recall,
298
+ value: data.effect?.recallCount,
299
+ icon: /*#__PURE__*/ jsx(ScanSearchIcon, {
300
+ width: 14,
301
+ height: 14
302
+ })
303
+ },
304
+ {
305
+ label: t.rate,
306
+ value: data.effect ? new Intl.NumberFormat('en-US', {
307
+ style: 'percent',
308
+ maximumFractionDigits: 1
309
+ }).format(data.effect.injectionRate) : void 0,
310
+ icon: /*#__PURE__*/ jsx(ActivityIcon, {
311
+ width: 14,
312
+ height: 14
313
+ })
314
+ }
315
+ ];
316
+ return /*#__PURE__*/ jsxs("div", {
317
+ className: "ov-experience-dashboard__impact",
318
+ children: [
319
+ /*#__PURE__*/ jsxs("div", {
320
+ className: "ov-experience-dashboard__heading",
321
+ children: [
322
+ /*#__PURE__*/ jsxs("div", {
144
323
  children: [
324
+ /*#__PURE__*/ jsx("h2", {
325
+ children: t.application
326
+ }),
145
327
  /*#__PURE__*/ jsx("span", {
146
- children: /*#__PURE__*/ jsx(Highlight, {
147
- text: option.label,
148
- keyword: keyword
149
- })
328
+ children: t.notice
329
+ })
330
+ ]
331
+ }),
332
+ /*#__PURE__*/ jsxs("select", {
333
+ "aria-label": t.range,
334
+ value: days,
335
+ onChange: (event)=>onDaysChange(Number(event.target.value)),
336
+ children: [
337
+ /*#__PURE__*/ jsx("option", {
338
+ value: 7,
339
+ children: t.week
340
+ }),
341
+ /*#__PURE__*/ jsx("option", {
342
+ value: 30,
343
+ children: t.month
150
344
  }),
151
- option.description && /*#__PURE__*/ jsx("small", {
152
- children: option.description
345
+ /*#__PURE__*/ jsx("option", {
346
+ value: 0,
347
+ children: t.all
153
348
  })
154
349
  ]
350
+ })
351
+ ]
352
+ }),
353
+ /*#__PURE__*/ jsx("dl", {
354
+ className: "ov-experience-dashboard__metrics",
355
+ children: metrics.map((metric)=>/*#__PURE__*/ jsxs("div", {
356
+ title: void 0 === metric.value ? t.unsupportedMetric : void 0,
357
+ children: [
358
+ metric.icon,
359
+ /*#__PURE__*/ jsx("dd", {
360
+ children: metric.value ?? '—'
361
+ }),
362
+ /*#__PURE__*/ jsx("dt", {
363
+ children: metric.label
364
+ })
365
+ ]
366
+ }, metric.label))
367
+ }),
368
+ /*#__PURE__*/ jsx("section", {
369
+ className: "ov-experience-dashboard__distribution",
370
+ "aria-label": t.outcomes,
371
+ children: data.outcomes?.length ? ORDER.map((outcome)=>{
372
+ const count = data.outcomes?.find((item)=>item.outcome === outcome)?.count ?? 0;
373
+ return /*#__PURE__*/ jsxs("div", {
374
+ className: "ov-experience-dashboard__outcome",
375
+ children: [
376
+ /*#__PURE__*/ jsxs("div", {
377
+ children: [
378
+ /*#__PURE__*/ jsx("span", {
379
+ children: t[outcome]
380
+ }),
381
+ /*#__PURE__*/ jsx("strong", {
382
+ children: count
383
+ })
384
+ ]
385
+ }),
386
+ /*#__PURE__*/ jsx("div", {
387
+ className: "ov-experience-dashboard__outcome-track",
388
+ "aria-hidden": "true",
389
+ children: /*#__PURE__*/ jsx("span", {
390
+ style: {
391
+ width: `${total > 0 ? Math.max(count / total * 100, count ? 2 : 0) : 0}%`
392
+ }
393
+ })
394
+ })
395
+ ]
396
+ }, outcome);
397
+ }) : /*#__PURE__*/ jsx(DashboardState, {
398
+ state: outcomesState,
399
+ empty: t.emptyOutcomes,
400
+ loading: t.loading,
401
+ failed: t.failed,
402
+ retry: t.retry
403
+ })
404
+ }),
405
+ /*#__PURE__*/ jsxs("section", {
406
+ className: "ov-experience-dashboard__trajectories",
407
+ children: [
408
+ /*#__PURE__*/ jsxs("h3", {
409
+ children: [
410
+ t.trajectories,
411
+ void 0 === data.trajectoryTotal ? '' : ` · ${data.trajectoryTotal}`
412
+ ]
155
413
  }),
156
- selected && /*#__PURE__*/ jsx("span", {
157
- className: "ov-scope-switcher__check",
158
- "aria-hidden": "true",
159
- children: /*#__PURE__*/ jsx(checkreact, {})
414
+ data.trajectories?.length ? /*#__PURE__*/ jsx(ExperienceTrajectories, {
415
+ items: data.trajectories,
416
+ onOpenUri: onOpenUri
417
+ }) : /*#__PURE__*/ jsx(DashboardState, {
418
+ state: trajectoriesState,
419
+ empty: t.empty,
420
+ loading: t.loading,
421
+ failed: t.failed,
422
+ retry: t.retry
160
423
  })
161
424
  ]
425
+ })
426
+ ]
427
+ });
428
+ }
429
+ function CopyButton({ value, labels: t }) {
430
+ const [result, setResult] = useState();
431
+ const state = result?.value === value ? result.state : void 0;
432
+ const copy = async ()=>{
433
+ setResult({
434
+ value,
435
+ state: 'pending'
436
+ });
437
+ try {
438
+ await navigator.clipboard.writeText(value);
439
+ setResult({
440
+ value,
441
+ state: 'copied'
162
442
  });
163
- return /*#__PURE__*/ jsx("div", {
164
- tabIndex: option.disabled || state?.busy ? -1 : 0,
165
- role: "option",
166
- "aria-selected": selected,
167
- className: "ov-scope-switcher__option",
168
- title: option.label,
169
- "aria-disabled": option.disabled || state?.busy || void 0,
170
- onClick: (event)=>{
171
- const target = event.target;
172
- if (option.disabled || state?.busy || target.closest('button, a, input, select, textarea, [role="button"]')) return;
173
- onSelect(option);
174
- },
175
- onKeyDown: (event)=>{
176
- if (event.target !== event.currentTarget || option.disabled || state?.busy) return;
177
- if ('Enter' === event.key || ' ' === event.key) {
178
- event.preventDefault();
179
- onSelect(option);
180
- }
181
- },
182
- children: slots?.renderOption ? slots?.renderOption(content, option) : content
183
- }, option.id);
184
- })
185
- }, keyword) : /*#__PURE__*/ jsx("div", {
186
- className: "ov-scope-switcher__state",
187
- role: "status",
188
- children: slots?.emptyFallback ?? (hasKeyword ? labels.noMatch : labels.empty)
443
+ } catch {
444
+ setResult({
445
+ value,
446
+ state: 'failed'
447
+ });
448
+ }
449
+ };
450
+ return /*#__PURE__*/ jsx("button", {
451
+ type: "button",
452
+ disabled: !value || 'pending' === state,
453
+ "aria-live": "polite",
454
+ onClick: ()=>void copy(),
455
+ children: 'copied' === state ? t.copied : 'failed' === state ? t.copyFailed : t.copy
189
456
  });
457
+ }
458
+ function ExperienceTests({ items, labels: t, onOpenUri }) {
190
459
  return /*#__PURE__*/ jsx("div", {
191
- role: "group",
192
- tabIndex: -1,
193
- ref: focusPanel,
194
- className: "ov-scope-switcher__panel-inner",
195
- onKeyDownCapture: moveScopeFocus,
196
- children: slots?.renderPanel ? slots?.renderPanel({
197
- search,
198
- list
199
- }) : /*#__PURE__*/ jsxs("div", {
200
- className: "ov-scope-switcher__panel-body",
201
- children: [
202
- search,
203
- list
204
- ]
205
- })
460
+ className: "ov-experience-dashboard__tests",
461
+ children: items.map((item)=>/*#__PURE__*/ jsxs("article", {
462
+ children: [
463
+ /*#__PURE__*/ jsxs("header", {
464
+ children: [
465
+ /*#__PURE__*/ jsxs("div", {
466
+ className: "ov-experience-dashboard__test-heading",
467
+ children: [
468
+ /*#__PURE__*/ jsx("strong", {
469
+ children: item.title
470
+ }),
471
+ /*#__PURE__*/ jsxs("div", {
472
+ className: "ov-experience-dashboard__test-meta",
473
+ children: [
474
+ /*#__PURE__*/ jsx("span", {
475
+ children: t.sourceUri
476
+ }),
477
+ /*#__PURE__*/ jsx("code", {
478
+ title: item.uri,
479
+ children: item.uri ?? '—'
480
+ }),
481
+ item.uri ? /*#__PURE__*/ jsxs(Fragment, {
482
+ children: [
483
+ /*#__PURE__*/ jsx(CopyButton, {
484
+ value: item.uri,
485
+ labels: t
486
+ }),
487
+ /*#__PURE__*/ jsx("button", {
488
+ type: "button",
489
+ disabled: !onOpenUri,
490
+ onClick: ()=>item.uri && onOpenUri?.(item.uri),
491
+ children: t.open
492
+ })
493
+ ]
494
+ }) : null
495
+ ]
496
+ }),
497
+ item.taskQuery ? /*#__PURE__*/ jsxs("div", {
498
+ className: "ov-experience-dashboard__test-meta",
499
+ children: [
500
+ /*#__PURE__*/ jsx("span", {
501
+ children: t.task
502
+ }),
503
+ /*#__PURE__*/ jsx("p", {
504
+ children: item.taskQuery
505
+ })
506
+ ]
507
+ }) : null
508
+ ]
509
+ }),
510
+ /*#__PURE__*/ jsx(CopyButton, {
511
+ value: item.content,
512
+ labels: t
513
+ })
514
+ ]
515
+ }),
516
+ /*#__PURE__*/ jsx("div", {
517
+ className: "ov-experience-dashboard__test-content",
518
+ children: item.content.split('\n').map((line, index)=>{
519
+ const role = line.match(/^(User|Assistant):(.*)$/);
520
+ return /*#__PURE__*/ jsx("div", {
521
+ children: role ? /*#__PURE__*/ jsxs(Fragment, {
522
+ children: [
523
+ /*#__PURE__*/ jsxs("strong", {
524
+ children: [
525
+ role[1],
526
+ ":"
527
+ ]
528
+ }),
529
+ role[2]
530
+ ]
531
+ }) : line.startsWith('# ') ? /*#__PURE__*/ jsx("strong", {
532
+ children: line
533
+ }) : line || '\u00a0'
534
+ }, index);
535
+ })
536
+ })
537
+ ]
538
+ }, item.id))
206
539
  });
207
540
  }
208
- function ScopeSelector(props) {
209
- const { identity, trigger: triggerContent, locale } = props;
210
- const labels = resolveScopeLabels(locale, props.labels);
211
- const selectable = 'selectable' === props.kind ? props : void 0;
212
- const data = selectable?.data;
213
- const state = selectable?.state;
214
- const actions = selectable?.actions;
215
- const slots = selectable?.slots;
216
- const [localVisible, setLocalVisible] = useState(false);
217
- const root = useRef(null);
218
- const trigger = useRef(null);
219
- const restoreSelectionFocus = useRef(false);
220
- const panelId = useId();
221
- const open = void 0 !== selectable && (state?.visible ?? localVisible) && !state?.disabled;
222
- const onVisibleChange = actions?.onVisibleChange;
223
- const changeVisible = useCallback((visible)=>{
224
- setLocalVisible(visible);
225
- onVisibleChange?.(visible);
226
- }, [
227
- onVisibleChange
228
- ]);
229
- useEffect(()=>{
230
- if (!open) return;
231
- const dismiss = (event)=>{
232
- if (event.target instanceof Node && !root.current?.contains(event.target)) changeVisible(false);
233
- };
234
- const escape = (event)=>{
235
- if ('Escape' === event.key) {
236
- event.preventDefault();
237
- changeVisible(false);
238
- trigger.current?.focus();
239
- }
240
- };
241
- document.addEventListener('pointerdown', dismiss);
242
- document.addEventListener('keydown', escape);
243
- return ()=>{
244
- document.removeEventListener('pointerdown', dismiss);
245
- document.removeEventListener('keydown', escape);
246
- };
247
- }, [
248
- open,
249
- changeVisible
250
- ]);
251
- useEffect(()=>{
252
- if (open || !restoreSelectionFocus.current) return;
253
- restoreSelectionFocus.current = false;
254
- if (document.activeElement === document.body || root.current?.contains(document.activeElement)) trigger.current?.focus();
255
- }, [
256
- open
257
- ]);
258
- const selected = data?.options.find((o)=>o.id === data.selectedId);
259
- const label = triggerContent?.label ?? selected?.label ?? '';
260
- const icon = triggerContent?.icon ?? selected?.icon;
261
- const content = /*#__PURE__*/ jsxs(Fragment, {
541
+ function ExperiencePagination({ page, hasMore, loading, labels: t, onPageChange }) {
542
+ if (!page && !hasMore) return null;
543
+ return /*#__PURE__*/ jsxs("div", {
544
+ className: "ov-experience-dashboard__pagination",
262
545
  children: [
263
- icon && /*#__PURE__*/ jsx("span", {
264
- className: "ov-scope-switcher__icon",
265
- "aria-hidden": "true",
266
- children: icon
546
+ /*#__PURE__*/ jsx("button", {
547
+ type: "button",
548
+ disabled: !page || loading || !onPageChange,
549
+ onClick: ()=>onPageChange?.(page - 1),
550
+ children: t.previous
267
551
  }),
268
552
  /*#__PURE__*/ jsx("span", {
269
- className: "ov-scope-switcher__label",
270
- children: label
553
+ children: page + 1
271
554
  }),
272
- identity.tag && /*#__PURE__*/ jsx("span", {
273
- className: "ov-scope-switcher__tag",
274
- children: identity.tag
555
+ /*#__PURE__*/ jsx("button", {
556
+ type: "button",
557
+ disabled: !hasMore || loading || !onPageChange,
558
+ onClick: ()=>onPageChange?.(page + 1),
559
+ children: t.next
275
560
  })
276
561
  ]
277
562
  });
278
- return /*#__PURE__*/ jsxs("div", {
279
- ref: root,
280
- role: "group",
281
- className: "ov-scope-switcher__level",
282
- onBlur: (event)=>{
283
- if (open && event.relatedTarget instanceof Node && !event.currentTarget.contains(event.relatedTarget)) changeVisible(false);
563
+ }
564
+ function ExperienceDashboard(props) {
565
+ return /*#__PURE__*/ jsx(ExperienceDashboardContent, {
566
+ ...props
567
+ }, props.uri);
568
+ }
569
+ function ExperienceDashboardContent({ uri, data = {}, kind, tab: controlledTab, days: controlledDays, page = 0, hasMore = false, startIndex = 0, states = {}, onTabChange, onDaysChange, onPageChange, locale: localeProp, onOpenUri, labels, className, ...rest }) {
570
+ const locale = useLocale(localeProp);
571
+ const [localTab, setLocalTab] = useState('impact');
572
+ const [localDays, setLocalDays] = useState(7);
573
+ const selectedTab = controlledTab ?? localTab;
574
+ const missingTest = void 0 === data.testMaterials;
575
+ const tab = 'test' === selectedTab && missingTest ? 'impact' : selectedTab;
576
+ if ('test' === localTab && missingTest) setLocalTab('impact');
577
+ const days = controlledDays ?? localDays;
578
+ const setTab = (value)=>{
579
+ setLocalTab(value);
580
+ onTabChange?.(value);
581
+ };
582
+ const setDays = (value)=>{
583
+ setLocalDays(value);
584
+ onDaysChange?.(value);
585
+ };
586
+ const t = experienceLabels(locale, labels);
587
+ const directory = 'directory' === kind;
588
+ const result = data;
589
+ const tabs = [
590
+ {
591
+ key: 'impact',
592
+ title: t.impact
284
593
  },
285
- children: [
286
- void 0 === selectable ? /*#__PURE__*/ jsx("span", {
287
- className: "ov-scope-switcher__trigger",
288
- "aria-label": identity.ariaLabel,
289
- title: label,
290
- children: content
291
- }) : /*#__PURE__*/ jsxs("button", {
292
- ref: trigger,
293
- type: "button",
294
- className: "ov-scope-switcher__trigger",
295
- "aria-label": identity.ariaLabel,
296
- title: label,
297
- disabled: state?.disabled,
298
- "aria-expanded": open,
299
- "aria-haspopup": "dialog",
300
- "aria-controls": open ? panelId : void 0,
301
- onClick: ()=>changeVisible(!open),
302
- onKeyDown: (event)=>{
303
- if ('ArrowDown' === event.key || 'ArrowUp' === event.key) {
304
- event.preventDefault();
305
- if (open) root.current?.querySelector('[role="option"]:not([aria-disabled="true"])')?.focus();
306
- else changeVisible(true);
307
- }
308
- },
309
- children: [
310
- content,
311
- /*#__PURE__*/ jsx("span", {
312
- className: "ov-scope-switcher__arrow",
313
- "aria-hidden": "true",
314
- children: /*#__PURE__*/ jsx(chevron_downreact, {})
315
- })
316
- ]
317
- }),
318
- open && void 0 !== selectable && void 0 !== data && /*#__PURE__*/ jsx("div", {
319
- id: panelId,
320
- className: slots?.renderPanel ? 'ov-scope-switcher__panel ov-scope-switcher__panel--custom' : 'ov-scope-switcher__panel',
321
- role: "dialog",
322
- "aria-label": identity.ariaLabel ?? label,
323
- children: /*#__PURE__*/ jsx(ScopePanel, {
324
- label: identity.ariaLabel ?? label,
325
- data: data,
326
- state: state,
327
- slots: slots,
328
- actions: actions,
329
- onSelect: (option)=>{
330
- restoreSelectionFocus.current = true;
331
- changeVisible(false);
332
- actions?.onSelect?.(option);
333
- },
334
- labels: labels
335
- })
336
- })
594
+ {
595
+ key: 'source',
596
+ title: t.source
597
+ },
598
+ ...void 0 === result.testMaterials ? [] : [
599
+ {
600
+ key: 'test',
601
+ title: t.test
602
+ }
337
603
  ]
604
+ ];
605
+ const activeState = directory ? states.list : 'source' === tab ? states.sources : states.trajectories;
606
+ const pagination = /*#__PURE__*/ jsx(ExperiencePagination, {
607
+ page: page,
608
+ hasMore: hasMore,
609
+ loading: activeState?.loading,
610
+ labels: t,
611
+ onPageChange: onPageChange
338
612
  });
339
- }
340
- function ScopeSwitcher({ locale, children, className = '', ...props }) {
341
613
  return /*#__PURE__*/ jsx("div", {
342
- lang: locale,
343
- ...props,
344
- className: `ov-scope-switcher ${className}`,
345
- children: children
614
+ ...rest,
615
+ "data-resource-uri": uri,
616
+ className: [
617
+ 'ov-experience-dashboard',
618
+ className
619
+ ].filter(Boolean).join(' '),
620
+ children: directory ? /*#__PURE__*/ jsxs("div", {
621
+ className: "ov-experience-dashboard__body",
622
+ children: [
623
+ result.experiences?.length ? /*#__PURE__*/ jsx(ExperienceList, {
624
+ items: result.experiences,
625
+ total: result.total,
626
+ locale: locale,
627
+ startIndex: startIndex,
628
+ labels: t,
629
+ onOpenUri: onOpenUri
630
+ }) : /*#__PURE__*/ jsx(DashboardState, {
631
+ state: states.list,
632
+ empty: t.empty,
633
+ loading: t.loading,
634
+ failed: t.failed,
635
+ retry: t.retry
636
+ }),
637
+ pagination
638
+ ]
639
+ }) : /*#__PURE__*/ jsx(DashboardTabs, {
640
+ tabs: tabs,
641
+ active: tab,
642
+ label: t.title,
643
+ onChange: setTab,
644
+ children: /*#__PURE__*/ jsx("div", {
645
+ className: "ov-experience-dashboard__body",
646
+ children: 'impact' === tab ? /*#__PURE__*/ jsxs(Fragment, {
647
+ children: [
648
+ /*#__PURE__*/ jsx(ExperienceImpact, {
649
+ data: result,
650
+ labels: t,
651
+ days: days,
652
+ onDaysChange: setDays,
653
+ outcomesState: states.outcomes ?? {},
654
+ trajectoriesState: states.trajectories ?? {},
655
+ onOpenUri: onOpenUri
656
+ }),
657
+ pagination
658
+ ]
659
+ }) : 'source' === tab ? result.sources?.length ? /*#__PURE__*/ jsxs("details", {
660
+ open: true,
661
+ className: "ov-experience-dashboard__source-group",
662
+ children: [
663
+ /*#__PURE__*/ jsxs("summary", {
664
+ children: [
665
+ /*#__PURE__*/ jsx("strong", {
666
+ children: t.latest
667
+ }),
668
+ /*#__PURE__*/ jsx("span", {
669
+ children: t.sourceCount.replace('{count}', String(result.sources.length))
670
+ })
671
+ ]
672
+ }),
673
+ /*#__PURE__*/ jsx(ExperienceTrajectories, {
674
+ items: result.sources,
675
+ source: true,
676
+ onOpenUri: onOpenUri
677
+ })
678
+ ]
679
+ }) : /*#__PURE__*/ jsx(DashboardState, {
680
+ state: states.sources,
681
+ empty: t.emptySource,
682
+ loading: t.loading,
683
+ failed: t.failed,
684
+ retry: t.retry
685
+ }) : result.testMaterials?.length ? /*#__PURE__*/ jsx(ExperienceTests, {
686
+ items: result.testMaterials,
687
+ labels: t,
688
+ onOpenUri: onOpenUri
689
+ }) : /*#__PURE__*/ jsx(DashboardState, {
690
+ state: states.tests,
691
+ empty: t.emptyTests,
692
+ loading: t.loading,
693
+ failed: t.failed,
694
+ retry: t.retry
695
+ })
696
+ })
697
+ })
346
698
  });
347
699
  }
348
- export { ScopeSelector, ScopeSwitcher };
700
+ export { ExperienceDashboard };