@openviking/react 0.0.0-stage → 0.1.1

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 (104) hide show
  1. package/README.md +82 -2
  2. package/dist/3~0.js +8 -0
  3. package/dist/a~0.js +21 -0
  4. package/dist/client/client.d.ts +12 -0
  5. package/dist/client/errors.d.ts +30 -0
  6. package/dist/client/index.d.ts +4 -0
  7. package/dist/client/options.d.ts +101 -0
  8. package/dist/client/provider.d.ts +52 -0
  9. package/dist/client/types.d.ts +160 -0
  10. package/dist/client.js +239 -0
  11. package/dist/components/agent-connect/agent-connect.d.ts +4 -0
  12. package/dist/components/agent-connect/index.d.ts +1 -0
  13. package/dist/components/agent-connect/style.css +16 -0
  14. package/dist/components/agent-connect/style.js +0 -0
  15. package/dist/components/agent-connect/types.d.ts +175 -0
  16. package/dist/components/agent-connect.js +1 -0
  17. package/dist/components/file-preview/file-preview-body.d.ts +15 -0
  18. package/dist/components/file-preview/file-preview-header.d.ts +16 -0
  19. package/dist/components/file-preview/file-preview-icons.d.ts +2 -0
  20. package/dist/components/file-preview/file-preview-labels.d.ts +5 -0
  21. package/dist/components/file-preview/file-preview-operations.d.ts +1 -0
  22. package/dist/components/file-preview/file-preview.d.ts +17 -0
  23. package/dist/components/file-preview/index.d.ts +1 -0
  24. package/dist/components/file-preview/style.css +285 -0
  25. package/dist/components/file-preview/style.js +0 -0
  26. package/dist/components/file-preview/types.d.ts +435 -0
  27. package/dist/components/file-preview/use-file-preview-editing.d.ts +13 -0
  28. package/dist/components/file-preview.js +442 -0
  29. package/dist/components/file-tree/file-tree-body.d.ts +14 -0
  30. package/dist/components/file-tree/file-tree-dom.d.ts +4 -0
  31. package/dist/components/file-tree/file-tree-entry-row.d.ts +6 -0
  32. package/dist/components/file-tree/file-tree-icons.d.ts +8 -0
  33. package/dist/components/file-tree/file-tree-keyboard.d.ts +10 -0
  34. package/dist/components/file-tree/file-tree-labels.d.ts +5 -0
  35. package/dist/components/file-tree/file-tree-row-context.d.ts +24 -0
  36. package/dist/components/file-tree/file-tree-rows.d.ts +12 -0
  37. package/dist/components/file-tree/file-tree-tooltip.d.ts +11 -0
  38. package/dist/components/file-tree/file-tree.d.ts +4 -0
  39. package/dist/components/file-tree/index.d.ts +1 -0
  40. package/dist/components/file-tree/style.css +244 -0
  41. package/dist/components/file-tree/style.js +0 -0
  42. package/dist/components/file-tree/types.d.ts +406 -0
  43. package/dist/components/file-tree/use-file-tree-actions.d.ts +10 -0
  44. package/dist/components/file-tree.js +1 -0
  45. package/dist/components/scope-switcher/index.d.ts +1 -0
  46. package/dist/components/scope-switcher/scope-keyboard.d.ts +2 -0
  47. package/dist/components/scope-switcher/scope-panel.d.ts +5 -0
  48. package/dist/components/scope-switcher/scope-selector.d.ts +2 -0
  49. package/dist/components/scope-switcher/scope-switcher.d.ts +6 -0
  50. package/dist/components/scope-switcher/style.css +248 -0
  51. package/dist/components/scope-switcher/style.js +0 -0
  52. package/dist/components/scope-switcher/types.d.ts +367 -0
  53. package/dist/components/scope-switcher.js +3 -0
  54. package/dist/components/style.css +811 -0
  55. package/dist/components/style.js +0 -0
  56. package/dist/components/tui/index.d.ts +1 -0
  57. package/dist/components/tui/style.css +16 -0
  58. package/dist/components/tui/style.js +0 -0
  59. package/dist/components/tui/tui.d.ts +3 -0
  60. package/dist/components/tui/types.d.ts +485 -0
  61. package/dist/components/tui.js +1 -0
  62. package/dist/f~0.js +284 -0
  63. package/dist/icons/index.d.ts +23 -0
  64. package/dist/icons.js +25 -0
  65. package/dist/index.d.ts +16 -0
  66. package/dist/index.js +8 -0
  67. package/dist/i~0.js +21 -0
  68. package/dist/lk~0.js +220 -0
  69. package/dist/l~0.js +44 -0
  70. package/dist/modules/console/console.d.ts +4 -0
  71. package/dist/modules/console/index.d.ts +1 -0
  72. package/dist/modules/console/style.css +29 -0
  73. package/dist/modules/console/style.js +0 -0
  74. package/dist/modules/console/types.d.ts +101 -0
  75. package/dist/modules/console.js +1 -0
  76. package/dist/modules/file-browser/file-browser-toolbar-button.d.ts +10 -0
  77. package/dist/modules/file-browser/file-browser.d.ts +6 -0
  78. package/dist/modules/file-browser/index.d.ts +1 -0
  79. package/dist/modules/file-browser/style.css +75 -0
  80. package/dist/modules/file-browser/style.js +0 -0
  81. package/dist/modules/file-browser/types.d.ts +101 -0
  82. package/dist/modules/file-browser.js +1 -0
  83. package/dist/modules/scope-cascade/controller.d.ts +6 -0
  84. package/dist/modules/scope-cascade/index.d.ts +3 -0
  85. package/dist/modules/scope-cascade/scope-cascade.d.ts +3 -0
  86. package/dist/modules/scope-cascade/style.css +250 -0
  87. package/dist/modules/scope-cascade/style.js +0 -0
  88. package/dist/modules/scope-cascade/types.d.ts +39 -0
  89. package/dist/modules/scope-cascade/use-scope-cascade.d.ts +5 -0
  90. package/dist/modules/scope-cascade.js +1 -0
  91. package/dist/modules/style.css +385 -0
  92. package/dist/modules/style.js +0 -0
  93. package/dist/modules/task-center/columns.d.ts +129 -0
  94. package/dist/modules/task-center/index.d.ts +1 -0
  95. package/dist/modules/task-center/style.css +29 -0
  96. package/dist/modules/task-center/style.js +0 -0
  97. package/dist/modules/task-center/task-center.d.ts +4 -0
  98. package/dist/modules/task-center/types.d.ts +168 -0
  99. package/dist/modules/task-center.js +1 -0
  100. package/dist/n~0.js +499 -0
  101. package/dist/style.css +1198 -0
  102. package/dist/style.js +0 -0
  103. package/dist/u~0.js +8 -0
  104. package/package.json +103 -4
@@ -0,0 +1,248 @@
1
+ .ov-scope-switcher {
2
+ box-sizing: border-box;
3
+ border: 1px solid var(--ov-ui-border, #edeef2);
4
+ background: var(--ov-ui-scope-background, transparent);
5
+ max-width: 100%;
6
+ min-height: 32px;
7
+ color: var(--ov-ui-text, #0b0b0f);
8
+ font-family: var(--ov-ui-font-family, "PingFang SC",
9
+ -apple-system,
10
+ BlinkMacSystemFont,
11
+ "Segoe UI",
12
+ sans-serif);
13
+ letter-spacing: .036px;
14
+ border-radius: 16px;
15
+ flex-wrap: wrap;
16
+ align-items: center;
17
+ gap: 4px;
18
+ padding: 3px 4px;
19
+ font-size: 12px;
20
+ line-height: 20px;
21
+ display: inline-flex;
22
+ }
23
+
24
+ .ov-scope-switcher *, .ov-scope-switcher :before, .ov-scope-switcher :after {
25
+ box-sizing: border-box;
26
+ }
27
+
28
+ .ov-scope-switcher__level {
29
+ align-items: center;
30
+ gap: 4px;
31
+ min-width: 0;
32
+ max-width: 100%;
33
+ display: inline-flex;
34
+ position: relative;
35
+ }
36
+
37
+ .ov-scope-switcher__level + .ov-scope-switcher__level:before {
38
+ content: "/";
39
+ color: var(--ov-ui-text-muted, #c9cbd4);
40
+ margin-right: 4px;
41
+ font-size: 13px;
42
+ font-weight: 500;
43
+ line-height: 22px;
44
+ }
45
+
46
+ .ov-scope-switcher__trigger {
47
+ max-width: min(260px, 100%);
48
+ height: 24px;
49
+ color: inherit;
50
+ font: inherit;
51
+ vertical-align: middle;
52
+ background: none;
53
+ border: 0;
54
+ border-radius: 99px;
55
+ align-items: center;
56
+ gap: 6px;
57
+ padding: 2px 8px;
58
+ display: inline-flex;
59
+ }
60
+
61
+ button.ov-scope-switcher__trigger {
62
+ cursor: pointer;
63
+ }
64
+
65
+ .ov-scope-switcher__trigger:hover:not(:disabled), .ov-scope-switcher__trigger[aria-expanded="true"] {
66
+ background: var(--ov-ui-hover, #edeffc);
67
+ }
68
+
69
+ .ov-scope-switcher__label {
70
+ white-space: nowrap;
71
+ text-overflow: ellipsis;
72
+ overflow: hidden;
73
+ }
74
+
75
+ .ov-scope-switcher__icon {
76
+ flex: none;
77
+ justify-content: center;
78
+ align-items: center;
79
+ width: 14px;
80
+ height: 14px;
81
+ display: inline-flex;
82
+ }
83
+
84
+ .ov-scope-switcher__icon img {
85
+ display: block;
86
+ }
87
+
88
+ .ov-scope-switcher__tag {
89
+ color: var(--ov-ui-text-muted, #9295a5);
90
+ font-size: 12px;
91
+ }
92
+
93
+ .ov-scope-switcher__arrow {
94
+ flex: 0 0 14px;
95
+ width: 14px;
96
+ height: 14px;
97
+ margin-left: -2px;
98
+ transition: transform .16s;
99
+ display: inline-flex;
100
+ }
101
+
102
+ .ov-scope-switcher__trigger[aria-expanded="true"] .ov-scope-switcher__arrow {
103
+ transform: rotate(180deg);
104
+ }
105
+
106
+ @media (prefers-reduced-motion: reduce) {
107
+ .ov-scope-switcher__arrow {
108
+ transition: none;
109
+ }
110
+ }
111
+
112
+ .ov-scope-switcher__panel {
113
+ z-index: 30;
114
+ border: 1px solid var(--ov-ui-border, #edeef2);
115
+ background: var(--ov-ui-surface, #fff);
116
+ width: min(272px, 100vw - 32px);
117
+ max-height: min(540px, 70vh);
118
+ color: var(--ov-ui-text, #0b0b0f);
119
+ letter-spacing: .039px;
120
+ border-radius: 12px;
121
+ padding: 7px;
122
+ font-size: 13px;
123
+ line-height: 22px;
124
+ position: absolute;
125
+ top: calc(100% + 8px);
126
+ left: 0;
127
+ overflow: auto;
128
+ box-shadow: 0 15px 35px -2px #0000000d, 0 5px 15px #0000000d;
129
+ }
130
+
131
+ .ov-scope-switcher__level:last-child:not(:first-child) .ov-scope-switcher__panel {
132
+ left: auto;
133
+ right: 0;
134
+ }
135
+
136
+ .ov-scope-switcher__search {
137
+ border: 1px solid var(--ov-ui-border, #dfe1e8);
138
+ width: 100%;
139
+ color: inherit;
140
+ font: inherit;
141
+ background: none;
142
+ border-radius: 8px;
143
+ margin-bottom: 8px;
144
+ padding: 8px 10px;
145
+ }
146
+
147
+ .ov-scope-switcher__list {
148
+ overscroll-behavior: contain;
149
+ flex-direction: column;
150
+ gap: 4px;
151
+ max-height: 280px;
152
+ display: flex;
153
+ overflow: auto;
154
+ }
155
+
156
+ .ov-scope-switcher__option {
157
+ width: 100%;
158
+ min-height: 44px;
159
+ color: inherit;
160
+ font: inherit;
161
+ text-align: start;
162
+ cursor: pointer;
163
+ background: none;
164
+ border: 0;
165
+ border-radius: 6px;
166
+ flex-shrink: 0;
167
+ align-items: center;
168
+ gap: 8px;
169
+ padding: 2px 8px;
170
+ display: flex;
171
+ }
172
+
173
+ .ov-scope-switcher__option:hover:not([aria-disabled="true"]), .ov-scope-switcher__option[aria-selected="true"] {
174
+ background: var(--ov-ui-hover, #f5f7ff);
175
+ }
176
+
177
+ .ov-scope-switcher__option-text {
178
+ flex-direction: column;
179
+ flex: 1;
180
+ min-width: 0;
181
+ display: flex;
182
+ overflow: hidden;
183
+ }
184
+
185
+ .ov-scope-switcher__option-text small {
186
+ color: var(--ov-ui-text-muted, #737889);
187
+ }
188
+
189
+ .ov-scope-switcher__option mark {
190
+ background: var(--ov-ui-highlight, #fff0b3);
191
+ color: inherit;
192
+ }
193
+
194
+ .ov-scope-switcher__check {
195
+ flex: 0 0 16px;
196
+ width: 16px;
197
+ height: 16px;
198
+ display: inline-flex;
199
+ }
200
+
201
+ .ov-scope-switcher__state {
202
+ color: var(--ov-ui-text-muted, #737889);
203
+ padding: 20px 10px;
204
+ }
205
+
206
+ .ov-scope-switcher button:disabled, .ov-scope-switcher__option[aria-disabled="true"] {
207
+ opacity: .5;
208
+ cursor: not-allowed;
209
+ }
210
+
211
+ .ov-scope-switcher :focus-visible {
212
+ outline: 2px solid var(--ov-ui-primary, #6256d9);
213
+ outline-offset: 2px;
214
+ }
215
+
216
+ @media (width <= 600px) {
217
+ .ov-scope-switcher__trigger {
218
+ max-width: 210px;
219
+ }
220
+
221
+ .ov-scope-switcher__panel, .ov-scope-switcher__level:last-child:not(:first-child) .ov-scope-switcher__panel {
222
+ width: auto;
223
+ max-height: 60dvh;
224
+ position: fixed;
225
+ inset: auto 16px 16px;
226
+ }
227
+ }
228
+
229
+ .ov-scope-switcher__option[aria-selected="true"] {
230
+ font-weight: 500;
231
+ }
232
+
233
+ .ov-scope-switcher__option-text > span {
234
+ text-overflow: ellipsis;
235
+ white-space: nowrap;
236
+ overflow: hidden;
237
+ }
238
+
239
+ .ov-scope-switcher__option .ov-scope-switcher__icon {
240
+ border: .5px solid var(--ov-ui-border, #edeef2);
241
+ background: var(--ov-ui-surface, #fff);
242
+ border-radius: 50%;
243
+ width: 24px;
244
+ height: 24px;
245
+ }
246
+
247
+
248
+
File without changes
@@ -0,0 +1,367 @@
1
+ import type { HTMLAttributes, ReactNode } from 'react';
2
+ /**
3
+ * 搜索框的显示阈值。已加载条数或 `total` 超过它,或关键字非空时,面板才渲染搜索框。
4
+ * 组件内部按该值判断,不开放为 Props。
5
+ *
6
+ * Threshold above which a panel renders its search box. The panel shows search
7
+ * once the loaded count or `total` exceeds it, or when a keyword is set. The
8
+ * component applies it internally and does not expose it as a prop.
9
+ */
10
+ export declare const SCOPE_SWITCHER_SEARCH_THRESHOLD = 10;
11
+ /**
12
+ * 一个层级中的可选项。宿主把库、数据空间、账号或用户记录映射成该结构。
13
+ *
14
+ * One selectable value in a level. Hosts map their own library, data space,
15
+ * account or user records onto this shape.
16
+ */
17
+ export interface ScopeSwitcherOption {
18
+ /**
19
+ * 选项唯一标识。
20
+ * Unique option key.
21
+ */
22
+ id: string;
23
+ /**
24
+ * 选项显示文本。搜索命中时由组件高亮匹配片段。
25
+ * Option label. The component highlights the matching part while searching.
26
+ */
27
+ label: string;
28
+ /**
29
+ * 行首图标,例如库、数据空间或用户的头像。
30
+ * Row leading icon, for example a library, data space or user avatar.
31
+ */
32
+ icon?: ReactNode;
33
+ /**
34
+ * 显示在标签下方的次要说明,例如套餐或地址。
35
+ * Secondary line under the label, for example a plan or an address.
36
+ */
37
+ description?: string;
38
+ /**
39
+ * 是否禁用该选项:渲染置灰样式且不响应点击。
40
+ * Whether the option is disabled: rendered dimmed and ignoring clicks.
41
+ */
42
+ disabled?: boolean;
43
+ }
44
+ /**
45
+ * 面包屑中一个层级的公共字段:标识、触发器的无障碍名与展示内容。
46
+ *
47
+ * 层级分成两种形态,见 `ScopeSwitcherFixedLevel` 与
48
+ * `ScopeSwitcherSelectableLevel`。同一行里两种形态可以混用,因此一个宿主可以
49
+ * 只让部分层级可切换。
50
+ *
51
+ * Fields shared by every level: its identity, the trigger's accessible name and
52
+ * what the trigger shows.
53
+ *
54
+ * A level is either fixed or selectable, see `ScopeSwitcherFixedLevel` and
55
+ * `ScopeSwitcherSelectableLevel`. Both can be mixed in one row, so a host can
56
+ * make only some levels switchable.
57
+ */
58
+ export interface ScopeSwitcherLevelBase {
59
+ /**
60
+ * 稳定标识,例如 `library`、`account` 或 `user`。
61
+ * Stable key, for example `library`, `account` or `user`.
62
+ */
63
+ key: string;
64
+ /**
65
+ * 触发器的无障碍名称,例如「切换库」。不传时不写 `aria-label`。
66
+ * Accessible name of the trigger, for example "Switch library". No
67
+ * `aria-label` is written when omitted.
68
+ */
69
+ ariaLabel?: string;
70
+ /**
71
+ * 触发器上展示的当前选中项文本。
72
+ *
73
+ * 由宿主单独给出,不要求等于 `options` 中对应项的 `label`:当前值可能不在已
74
+ * 加载的那一页里,此时展示宿主给的文本。
75
+ *
76
+ * Text shown on the trigger for the current selection.
77
+ *
78
+ * Supplied by the host and not required to equal the matching `label` in
79
+ * `options`: the current value may not be on the loaded page.
80
+ */
81
+ selectedLabel: string;
82
+ /**
83
+ * 触发器图标,也可以是头像。
84
+ * Trigger icon, which can also be an avatar.
85
+ */
86
+ icon?: ReactNode;
87
+ /**
88
+ * 触发器末尾的标记,例如套餐名。不传时不渲染。
89
+ * Tag at the end of the trigger, for example a plan name. Not rendered when
90
+ * omitted.
91
+ */
92
+ tag?: ReactNode;
93
+ }
94
+ /**
95
+ * 固定层级:只展示当前值,不渲染下拉,也不接收任何选项或面板字段。
96
+ *
97
+ * 用于当前作用域不可切换的情形,例如个人终端里跟随登录态固定的库与数据空间、
98
+ * 管理模式下不能切换的数据空间。这类层级在视觉上同样是一条面包屑,只是没有
99
+ * 展开箭头、不可点击,也不需要宿主伪造一份空选项列表。
100
+ *
101
+ * A fixed level: shows the current value only, renders no dropdown and takes no
102
+ * option or panel fields.
103
+ *
104
+ * Used where the current scope cannot be switched, for example a library and
105
+ * data space fixed by the sign-in in a personal terminal, or a data space that
106
+ * cannot be switched in management mode. It still looks like a breadcrumb
107
+ * segment, just without an expand affordance and not clickable, and the host
108
+ * does not have to fabricate an empty option list.
109
+ */
110
+ export interface ScopeSwitcherFixedLevel extends ScopeSwitcherLevelBase {
111
+ /**
112
+ * 判别字段,固定层级为 `'fixed'`。
113
+ * Discriminant, always `'fixed'` for a fixed level.
114
+ */
115
+ kind: 'fixed';
116
+ }
117
+ /**
118
+ * 可切换层级:渲染可展开的触发器与下拉面板。
119
+ *
120
+ * 面板结构、搜索、分页与选中状态全部受控,由宿主传入。同一行里可以只有一个
121
+ * 可切换层级,也可以三个都可切换。
122
+ *
123
+ * A selectable level: renders an expandable trigger and its dropdown panel.
124
+ *
125
+ * The panel structure, search, paging and selection are all controlled and come
126
+ * from the host. A row can hold one selectable level or several.
127
+ */
128
+ export interface ScopeSwitcherSelectableLevel extends ScopeSwitcherLevelBase {
129
+ /**
130
+ * 判别字段,可切换层级为 `'selectable'`。
131
+ * Discriminant, always `'selectable'` for a selectable level.
132
+ */
133
+ kind: 'selectable';
134
+ /**
135
+ * 可选项列表,按宿主给定的顺序渲染。
136
+ * Selectable options, rendered in the order the host gives.
137
+ */
138
+ options: readonly ScopeSwitcherOption[];
139
+ /**
140
+ * 当前选中项 id,由宿主持有。命中项渲染勾选标记并使用
141
+ * `role="option"` + `aria-selected` 表达状态。
142
+ *
143
+ * 必填。可切换层级始终有一个当前作用域,没有「尚未选中」的形态:宿主若还没取到
144
+ * 数据,传空字符串,由 `selectedLabel` 决定触发器上显示什么。
145
+ *
146
+ * Selected option id, owned by the host. The matching option renders a check
147
+ * mark and expresses its state with `role="option"` and `aria-selected`.
148
+ *
149
+ * Required. A selectable level always has a current scope and has no
150
+ * "nothing selected" form: a host that has not loaded data yet passes an empty
151
+ * string, and `selectedLabel` decides what the trigger shows.
152
+ */
153
+ selectedId: string;
154
+ /**
155
+ * 该层级的总条数,用于判断搜索框是否可见。不传时以已加载条数为准。
156
+ * Total number of entries, used to decide whether the search box is shown.
157
+ * The loaded count is used when omitted.
158
+ */
159
+ total?: number;
160
+ /**
161
+ * 选项列表是否正在首次加载。为 `true` 时面板显示加载态,不渲染列表。
162
+ * Whether the option list is loading for the first time. While true the panel
163
+ * shows a loading state instead of the list.
164
+ */
165
+ loading?: boolean;
166
+ /**
167
+ * 当前搜索关键字。非空时搜索框保持可见,并用于高亮命中片段。
168
+ * Current search keyword. A non-empty value keeps the search box visible and
169
+ * drives hit highlighting.
170
+ */
171
+ searchKeyword?: string;
172
+ /**
173
+ * 该层级是否暂时不可切换,例如权限尚未就绪。为 `true` 时触发器置灰、不响应
174
+ * 点击,也不渲染下拉。恒为可切换的宿主不传。
175
+ *
176
+ * Whether the level is temporarily not switchable, for example while
177
+ * permissions load. While true the trigger is dimmed, ignores clicks and
178
+ * renders no dropdown. Hosts whose levels are always switchable leave it out.
179
+ */
180
+ disabled?: boolean;
181
+ /**
182
+ * 选项列表是否加载失败。为 `true` 时面板渲染 `errorFallback`。
183
+ * Whether the option list failed to load. While true the panel renders
184
+ * `errorFallback`.
185
+ */
186
+ error?: boolean;
187
+ /**
188
+ * 该层级是否有一个变更正在进行,例如正在删除某个库或正在切换数据空间。
189
+ * 为 `true` 时组件禁用整个列表,避免并发切换。
190
+ *
191
+ * Whether a change is in flight for this level, for example deleting a library
192
+ * or switching the data space. While true the component disables the whole
193
+ * list so no second switch can start.
194
+ */
195
+ busy?: boolean;
196
+ /**
197
+ * 面板内除列表以外的全部内容,由宿主自行实现。
198
+ *
199
+ * 参数是组件渲染好的两块内容:`search` 是搜索框,`list` 是选项列表与加载/空/
200
+ * 失败三态。宿主可以分别摆放它们,也可以只放其中一块;面板标题、顶部入口、底部
201
+ * 管理入口、说明文字都由宿主用自己的组件、链接和路由渲染。不传时面板只渲染
202
+ * `search` 与 `list`。
203
+ *
204
+ * Everything in the panel except the list, implemented by the host.
205
+ *
206
+ * The argument holds two blocks the component rendered: `search` is the search
207
+ * box and `list` is the option list with its loading, empty and failed states.
208
+ * The host can place them separately or use only one. Panel headings, top
209
+ * entries, bottom management entries and explanatory text are all rendered by
210
+ * the host with its own components, links and router. When omitted the panel
211
+ * renders `search` and `list` alone.
212
+ */
213
+ renderPanel?: (panel: ScopeSwitcherPanelContent) => ReactNode;
214
+ /**
215
+ * 在默认行内容的基础上追加或替换,例如行尾的「更多」菜单、失效态标记。
216
+ *
217
+ * 参数 `content` 是组件渲染好的默认行内容(图标、标签、描述、搜索高亮与选中
218
+ * 标记),`option` 是原始数据。宿主原样使用 `content` 只加行尾,或丢掉它自己
219
+ * 渲染。不传时渲染默认行。
220
+ *
221
+ * 行本身的点击、选中态与键盘交互始终由组件处理。
222
+ *
223
+ * Adds to or replaces the default row content, for example a "more" menu at the
224
+ * row end or an expired marker.
225
+ *
226
+ * `content` is the default row content the component rendered (icon, label,
227
+ * description, search highlight and check mark), and `option` is the raw data.
228
+ * The host reuses `content` and only appends, or discards it and renders its
229
+ * own. The default row renders when omitted.
230
+ *
231
+ * The row's click, selection state and keyboard interaction always stay with
232
+ * the component.
233
+ */
234
+ renderOption?: (content: ReactNode, option: ScopeSwitcherOption) => ReactNode;
235
+ /**
236
+ * 没有可选项时替代列表显示的内容。不传时使用 `labels.empty`。
237
+ * Rendered instead of the list when there are no options. `labels.empty` is
238
+ * used when omitted.
239
+ */
240
+ emptyFallback?: ReactNode;
241
+ /**
242
+ * 加载失败时替代列表显示的内容。不传时使用 `labels.error`。
243
+ * Rendered instead of the list when loading failed. `labels.error` is used
244
+ * when omitted.
245
+ */
246
+ errorFallback?: ReactNode;
247
+ /**
248
+ * 选中时触发;组件关闭本级面板,不改变搜索词和业务选中值。
249
+ * Invoked on selection. Closes this panel; selection and search remain host-owned.
250
+ */
251
+ onSelect?: (option: ScopeSwitcherOption) => void;
252
+ /**
253
+ * 可选受控展开状态;不传时由本级选择器独立维护。
254
+ * Optional controlled visibility; otherwise local to this selector.
255
+ */
256
+ visible?: boolean;
257
+ /**
258
+ * 面板可见性变化时触发,打开和关闭都会调用,参数是变化后的状态。
259
+ *
260
+ * 宿主在这里写回 `visible`,同时可按需取数,例如打开时才请求第一页选项。
261
+ *
262
+ * Invoked whenever the panel's visibility changes — on both open and close —
263
+ * with the new state.
264
+ *
265
+ * The host writes it back to `visible` and can load data on demand from it,
266
+ * for example requesting the first page only when the panel opens.
267
+ */
268
+ onVisibleChange?: (visible: boolean) => void;
269
+ /**
270
+ * 搜索关键字变化时触发。不传时不渲染搜索框。
271
+ * Invoked when the search keyword changes. No search box is rendered when
272
+ * omitted.
273
+ */
274
+ onSearchKeywordChange?: (keyword: string) => void;
275
+ /**
276
+ * 选项列表滚动时触发,参数是滚动后的位置信息。是否加载下一页由宿主判断,加载
277
+ * 完成后把新一页通过 `options` 传回。不传时不响应滚动。
278
+ *
279
+ * Invoked when the option list scrolls, with the resulting scroll metrics. The
280
+ * host decides whether to load the next page and passes it back through
281
+ * `options`. Scrolling is not observed when omitted.
282
+ */
283
+ onScroll?: (metrics: ScopeSwitcherScrollMetrics) => void;
284
+ }
285
+ /**
286
+ * 组件渲染好的面板内容,作为参数传给 `renderPanel`。
287
+ *
288
+ * Panel content the component rendered, passed to `renderPanel`.
289
+ */
290
+ export interface ScopeSwitcherPanelContent {
291
+ /**
292
+ * 搜索框。搜索框不可见时为空节点。
293
+ * The search box; an empty node when it is not shown.
294
+ */
295
+ search: ReactNode;
296
+ /**
297
+ * 选项列表与加载、空、失败三态。
298
+ * The option list with its loading, empty and failed states.
299
+ */
300
+ list: ReactNode;
301
+ }
302
+ /**
303
+ * 选项列表滚动时的位置信息,由组件从列表元素上读取后传入 `onScroll`。
304
+ *
305
+ * Scroll metrics of the option list, read from the list element and passed to
306
+ * `onScroll`.
307
+ */
308
+ export interface ScopeSwitcherScrollMetrics {
309
+ /**
310
+ * 列表已滚动的距离。
311
+ * Distance the list has scrolled.
312
+ */
313
+ scrollTop: number;
314
+ /**
315
+ * 列表内容总高度。
316
+ * Total height of the list content.
317
+ */
318
+ scrollHeight: number;
319
+ /**
320
+ * 列表可视区域高度。
321
+ * Height of the list viewport.
322
+ */
323
+ clientHeight: number;
324
+ }
325
+ /**
326
+ * 面包屑中的一个层级。按 `kind` 区分固定与可切换两种形态,同一行里可以混用。
327
+ *
328
+ * One level of the breadcrumb. `kind` separates the fixed and selectable forms;
329
+ * both can be mixed in one row.
330
+ */
331
+ export type ScopeSwitcherLevel = ScopeSwitcherFixedLevel | ScopeSwitcherSelectableLevel;
332
+ /**
333
+ * 可替换文案,组件内置英文默认值。
334
+ * Replaceable copy; the component ships English defaults.
335
+ */
336
+ export interface ScopeSwitcherLabels {
337
+ /** Loading status text / 加载提示。 */
338
+ loading?: string;
339
+ /**
340
+ * 搜索框占位文本。
341
+ * Search input placeholder.
342
+ */
343
+ searchPlaceholder?: string;
344
+ /**
345
+ * 没有可选项时的提示。
346
+ * Message shown when there are no options.
347
+ */
348
+ empty?: string;
349
+ /**
350
+ * 有关键字但没有命中项时的提示。不传时回落到 `empty`。
351
+ * Message shown when a keyword matches nothing. Falls back to `empty` when
352
+ * omitted.
353
+ */
354
+ noMatch?: string;
355
+ /**
356
+ * 加载失败时的提示。
357
+ * Message shown when loading failed.
358
+ */
359
+ error?: string;
360
+ }
361
+ /** Layout only: each child owns its state and data subscription. */
362
+ export type ScopeSwitcherProps = HTMLAttributes<HTMLDivElement>;
363
+ /** A single independently rendered scope view. */
364
+ export interface ScopeSelectorProps {
365
+ level: ScopeSwitcherLevel;
366
+ labels?: ScopeSwitcherLabels;
367
+ }
@@ -0,0 +1,3 @@
1
+ var scope_switcher_SCOPE_SWITCHER_SEARCH_THRESHOLD = 10;
2
+ export { ScopeSelector, ScopeSwitcher } from "../f~0.js";
3
+ export { scope_switcher_SCOPE_SWITCHER_SEARCH_THRESHOLD as SCOPE_SWITCHER_SEARCH_THRESHOLD };