@astryx-vue/lab 0.3.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
- import { Fragment, Teleport, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createSlots, createTextVNode, createVNode, defineComponent, getCurrentInstance, guardReactiveProps, h, mergeModels, mergeProps, nextTick, normalizeClass, normalizeProps, normalizeStyle, onScopeDispose, openBlock, ref, renderList, renderSlot, resolveDynamicComponent, toDisplayString, unref, useAttrs, useId, useModel, useSlots, useTemplateRef, watch, withCtx } from "vue";
1
+ import { Fragment, Teleport, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createSlots, createTextVNode, createVNode, defineComponent, getCurrentInstance, guardReactiveProps, h, inject, mergeModels, mergeProps, nextTick, normalizeClass, normalizeProps, normalizeStyle, onBeforeUnmount, onMounted, onScopeDispose, openBlock, provide, ref, renderList, renderSlot, resolveDynamicComponent, shallowRef, toDisplayString, toValue, unref, useAttrs, useId, useModel, useSlots, useTemplateRef, watch, withCtx } from "vue";
2
2
  import "../styles/circular-progress.css";
3
- import { AlertDialog, BottomSheet, Button, CheckboxIndicator, ComplexSelector, EmptyState, Field, FieldStatus, Icon, IconButton, Item, List, SyntaxTheme, Text, TextInput, Token, Tooltip, VisuallyHidden, tokenize, useAnnounce, useScrollableArea, useTranslator } from "@astryx-vue/core";
3
+ import { AlertDialog, BottomSheet, Button, CheckboxIndicator, ComplexSelector, EmptyState, Field, FieldStatus, HStack, Heading, Icon, IconButton, Item, List, Popover, SYNC_TOKENIZE_THRESHOLD, SyntaxTheme, Text, TextInput, Token, Tooltip, VStack, VisuallyHidden, applyHighlightRangesFlat, tokenize, tokenizeAsync, useAnnounce, useScrollableArea, useTranslator } from "@astryx-vue/core";
4
+ import "../styles/code-editor.css";
4
5
  import "../styles/diff-viewer.css";
5
6
  import "../styles/info-tip.css";
6
7
  import "../styles/list-input.css";
@@ -8,6 +9,7 @@ import "../styles/log-stream.css";
8
9
  import "../styles/mobile-tokenizer.css";
9
10
  import "../styles/stat.css";
10
11
  import "../styles/svg-icon.css";
12
+ import "../styles/tour.css";
11
13
  import "../styles/transfer-list.css";
12
14
  import "../styles/transfer-list-selector.css";
13
15
  //#region src/CircularProgress/types.ts
@@ -32,9 +34,9 @@ function defaultFormatValueLabel(value, max) {
32
34
  }
33
35
  //#endregion
34
36
  //#region src/CircularProgress/CircularProgress.vue
35
- const _hoisted_1$13 = ["data-size", "data-variant"];
36
- const _hoisted_2$12 = { class: "astryx-circular-progress__ring" };
37
- const _hoisted_3$11 = [
37
+ const _hoisted_1$16 = ["data-size", "data-variant"];
38
+ const _hoisted_2$14 = { class: "astryx-circular-progress__ring" };
39
+ const _hoisted_3$12 = [
38
40
  "aria-valuenow",
39
41
  "aria-valuemin",
40
42
  "aria-valuemax",
@@ -43,14 +45,14 @@ const _hoisted_3$11 = [
43
45
  "height",
44
46
  "viewBox"
45
47
  ];
46
- const _hoisted_4$10 = [
48
+ const _hoisted_4$11 = [
47
49
  "data-variant",
48
50
  "cx",
49
51
  "cy",
50
52
  "r",
51
53
  "stroke-width"
52
54
  ];
53
- const _hoisted_5$9 = [
55
+ const _hoisted_5$10 = [
54
56
  "data-variant",
55
57
  "cx",
56
58
  "cy",
@@ -138,7 +140,7 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
138
140
  "astryx-circular-progress__visually-hidden": !showLabel.value,
139
141
  "astryx-circular-progress__label--disabled": showLabel.value && __props.isDisabled
140
142
  }])
141
- }, toDisplayString(__props.label), 3), createElementVNode("div", _hoisted_2$12, [(openBlock(), createElementBlock("svg", {
143
+ }, toDisplayString(__props.label), 3), createElementVNode("div", _hoisted_2$14, [(openBlock(), createElementBlock("svg", {
142
144
  class: normalizeClass(["astryx-circular-progress__svg", { "astryx-circular-progress__svg--indeterminate": __props.isIndeterminate }]),
143
145
  role: "progressbar",
144
146
  "aria-labelledby": labelId,
@@ -156,7 +158,7 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
156
158
  cy: geometry.value.center,
157
159
  r: geometry.value.radius,
158
160
  "stroke-width": geometry.value.strokeWidth
159
- }, null, 8, _hoisted_4$10), __props.isIndeterminate ? (openBlock(), createElementBlock("circle", {
161
+ }, null, 8, _hoisted_4$11), __props.isIndeterminate ? (openBlock(), createElementBlock("circle", {
160
162
  key: 0,
161
163
  class: "astryx-circular-progress__fill astryx-circular-progress__fill--indeterminate",
162
164
  "data-variant": fillVariant.value,
@@ -164,7 +166,7 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
164
166
  cy: geometry.value.center,
165
167
  r: geometry.value.radius,
166
168
  "stroke-width": geometry.value.strokeWidth
167
- }, null, 8, _hoisted_5$9)) : (openBlock(), createElementBlock("circle", {
169
+ }, null, 8, _hoisted_5$10)) : (openBlock(), createElementBlock("circle", {
168
170
  key: 1,
169
171
  class: "astryx-circular-progress__fill",
170
172
  "data-variant": fillVariant.value,
@@ -174,10 +176,278 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
174
176
  "stroke-width": geometry.value.strokeWidth,
175
177
  "stroke-dasharray": geometry.value.circumference,
176
178
  "stroke-dashoffset": dashoffset.value
177
- }, null, 8, _hoisted_6$8))], 10, _hoisted_3$11)), _ctx.$slots.default || hasCenterContent.value ? (openBlock(), createElementBlock("div", _hoisted_7$6, [renderSlot(_ctx.$slots, "default", {}, () => [hasCenterContent.value ? (openBlock(), createElementBlock("span", {
179
+ }, null, 8, _hoisted_6$8))], 10, _hoisted_3$12)), _ctx.$slots.default || hasCenterContent.value ? (openBlock(), createElementBlock("div", _hoisted_7$6, [renderSlot(_ctx.$slots, "default", {}, () => [hasCenterContent.value ? (openBlock(), createElementBlock("span", {
178
180
  key: 0,
179
181
  class: normalizeClass(["astryx-circular-progress__value", { "astryx-circular-progress__value--disabled": __props.isDisabled }])
180
- }, toDisplayString(valueText.value), 3)) : createCommentVNode("v-if", true)])])) : createCommentVNode("v-if", true)])], 16, _hoisted_1$13);
182
+ }, toDisplayString(valueText.value), 3)) : createCommentVNode("v-if", true)])])) : createCommentVNode("v-if", true)])], 16, _hoisted_1$16);
183
+ };
184
+ }
185
+ });
186
+ //#endregion
187
+ //#region src/CodeEditor/keyboard.ts
188
+ /** 把 caret 放到元素文本的字符偏移处。 */
189
+ function setCaretAtTextOffset(element, offset) {
190
+ const selection = element.ownerDocument.defaultView?.getSelection();
191
+ if (!selection) return;
192
+ const range = element.ownerDocument.createRange();
193
+ const walker = element.ownerDocument.createTreeWalker(element, NodeFilter.SHOW_TEXT);
194
+ let node = walker.nextNode();
195
+ let remaining = Math.max(0, offset);
196
+ while (node) {
197
+ const length = node.textContent?.length ?? 0;
198
+ if (remaining <= length) {
199
+ range.setStart(node, remaining);
200
+ range.collapse(true);
201
+ selection.removeAllRanges();
202
+ selection.addRange(range);
203
+ return;
204
+ }
205
+ remaining -= length;
206
+ node = walker.nextNode();
207
+ }
208
+ range.selectNodeContents(element);
209
+ range.collapse(false);
210
+ selection.removeAllRanges();
211
+ selection.addRange(range);
212
+ }
213
+ /** 当前 caret 在元素纯文本里的偏移。 */
214
+ function caretTextOffset(element) {
215
+ const selection = element.ownerDocument.defaultView?.getSelection();
216
+ if (!selection || selection.rangeCount === 0) return null;
217
+ const range = selection.getRangeAt(0);
218
+ const before = range.cloneRange();
219
+ before.selectNodeContents(element);
220
+ before.setEnd(range.startContainer, range.startOffset);
221
+ return before.toString().length;
222
+ }
223
+ /** 用一段文本替换当前选区,并把 caret 放在新文本后面。 */
224
+ function insertAtCaret(element, text) {
225
+ const selection = element.ownerDocument.defaultView?.getSelection();
226
+ if (!selection || selection.rangeCount === 0) return;
227
+ const range = selection.getRangeAt(0);
228
+ range.deleteContents();
229
+ const node = element.ownerDocument.createTextNode(text);
230
+ range.insertNode(node);
231
+ range.setStartAfter(node);
232
+ range.setEndAfter(node);
233
+ selection.removeAllRanges();
234
+ selection.addRange(range);
235
+ }
236
+ /** 去掉当前行开头最多两个空格,返回新文本和 caret 应到的位置。 */
237
+ function outdentCurrentLine(element) {
238
+ const offset = caretTextOffset(element);
239
+ if (offset == null) return null;
240
+ const value = element.textContent ?? "";
241
+ const lineStart = value.lastIndexOf("\n", offset - 1) + 1;
242
+ const line = value.slice(lineStart);
243
+ const removeCount = line.startsWith(" ") ? 2 : line.startsWith(" ") ? 1 : 0;
244
+ if (removeCount === 0) return null;
245
+ return {
246
+ value: `${value.slice(0, lineStart)}${value.slice(lineStart + removeCount)}`,
247
+ caret: offset - Math.min(removeCount, Math.max(0, offset - lineStart))
248
+ };
249
+ }
250
+ //#endregion
251
+ //#region src/CodeEditor/CodeEditor.vue
252
+ const _hoisted_1$15 = ["data-size", "data-language"];
253
+ const _hoisted_2$13 = {
254
+ key: 0,
255
+ class: "astryx-code-editor__gutter",
256
+ "aria-hidden": "true"
257
+ };
258
+ const _hoisted_3$11 = { class: "astryx-code-editor__body" };
259
+ const _hoisted_4$10 = {
260
+ key: 0,
261
+ class: "astryx-code-editor__placeholder",
262
+ "aria-hidden": "true"
263
+ };
264
+ const _hoisted_5$9 = [
265
+ "contenteditable",
266
+ "aria-label",
267
+ "aria-readonly",
268
+ "aria-describedby"
269
+ ];
270
+ const _sfc_main$1 = /*@__PURE__*/ defineComponent({
271
+ name: "AstryxCodeEditor",
272
+ __name: "CodeEditor",
273
+ props: {
274
+ value: {},
275
+ language: { default: "plaintext" },
276
+ label: {},
277
+ hasLineNumbers: { type: Boolean },
278
+ isReadOnly: { type: Boolean },
279
+ placeholder: {},
280
+ maxHeight: {},
281
+ size: { default: "md" },
282
+ tokenizer: {},
283
+ escapeHint: { default: "Press Escape then Tab to move focus out of the editor." }
284
+ },
285
+ emits: ["change"],
286
+ setup(__props, { emit: __emit }) {
287
+ const props = __props;
288
+ const emit = __emit;
289
+ const editor = useTemplateRef("editor");
290
+ const focused = ref(false);
291
+ const composing = ref(false);
292
+ const tabMovesFocus = ref(false);
293
+ const hintId = `astryx-code-editor-${useId()}-escape`;
294
+ const lines = computed(() => props.value.split("\n"));
295
+ const showPlaceholder = computed(() => props.value === "" && Boolean(props.placeholder));
296
+ const containerStyle = computed(() => props.maxHeight == null ? void 0 : { maxHeight: typeof props.maxHeight === "number" ? `${props.maxHeight}px` : props.maxHeight });
297
+ const AUTO_CLOSE_PAIRS = {
298
+ "(": ")",
299
+ "[": "]",
300
+ "{": "}",
301
+ "\"": "\"",
302
+ "'": "'",
303
+ "`": "`"
304
+ };
305
+ const MODE_NEUTRAL_KEYS = /* @__PURE__ */ new Set([
306
+ "Shift",
307
+ "Control",
308
+ "Alt",
309
+ "Meta",
310
+ "CapsLock"
311
+ ]);
312
+ let highlightCleanup;
313
+ let highlightAbort;
314
+ function hasHighlightAPI() {
315
+ return typeof CSS !== "undefined" && "highlights" in CSS && typeof Highlight !== "undefined";
316
+ }
317
+ function paint(tokens, element) {
318
+ highlightCleanup?.();
319
+ highlightCleanup = tokens.length === 0 ? void 0 : applyHighlightRangesFlat(element, tokens);
320
+ }
321
+ function paintCurrent() {
322
+ const element = editor.value;
323
+ if (!element || !hasHighlightAPI()) return;
324
+ highlightAbort?.abort();
325
+ highlightCleanup?.();
326
+ highlightCleanup = void 0;
327
+ const custom = props.tokenizer;
328
+ if (props.value.length >= SYNC_TOKENIZE_THRESHOLD && custom == null) {
329
+ const controller = new AbortController();
330
+ highlightAbort = controller;
331
+ tokenizeAsync(props.value, props.language, controller.signal).then((tokens) => {
332
+ if (!controller.signal.aborted && editor.value === element) paint(tokens, element);
333
+ });
334
+ return;
335
+ }
336
+ paint((custom ?? tokenize)(props.value, props.language), element);
337
+ }
338
+ watch([
339
+ () => props.value,
340
+ () => props.language,
341
+ () => props.tokenizer
342
+ ], () => {
343
+ nextTick(paintCurrent);
344
+ }, {
345
+ immediate: true,
346
+ flush: "post"
347
+ });
348
+ watch(() => props.value, (value) => {
349
+ const element = editor.value;
350
+ if (element && element.textContent !== value) element.textContent = value;
351
+ }, { flush: "post" });
352
+ onBeforeUnmount(() => {
353
+ highlightAbort?.abort();
354
+ highlightCleanup?.();
355
+ });
356
+ function commit() {
357
+ emit("change", editor.value?.textContent ?? "");
358
+ }
359
+ function onInput() {
360
+ if (!composing.value) commit();
361
+ }
362
+ function onKeydown(event) {
363
+ if (props.isReadOnly) return;
364
+ if (event.key === "Escape") {
365
+ if (!event.defaultPrevented) tabMovesFocus.value = true;
366
+ return;
367
+ }
368
+ const element = editor.value;
369
+ if (!element) return;
370
+ if (event.key === "Tab") {
371
+ if (tabMovesFocus.value) {
372
+ tabMovesFocus.value = false;
373
+ return;
374
+ }
375
+ event.preventDefault();
376
+ if (event.shiftKey) {
377
+ const result = outdentCurrentLine(element);
378
+ if (result == null) return;
379
+ element.textContent = result.value;
380
+ setCaretAtTextOffset(element, result.caret);
381
+ } else insertAtCaret(element, " ");
382
+ commit();
383
+ return;
384
+ }
385
+ if (!MODE_NEUTRAL_KEYS.has(event.key)) tabMovesFocus.value = false;
386
+ if (event.key === "Enter") {
387
+ event.preventDefault();
388
+ const offset = caretTextOffset(element);
389
+ if (offset == null) return;
390
+ const before = (element.textContent ?? "").slice(0, offset);
391
+ insertAtCaret(element, `\n${before.slice(before.lastIndexOf("\n") + 1).match(/^\s*/)?.[0] ?? ""}`);
392
+ commit();
393
+ return;
394
+ }
395
+ const close = AUTO_CLOSE_PAIRS[event.key];
396
+ if (close) {
397
+ const selection = element.ownerDocument.defaultView?.getSelection();
398
+ if (!selection || selection.rangeCount === 0 || !selection.getRangeAt(0).collapsed) return;
399
+ event.preventDefault();
400
+ insertAtCaret(element, `${event.key}${close}`);
401
+ const offset = caretTextOffset(element);
402
+ if (offset != null) setCaretAtTextOffset(element, offset - close.length);
403
+ commit();
404
+ }
405
+ }
406
+ return (_ctx, _cache) => {
407
+ return openBlock(), createElementBlock("div", {
408
+ class: normalizeClass(["astryx-code-editor", { "is-focused": focused.value }]),
409
+ "data-size": __props.size,
410
+ "data-language": __props.language
411
+ }, [createElementVNode("div", {
412
+ class: "astryx-code-editor__container",
413
+ style: normalizeStyle(containerStyle.value)
414
+ }, [__props.hasLineNumbers ? (openBlock(), createElementBlock("div", _hoisted_2$13, [(openBlock(true), createElementBlock(Fragment, null, renderList(lines.value, (_, index) => {
415
+ return openBlock(), createElementBlock("div", { key: index }, toDisplayString(index + 1), 1);
416
+ }), 128))])) : createCommentVNode("v-if", true), createElementVNode("div", _hoisted_3$11, [
417
+ showPlaceholder.value ? (openBlock(), createElementBlock("div", _hoisted_4$10, toDisplayString(__props.placeholder), 1)) : createCommentVNode("v-if", true),
418
+ createElementVNode("code", {
419
+ ref_key: "editor",
420
+ ref: editor,
421
+ class: "astryx-code-editor__input",
422
+ contenteditable: __props.isReadOnly ? "false" : "plaintext-only",
423
+ tabindex: "0",
424
+ role: "textbox",
425
+ "aria-multiline": "true",
426
+ "aria-label": __props.label,
427
+ "aria-readonly": __props.isReadOnly || void 0,
428
+ "aria-describedby": __props.isReadOnly ? void 0 : hintId,
429
+ spellcheck: "false",
430
+ onInput,
431
+ onKeydown,
432
+ onFocus: _cache[0] || (_cache[0] = ($event) => focused.value = true),
433
+ onBlur: _cache[1] || (_cache[1] = ($event) => {
434
+ focused.value = false;
435
+ tabMovesFocus.value = false;
436
+ }),
437
+ onCompositionstart: _cache[2] || (_cache[2] = ($event) => composing.value = true),
438
+ onCompositionend: _cache[3] || (_cache[3] = ($event) => {
439
+ composing.value = false;
440
+ onInput();
441
+ })
442
+ }, toDisplayString(__props.value), 41, _hoisted_5$9),
443
+ !__props.isReadOnly ? (openBlock(), createBlock(unref(VisuallyHidden), {
444
+ key: 1,
445
+ id: hintId
446
+ }, {
447
+ default: withCtx(() => [createTextVNode(toDisplayString(__props.escapeHint), 1)]),
448
+ _: 1
449
+ })) : createCommentVNode("v-if", true)
450
+ ])], 4)], 10, _hoisted_1$15);
181
451
  };
182
452
  }
183
453
  });
@@ -409,13 +679,13 @@ var RenderVNode_default = defineComponent({
409
679
  });
410
680
  //#endregion
411
681
  //#region src/DiffViewer/DiffViewerTable.vue
412
- const _hoisted_1$12 = [
682
+ const _hoisted_1$14 = [
413
683
  "data-view-mode",
414
684
  "data-has-line-numbers",
415
685
  "data-change-indicator",
416
686
  "data-change-background"
417
687
  ];
418
- const _hoisted_2$11 = {
688
+ const _hoisted_2$12 = {
419
689
  key: 0,
420
690
  scope: "col",
421
691
  class: "astryx-diff-viewer__column-header"
@@ -530,7 +800,7 @@ const _hoisted_47 = {
530
800
  key: 0,
531
801
  class: "astryx-diff-viewer__annotation-content"
532
802
  };
533
- const _sfc_main$13 = /*@__PURE__*/ defineComponent({
803
+ const _sfc_main$17 = /*@__PURE__*/ defineComponent({
534
804
  name: "AstryxDiffViewerTable",
535
805
  __name: "DiffViewerTable",
536
806
  props: {
@@ -610,7 +880,7 @@ const _sfc_main$13 = /*@__PURE__*/ defineComponent({
610
880
  _cache[3] || (_cache[3] = createElementVNode("col", null, null, -1))
611
881
  ]),
612
882
  createElementVNode("thead", null, [createElementVNode("tr", null, [
613
- __props.hasLineNumbers ? (openBlock(), createElementBlock("th", _hoisted_2$11, [createVNode(unref(VisuallyHidden), null, {
883
+ __props.hasLineNumbers ? (openBlock(), createElementBlock("th", _hoisted_2$12, [createVNode(unref(VisuallyHidden), null, {
614
884
  default: withCtx(() => [..._cache[4] || (_cache[4] = [createTextVNode("Original line number", -1)])]),
615
885
  _: 1
616
886
  })])) : createCommentVNode("v-if", true),
@@ -687,7 +957,7 @@ const _sfc_main$13 = /*@__PURE__*/ defineComponent({
687
957
  class: "astryx-diff-viewer__annotation"
688
958
  }, [createElementVNode("div", _hoisted_18, [createVNode(unref(RenderVNode_default), { content: row.cell.note }, null, 8, ["content"])])], 8, _hoisted_17)])) : createCommentVNode("v-if", true)], 64))], 64);
689
959
  }), 128))])
690
- ], 14, _hoisted_1$12)) : (openBlock(), createElementBlock("table", {
960
+ ], 14, _hoisted_1$14)) : (openBlock(), createElementBlock("table", {
691
961
  key: 1,
692
962
  ref_key: "splitTable",
693
963
  ref: splitTable,
@@ -1228,8 +1498,8 @@ function buildSplitRows(file, cells) {
1228
1498
  }
1229
1499
  //#endregion
1230
1500
  //#region src/DiffViewer/DiffViewer.vue
1231
- const _hoisted_1$11 = ["data-view-mode"];
1232
- const _hoisted_2$10 = ["aria-expanded"];
1501
+ const _hoisted_1$13 = ["data-view-mode"];
1502
+ const _hoisted_2$11 = ["aria-expanded"];
1233
1503
  const _hoisted_3$9 = { class: "astryx-diff-viewer__path" };
1234
1504
  const _hoisted_4$8 = {
1235
1505
  key: 1,
@@ -1261,7 +1531,7 @@ const _hoisted_11$1 = {
1261
1531
  class: "astryx-diff-viewer__message"
1262
1532
  };
1263
1533
  const _hoisted_12 = ["aria-label"];
1264
- const _sfc_main$1 = /*@__PURE__*/ defineComponent({
1534
+ const _sfc_main$2 = /*@__PURE__*/ defineComponent({
1265
1535
  name: "AstryxDiffViewer",
1266
1536
  inheritAttrs: false,
1267
1537
  __name: "DiffViewer",
@@ -1421,7 +1691,7 @@ const _sfc_main$1 = /*@__PURE__*/ defineComponent({
1421
1691
  icon: "chevronRight",
1422
1692
  size: "xsm",
1423
1693
  color: "inherit"
1424
- })], 2), createElementVNode("span", _hoisted_3$9, toDisplayString(displayPath.value), 1)], 8, _hoisted_2$10)) : displayPath.value != null ? (openBlock(), createElementBlock("span", _hoisted_4$8, toDisplayString(displayPath.value), 1)) : createCommentVNode("v-if", true),
1694
+ })], 2), createElementVNode("span", _hoisted_3$9, toDisplayString(displayPath.value), 1)], 8, _hoisted_2$11)) : displayPath.value != null ? (openBlock(), createElementBlock("span", _hoisted_4$8, toDisplayString(displayPath.value), 1)) : createCommentVNode("v-if", true),
1425
1695
  statusColor.value != null && statusLabel.value != null ? (openBlock(), createBlock(unref(Token), {
1426
1696
  key: 2,
1427
1697
  size: "sm",
@@ -1450,7 +1720,7 @@ const _sfc_main$1 = /*@__PURE__*/ defineComponent({
1450
1720
  }), [createElementVNode("div", {
1451
1721
  ref: unref(scroll).content,
1452
1722
  class: "astryx-diff-viewer__content"
1453
- }, [createVNode(_sfc_main$13, {
1723
+ }, [createVNode(_sfc_main$17, {
1454
1724
  "view-mode": __props.viewMode,
1455
1725
  "unified-rows": unifiedRows.value,
1456
1726
  "split-rows": splitRows.value,
@@ -1473,7 +1743,7 @@ const _sfc_main$1 = /*@__PURE__*/ defineComponent({
1473
1743
  "digits"
1474
1744
  ])], 512)], 16, _hoisted_12))], 64)) : createCommentVNode("v-if", true)], 8, _hoisted_9$3)]),
1475
1745
  _: 3
1476
- }, 16))], 16, _hoisted_1$11);
1746
+ }, 16))], 16, _hoisted_1$13);
1477
1747
  };
1478
1748
  }
1479
1749
  });
@@ -1771,8 +2041,8 @@ function parseUnifiedDiff(patch) {
1771
2041
  }
1772
2042
  //#endregion
1773
2043
  //#region src/InfoTip/InfoTip.vue
1774
- const _hoisted_1$10 = ["aria-label"];
1775
- const _sfc_main$2 = /*@__PURE__*/ defineComponent({
2044
+ const _hoisted_1$12 = ["aria-label"];
2045
+ const _sfc_main$3 = /*@__PURE__*/ defineComponent({
1776
2046
  name: "AstryxInfoTip",
1777
2047
  __name: "InfoTip",
1778
2048
  props: {
@@ -1793,7 +2063,7 @@ const _sfc_main$2 = /*@__PURE__*/ defineComponent({
1793
2063
  }, [createVNode(unref(Icon), {
1794
2064
  icon: "info",
1795
2065
  size: __props.size
1796
- }, null, 8, ["size"])], 8, _hoisted_1$10)]),
2066
+ }, null, 8, ["size"])], 8, _hoisted_1$12)]),
1797
2067
  _: 2
1798
2068
  }, [_ctx.$slots.content ? {
1799
2069
  name: "content",
@@ -1882,7 +2152,7 @@ var ListInputCell_default = defineComponent({
1882
2152
  });
1883
2153
  //#endregion
1884
2154
  //#region src/ListInput/ListInputRow.vue
1885
- const _hoisted_1$9 = [
2155
+ const _hoisted_1$11 = [
1886
2156
  "data-list-input-motion-key",
1887
2157
  "data-list-input-drop-target",
1888
2158
  "aria-describedby",
@@ -1890,7 +2160,7 @@ const _hoisted_1$9 = [
1890
2160
  "aria-posinset",
1891
2161
  "aria-setsize"
1892
2162
  ];
1893
- const _hoisted_2$9 = ["data-list-input-reorder-source", "data-list-input-row"];
2163
+ const _hoisted_2$10 = ["data-list-input-reorder-source", "data-list-input-row"];
1894
2164
  const _hoisted_3$8 = ["data-list-input-cell"];
1895
2165
  const _hoisted_4$7 = ["data-list-input-column-label", "data-list-input-repeated"];
1896
2166
  const _hoisted_5$6 = { class: "astryx-list-input__cell-content" };
@@ -1899,7 +2169,7 @@ const _hoisted_7$3 = {
1899
2169
  key: 0,
1900
2170
  class: "astryx-list-input__control-cell astryx-list-input__control-cell--reorder"
1901
2171
  };
1902
- const _sfc_main$12 = /*@__PURE__*/ defineComponent({
2172
+ const _sfc_main$16 = /*@__PURE__*/ defineComponent({
1903
2173
  name: "AstryxListInputRow",
1904
2174
  __name: "ListInputRow",
1905
2175
  props: {
@@ -2033,7 +2303,7 @@ const _sfc_main$12 = /*@__PURE__*/ defineComponent({
2033
2303
  "type",
2034
2304
  "message"
2035
2305
  ])) : createCommentVNode("v-if", true)
2036
- ], 10, _hoisted_2$9)], 8, _hoisted_1$9);
2306
+ ], 10, _hoisted_2$10)], 8, _hoisted_1$11);
2037
2307
  };
2038
2308
  }
2039
2309
  });
@@ -2323,14 +2593,14 @@ function useListReorder(options) {
2323
2593
  }
2324
2594
  //#endregion
2325
2595
  //#region src/ListInput/ListInput.vue
2326
- const _hoisted_1$8 = [
2596
+ const _hoisted_1$10 = [
2327
2597
  "aria-describedby",
2328
2598
  "aria-disabled",
2329
2599
  "aria-busy",
2330
2600
  "data-reorderable",
2331
2601
  "data-state"
2332
2602
  ];
2333
- const _hoisted_2$8 = ["aria-describedby"];
2603
+ const _hoisted_2$9 = ["aria-describedby"];
2334
2604
  const _hoisted_3$7 = {
2335
2605
  key: 0,
2336
2606
  "data-list-input-motion-key": "state:empty",
@@ -2345,7 +2615,7 @@ const _hoisted_5$5 = {
2345
2615
  class: "astryx-list-input__action-content"
2346
2616
  };
2347
2617
  const focusableFieldSelector = "[data-list-input-cell] input, [data-list-input-cell] select, [data-list-input-cell] textarea, [data-list-input-cell] button, [data-list-input-cell] [tabindex]:not([tabindex=\"-1\"])";
2348
- const _sfc_main$3 = /*@__PURE__*/ defineComponent({
2618
+ const _sfc_main$4 = /*@__PURE__*/ defineComponent({
2349
2619
  name: "AstryxListInput",
2350
2620
  inheritAttrs: false,
2351
2621
  __name: "ListInput",
@@ -2623,7 +2893,7 @@ const _sfc_main$3 = /*@__PURE__*/ defineComponent({
2623
2893
  description: unref(t)("@astryx.listInput.emptyDescription", { itemName: __props.itemName }),
2624
2894
  "is-compact": ""
2625
2895
  }, null, 8, ["title", "description"])])) : createCommentVNode("v-if", true), (openBlock(true), createElementBlock(Fragment, null, renderList(unref(reorder).displayValue.value, (item, index) => {
2626
- return openBlock(), createBlock(_sfc_main$12, {
2896
+ return openBlock(), createBlock(_sfc_main$16, {
2627
2897
  key: itemKeyOf(item),
2628
2898
  item,
2629
2899
  index,
@@ -2665,7 +2935,7 @@ const _sfc_main$3 = /*@__PURE__*/ defineComponent({
2665
2935
  "item-status-id",
2666
2936
  "handlers"
2667
2937
  ]);
2668
- }), 128))], 8, _hoisted_2$8),
2938
+ }), 128))], 8, _hoisted_2$9),
2669
2939
  createElementVNode("div", _hoisted_4$6, [createElementVNode("div", _hoisted_5$5, [createVNode(unref(Button), {
2670
2940
  ref_key: "addButtonRef",
2671
2941
  ref: addButtonRef,
@@ -2689,7 +2959,7 @@ const _sfc_main$3 = /*@__PURE__*/ defineComponent({
2689
2959
  default: withCtx(() => [createTextVNode(toDisplayString(unref(t)("@astryx.listInput.reorderInstructions")), 1)]),
2690
2960
  _: 1
2691
2961
  })) : createCommentVNode("v-if", true)
2692
- ], 8, _hoisted_1$8), (openBlock(), createBlock(Teleport, { to: "body" }, [unref(reorder).previewStyle.value != null ? (openBlock(), createElementBlock("div", {
2962
+ ], 8, _hoisted_1$10), (openBlock(), createBlock(Teleport, { to: "body" }, [unref(reorder).previewStyle.value != null ? (openBlock(), createElementBlock("div", {
2693
2963
  key: 0,
2694
2964
  ref_key: "previewHost",
2695
2965
  ref: previewHost,
@@ -2714,8 +2984,8 @@ const _sfc_main$3 = /*@__PURE__*/ defineComponent({
2714
2984
  });
2715
2985
  //#endregion
2716
2986
  //#region src/LogStream/LogStreamRow.vue
2717
- const _hoisted_1$7 = ["data-level", "data-cols"];
2718
- const _hoisted_2$7 = {
2987
+ const _hoisted_1$9 = ["data-level", "data-cols"];
2988
+ const _hoisted_2$8 = {
2719
2989
  key: 0,
2720
2990
  class: "astryx-log-stream__time"
2721
2991
  };
@@ -2738,7 +3008,7 @@ const _hoisted_11 = {
2738
3008
  key: 0,
2739
3009
  class: "astryx-log-stream__detail"
2740
3010
  };
2741
- const _sfc_main$11 = /*@__PURE__*/ defineComponent({
3011
+ const _sfc_main$15 = /*@__PURE__*/ defineComponent({
2742
3012
  name: "AstryxLogStreamRow",
2743
3013
  __name: "LogStreamRow",
2744
3014
  props: {
@@ -2764,7 +3034,7 @@ const _sfc_main$11 = /*@__PURE__*/ defineComponent({
2764
3034
  "data-level": __props.entry.level,
2765
3035
  "data-cols": cols.value
2766
3036
  }, [
2767
- __props.hasTimestamps ? (openBlock(), createElementBlock("span", _hoisted_2$7, toDisplayString(__props.entry.timestamp), 1)) : createCommentVNode("v-if", true),
3037
+ __props.hasTimestamps ? (openBlock(), createElementBlock("span", _hoisted_2$8, toDisplayString(__props.entry.timestamp), 1)) : createCommentVNode("v-if", true),
2768
3038
  createElementVNode("span", _hoisted_3$6, toDisplayString(__props.entry.level), 1),
2769
3039
  __props.hasSource ? (openBlock(), createElementBlock("span", {
2770
3040
  key: 1,
@@ -2772,7 +3042,7 @@ const _sfc_main$11 = /*@__PURE__*/ defineComponent({
2772
3042
  title: __props.entry.source
2773
3043
  }, toDisplayString(__props.entry.source), 9, _hoisted_4$5)) : createCommentVNode("v-if", true),
2774
3044
  createElementVNode("span", _hoisted_5$4, toDisplayString(__props.entry.message), 1)
2775
- ], 8, _hoisted_1$7)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [createElementVNode("button", {
3045
+ ], 8, _hoisted_1$9)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [createElementVNode("button", {
2776
3046
  type: "button",
2777
3047
  class: "astryx-log-stream__row astryx-log-stream__row--button",
2778
3048
  "data-level": __props.entry.level,
@@ -2840,9 +3110,9 @@ function useLogFollow(options) {
2840
3110
  }
2841
3111
  //#endregion
2842
3112
  //#region src/LogStream/LogStream.vue
2843
- const _hoisted_1$6 = ["data-variant"];
2844
- const _hoisted_2$6 = ["aria-label", "aria-live"];
2845
- const _sfc_main$4 = /*@__PURE__*/ defineComponent({
3113
+ const _hoisted_1$8 = ["data-variant"];
3114
+ const _hoisted_2$7 = ["aria-label", "aria-live"];
3115
+ const _sfc_main$5 = /*@__PURE__*/ defineComponent({
2846
3116
  name: "AstryxLogStream",
2847
3117
  inheritAttrs: false,
2848
3118
  __name: "LogStream",
@@ -2908,7 +3178,7 @@ const _sfc_main$4 = /*@__PURE__*/ defineComponent({
2908
3178
  style: normalizeStyle(scrollerStyle.value),
2909
3179
  onScrollPassive: _cache[0] || (_cache[0] = (...args) => unref(handleScroll) && unref(handleScroll)(...args))
2910
3180
  }, [(openBlock(true), createElementBlock(Fragment, null, renderList(__props.entries, (entry) => {
2911
- return renderSlot(_ctx.$slots, "entry", { entry }, () => [createVNode(_sfc_main$11, {
3181
+ return renderSlot(_ctx.$slots, "entry", { entry }, () => [createVNode(_sfc_main$15, {
2912
3182
  entry,
2913
3183
  "has-timestamps": __props.hasTimestamps,
2914
3184
  "has-source": hasSource.value,
@@ -2925,14 +3195,14 @@ const _sfc_main$4 = /*@__PURE__*/ defineComponent({
2925
3195
  "is-expanded",
2926
3196
  "onToggle"
2927
3197
  ])], void 0, entry.id);
2928
- }), 128))], 44, _hoisted_2$6),
3198
+ }), 128))], 44, _hoisted_2$7),
2929
3199
  !following.value && !unref(isAtBottom) && __props.entries.length > 0 ? (openBlock(), createElementBlock("button", {
2930
3200
  key: 0,
2931
3201
  type: "button",
2932
3202
  class: "astryx-log-stream__jump",
2933
3203
  onClick: _cache[1] || (_cache[1] = (...args) => unref(jumpToLatest) && unref(jumpToLatest)(...args))
2934
3204
  }, " Jump to latest ↓ ")) : createCommentVNode("v-if", true)
2935
- ], 16, _hoisted_1$6);
3205
+ ], 16, _hoisted_1$8);
2936
3206
  };
2937
3207
  }
2938
3208
  });
@@ -3040,12 +3310,12 @@ function useSheetSearch(options) {
3040
3310
  }
3041
3311
  //#endregion
3042
3312
  //#region src/MobileTokenizer/MobileTokenizer.vue
3043
- const _hoisted_1$5 = [
3313
+ const _hoisted_1$7 = [
3044
3314
  "aria-expanded",
3045
3315
  "aria-label",
3046
3316
  "aria-disabled"
3047
3317
  ];
3048
- const _hoisted_2$5 = {
3318
+ const _hoisted_2$6 = {
3049
3319
  key: 1,
3050
3320
  class: "astryx-mobile-tokenizer__trigger-placeholder"
3051
3321
  };
@@ -3074,7 +3344,7 @@ const _hoisted_10$1 = {
3074
3344
  class: "astryx-mobile-tokenizer__footer"
3075
3345
  };
3076
3346
  const CREATABLE_ID_PREFIX = "__xds_create__";
3077
- const _sfc_main$5 = /*@__PURE__*/ defineComponent({
3347
+ const _sfc_main$6 = /*@__PURE__*/ defineComponent({
3078
3348
  name: "AstryxMobileTokenizer",
3079
3349
  inheritAttrs: false,
3080
3350
  __name: "MobileTokenizer",
@@ -3240,7 +3510,7 @@ const _sfc_main$5 = /*@__PURE__*/ defineComponent({
3240
3510
  label: item.label,
3241
3511
  disabled: __props.isDisabled
3242
3512
  }, null, 8, ["label", "disabled"]);
3243
- }), 128)) : (openBlock(), createElementBlock("span", _hoisted_2$5, toDisplayString(__props.placeholder ?? ""), 1))], 8, _hoisted_1$5), !__props.isDisabled ? (openBlock(), createBlock(unref(BottomSheet), {
3513
+ }), 128)) : (openBlock(), createElementBlock("span", _hoisted_2$6, toDisplayString(__props.placeholder ?? ""), 1))], 8, _hoisted_1$7), !__props.isDisabled ? (openBlock(), createBlock(unref(BottomSheet), {
3244
3514
  key: 0,
3245
3515
  "is-open": isOpen.value,
3246
3516
  label: __props.label,
@@ -3370,8 +3640,8 @@ const DELTA_GLYPH_PATHS = {
3370
3640
  };
3371
3641
  //#endregion
3372
3642
  //#region src/Stat/Stat.vue
3373
- const _hoisted_1$4 = ["data-size"];
3374
- const _hoisted_2$4 = { class: "astryx-stat__label" };
3643
+ const _hoisted_1$6 = ["data-size"];
3644
+ const _hoisted_2$5 = { class: "astryx-stat__label" };
3375
3645
  const _hoisted_3$4 = { class: "astryx-stat__value-row" };
3376
3646
  const _hoisted_4$3 = { class: "astryx-stat__value" };
3377
3647
  const _hoisted_5$2 = ["data-sentiment"];
@@ -3397,7 +3667,7 @@ const _hoisted_10 = {
3397
3667
  key: 1,
3398
3668
  class: "astryx-stat__media"
3399
3669
  };
3400
- const _sfc_main$7 = /*@__PURE__*/ defineComponent({
3670
+ const _sfc_main$8 = /*@__PURE__*/ defineComponent({
3401
3671
  name: "AstryxStat",
3402
3672
  inheritAttrs: false,
3403
3673
  __name: "Stat",
@@ -3420,7 +3690,7 @@ const _sfc_main$7 = /*@__PURE__*/ defineComponent({
3420
3690
  class: ["astryx-stat", unref(attrs).class],
3421
3691
  "data-size": __props.size
3422
3692
  }), [
3423
- createElementVNode("span", _hoisted_2$4, toDisplayString(__props.label), 1),
3693
+ createElementVNode("span", _hoisted_2$5, toDisplayString(__props.label), 1),
3424
3694
  createElementVNode("span", _hoisted_3$4, [createElementVNode("span", _hoisted_4$3, [renderSlot(_ctx.$slots, "default", {}, () => [createTextVNode(toDisplayString(__props.value), 1)])]), __props.delta != null && sentiment.value != null ? (openBlock(), createElementBlock("span", {
3425
3695
  key: 0,
3426
3696
  class: "astryx-stat__delta",
@@ -3432,7 +3702,7 @@ const _sfc_main$7 = /*@__PURE__*/ defineComponent({
3432
3702
  ], 8, _hoisted_5$2)) : createCommentVNode("v-if", true)]),
3433
3703
  __props.description != null ? (openBlock(), createElementBlock("span", _hoisted_9, toDisplayString(__props.description), 1)) : createCommentVNode("v-if", true),
3434
3704
  _ctx.$slots.media ? (openBlock(), createElementBlock("div", _hoisted_10, [renderSlot(_ctx.$slots, "media")])) : createCommentVNode("v-if", true)
3435
- ], 16, _hoisted_1$4);
3705
+ ], 16, _hoisted_1$6);
3436
3706
  };
3437
3707
  }
3438
3708
  });
@@ -4234,13 +4504,13 @@ function applyPersonality(d, personality) {
4234
4504
  }
4235
4505
  //#endregion
4236
4506
  //#region src/SVGIcon/SVGIcon.vue
4237
- const _hoisted_1$3 = [
4507
+ const _hoisted_1$5 = [
4238
4508
  "viewBox",
4239
4509
  "data-variation",
4240
4510
  "data-size",
4241
4511
  "data-color"
4242
4512
  ];
4243
- const _hoisted_2$3 = { key: 0 };
4513
+ const _hoisted_2$4 = { key: 0 };
4244
4514
  const _hoisted_3$3 = ["mask"];
4245
4515
  const _hoisted_4$2 = {
4246
4516
  key: 2,
@@ -4254,7 +4524,7 @@ const _hoisted_6$1 = {
4254
4524
  key: 1,
4255
4525
  class: "astryx-svg-icon__layer astryx-svg-icon__layer--secondary-stroke"
4256
4526
  };
4257
- const _sfc_main$6 = /*@__PURE__*/ defineComponent({
4527
+ const _sfc_main$7 = /*@__PURE__*/ defineComponent({
4258
4528
  name: "AstryxSvgIcon",
4259
4529
  inheritAttrs: false,
4260
4530
  __name: "SVGIcon",
@@ -4318,7 +4588,7 @@ const _sfc_main$6 = /*@__PURE__*/ defineComponent({
4318
4588
  "data-color": __props.color
4319
4589
  }, mergedAttrs.value, { style: svgStyle.value }), [
4320
4590
  createCommentVNode(" 遮罩:把次层的填充形状从主层里挖出带间隙的洞。 "),
4321
- useMask.value ? (openBlock(), createElementBlock("defs", _hoisted_2$3, [createElementVNode("mask", { id: maskId }, [_cache[0] || (_cache[0] = createElementVNode("rect", {
4591
+ useMask.value ? (openBlock(), createElementBlock("defs", _hoisted_2$4, [createElementVNode("mask", { id: maskId }, [_cache[0] || (_cache[0] = createElementVNode("rect", {
4322
4592
  width: "24",
4323
4593
  height: "24",
4324
4594
  fill: "white"
@@ -4348,7 +4618,7 @@ const _sfc_main$6 = /*@__PURE__*/ defineComponent({
4348
4618
  }), 128))])) : createCommentVNode("v-if", true), secondary.value.stroke.length > 0 ? (openBlock(), createElementBlock("g", _hoisted_6$1, [(openBlock(true), createElementBlock(Fragment, null, renderList(secondary.value.stroke, (shape, index) => {
4349
4619
  return openBlock(), createBlock(resolveDynamicComponent(shape.type), mergeProps({ key: `secondary-stroke-${index}` }, { ref_for: true }, shape.attrs), null, 16);
4350
4620
  }), 128))])) : createCommentVNode("v-if", true)], 64)) : createCommentVNode("v-if", true)
4351
- ], 16, _hoisted_1$3);
4621
+ ], 16, _hoisted_1$5);
4352
4622
  };
4353
4623
  }
4354
4624
  });
@@ -4486,6 +4756,280 @@ const xifExamples = [
4486
4756
  xifBellOverride
4487
4757
  ];
4488
4758
  //#endregion
4759
+ //#region src/Tour/context.ts
4760
+ const TOUR_CONTEXT_KEY = Symbol("AstryxTour");
4761
+ //#endregion
4762
+ //#region src/Tour/Tour.vue
4763
+ const _sfc_main$9 = /*@__PURE__*/ defineComponent({
4764
+ name: "AstryxTour",
4765
+ __name: "Tour",
4766
+ props: {
4767
+ isActive: { type: Boolean },
4768
+ hasBackdrop: {
4769
+ type: Boolean,
4770
+ default: false
4771
+ },
4772
+ isStepCountShown: {
4773
+ type: Boolean,
4774
+ default: false
4775
+ }
4776
+ },
4777
+ emits: ["dismiss"],
4778
+ setup(__props, { emit: __emit }) {
4779
+ const props = __props;
4780
+ const emit = __emit;
4781
+ const stepIds = ref([]);
4782
+ const activeStepIndex = ref(0);
4783
+ const stepCount = computed(() => stepIds.value.length);
4784
+ const activeStepId = computed(() => props.isActive ? stepIds.value[activeStepIndex.value] ?? null : null);
4785
+ function registerStep(id) {
4786
+ if (!stepIds.value.includes(id)) stepIds.value.push(id);
4787
+ return () => {
4788
+ const index = stepIds.value.indexOf(id);
4789
+ if (index >= 0) stepIds.value.splice(index, 1);
4790
+ };
4791
+ }
4792
+ function next() {
4793
+ if (activeStepIndex.value < stepCount.value - 1) activeStepIndex.value += 1;
4794
+ else emit("dismiss", "complete");
4795
+ }
4796
+ function previous() {
4797
+ if (activeStepIndex.value > 0) activeStepIndex.value -= 1;
4798
+ }
4799
+ function dismiss(source) {
4800
+ emit("dismiss", source);
4801
+ }
4802
+ watch(() => props.isActive, (active) => {
4803
+ if (!active) activeStepIndex.value = 0;
4804
+ }, { flush: "sync" });
4805
+ watch(stepCount, (count) => {
4806
+ if (activeStepIndex.value >= count) activeStepIndex.value = Math.max(0, count - 1);
4807
+ });
4808
+ provide(TOUR_CONTEXT_KEY, {
4809
+ registerStep,
4810
+ activeStepId,
4811
+ activeStepIndex: computed(() => activeStepIndex.value),
4812
+ stepCount,
4813
+ isStepCountShown: computed(() => props.isStepCountShown),
4814
+ hasBackdrop: computed(() => props.hasBackdrop),
4815
+ onNext: next,
4816
+ onPrevious: previous,
4817
+ onDismiss: dismiss
4818
+ });
4819
+ return (_ctx, _cache) => {
4820
+ return renderSlot(_ctx.$slots, "default");
4821
+ };
4822
+ }
4823
+ });
4824
+ //#endregion
4825
+ //#region src/Tour/TourHighlight.vue
4826
+ const _hoisted_1$4 = ["data-testid"];
4827
+ const _sfc_main$14 = /*@__PURE__*/ defineComponent({
4828
+ __name: "TourHighlight",
4829
+ props: {
4830
+ rect: {},
4831
+ hasBackdrop: { type: Boolean }
4832
+ },
4833
+ emits: ["backdropClick"],
4834
+ setup(__props, { emit: __emit }) {
4835
+ const props = __props;
4836
+ const emit = __emit;
4837
+ function onBackdropPointerDown(event) {
4838
+ if (!props.hasBackdrop) return;
4839
+ event.preventDefault();
4840
+ event.stopPropagation();
4841
+ emit("backdropClick");
4842
+ }
4843
+ const highlightStyle = computed(() => props.rect == null ? void 0 : {
4844
+ top: `${props.rect.top - 4}px`,
4845
+ left: `${props.rect.left - 4}px`,
4846
+ width: `${props.rect.width + 8}px`,
4847
+ height: `${props.rect.height + 8}px`,
4848
+ borderRadius: props.rect.radius
4849
+ });
4850
+ return (_ctx, _cache) => {
4851
+ return openBlock(), createElementBlock("div", {
4852
+ class: normalizeClass(["astryx-tour-highlight-root", { "is-interactive": __props.hasBackdrop }]),
4853
+ "data-testid": __props.hasBackdrop ? "tour-backdrop" : void 0,
4854
+ "aria-hidden": "true",
4855
+ onPointerdown: onBackdropPointerDown
4856
+ }, [createElementVNode("div", {
4857
+ class: normalizeClass(["astryx-tour-highlight", {
4858
+ "has-backdrop": __props.hasBackdrop,
4859
+ "is-hidden": __props.rect == null
4860
+ }]),
4861
+ style: normalizeStyle(highlightStyle.value),
4862
+ "data-testid": "tour-highlight"
4863
+ }, null, 6)], 42, _hoisted_1$4);
4864
+ };
4865
+ }
4866
+ });
4867
+ //#endregion
4868
+ //#region src/Tour/TourStep.vue
4869
+ const _hoisted_1$3 = ["data-testid"];
4870
+ const _hoisted_2$3 = { key: 1 };
4871
+ const _sfc_main$10 = /*@__PURE__*/ defineComponent({
4872
+ name: "AstryxTourStep",
4873
+ __name: "TourStep",
4874
+ props: {
4875
+ targetRef: {},
4876
+ heading: {},
4877
+ placement: { default: "below" },
4878
+ alignment: { default: "start" },
4879
+ "data-testid": {}
4880
+ },
4881
+ setup(__props) {
4882
+ const props = __props;
4883
+ const slots = useSlots();
4884
+ const tour = inject(TOUR_CONTEXT_KEY, null);
4885
+ const id = `astryx-tour-step-${useId()}`;
4886
+ const isActiveStep = computed(() => tour?.activeStepId.value === id);
4887
+ const activeStepIndex = computed(() => tour?.activeStepIndex.value ?? 0);
4888
+ const stepCount = computed(() => tour?.stepCount.value ?? 0);
4889
+ const isFirstStep = computed(() => activeStepIndex.value <= 0);
4890
+ const isLastStep = computed(() => stepCount.value > 0 && activeStepIndex.value === stepCount.value - 1);
4891
+ const target = computed(() => toValue(props.targetRef));
4892
+ const rect = shallowRef(null);
4893
+ let unregister;
4894
+ function measure() {
4895
+ const element = target.value;
4896
+ if (element == null || !isActiveStep.value) {
4897
+ rect.value = null;
4898
+ return;
4899
+ }
4900
+ const box = element.getBoundingClientRect();
4901
+ rect.value = {
4902
+ top: box.top,
4903
+ left: box.left,
4904
+ width: box.width,
4905
+ height: box.height,
4906
+ radius: getComputedStyle(element).borderRadius || "0px"
4907
+ };
4908
+ }
4909
+ function stopMeasuring() {
4910
+ window.removeEventListener("scroll", measure, true);
4911
+ window.removeEventListener("resize", measure);
4912
+ }
4913
+ watch([isActiveStep, target], async ([active]) => {
4914
+ stopMeasuring();
4915
+ if (!active || tour == null) {
4916
+ rect.value = null;
4917
+ return;
4918
+ }
4919
+ await nextTick();
4920
+ measure();
4921
+ window.addEventListener("scroll", measure, true);
4922
+ window.addEventListener("resize", measure);
4923
+ }, {
4924
+ immediate: true,
4925
+ flush: "post"
4926
+ });
4927
+ onMounted(() => {
4928
+ unregister = tour?.registerStep(id);
4929
+ });
4930
+ onBeforeUnmount(() => {
4931
+ stopMeasuring();
4932
+ unregister?.();
4933
+ });
4934
+ function onOpenChange(open) {
4935
+ if (!open) tour?.onDismiss("close");
4936
+ }
4937
+ return (_ctx, _cache) => {
4938
+ return unref(tour) && isActiveStep.value ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createVNode(_sfc_main$14, {
4939
+ rect: rect.value,
4940
+ "has-backdrop": unref(tour).hasBackdrop.value,
4941
+ onBackdropClick: _cache[0] || (_cache[0] = ($event) => unref(tour).onDismiss("backdrop"))
4942
+ }, null, 8, ["rect", "has-backdrop"]), createVNode(unref(Popover), {
4943
+ anchor: target.value,
4944
+ "is-open": "",
4945
+ placement: __props.placement,
4946
+ alignment: __props.alignment,
4947
+ width: "fit-content",
4948
+ label: __props.heading,
4949
+ "has-light-dismiss": !unref(tour).hasBackdrop.value,
4950
+ "close-button-label": "Close tour",
4951
+ onOpenChange
4952
+ }, {
4953
+ content: withCtx(() => [createElementVNode("div", {
4954
+ class: "astryx-tour-step",
4955
+ "data-testid": props["data-testid"]
4956
+ }, [createVNode(unref(VStack), { gap: 1 }, {
4957
+ default: withCtx(() => [createVNode(unref(Heading), { level: 4 }, {
4958
+ default: withCtx(() => [createTextVNode(toDisplayString(__props.heading), 1)]),
4959
+ _: 1
4960
+ }), unref(slots).default ? (openBlock(), createBlock(unref(Text), {
4961
+ key: 0,
4962
+ type: "body"
4963
+ }, {
4964
+ default: withCtx(() => [renderSlot(_ctx.$slots, "default")]),
4965
+ _: 3
4966
+ })) : createCommentVNode("v-if", true)]),
4967
+ _: 3
4968
+ }), createVNode(unref(HStack), {
4969
+ class: "astryx-tour-step__footer",
4970
+ gap: 2,
4971
+ "h-align": "between"
4972
+ }, {
4973
+ default: withCtx(() => [unref(tour).isStepCountShown.value && stepCount.value > 0 ? (openBlock(), createBlock(unref(Text), {
4974
+ key: 0,
4975
+ type: "supporting",
4976
+ color: "secondary"
4977
+ }, {
4978
+ default: withCtx(() => [createTextVNode(toDisplayString(activeStepIndex.value + 1) + " of " + toDisplayString(stepCount.value), 1)]),
4979
+ _: 1
4980
+ })) : (openBlock(), createElementBlock("span", _hoisted_2$3)), createVNode(unref(HStack), { gap: 2 }, {
4981
+ default: withCtx(() => [!isFirstStep.value ? (openBlock(), createBlock(unref(Button), {
4982
+ key: 0,
4983
+ variant: "ghost",
4984
+ size: "sm",
4985
+ label: "Back",
4986
+ onClick: unref(tour).onPrevious
4987
+ }, null, 8, ["onClick"])) : createCommentVNode("v-if", true), createVNode(unref(Button), {
4988
+ variant: "primary",
4989
+ size: "sm",
4990
+ label: isLastStep.value ? "Done" : "Next",
4991
+ onClick: unref(tour).onNext
4992
+ }, null, 8, ["label", "onClick"])]),
4993
+ _: 1
4994
+ })]),
4995
+ _: 1
4996
+ })], 8, _hoisted_1$3)]),
4997
+ _: 3
4998
+ }, 8, [
4999
+ "anchor",
5000
+ "placement",
5001
+ "alignment",
5002
+ "label",
5003
+ "has-light-dismiss"
5004
+ ])], 64)) : createCommentVNode("v-if", true);
5005
+ };
5006
+ }
5007
+ });
5008
+ //#endregion
5009
+ //#region src/Tour/useTour.ts
5010
+ /** 读取最近的 Tour。没有控制器时返回 null,由调用方决定是否跳过自定义 UI。 */
5011
+ function useTour() {
5012
+ const tour = inject(TOUR_CONTEXT_KEY, null);
5013
+ if (tour == null) return null;
5014
+ return {
5015
+ get activeStepIndex() {
5016
+ return tour.activeStepIndex.value;
5017
+ },
5018
+ get stepCount() {
5019
+ return tour.stepCount.value;
5020
+ },
5021
+ get isFirstStep() {
5022
+ return tour.activeStepIndex.value <= 0;
5023
+ },
5024
+ get isLastStep() {
5025
+ return tour.stepCount.value > 0 && tour.activeStepIndex.value === tour.stepCount.value - 1;
5026
+ },
5027
+ next: tour.onNext,
5028
+ previous: tour.onPrevious,
5029
+ dismiss: tour.onDismiss
5030
+ };
5031
+ }
5032
+ //#endregion
4489
5033
  //#region src/TransferList/transferItems.ts
4490
5034
  /** 把 `fromIndex` 那一项挪到 `toIndex`,返回新数组。 */
4491
5035
  function moveItem(value, fromIndex, toIndex) {
@@ -4558,7 +5102,7 @@ const _hoisted_5 = {
4558
5102
  class: "astryx-transfer-list-panel__group-heading"
4559
5103
  };
4560
5104
  const _hoisted_6 = ["data-transfer-list-empty"];
4561
- const _sfc_main$10 = /*@__PURE__*/ defineComponent({
5105
+ const _sfc_main$13 = /*@__PURE__*/ defineComponent({
4562
5106
  name: "AstryxTransferListPanel",
4563
5107
  __name: "TransferListPanel",
4564
5108
  props: {
@@ -5030,7 +5574,7 @@ const _hoisted_3$1 = {
5030
5574
  class: "astryx-transfer-list__controls"
5031
5575
  };
5032
5576
  const _hoisted_4 = { class: "astryx-transfer-list-collection" };
5033
- const _sfc_main$8 = /*@__PURE__*/ defineComponent({
5577
+ const _sfc_main$11 = /*@__PURE__*/ defineComponent({
5034
5578
  name: "AstryxTransferList",
5035
5579
  inheritAttrs: false,
5036
5580
  __name: "TransferList",
@@ -5304,7 +5848,7 @@ const _sfc_main$8 = /*@__PURE__*/ defineComponent({
5304
5848
  default: withCtx(() => [createTextVNode(toDisplayString(unref(t)("@astryx.transferList.reorderInstructions")), 1)]),
5305
5849
  _: 1
5306
5850
  }),
5307
- createElementVNode("div", _hoisted_4, [createVNode(_sfc_main$10, {
5851
+ createElementVNode("div", _hoisted_4, [createVNode(_sfc_main$13, {
5308
5852
  side: "selected",
5309
5853
  "heading-id": selectedHeadingId,
5310
5854
  label: selectedLabel.value,
@@ -5340,7 +5884,7 @@ const _sfc_main$8 = /*@__PURE__*/ defineComponent({
5340
5884
  "dragging-value",
5341
5885
  "grabbed-value",
5342
5886
  "drop-target"
5343
- ]), createVNode(_sfc_main$10, {
5887
+ ]), createVNode(_sfc_main$13, {
5344
5888
  side: "available",
5345
5889
  "heading-id": availableHeadingId,
5346
5890
  label: availableLabel.value,
@@ -5395,7 +5939,7 @@ const _hoisted_3 = {
5395
5939
  class: "astryx-transfer-list-selector__footer"
5396
5940
  };
5397
5941
  const DEFAULT_SELECTOR_WIDTH = "min(41rem, calc(100vw - 32px))";
5398
- const _sfc_main$9 = /*@__PURE__*/ defineComponent({
5942
+ const _sfc_main$12 = /*@__PURE__*/ defineComponent({
5399
5943
  name: "AstryxTransferListSelector",
5400
5944
  __name: "TransferListSelector",
5401
5945
  props: {
@@ -5532,7 +6076,7 @@ const _sfc_main$9 = /*@__PURE__*/ defineComponent({
5532
6076
  }, [createElementVNode("fieldset", {
5533
6077
  class: "astryx-transfer-list-selector__fieldset",
5534
6078
  disabled: __props.isDisabled
5535
- }, [createVNode(_sfc_main$8, {
6079
+ }, [createVNode(_sfc_main$11, {
5536
6080
  label: __props.label,
5537
6081
  "is-label-hidden": "",
5538
6082
  options: __props.options,
@@ -5611,4 +6155,4 @@ const _sfc_main$9 = /*@__PURE__*/ defineComponent({
5611
6155
  }
5612
6156
  });
5613
6157
  //#endregion
5614
- export { _sfc_main as CircularProgress, _sfc_main$1 as DiffViewer, _sfc_main$2 as InfoTip, _sfc_main$3 as ListInput, _sfc_main$4 as LogStream, _sfc_main$5 as MobileTokenizer, _sfc_main$6 as SVGIcon, _sfc_main$7 as Stat, _sfc_main$8 as TransferList, _sfc_main$9 as TransferListSelector, addCurvature, adjustTension, applyPersonality, bellIcon, calendarIcon, checkIcon, createDiffFile, eyeIcon, folderIcon, heartIcon, homeIcon, lockIcon, mailIcon, menuIcon, parseUnifiedDiff, roundCorners, searchIcon, settingsIcon, shieldIcon, starIcon, starterIcons, xIcon, xifBell, xifBellOverride, xifCheck, xifExamples, xifFile, xifHome, xifShield, xifStar };
6158
+ export { _sfc_main as CircularProgress, _sfc_main$1 as CodeEditor, _sfc_main$2 as DiffViewer, _sfc_main$3 as InfoTip, _sfc_main$4 as ListInput, _sfc_main$5 as LogStream, _sfc_main$6 as MobileTokenizer, _sfc_main$7 as SVGIcon, _sfc_main$8 as Stat, _sfc_main$9 as Tour, _sfc_main$10 as TourStep, _sfc_main$11 as TransferList, _sfc_main$12 as TransferListSelector, addCurvature, adjustTension, applyPersonality, bellIcon, calendarIcon, checkIcon, createDiffFile, eyeIcon, folderIcon, heartIcon, homeIcon, lockIcon, mailIcon, menuIcon, parseUnifiedDiff, roundCorners, searchIcon, settingsIcon, shieldIcon, starIcon, starterIcons, useTour, xIcon, xifBell, xifBellOverride, xifCheck, xifExamples, xifFile, xifHome, xifShield, xifStar };