@xihan-ui/web-components 1.0.0-alpha.3 → 1.0.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/define.js CHANGED
@@ -1,7 +1,7 @@
1
- import { a as containsPart, c as applyMotionOverride, d as notifyXhConfigChange, f as onXhConfigChange, h as withXhConfig, i as PART_ATTR, o as discoverParts, p as resolveXhConfig, r as createSpreader, s as wcNormalize, t as MachineController } from "./machine-controller-j_fnUsFq.js";
1
+ import { a as containsPart, c as applyMotionOverride, d as notifyXhConfigChange, f as onXhConfigChange, h as withXhConfig, i as PART_ATTR, o as discoverParts, p as resolveXhConfig, r as createSpreader, s as wcNormalize, t as MachineController } from "./machine-controller-DE6edQbK.js";
2
2
  import { t as defineElement } from "./registry-DR6I2_zF.js";
3
- import { n as version, t as XhReactiveElement } from "./element-Cpkqkn_U.js";
4
- import { HEATMAP_LEGEND_TEXT, accordionAnatomy, accordionMachine, accordionMeta, affixAnatomy, affixMachine, affixMeta, alertAnatomy, alertMachine, alertMeta, anchorAnatomy, anchorMachine, anchorMeta, autoSizeTextarea, avatarAnatomy, avatarGroupAnatomy, avatarGroupMeta, avatarMachine, avatarMeta, backTopAnatomy, backTopMachine, backTopMeta, badgeAnatomy, badgeMeta, breadcrumbAnatomy, breadcrumbMeta, buildHeatmapGrid, buttonAnatomy, buttonGroupAnatomy, buttonGroupMeta, buttonMeta, calendarAnatomy, calendarMachine, calendarMeta, cardAnatomy, cardMeta, carouselAnatomy, carouselMachine, carouselMeta, cascaderAnatomy, cascaderMachine, cascaderMeta, checkboxAnatomy, checkboxGroupAnatomy, checkboxGroupMachine, checkboxGroupMeta, checkboxMachine, checkboxMeta, clipboardAnatomy, clipboardMachine, clipboardMeta, codeBlockAnatomy, codeBlockMeta, collapsibleAnatomy, collapsibleMachine, collapsibleMeta, colorPickerAnatomy, colorPickerMachine, colorPickerMeta, colorPickerToChannel, colorPickerToInputChannel, comboboxAnatomy, comboboxMachine, comboboxMeta, composerAnatomy, composerMachine, composerMeta, connectAccordion, connectAffix, connectAlert, connectAnchor, connectAvatar, connectAvatarGroup, connectBackTop, connectBadge, connectBreadcrumb, connectButton, connectButtonGroup, connectCalendar, connectCard, connectCarousel, connectCascader, connectCheckbox, connectCheckboxGroup, connectClipboard, connectCodeBlock, connectCollapsible, connectColorPicker, connectCombobox, connectComposer, connectContextMenu, connectCountdown, connectDateField, connectDatePicker, connectDescriptions, connectDialog, connectDownloadTrigger, connectDrawer, connectDynamicInput, connectEditable, connectEllipsis, connectEmptyState, connectField, connectFieldset, connectFileUpload, connectFlex, connectFloatButton, connectFloatingPanel, connectForm, connectGradientText, connectGrid, connectHeatmap, connectHighlight, connectHotkeys, connectHoverCard, connectIcon, connectIconWrapper, connectImage, connectImageCropper, connectImageViewer, connectInfiniteScroll, connectJsonViewer, connectLayout, connectList, connectListbox, connectLoadingBar, connectLog, connectMarquee, connectMasonry, connectMention, connectMenu, connectMenubar, connectNavigationMenu, connectNumberAnimation, connectNumberField, connectPageHeader, connectPagination, connectPasswordInput, connectPinInput, connectPopconfirm, connectPopover, connectPopselect, connectProgress, connectQrCode, connectRadioGroup, connectRating, connectResult, connectScrollArea, connectScrollbar, connectSegmented, connectSelect, connectSeparator, connectSideNav, connectSignaturePad, connectSkeleton, connectSlider, connectSpace, connectSpinner, connectSplitter, connectStatistic, connectSteps, connectSwitch, connectTable, connectTabs, connectTag, connectTagsInput, connectTextField, connectThread, connectTime, connectTimeField, connectTimePicker, connectTimeline, connectTimer, connectToast, connectToaster, connectToggle, connectToggleGroup, connectToolbar, connectTooltip, connectTour, connectTransfer, connectTree, connectTreeSelect, connectTypography, connectVirtualizer, connectWatermark, contextMenuAnatomy, contextMenuMachine, contextMenuMeta, countdownAnatomy, countdownMachine, countdownMeta, dateFieldAnatomy, dateFieldMachine, dateFieldMeta, datePickerAnatomy, datePickerCalendarProps, datePickerFieldEndProps, datePickerFieldProps, datePickerMachine, datePickerMeta, descriptionsAnatomy, descriptionsMeta, detectHotkeysPlatform, dialogAnatomy, dialogMachine, dialogMeta, distributeMasonry, downloadTriggerAnatomy, downloadTriggerMachine, downloadTriggerMeta, drawerAnatomy, drawerMachine, drawerMeta, dynamicInputAnatomy, dynamicInputMachine, dynamicInputMeta, editableAnatomy, editableMachine, editableMeta, ellipsisAnatomy, ellipsisMachine, ellipsisMeta, emptyStateAnatomy, emptyStateMeta, fieldAnatomy, fieldMeta, fieldsetAnatomy, fieldsetMeta, fileUploadAnatomy, fileUploadMachine, fileUploadMeta, flexAnatomy, flexMeta, floatButtonAnatomy, floatButtonMeta, floatingPanelAnatomy, floatingPanelMachine, floatingPanelMeta, formAnatomy, formMachine, formMeta, gradientTextAnatomy, gradientTextMeta, gridAnatomy, gridMeta, heatmapAnatomy, heatmapMachine, heatmapMeta, highlightAnatomy, highlightMeta, hotkeysAnatomy, hotkeysMeta, hoverCardAnatomy, hoverCardMachine, hoverCardMeta, iconAnatomy, iconMeta, iconWrapperAnatomy, iconWrapperMeta, imageAnatomy, imageCropperAnatomy, imageCropperMachine, imageCropperMeta, imageMachine, imageMeta, imageViewerAnatomy, imageViewerCounterText, imageViewerMachine, imageViewerMeta, infiniteScrollAnatomy, infiniteScrollMachine, infiniteScrollMeta, isTimerUnit, jsonViewerAnatomy, jsonViewerMachine, jsonViewerMeta, layoutAnatomy, layoutMachine, layoutMeta, listAnatomy, listMeta, listboxAnatomy, listboxMachine, listboxMeta, loadingBarAnatomy, loadingBarMachine, loadingBarMeta, logAnatomy, logMeta, marqueeAnatomy, marqueeMeta, masonryAnatomy, masonryMeta, mentionAnatomy, mentionMachine, mentionMeta, menuAnatomy, menuMachine, menuMeta, menubarAnatomy, menubarMachine, menubarMeta, navigationMenuAnatomy, navigationMenuMachine, navigationMenuMeta, numberAnimationAnatomy, numberAnimationMachine, numberAnimationMeta, numberFieldAnatomy, numberFieldMachine, numberFieldMeta, pageHeaderAnatomy, pageHeaderMeta, paginationAnatomy, paginationMachine, paginationMeta, passwordInputAnatomy, passwordInputMachine, passwordInputMeta, pinInputAnatomy, pinInputMachine, pinInputMeta, popconfirmAnatomy, popconfirmMeta, popoverAnatomy, popoverMachine, popoverMeta, popselectAnatomy, popselectInitialFocus, popselectMeta, progressAnatomy, progressMeta, qrCodeAnatomy, qrCodeMeta, radioGroupAnatomy, radioGroupMachine, radioGroupMeta, ratingAnatomy, ratingMachine, ratingMeta, resolveMasonryColumns, resultAnatomy, resultMeta, scrollAreaAnatomy, scrollAreaMeta, scrollAreaScrollbarProps, scrollbarAnatomy, scrollbarMachine, scrollbarMeta, segmentedAnatomy, segmentedMachine, segmentedMeta, selectAnatomy, selectMachine, selectMeta, separatorAnatomy, separatorMeta, sideNavAnatomy, sideNavMachine, sideNavMeta, signaturePadAnatomy, signaturePadMachine, signaturePadMeta, skeletonAnatomy, skeletonMeta, sliderAnatomy, sliderMachine, sliderMeta, spaceAnatomy, spaceMeta, spinnerAnatomy, spinnerMeta, splitterAnatomy, splitterMachine, splitterMeta, statisticAnatomy, statisticMeta, stepsAnatomy, stepsMachine, stepsMeta, switchAnatomy, switchMachine, switchMeta, tableAnatomy, tableMachine, tableMeta, tabsAnatomy, tabsMachine, tabsMeta, tagAnatomy, tagMachine, tagMeta, tagsInputAnatomy, tagsInputMachine, tagsInputMeta, textFieldAnatomy, textFieldMachine, textFieldMeta, threadAnatomy, threadMachine, threadMeta, timeAnatomy, timeFieldAnatomy, timeFieldMachine, timeFieldMeta, timeMeta, timePickerAnatomy, timePickerMachine, timePickerMeta, timelineAnatomy, timelineMeta, timerAnatomy, timerMachine, timerMeta, toastAnatomy, toastMachine, toastMeta, toasterAnatomy, toasterMachine, toasterMeta, toggleAnatomy, toggleGroupAnatomy, toggleGroupMachine, toggleGroupMeta, toggleMachine, toggleMeta, toolbarAnatomy, toolbarMachine, toolbarMeta, tooltipAnatomy, tooltipMachine, tooltipMeta, tourAnatomy, tourMachine, tourMeta, transferAnatomy, transferFocusKey, transferMachine, transferMeta, treeAnatomy, treeMachine, treeMeta, treeSelectAnatomy, treeSelectMachine, treeSelectMeta, typographyAnatomy, typographyMeta, virtualizerAnatomy, virtualizerMachine, virtualizerMeta, watermarkAnatomy, watermarkMeta } from "@xihan-ui/headless";
3
+ import { n as version, t as XhReactiveElement } from "./element-ib25-l85.js";
4
+ import { HEATMAP_LEGEND_TEXT, SCROLLBAR_DEFAULT_TYPE, accordionAnatomy, accordionMachine, accordionMeta, affixAnatomy, affixMachine, affixMeta, alertAnatomy, alertMachine, alertMeta, anchorAnatomy, anchorMachine, anchorMeta, autoSizeTextarea, avatarAnatomy, avatarGroupAnatomy, avatarGroupMeta, avatarMachine, avatarMeta, backTopAnatomy, backTopMachine, backTopMeta, badgeAnatomy, badgeMeta, breadcrumbAnatomy, breadcrumbMeta, buildHeatmapGrid, buttonAnatomy, buttonGroupAnatomy, buttonGroupMeta, buttonMeta, calendarAnatomy, calendarMachine, calendarMeta, cardAnatomy, cardMeta, carouselAnatomy, carouselMachine, carouselMeta, cascaderAnatomy, cascaderMachine, cascaderMeta, checkboxAnatomy, checkboxGroupAnatomy, checkboxGroupMachine, checkboxGroupMeta, checkboxMachine, checkboxMeta, clipboardAnatomy, clipboardMachine, clipboardMeta, codeBlockAnatomy, codeBlockMeta, collapsibleAnatomy, collapsibleMachine, collapsibleMeta, colorPickerAnatomy, colorPickerMachine, colorPickerMeta, colorPickerToChannel, colorPickerToInputChannel, comboboxAnatomy, comboboxMachine, comboboxMeta, composerAnatomy, composerMachine, composerMeta, connectAccordion, connectAffix, connectAlert, connectAnchor, connectAvatar, connectAvatarGroup, connectBackTop, connectBadge, connectBreadcrumb, connectButton, connectButtonGroup, connectCalendar, connectCard, connectCarousel, connectCascader, connectCheckbox, connectCheckboxGroup, connectClipboard, connectCodeBlock, connectCollapsible, connectColorPicker, connectCombobox, connectComposer, connectContextMenu, connectCountdown, connectDateField, connectDatePicker, connectDescriptions, connectDialog, connectDownloadTrigger, connectDrawer, connectDynamicInput, connectEditable, connectEllipsis, connectEmptyState, connectField, connectFieldset, connectFileUpload, connectFlex, connectFloatButton, connectFloatingPanel, connectForm, connectGradientText, connectGrid, connectHeatmap, connectHighlight, connectHotkeys, connectHoverCard, connectIcon, connectIconWrapper, connectImage, connectImageCropper, connectImageViewer, connectInfiniteScroll, connectJsonViewer, connectLayout, connectList, connectListbox, connectLoadingBar, connectLog, connectMarquee, connectMasonry, connectMention, connectMenu, connectMenubar, connectNavigationMenu, connectNotification, connectNotificationItem, connectNumberAnimation, connectNumberField, connectPageHeader, connectPagination, connectPasswordInput, connectPinInput, connectPopconfirm, connectPopover, connectPopselect, connectProgress, connectQrCode, connectRadioGroup, connectRating, connectResult, connectScrollArea, connectScrollbar, connectSegmented, connectSelect, connectSeparator, connectSideNav, connectSignaturePad, connectSkeleton, connectSlider, connectSpace, connectSpinner, connectSplitter, connectStatistic, connectSteps, connectSwitch, connectTable, connectTabs, connectTag, connectTagsInput, connectTextField, connectThread, connectTime, connectTimeField, connectTimePicker, connectTimeline, connectTimer, connectToast, connectToggle, connectToggleGroup, connectToolbar, connectTooltip, connectTour, connectTransfer, connectTree, connectTreeSelect, connectTypography, connectVirtualizer, connectWatermark, contextMenuAnatomy, contextMenuMachine, contextMenuMeta, countdownAnatomy, countdownMachine, countdownMeta, dateFieldAnatomy, dateFieldMachine, dateFieldMeta, datePickerAnatomy, datePickerCalendarProps, datePickerFieldEndProps, datePickerFieldProps, datePickerMachine, datePickerMeta, descriptionsAnatomy, descriptionsMeta, detectHotkeysPlatform, dialogAnatomy, dialogMachine, dialogMeta, distributeMasonry, downloadTriggerAnatomy, downloadTriggerMachine, downloadTriggerMeta, drawerAnatomy, drawerMachine, drawerMeta, dynamicInputAnatomy, dynamicInputMachine, dynamicInputMeta, editableAnatomy, editableMachine, editableMeta, ellipsisAnatomy, ellipsisMachine, ellipsisMeta, emptyStateAnatomy, emptyStateMeta, fieldAnatomy, fieldMeta, fieldsetAnatomy, fieldsetMeta, fileUploadAnatomy, fileUploadMachine, fileUploadMeta, flexAnatomy, flexMeta, floatButtonAnatomy, floatButtonMeta, floatingPanelAnatomy, floatingPanelMachine, floatingPanelMeta, formAnatomy, formMachine, formMeta, gradientTextAnatomy, gradientTextMeta, gridAnatomy, gridMeta, heatmapAnatomy, heatmapMachine, heatmapMeta, highlightAnatomy, highlightMeta, hotkeysAnatomy, hotkeysMeta, hoverCardAnatomy, hoverCardMachine, hoverCardMeta, iconAnatomy, iconMeta, iconWrapperAnatomy, iconWrapperMeta, imageAnatomy, imageCropperAnatomy, imageCropperMachine, imageCropperMeta, imageMachine, imageMeta, imageViewerAnatomy, imageViewerCounterText, imageViewerMachine, imageViewerMeta, infiniteScrollAnatomy, infiniteScrollMachine, infiniteScrollMeta, isOverflowing, isTimerUnit, jsonViewerAnatomy, jsonViewerMachine, jsonViewerMeta, layoutAnatomy, layoutMachine, layoutMeta, listAnatomy, listMeta, listboxAnatomy, listboxMachine, listboxMeta, loadingBarAnatomy, loadingBarMachine, loadingBarMeta, logAnatomy, logMeta, marqueeAnatomy, marqueeMeta, masonryAnatomy, masonryMeta, mentionAnatomy, mentionMachine, mentionMeta, menuAnatomy, menuMachine, menuMeta, menubarAnatomy, menubarMachine, menubarMeta, navigationMenuAnatomy, navigationMenuMachine, navigationMenuMeta, notificationAnatomy, notificationMachine, notificationMeta, numberAnimationAnatomy, numberAnimationMachine, numberAnimationMeta, numberFieldAnatomy, numberFieldMachine, numberFieldMeta, pageHeaderAnatomy, pageHeaderMeta, paginationAnatomy, paginationMachine, paginationMeta, passwordInputAnatomy, passwordInputMachine, passwordInputMeta, pinInputAnatomy, pinInputMachine, pinInputMeta, popconfirmAnatomy, popconfirmMeta, popoverAnatomy, popoverMachine, popoverMeta, popselectAnatomy, popselectInitialFocus, popselectMeta, progressAnatomy, progressMeta, qrCodeAnatomy, qrCodeMeta, radioGroupAnatomy, radioGroupMachine, radioGroupMeta, ratingAnatomy, ratingMachine, ratingMeta, resolveMasonryColumns, resultAnatomy, resultMeta, scrollAreaAnatomy, scrollAreaMeta, scrollAreaScrollbarProps, scrollbarAnatomy, scrollbarMachine, scrollbarMeta, segmentedAnatomy, segmentedMachine, segmentedMeta, selectAnatomy, selectMachine, selectMeta, separatorAnatomy, separatorMeta, sideNavAnatomy, sideNavMachine, sideNavMeta, signaturePadAnatomy, signaturePadMachine, signaturePadMeta, skeletonAnatomy, skeletonMeta, sliderAnatomy, sliderMachine, sliderMeta, spaceAnatomy, spaceMeta, spinnerAnatomy, spinnerMeta, splitterAnatomy, splitterMachine, splitterMeta, statisticAnatomy, statisticMeta, stepsAnatomy, stepsMachine, stepsMeta, switchAnatomy, switchMachine, switchMeta, tableAnatomy, tableMachine, tableMeta, tabsAnatomy, tabsMachine, tabsMeta, tagAnatomy, tagMachine, tagMeta, tagsInputAnatomy, tagsInputMachine, tagsInputMeta, textFieldAnatomy, textFieldMachine, textFieldMeta, threadAnatomy, threadMachine, threadMeta, timeAnatomy, timeFieldAnatomy, timeFieldMachine, timeFieldMeta, timeMeta, timePickerAnatomy, timePickerMachine, timePickerMeta, timelineAnatomy, timelineMeta, timerAnatomy, timerMachine, timerMeta, toastAnatomy, toastMachine, toastMeta, toggleAnatomy, toggleGroupAnatomy, toggleGroupMachine, toggleGroupMeta, toggleMachine, toggleMeta, toolbarAnatomy, toolbarMachine, toolbarMeta, tooltipAnatomy, tooltipMachine, tooltipMeta, tourAnatomy, tourMachine, tourMeta, transferAnatomy, transferFocusKey, transferMachine, transferMeta, treeAnatomy, treeMachine, treeMeta, treeSelectAnatomy, treeSelectMachine, treeSelectMeta, typographyAnatomy, typographyMeta, virtualizerAnatomy, virtualizerMachine, virtualizerMeta, watermarkAnatomy, watermarkMeta } from "@xihan-ui/headless";
5
5
  import { DATA_PART, DATA_SCOPE, DIAGNOSTIC_CODES, VERSION, createCounterIdGenerator, createRuntimeConfig, createScope, getDiagnostics, isDev, reportDiagnostic } from "@xihan-ui/kernel";
6
6
  import { ITEM_VALUE_ATTR, declaredItemDisabled, isItemDisabled } from "@xihan-ui/behavior";
7
7
  import { findDeprecatedPart, startDeprecationScan } from "@xihan-ui/kernel/deprecations";
@@ -9,42 +9,6 @@ import { checkLockstepVersion, printMetadataBannerOnce, registerRuntimeHost } fr
9
9
  import { attachCssExit, createPresence } from "@xihan-ui/behavior/presence";
10
10
  import { createPositionEngine } from "@xihan-ui/position";
11
11
  import { createHighlighter } from "@xihan-ui/code-highlight";
12
- //#region src/overlay-exit.ts
13
- function createOverlayExit(options) {
14
- let disposed = false;
15
- let node = null;
16
- let detach;
17
- const presence = createPresence({
18
- config: options.config,
19
- open: options.open,
20
- onRenderedChange: (rendered) => {
21
- if (!rendered && !disposed) options.onExitComplete();
22
- }
23
- });
24
- return {
25
- get visible() {
26
- return !disposed && presence.rendered;
27
- },
28
- track(next) {
29
- if (disposed || next === node) return;
30
- node = next;
31
- detach?.();
32
- detach = next ? attachCssExit(next, presence) : void 0;
33
- },
34
- update(open) {
35
- if (!disposed) presence.update(open);
36
- },
37
- dispose() {
38
- if (disposed) return;
39
- disposed = true;
40
- detach?.();
41
- detach = void 0;
42
- node = null;
43
- presence.dispose();
44
- }
45
- };
46
- }
47
- //#endregion
48
12
  //#region src/dom/part-contract.ts
49
13
  /**
50
14
  * 比对已发现的角色节点与契约:缺必需 part 报 error,出现解剖外的 part 名报 warn。
@@ -406,6 +370,42 @@ var XhElement = class extends XhReactiveElement {
406
370
  }
407
371
  };
408
372
  //#endregion
373
+ //#region src/overlay-exit.ts
374
+ function createOverlayExit(options) {
375
+ let disposed = false;
376
+ let node = null;
377
+ let detach;
378
+ const presence = createPresence({
379
+ config: options.config,
380
+ open: options.open,
381
+ onRenderedChange: (rendered) => {
382
+ if (!rendered && !disposed) options.onExitComplete();
383
+ }
384
+ });
385
+ return {
386
+ get visible() {
387
+ return !disposed && presence.rendered;
388
+ },
389
+ track(next) {
390
+ if (disposed || next === node) return;
391
+ node = next;
392
+ detach?.();
393
+ detach = next ? attachCssExit(next, presence) : void 0;
394
+ },
395
+ update(open) {
396
+ if (!disposed) presence.update(open);
397
+ },
398
+ dispose() {
399
+ if (disposed) return;
400
+ disposed = true;
401
+ detach?.();
402
+ detach = void 0;
403
+ node = null;
404
+ presence.dispose();
405
+ }
406
+ };
407
+ }
408
+ //#endregion
409
409
  //#region src/elements/accordion.ts
410
410
  const ITEM_SELECTOR$5 = "[data-xh-part=\"item\"]";
411
411
  /**
@@ -516,7 +516,7 @@ var XhAccordionElement = class extends XhElement {
516
516
  };
517
517
  //#endregion
518
518
  //#region src/elements/affix.ts
519
- const NUMBER_CONVERTER$56 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
519
+ const NUMBER_CONVERTER$57 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
520
520
  /**
521
521
  * `<xh-affix>` —— 吸附行为宿主:滚过判定线就把 content 钉在滚动容器可视区的边上。
522
522
  *
@@ -539,11 +539,11 @@ var XhAffixElement = class extends XhElement {
539
539
  };
540
540
  static properties = {
541
541
  topOffset: {
542
- converter: NUMBER_CONVERTER$56,
542
+ converter: NUMBER_CONVERTER$57,
543
543
  attribute: "offset-top"
544
544
  },
545
545
  bottomOffset: {
546
- converter: NUMBER_CONVERTER$56,
546
+ converter: NUMBER_CONVERTER$57,
547
547
  attribute: "offset-bottom"
548
548
  },
549
549
  target: { attribute: false }
@@ -645,7 +645,7 @@ var XhAlertElement = class extends XhElement {
645
645
  //#endregion
646
646
  //#region src/elements/anchor.ts
647
647
  const STRING_CONVERTER$95 = { fromAttribute: (v) => v ?? void 0 };
648
- const NUMBER_CONVERTER$55 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
648
+ const NUMBER_CONVERTER$56 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
649
649
  const BOOLEAN_CONVERTER$68 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
650
650
  /**
651
651
  * `<xh-anchor>` —— 锚点导航行为宿主,激活项由机器的滚动观察器结算,
@@ -682,7 +682,7 @@ var XhAnchorElement = class extends XhElement {
682
682
  converter: STRING_CONVERTER$95,
683
683
  attribute: "default-value"
684
684
  },
685
- offset: { converter: NUMBER_CONVERTER$55 },
685
+ offset: { converter: NUMBER_CONVERTER$56 },
686
686
  smooth: { converter: BOOLEAN_CONVERTER$68 },
687
687
  orientation: { converter: STRING_CONVERTER$95 },
688
688
  direction: {
@@ -846,7 +846,7 @@ var XhAvatarGroupElement = class extends XhElement {
846
846
  //#endregion
847
847
  //#region src/elements/back-top.ts
848
848
  const STRING_CONVERTER$93 = { fromAttribute: (v) => v ?? void 0 };
849
- const NUMBER_CONVERTER$54 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
849
+ const NUMBER_CONVERTER$55 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
850
850
  /**
851
851
  * `<xh-back-top>` —— 回到顶部行为宿主:滚动量过线时露出按钮,点它滚回顶部。
852
852
  *
@@ -870,7 +870,7 @@ var XhBackTopElement = class extends XhElement {
870
870
  };
871
871
  static properties = {
872
872
  visibilityHeight: {
873
- converter: NUMBER_CONVERTER$54,
873
+ converter: NUMBER_CONVERTER$55,
874
874
  attribute: "visibility-height"
875
875
  },
876
876
  behavior: { converter: STRING_CONVERTER$93 },
@@ -915,18 +915,22 @@ var XhBackTopElement = class extends XhElement {
915
915
  //#endregion
916
916
  //#region src/elements/badge.ts
917
917
  /**
918
- * `<xh-badge>` —— 徽标展示宿主,无状态机,外观来自 variant 属性。
918
+ * `<xh-badge>` —— 角标宿主,无状态机。
919
+ *
920
+ * 被标记的东西写进 root,角标本身写进 indicator;角标是挂在别的元素角上的一枚标记,
921
+ * 行内的状态药丸请用 `<xh-tag>`。
919
922
  *
920
923
  * @customElement xh-badge
921
- * @attr {'solid'|'subtle'|'outline'} variant - 视觉变体
924
+ * @attr {'top-end'|'top-start'|'bottom-end'|'bottom-start'} placement - 挂在哪个角上,默认 top-end
922
925
  * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气
923
926
  * @attr {'sm'|'md'|'lg'} size - 尺寸
924
927
  * @attr {number} count - 计数:给了它徽标就自己出数字,超过 max 写成「max+」;节点已有内容时以内容为准
925
928
  * @attr {number} max - 计数上限,默认 99
926
929
  * @attr {boolean} show-zero - 计数为 0 时也显示,默认不显示
927
930
  * @attr {boolean} dot - 只出一个点,不出数字
928
- * @attr {string} label - 读屏怎么念这枚徽标,例如「3 条未读」
929
- * @csspart root - 承载 data-scope/data-part/data-* 的展示节点
931
+ * @attr {string} label - 读屏怎么念这枚角标,例如「3 条未读」
932
+ * @csspart root - 锚点:被标记的那个东西放进它里面
933
+ * @csspart indicator - 角标本身,绝对定位在 root 的某个角上
930
934
  */
931
935
  var XhBadgeElement = class extends XhElement {
932
936
  static partContract = {
@@ -934,7 +938,7 @@ var XhBadgeElement = class extends XhElement {
934
938
  meta: badgeMeta
935
939
  };
936
940
  static properties = {
937
- variant: { converter: { fromAttribute: (v) => v ?? void 0 } },
941
+ placement: { converter: { fromAttribute: (v) => v ?? void 0 } },
938
942
  tone: { converter: { fromAttribute: (v) => v ?? void 0 } },
939
943
  size: { converter: { fromAttribute: (v) => v ?? void 0 } },
940
944
  count: { converter: { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) } },
@@ -950,7 +954,7 @@ var XhBadgeElement = class extends XhElement {
950
954
  const root = this.getPart("root");
951
955
  if (!root) return;
952
956
  const api = connectBadge(this.configured("badge", {
953
- variant: this.variant,
957
+ placement: this.placement,
954
958
  tone: this.tone,
955
959
  size: this.size,
956
960
  count: this.count,
@@ -960,7 +964,10 @@ var XhBadgeElement = class extends XhElement {
960
964
  label: this.label
961
965
  }), wcNormalize);
962
966
  this.spreader.spread(root, api.getRootProps());
963
- if (api.text && !root.textContent?.trim()) root.textContent = api.text;
967
+ const indicator = this.getPart("indicator");
968
+ if (!indicator) return;
969
+ this.spreader.spread(indicator, api.getIndicatorProps());
970
+ if (api.text && !indicator.textContent?.trim()) indicator.textContent = api.text;
964
971
  }
965
972
  };
966
973
  //#endregion
@@ -1129,7 +1136,7 @@ var XhButtonGroupElement = class extends XhElement {
1129
1136
  //#region src/elements/calendar.ts
1130
1137
  const STRING_CONVERTER$91 = { fromAttribute: (v) => v ?? void 0 };
1131
1138
  const BOOLEAN_CONVERTER$67 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
1132
- const NUMBER_CONVERTER$53 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
1139
+ const NUMBER_CONVERTER$54 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
1133
1140
  /** 作者写的面板下标;写坏了或没写按 0 算。 */
1134
1141
  function declaredIndex$6(el, fallback = 0) {
1135
1142
  const raw = el?.getAttribute("index")?.trim();
@@ -1241,7 +1248,7 @@ var XhCalendarElement = class extends XhElement {
1241
1248
  attribute: "week-selection"
1242
1249
  },
1243
1250
  visibleCount: {
1244
- converter: NUMBER_CONVERTER$53,
1251
+ converter: NUMBER_CONVERTER$54,
1245
1252
  attribute: "visible-count"
1246
1253
  },
1247
1254
  isDateUnavailable: { attribute: false }
@@ -1425,7 +1432,7 @@ var XhCardElement = class extends XhElement {
1425
1432
  //#endregion
1426
1433
  //#region src/elements/carousel.ts
1427
1434
  const STRING_CONVERTER$90 = { fromAttribute: (v) => v ?? void 0 };
1428
- const NUMBER_CONVERTER$52 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
1435
+ const NUMBER_CONVERTER$53 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
1429
1436
  const BOOLEAN_CONVERTER$66 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
1430
1437
  /**
1431
1438
  * autoplay 布尔或毫秒两用:缺席 = undefined,`autoplay` / `autoplay="true"` = 默认间隔,
@@ -1480,21 +1487,21 @@ var XhCarouselElement = class extends XhElement {
1480
1487
  meta: carouselMeta
1481
1488
  };
1482
1489
  static properties = {
1483
- page: { converter: NUMBER_CONVERTER$52 },
1490
+ page: { converter: NUMBER_CONVERTER$53 },
1484
1491
  defaultPage: {
1485
- converter: NUMBER_CONVERTER$52,
1492
+ converter: NUMBER_CONVERTER$53,
1486
1493
  attribute: "default-page"
1487
1494
  },
1488
1495
  slideCount: {
1489
- converter: NUMBER_CONVERTER$52,
1496
+ converter: NUMBER_CONVERTER$53,
1490
1497
  attribute: "slide-count"
1491
1498
  },
1492
1499
  slidesPerPage: {
1493
- converter: NUMBER_CONVERTER$52,
1500
+ converter: NUMBER_CONVERTER$53,
1494
1501
  attribute: "slides-per-page"
1495
1502
  },
1496
1503
  slidesPerMove: {
1497
- converter: NUMBER_CONVERTER$52,
1504
+ converter: NUMBER_CONVERTER$53,
1498
1505
  attribute: "slides-per-move"
1499
1506
  },
1500
1507
  orientation: { converter: STRING_CONVERTER$90 },
@@ -1557,9 +1564,126 @@ var XhCarouselElement = class extends XhElement {
1557
1564
  }
1558
1565
  };
1559
1566
  //#endregion
1567
+ //#region src/runtime/scrollbars-controller.ts
1568
+ const DEFAULT_AXES = ["vertical"];
1569
+ var ScrollbarsController = class {
1570
+ host;
1571
+ options;
1572
+ axes;
1573
+ ctrls = /* @__PURE__ */ new Map();
1574
+ nodes = /* @__PURE__ */ new Map();
1575
+ spreader = createSpreader();
1576
+ /** 几条轴共用一个 scope:id 由它派生,同一套条子归在一起。 */
1577
+ scope = createScope(null, createCounterIdGenerator());
1578
+ /** 此刻这套节点挂在哪个壳上;壳换了就整套重建。 */
1579
+ mountedShell = null;
1580
+ constructor(host, options) {
1581
+ this.host = host;
1582
+ this.options = options;
1583
+ this.axes = options.axes ?? DEFAULT_AXES;
1584
+ }
1585
+ /** 宿主在自己的 wire() 末尾调一次:建节点、建机器、把 connect 产出打上去。 */
1586
+ wire() {
1587
+ if (!this.ensureNodes()) return;
1588
+ this.ensureMachines();
1589
+ const both = this.both();
1590
+ for (const axis of this.axes) {
1591
+ const service = this.serviceOf(axis);
1592
+ const nodes = this.nodes.get(axis);
1593
+ if (!service || !nodes) continue;
1594
+ const api = connectScrollbar(service, wcNormalize);
1595
+ this.spreader.spread(nodes.root, api.getRootProps());
1596
+ this.spreader.spread(nodes.track, api.getTrackProps());
1597
+ this.spreader.spread(nodes.thumb, api.getThumbProps());
1598
+ if (nodes.corner) this.spreader.spread(nodes.corner, {
1599
+ ...api.getCornerProps(),
1600
+ hidden: both ? void 0 : true
1601
+ });
1602
+ }
1603
+ }
1604
+ /**
1605
+ * 节点就位之后才建机器。
1606
+ * 机器一跑起来就去解析滚动容器,解析到就给它打 data-xh-scrollbar(皮肤据此把原生条藏成零宽),
1607
+ * 解析不到则投一条 scrollbar.missing-scrollable。
1608
+ * 壳不在场时一条自绘条都没建出来,这两件事都不该发生。
1609
+ */
1610
+ ensureMachines() {
1611
+ if (this.ctrls.size) return;
1612
+ for (const axis of this.axes) this.ctrls.set(axis, new MachineController(this.host, scrollbarMachine, () => this.machineProps(axis), {
1613
+ scope: this.scope,
1614
+ onBuilt: (svc) => this.injectRefs(svc, axis)
1615
+ }));
1616
+ }
1617
+ /** 机器建起来之前 service 还不存在,取用处一律先问一句。 */
1618
+ serviceOf(axis) {
1619
+ return this.ctrls.get(axis)?.service ?? null;
1620
+ }
1621
+ machineProps(axis) {
1622
+ return {
1623
+ ...this.options.props?.(),
1624
+ orientation: axis,
1625
+ gutter: this.both()
1626
+ };
1627
+ }
1628
+ /**
1629
+ * 两条轴都在场:各自在末端让出交叉口那一格,只有一条时不让,免得滑块行程平白短一截。
1630
+ * 判据不走 connect:那里就要读 gutter,读回来会绕成环,所以直接读作者给的 props 与量到的尺寸。
1631
+ */
1632
+ both() {
1633
+ if (this.axes.length < 2) return false;
1634
+ const given = this.options.props?.();
1635
+ const type = given?.type ?? SCROLLBAR_DEFAULT_TYPE;
1636
+ for (const axis of this.axes) {
1637
+ const service = this.serviceOf(axis);
1638
+ if (!service) return false;
1639
+ if (service.context.get("coarse") && !given?.forceVisible || !(type === "always" || isOverflowing(service.context.get("metrics")))) return false;
1640
+ }
1641
+ return true;
1642
+ }
1643
+ injectRefs(service, axis) {
1644
+ service.refs.set("getScrollableEl", this.options.scrollable);
1645
+ service.refs.set("getTrackEl", () => this.nodes.get(axis)?.track ?? null);
1646
+ service.refs.set("getRootEl", () => this.nodes.get(axis)?.root ?? null);
1647
+ }
1648
+ /** 按当前壳建一套条子;壳没到就早退,壳换了就把旧那套摘掉重建。 */
1649
+ ensureNodes() {
1650
+ const shell = this.options.shell();
1651
+ if (!shell) return false;
1652
+ if (this.mountedShell === shell) return true;
1653
+ for (const nodes of this.nodes.values()) {
1654
+ this.spreader.release(nodes.root);
1655
+ this.spreader.release(nodes.track);
1656
+ this.spreader.release(nodes.thumb);
1657
+ if (nodes.corner) this.spreader.release(nodes.corner);
1658
+ nodes.root.remove();
1659
+ }
1660
+ this.nodes.clear();
1661
+ const doc = this.host.ownerDocument;
1662
+ for (const axis of this.axes) {
1663
+ const root = doc.createElement("div");
1664
+ const track = doc.createElement("div");
1665
+ const thumb = doc.createElement("div");
1666
+ track.append(thumb);
1667
+ root.append(track);
1668
+ const corner = this.axes.length > 1 && axis === "vertical" ? doc.createElement("div") : null;
1669
+ if (corner) root.append(corner);
1670
+ shell.append(root);
1671
+ this.nodes.set(axis, {
1672
+ root,
1673
+ track,
1674
+ thumb,
1675
+ corner
1676
+ });
1677
+ }
1678
+ this.mountedShell = shell;
1679
+ this.host.requestUpdate();
1680
+ return true;
1681
+ }
1682
+ };
1683
+ //#endregion
1560
1684
  //#region src/elements/cascader.ts
1561
1685
  const STRING_CONVERTER$89 = { fromAttribute: (v) => v ?? void 0 };
1562
- const NUMBER_CONVERTER$51 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
1686
+ const NUMBER_CONVERTER$52 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
1563
1687
  const BOOLEAN_CONVERTER$65 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
1564
1688
  /** 条目一系的归属容器:文本与勾选标记向上找最近的那个条目。 */
1565
1689
  const ITEM_SELECTOR$4 = "[data-xh-part=\"item\"]";
@@ -1663,7 +1787,7 @@ var XhCascaderElement = class extends XhElement {
1663
1787
  separator: { converter: STRING_CONVERTER$89 },
1664
1788
  translations: { attribute: false },
1665
1789
  placement: { converter: STRING_CONVERTER$89 },
1666
- offset: { converter: NUMBER_CONVERTER$51 },
1790
+ offset: { converter: NUMBER_CONVERTER$52 },
1667
1791
  loop: { converter: BOOLEAN_CONVERTER$65 },
1668
1792
  direction: {
1669
1793
  converter: STRING_CONVERTER$89,
@@ -1698,6 +1822,17 @@ var XhCascaderElement = class extends XhElement {
1698
1822
  scope: this.cascaderScope,
1699
1823
  onBuilt: (svc) => this.injectRefs(svc)
1700
1824
  });
1825
+ /**
1826
+ * 列区的自绘条:与 content 同级挂在已经 fixed 的 positioner 上。
1827
+ * 只摆横的——列多到放不下时整体横向滚动,纵向溢出归每一列自己;
1828
+ * 横条的正负按排版方向算,而组件不读计算样式,把作者写的那份显式交过去。
1829
+ */
1830
+ bars = new ScrollbarsController(this, {
1831
+ shell: () => this.getPart("positioner"),
1832
+ scrollable: () => this.getPart("content"),
1833
+ axes: ["horizontal"],
1834
+ props: () => ({ dir: this.direction })
1835
+ });
1701
1836
  machineProps() {
1702
1837
  return {
1703
1838
  collection: this.collection,
@@ -1740,7 +1875,7 @@ var XhCascaderElement = class extends XhElement {
1740
1875
  return this.config.layerRegistry.register({
1741
1876
  kind: "popover",
1742
1877
  node: () => this.getPart("content"),
1743
- branches: () => [this.getPart("trigger")].filter(Boolean),
1878
+ branches: () => [this.getPart("trigger"), this.getPart("positioner")].filter(Boolean),
1744
1879
  isModal: () => false,
1745
1880
  setModal: () => {},
1746
1881
  surfaces: () => []
@@ -1875,6 +2010,7 @@ var XhCascaderElement = class extends XhElement {
1875
2010
  this.setPartHidden(el, this.levelOf(el, position) >= api.columns.length);
1876
2011
  });
1877
2012
  for (const el of this.getParts("item")) this.setPartHidden(el, !api.isVisible(this.itemOf(el).value));
2013
+ this.bars.wire();
1878
2014
  }
1879
2015
  disconnectedCallback() {
1880
2016
  super.disconnectedCallback();
@@ -2123,7 +2259,7 @@ var XhCheckboxGroupElement = class extends XhElement {
2123
2259
  //#endregion
2124
2260
  //#region src/elements/clipboard.ts
2125
2261
  const STRING_CONVERTER$87 = { fromAttribute: (v) => v ?? void 0 };
2126
- const NUMBER_CONVERTER$50 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
2262
+ const NUMBER_CONVERTER$51 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
2127
2263
  /**
2128
2264
  * `<xh-clipboard>` —— Light-DOM 行为宿主,跑 clipboard 机器并把 connect 产出打到角色节点上。
2129
2265
  *
@@ -2151,7 +2287,7 @@ var XhClipboardElement = class extends XhElement {
2151
2287
  };
2152
2288
  static properties = {
2153
2289
  value: { converter: STRING_CONVERTER$87 },
2154
- timeout: { converter: NUMBER_CONVERTER$50 }
2290
+ timeout: { converter: NUMBER_CONVERTER$51 }
2155
2291
  };
2156
2292
  notifyStatus = (details) => {
2157
2293
  this.dispatchEvent(new CustomEvent("status-change", {
@@ -2366,7 +2502,7 @@ var XhCollapsibleElement = class extends XhElement {
2366
2502
  //#endregion
2367
2503
  //#region src/elements/color-picker.ts
2368
2504
  const STRING_CONVERTER$85 = { fromAttribute: (v) => v ?? void 0 };
2369
- const NUMBER_CONVERTER$49 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
2505
+ const NUMBER_CONVERTER$50 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
2370
2506
  const BOOLEAN_CONVERTER$62 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
2371
2507
  /** 预设色板写成逗号分隔(swatches="#ff0000,#00ff00"),空串当没写。 */
2372
2508
  const STRING_LIST_CONVERTER = { fromAttribute: (v) => {
@@ -2396,6 +2532,7 @@ const STRING_LIST_CONVERTER = { fromAttribute: (v) => {
2396
2532
  * @attr {boolean} read-only - 只读:浮层照开,进去只是改不动
2397
2533
  * @attr {boolean} alpha - 带透明度,默认关;关掉时透明度那条滑杆与输入框整条禁用
2398
2534
  * @attr {string} swatches - 预设色板,逗号分隔(如 "#ff0000,#00ff00")
2535
+ * @attr {'sm'|'md'|'lg'} size - 尺寸
2399
2536
  * @attr {'ltr'|'rtl'} dir - 文字方向,只改写横轴上左右两键与指针的语义,默认 ltr
2400
2537
  * @attr {string} placement - 首选放置位,默认 bottom-start;避让后的实际位写在 data-placement 上
2401
2538
  * @attr {number} offset - 浮层与锚点的间距(px)
@@ -2446,12 +2583,13 @@ var XhColorPickerElement = class extends XhElement {
2446
2583
  alpha: { converter: BOOLEAN_CONVERTER$62 },
2447
2584
  swatches: { converter: STRING_LIST_CONVERTER },
2448
2585
  name: { converter: STRING_CONVERTER$85 },
2586
+ size: { converter: STRING_CONVERTER$85 },
2449
2587
  direction: {
2450
2588
  converter: STRING_CONVERTER$85,
2451
2589
  attribute: "dir"
2452
2590
  },
2453
2591
  placement: { converter: STRING_CONVERTER$85 },
2454
- offset: { converter: NUMBER_CONVERTER$49 },
2592
+ offset: { converter: NUMBER_CONVERTER$50 },
2455
2593
  translations: { attribute: false }
2456
2594
  };
2457
2595
  idGen = createCounterIdGenerator();
@@ -2478,6 +2616,11 @@ var XhColorPickerElement = class extends XhElement {
2478
2616
  scope: this.pickerScope,
2479
2617
  onBuilt: (svc) => this.injectRefs(svc)
2480
2618
  });
2619
+ /** 面板的自绘条:与 content 同级挂在已经 fixed 的 positioner 上 */
2620
+ bars = new ScrollbarsController(this, {
2621
+ shell: () => this.getPart("positioner"),
2622
+ scrollable: () => this.getPart("content")
2623
+ });
2481
2624
  machineProps() {
2482
2625
  return {
2483
2626
  value: this.value,
@@ -2490,6 +2633,7 @@ var XhColorPickerElement = class extends XhElement {
2490
2633
  alpha: this.alpha ?? false,
2491
2634
  swatches: this.swatches,
2492
2635
  name: this.name,
2636
+ size: this.size,
2493
2637
  dir: this.direction,
2494
2638
  placement: this.placement,
2495
2639
  offset: this.offset,
@@ -2510,7 +2654,7 @@ var XhColorPickerElement = class extends XhElement {
2510
2654
  return this.config.layerRegistry.register({
2511
2655
  kind: "popover",
2512
2656
  node: () => this.getPart("content"),
2513
- branches: () => [this.getPart("trigger")].filter(Boolean),
2657
+ branches: () => [this.getPart("trigger"), this.getPart("positioner")].filter(Boolean),
2514
2658
  isModal: () => false,
2515
2659
  setModal: () => {},
2516
2660
  surfaces: () => []
@@ -2595,6 +2739,7 @@ var XhColorPickerElement = class extends XhElement {
2595
2739
  this.exit.track(this.getPart("content"));
2596
2740
  this.exit.update(api.open);
2597
2741
  this.setPartHidden(this.getPart("content"), !this.exit.visible);
2742
+ this.bars.wire();
2598
2743
  }
2599
2744
  disconnectedCallback() {
2600
2745
  super.disconnectedCallback();
@@ -2607,7 +2752,7 @@ var XhColorPickerElement = class extends XhElement {
2607
2752
  //#endregion
2608
2753
  //#region src/elements/combobox.ts
2609
2754
  const STRING_CONVERTER$84 = { fromAttribute: (v) => v ?? void 0 };
2610
- const NUMBER_CONVERTER$48 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
2755
+ const NUMBER_CONVERTER$49 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
2611
2756
  const BOOLEAN_CONVERTER$61 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
2612
2757
  /**
2613
2758
  * `<xh-combobox>` —— Light-DOM 行为宿主:作者写 root/label/control/input/trigger/positioner/content/item/...
@@ -2709,7 +2854,7 @@ var XhComboboxElement = class extends XhElement {
2709
2854
  attribute: "input-behavior"
2710
2855
  },
2711
2856
  placement: { converter: STRING_CONVERTER$84 },
2712
- offset: { converter: NUMBER_CONVERTER$48 },
2857
+ offset: { converter: NUMBER_CONVERTER$49 },
2713
2858
  variant: { converter: STRING_CONVERTER$84 },
2714
2859
  tone: { converter: STRING_CONVERTER$84 },
2715
2860
  size: { converter: STRING_CONVERTER$84 }
@@ -2745,6 +2890,11 @@ var XhComboboxElement = class extends XhElement {
2745
2890
  scope: this.comboboxScope,
2746
2891
  onBuilt: (svc) => this.injectRefs(svc)
2747
2892
  });
2893
+ /** 候选列表的自绘条:与 content 同级挂在已经 fixed 的 positioner 上 */
2894
+ bars = new ScrollbarsController(this, {
2895
+ shell: () => this.getPart("positioner"),
2896
+ scrollable: () => this.getPart("content")
2897
+ });
2748
2898
  /** 作者声明的条目禁用,只认首见那一份;给了 collection 时用它,否则现读 */
2749
2899
  declaredDisabled = createDeclaredDisabled();
2750
2900
  machineProps() {
@@ -2789,7 +2939,7 @@ var XhComboboxElement = class extends XhElement {
2789
2939
  return this.config.layerRegistry.register({
2790
2940
  kind: "popover",
2791
2941
  node: () => this.getPart("content"),
2792
- branches: () => [this.getPart("control")].filter(Boolean),
2942
+ branches: () => [this.getPart("control"), this.getPart("positioner")].filter(Boolean),
2793
2943
  isModal: () => false,
2794
2944
  setModal: () => {},
2795
2945
  surfaces: () => []
@@ -2858,6 +3008,7 @@ var XhComboboxElement = class extends XhElement {
2858
3008
  this.setPartHidden(this.getPart("content"), !this.exit.visible);
2859
3009
  this.setPartHidden(this.getPart("empty"), !api.empty);
2860
3010
  if (this.ctrl.service.getStatus() === "Started") this.ctrl.service.send({ type: "ITEMS.SYNC" });
3011
+ this.bars.wire();
2861
3012
  }
2862
3013
  disconnectedCallback() {
2863
3014
  super.disconnectedCallback();
@@ -3009,7 +3160,7 @@ var XhConfigElement = class extends XhReactiveElement {
3009
3160
  //#endregion
3010
3161
  //#region src/elements/context-menu.ts
3011
3162
  const STRING_CONVERTER$81 = { fromAttribute: (v) => v ?? void 0 };
3012
- const NUMBER_CONVERTER$47 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
3163
+ const NUMBER_CONVERTER$48 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
3013
3164
  const BOOLEAN_CONVERTER$59 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
3014
3165
  /**
3015
3166
  * `<xh-context-menu>` —— Light-DOM 行为宿主:作者写 root/trigger/positioner/content 与若干
@@ -3059,7 +3210,7 @@ var XhContextMenuElement = class extends XhElement {
3059
3210
  attribute: "default-open"
3060
3211
  },
3061
3212
  placement: { converter: STRING_CONVERTER$81 },
3062
- offset: { converter: NUMBER_CONVERTER$47 },
3213
+ offset: { converter: NUMBER_CONVERTER$48 },
3063
3214
  loop: { converter: BOOLEAN_CONVERTER$59 },
3064
3215
  typeahead: { converter: BOOLEAN_CONVERTER$59 },
3065
3216
  translations: { attribute: false },
@@ -3068,7 +3219,7 @@ var XhContextMenuElement = class extends XhElement {
3068
3219
  attribute: "dir"
3069
3220
  },
3070
3221
  longPressDelay: {
3071
- converter: NUMBER_CONVERTER$47,
3222
+ converter: NUMBER_CONVERTER$48,
3072
3223
  attribute: "long-press-delay"
3073
3224
  },
3074
3225
  tone: { converter: STRING_CONVERTER$81 },
@@ -3098,6 +3249,11 @@ var XhContextMenuElement = class extends XhElement {
3098
3249
  scope: this.menuScope,
3099
3250
  onBuilt: (svc) => this.injectRefs(svc)
3100
3251
  });
3252
+ /** 条目列表的自绘条:与 content 同级挂在已经 fixed 的 positioner 上 */
3253
+ bars = new ScrollbarsController(this, {
3254
+ shell: () => this.getPart("positioner"),
3255
+ scrollable: () => this.getPart("content")
3256
+ });
3101
3257
  /** 作者声明的条目禁用,只认首见那一份;给了 collection 时用它,否则现读 */
3102
3258
  declaredDisabled = createDeclaredDisabled();
3103
3259
  machineProps() {
@@ -3130,7 +3286,7 @@ var XhContextMenuElement = class extends XhElement {
3130
3286
  return this.config.layerRegistry.register({
3131
3287
  kind: "popover",
3132
3288
  node: () => this.getPart("content"),
3133
- branches: () => [this.getPart("trigger")].filter(Boolean),
3289
+ branches: () => [this.getPart("trigger"), this.getPart("positioner")].filter(Boolean),
3134
3290
  isModal: () => false,
3135
3291
  setModal: () => {},
3136
3292
  surfaces: () => []
@@ -3206,6 +3362,7 @@ var XhContextMenuElement = class extends XhElement {
3206
3362
  this.exit.track(content);
3207
3363
  this.exit.update(api.open);
3208
3364
  this.setPartHidden(content, !this.exit.visible);
3365
+ this.bars.wire();
3209
3366
  }
3210
3367
  disconnectedCallback() {
3211
3368
  super.disconnectedCallback();
@@ -3218,7 +3375,7 @@ var XhContextMenuElement = class extends XhElement {
3218
3375
  //#endregion
3219
3376
  //#region src/elements/countdown.ts
3220
3377
  const STRING_CONVERTER$80 = { fromAttribute: (v) => v ?? void 0 };
3221
- const NUMBER_CONVERTER$46 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
3378
+ const NUMBER_CONVERTER$47 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
3222
3379
  const BOOLEAN_CONVERTER$58 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
3223
3380
  /**
3224
3381
  * `<xh-countdown>` —— Light-DOM 行为宿主:作者写一个 root 角色节点,
@@ -3249,10 +3406,10 @@ var XhCountdownElement = class extends XhElement {
3249
3406
  meta: countdownMeta
3250
3407
  };
3251
3408
  static properties = {
3252
- value: { converter: NUMBER_CONVERTER$46 },
3409
+ value: { converter: NUMBER_CONVERTER$47 },
3253
3410
  format: { converter: STRING_CONVERTER$80 },
3254
3411
  active: { converter: BOOLEAN_CONVERTER$58 },
3255
- precision: { converter: NUMBER_CONVERTER$46 },
3412
+ precision: { converter: NUMBER_CONVERTER$47 },
3256
3413
  live: { converter: STRING_CONVERTER$80 }
3257
3414
  };
3258
3415
  notify = (details) => {
@@ -3454,7 +3611,7 @@ var XhDateFieldElement = class extends XhElement {
3454
3611
  //#endregion
3455
3612
  //#region src/elements/date-picker.ts
3456
3613
  const STRING_CONVERTER$78 = { fromAttribute: (v) => v ?? void 0 };
3457
- const NUMBER_CONVERTER$45 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
3614
+ const NUMBER_CONVERTER$46 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
3458
3615
  const BOOLEAN_CONVERTER$56 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
3459
3616
  /** 九块段位的名字,按段名声明时照它认。 */
3460
3617
  const SEGMENT_TYPES$2 = [
@@ -3517,7 +3674,9 @@ function declaredIndex$3(el, position) {
3517
3674
  * @attr {'day'|'month'|'quarter'|'year'} active-view - 受控:面板此刻钻到了哪一层;缺省跟着 view,每次展开都拨回去
3518
3675
  * @attr {boolean} week-selection - 周选:点任意一天选中它所在的整周(view=day 且区间模式下生效)
3519
3676
  * @prop {DatePickerPreset[]} presets - 快捷选项(数组只走 property):给了就在浮层里多出一列
3520
- * @attr {number} visible-count - 并排展示几页
3677
+ * @attr {number} visible-count - 并排展示几页;缺省单选 1,区间按两端定,同一页放得下就 1
3678
+ * @attr {boolean} fixed-weeks - 日历恒渲染六行,默认开;写 fixed-weeks="false" 关掉
3679
+ * @attr {string} default-focused-value - 初始聚焦日,同时决定展开时先落在哪一页
3521
3680
  * @attr {boolean} disabled - 整个控件禁用:trigger 转原生 disabled,段位退出 Tab 序
3522
3681
  * @attr {boolean} read-only - 只读:浮层照常展开、日历照常浏览,但选中值改不动
3523
3682
  * @attr {boolean} invalid - 校验失败标注
@@ -3608,9 +3767,17 @@ var XhDatePickerElement = class extends XhElement {
3608
3767
  },
3609
3768
  presets: { attribute: false },
3610
3769
  visibleCount: {
3611
- converter: NUMBER_CONVERTER$45,
3770
+ converter: NUMBER_CONVERTER$46,
3612
3771
  attribute: "visible-count"
3613
3772
  },
3773
+ fixedWeeks: {
3774
+ converter: BOOLEAN_CONVERTER$56,
3775
+ attribute: "fixed-weeks"
3776
+ },
3777
+ defaultFocusedValue: {
3778
+ converter: STRING_CONVERTER$78,
3779
+ attribute: "default-focused-value"
3780
+ },
3614
3781
  disabled: { converter: BOOLEAN_CONVERTER$56 },
3615
3782
  readOnly: {
3616
3783
  converter: BOOLEAN_CONVERTER$56,
@@ -3628,7 +3795,7 @@ var XhDatePickerElement = class extends XhElement {
3628
3795
  tone: { converter: STRING_CONVERTER$78 },
3629
3796
  size: { converter: STRING_CONVERTER$78 },
3630
3797
  placement: { converter: STRING_CONVERTER$78 },
3631
- offset: { converter: NUMBER_CONVERTER$45 },
3798
+ offset: { converter: NUMBER_CONVERTER$46 },
3632
3799
  closeOnSelect: {
3633
3800
  converter: BOOLEAN_CONVERTER$56,
3634
3801
  attribute: "close-on-select"
@@ -3689,6 +3856,11 @@ var XhDatePickerElement = class extends XhElement {
3689
3856
  });
3690
3857
  fieldCtrl = new MachineController(this, dateFieldMachine, () => datePickerFieldProps(this.rootCtrl.service), { scope: this.pickerScope });
3691
3858
  fieldEndCtrl = new MachineController(this, dateFieldMachine, () => datePickerFieldEndProps(this.rootCtrl.service), { scope: this.pickerScope });
3859
+ /** 浮层面板的自绘条:与 content 同级挂在已经 fixed 的 positioner 上 */
3860
+ bars = new ScrollbarsController(this, {
3861
+ shell: () => this.getPart("positioner"),
3862
+ scrollable: () => this.getPart("content")
3863
+ });
3692
3864
  services() {
3693
3865
  return {
3694
3866
  root: this.rootCtrl.service,
@@ -3714,6 +3886,8 @@ var XhDatePickerElement = class extends XhElement {
3714
3886
  weekSelection: this.weekSelection,
3715
3887
  presets: this.presets,
3716
3888
  visibleCount: this.visibleCount,
3889
+ fixedWeeks: this.fixedWeeks,
3890
+ defaultFocusedValue: this.defaultFocusedValue,
3717
3891
  isDateUnavailable: this.isDateUnavailable,
3718
3892
  disabled: this.disabled ?? false,
3719
3893
  readOnly: this.readOnly ?? false,
@@ -3748,7 +3922,7 @@ var XhDatePickerElement = class extends XhElement {
3748
3922
  return this.config.layerRegistry.register({
3749
3923
  kind: "popover",
3750
3924
  node: () => this.getPart("content"),
3751
- branches: () => [this.getPart("control")].filter(Boolean),
3925
+ branches: () => [this.getPart("control"), this.getPart("positioner")].filter(Boolean),
3752
3926
  isModal: () => false,
3753
3927
  setModal: () => {},
3754
3928
  surfaces: () => []
@@ -3899,6 +4073,7 @@ var XhDatePickerElement = class extends XhElement {
3899
4073
  this.exit.track(this.getPart("content"));
3900
4074
  this.exit.update(api.open);
3901
4075
  this.setPartHidden(this.getPart("content"), !this.exit.visible);
4076
+ this.bars.wire();
3902
4077
  }
3903
4078
  disconnectedCallback() {
3904
4079
  super.disconnectedCallback();
@@ -4348,7 +4523,7 @@ var XhDrawerElement = class extends XhElement {
4348
4523
  };
4349
4524
  //#endregion
4350
4525
  //#region src/elements/dynamic-input.ts
4351
- const NUMBER_CONVERTER$44 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
4526
+ const NUMBER_CONVERTER$45 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
4352
4527
  const BOOLEAN_CONVERTER$52 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
4353
4528
  /** 作者写在行上的下标。缺席或写坏了就退回文档序——把行按顺序排下来本身就是声明。 */
4354
4529
  function declaredIndex$2(el, position) {
@@ -4391,8 +4566,8 @@ var XhDynamicInputElement = class extends XhElement {
4391
4566
  static properties = {
4392
4567
  value: { attribute: false },
4393
4568
  defaultValue: { attribute: false },
4394
- min: { converter: NUMBER_CONVERTER$44 },
4395
- max: { converter: NUMBER_CONVERTER$44 },
4569
+ min: { converter: NUMBER_CONVERTER$45 },
4570
+ max: { converter: NUMBER_CONVERTER$45 },
4396
4571
  createItem: { attribute: false },
4397
4572
  movable: { converter: BOOLEAN_CONVERTER$52 },
4398
4573
  disabled: { converter: BOOLEAN_CONVERTER$52 },
@@ -4450,7 +4625,7 @@ var XhDynamicInputElement = class extends XhElement {
4450
4625
  //#endregion
4451
4626
  //#region src/elements/editable.ts
4452
4627
  const STRING_CONVERTER$73 = { fromAttribute: (v) => v ?? void 0 };
4453
- const NUMBER_CONVERTER$43 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
4628
+ const NUMBER_CONVERTER$44 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
4454
4629
  const BOOLEAN_CONVERTER$51 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
4455
4630
  /**
4456
4631
  * `<xh-editable>` —— Light-DOM 行为宿主:作者写 root/label/area/preview/input/control
@@ -4518,7 +4693,7 @@ var XhEditableElement = class extends XhElement {
4518
4693
  },
4519
4694
  invalid: { converter: BOOLEAN_CONVERTER$51 },
4520
4695
  maxLength: {
4521
- converter: NUMBER_CONVERTER$43,
4696
+ converter: NUMBER_CONVERTER$44,
4522
4697
  attribute: "max-length"
4523
4698
  },
4524
4699
  name: { converter: STRING_CONVERTER$73 },
@@ -4644,7 +4819,7 @@ var XhEditableElement = class extends XhElement {
4644
4819
  };
4645
4820
  //#endregion
4646
4821
  //#region src/elements/ellipsis.ts
4647
- const NUMBER_CONVERTER$42 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
4822
+ const NUMBER_CONVERTER$43 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
4648
4823
  const TRISTATE_CONVERTER$1 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
4649
4824
  /**
4650
4825
  * `<xh-ellipsis>` —— 省略行为宿主:把一段文字夹在给定行数内,并如实报出它有没有被裁掉。
@@ -4672,7 +4847,7 @@ var XhEllipsisElement = class extends XhElement {
4672
4847
  meta: ellipsisMeta
4673
4848
  };
4674
4849
  static properties = {
4675
- lines: { converter: NUMBER_CONVERTER$42 },
4850
+ lines: { converter: NUMBER_CONVERTER$43 },
4676
4851
  expandable: { type: Boolean },
4677
4852
  expanded: { converter: TRISTATE_CONVERTER$1 },
4678
4853
  defaultExpanded: {
@@ -4893,7 +5068,7 @@ var XhFieldsetElement = class extends XhElement {
4893
5068
  //#endregion
4894
5069
  //#region src/elements/file-upload.ts
4895
5070
  const STRING_CONVERTER$70 = { fromAttribute: (v) => v ?? void 0 };
4896
- const NUMBER_CONVERTER$41 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
5071
+ const NUMBER_CONVERTER$42 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
4897
5072
  const BOOLEAN_CONVERTER$49 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
4898
5073
  /** 取作者写在条目上的 index,缺席或写坏了退回文档序。 */
4899
5074
  function declaredIndex$1(el, position) {
@@ -4963,15 +5138,15 @@ var XhFileUploadElement = class XhFileUploadElement extends XhElement {
4963
5138
  },
4964
5139
  accept: { converter: STRING_CONVERTER$70 },
4965
5140
  maxFiles: {
4966
- converter: NUMBER_CONVERTER$41,
5141
+ converter: NUMBER_CONVERTER$42,
4967
5142
  attribute: "max-files"
4968
5143
  },
4969
5144
  maxFileSize: {
4970
- converter: NUMBER_CONVERTER$41,
5145
+ converter: NUMBER_CONVERTER$42,
4971
5146
  attribute: "max-file-size"
4972
5147
  },
4973
5148
  minFileSize: {
4974
- converter: NUMBER_CONVERTER$41,
5149
+ converter: NUMBER_CONVERTER$42,
4975
5150
  attribute: "min-file-size"
4976
5151
  },
4977
5152
  disabled: { type: Boolean },
@@ -5161,13 +5336,14 @@ var XhFileUploadElement = class XhFileUploadElement extends XhElement {
5161
5336
  * 根上不写 role:容器只做排布,里面装的是列表还是一组按钮由作者自己声明。
5162
5337
  *
5163
5338
  * @customElement xh-flex
5164
- * @attr {'row'|'column'} direction - 主轴方向,缺省 row
5339
+ * @attr {'horizontal'|'vertical'} orientation - 主轴方向,缺省 horizontal
5340
+ * @attr {'row'|'column'} direction - 主轴方向的旧写法,两个都写时以 orientation 为准
5165
5341
  * @attr {'start'|'center'|'end'|'stretch'|'baseline'} align - 交叉轴对齐
5166
5342
  * @attr {'start'|'center'|'end'|'between'|'around'|'evenly'} justify - 主轴分布
5167
5343
  * @attr {'xs'|'sm'|'md'|'lg'|'xl'} gap - 子项间距档位,逐档对应一个间距令牌
5168
5344
  * @attr {boolean} wrap - 一行放不下时折行
5169
5345
  * @attr {boolean} inline - 容器按行内盒排版,宽度收到内容
5170
- * @csspart root - 排布容器,承载 data-direction / data-align / data-justify / data-gap / data-wrap / data-inline
5346
+ * @csspart root - 排布容器,承载 data-orientation / data-align / data-justify / data-gap / data-wrap / data-inline
5171
5347
  */
5172
5348
  var XhFlexElement = class extends XhElement {
5173
5349
  static partContract = {
@@ -5175,6 +5351,7 @@ var XhFlexElement = class extends XhElement {
5175
5351
  meta: flexMeta
5176
5352
  };
5177
5353
  static properties = {
5354
+ orientation: { converter: { fromAttribute: (v) => v ?? void 0 } },
5178
5355
  direction: { converter: { fromAttribute: (v) => v ?? void 0 } },
5179
5356
  align: { converter: { fromAttribute: (v) => v ?? void 0 } },
5180
5357
  justify: { converter: { fromAttribute: (v) => v ?? void 0 } },
@@ -5184,6 +5361,7 @@ var XhFlexElement = class extends XhElement {
5184
5361
  };
5185
5362
  wire() {
5186
5363
  const api = connectFlex({
5364
+ orientation: this.orientation,
5187
5365
  direction: this.direction,
5188
5366
  align: this.align,
5189
5367
  justify: this.justify,
@@ -5198,7 +5376,7 @@ var XhFlexElement = class extends XhElement {
5198
5376
  //#endregion
5199
5377
  //#region src/elements/float-button.ts
5200
5378
  const STRING_CONVERTER$69 = { fromAttribute: (v) => v ?? void 0 };
5201
- const NUMBER_CONVERTER$40 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
5379
+ const NUMBER_CONVERTER$41 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
5202
5380
  const TRISTATE_CONVERTER = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
5203
5381
  /**
5204
5382
  * `<xh-float-button>` —— 悬浮按钮行为宿主:一颗钉在视口一角的触发器,展开一组动作。
@@ -5237,7 +5415,7 @@ var XhFloatButtonElement = class extends XhElement {
5237
5415
  },
5238
5416
  disabled: { type: Boolean },
5239
5417
  placement: { converter: STRING_CONVERTER$69 },
5240
- offset: { converter: NUMBER_CONVERTER$40 },
5418
+ offset: { converter: NUMBER_CONVERTER$41 },
5241
5419
  shape: { converter: STRING_CONVERTER$69 },
5242
5420
  expandTrigger: {
5243
5421
  converter: STRING_CONVERTER$69,
@@ -5824,7 +6002,7 @@ var XhGridElement = class extends XhElement {
5824
6002
  //#endregion
5825
6003
  //#region src/elements/heatmap.ts
5826
6004
  const STRING_CONVERTER$64 = { fromAttribute: (v) => v ?? void 0 };
5827
- const NUMBER_CONVERTER$39 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
6005
+ const NUMBER_CONVERTER$40 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
5828
6006
  /** 角色节点上作者写的 value,解不出数字即当没写。 */
5829
6007
  function numberOf(el) {
5830
6008
  const raw = el.getAttribute("value");
@@ -5906,9 +6084,9 @@ var XhHeatmapElement = class extends XhElement {
5906
6084
  converter: STRING_CONVERTER$64,
5907
6085
  attribute: "end-date"
5908
6086
  },
5909
- levels: { converter: NUMBER_CONVERTER$39 },
6087
+ levels: { converter: NUMBER_CONVERTER$40 },
5910
6088
  firstDayOfWeek: {
5911
- converter: NUMBER_CONVERTER$39,
6089
+ converter: NUMBER_CONVERTER$40,
5912
6090
  attribute: "first-day-of-week"
5913
6091
  },
5914
6092
  locale: { converter: STRING_CONVERTER$64 },
@@ -6219,7 +6397,7 @@ var XhHotkeysElement = class extends XhElement {
6219
6397
  //#endregion
6220
6398
  //#region src/elements/hover-card.ts
6221
6399
  const STRING_CONVERTER$61 = { fromAttribute: (v) => v ?? void 0 };
6222
- const NUMBER_CONVERTER$38 = { fromAttribute: (v) => {
6400
+ const NUMBER_CONVERTER$39 = { fromAttribute: (v) => {
6223
6401
  if (v === null) return void 0;
6224
6402
  const n = Number(v);
6225
6403
  return Number.isFinite(n) ? n : void 0;
@@ -6263,13 +6441,13 @@ var XhHoverCardElement = class extends XhElement {
6263
6441
  attribute: "default-open"
6264
6442
  },
6265
6443
  placement: { converter: STRING_CONVERTER$61 },
6266
- offset: { converter: NUMBER_CONVERTER$38 },
6444
+ offset: { converter: NUMBER_CONVERTER$39 },
6267
6445
  openDelay: {
6268
- converter: NUMBER_CONVERTER$38,
6446
+ converter: NUMBER_CONVERTER$39,
6269
6447
  attribute: "open-delay"
6270
6448
  },
6271
6449
  closeDelay: {
6272
- converter: NUMBER_CONVERTER$38,
6450
+ converter: NUMBER_CONVERTER$39,
6273
6451
  attribute: "close-delay"
6274
6452
  },
6275
6453
  direction: {
@@ -6296,6 +6474,11 @@ var XhHoverCardElement = class extends XhElement {
6296
6474
  scope: this.hoverCardScope,
6297
6475
  onBuilt: (svc) => this.injectRefs(svc)
6298
6476
  });
6477
+ /** 卡片内容的自绘条:与 content 同级挂在已经 fixed 的 positioner 上 */
6478
+ bars = new ScrollbarsController(this, {
6479
+ shell: () => this.getPart("positioner"),
6480
+ scrollable: () => this.getPart("content")
6481
+ });
6299
6482
  machineProps() {
6300
6483
  return {
6301
6484
  open: this.open,
@@ -6322,7 +6505,7 @@ var XhHoverCardElement = class extends XhElement {
6322
6505
  return this.config.layerRegistry.register({
6323
6506
  kind: "popover",
6324
6507
  node: () => this.getPart("content"),
6325
- branches: () => [this.getPart("trigger")].filter(Boolean),
6508
+ branches: () => [this.getPart("trigger"), this.getPart("positioner")].filter(Boolean),
6326
6509
  isModal: () => false,
6327
6510
  setModal: () => {},
6328
6511
  surfaces: () => []
@@ -6367,6 +6550,7 @@ var XhHoverCardElement = class extends XhElement {
6367
6550
  this.exit.track(content);
6368
6551
  this.exit.update(api.open);
6369
6552
  this.setPartHidden(content, !this.exit.visible);
6553
+ this.bars.wire();
6370
6554
  }
6371
6555
  disconnectedCallback() {
6372
6556
  super.disconnectedCallback();
@@ -6547,7 +6731,7 @@ var XhIconWrapperElement = class extends XhElement {
6547
6731
  //#endregion
6548
6732
  //#region src/elements/image.ts
6549
6733
  const STRING_CONVERTER$59 = { fromAttribute: (v) => v ?? void 0 };
6550
- const NUMBER_CONVERTER$37 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
6734
+ const NUMBER_CONVERTER$38 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
6551
6735
  /**
6552
6736
  * `<xh-image>` —— Light-DOM 行为宿主:作者写 root/image/fallback 角色节点,
6553
6737
  * 元素跑 image 机器并把 connect 产出打上去。图片来源由宿主的 src/alt 写进 image 节点,
@@ -6574,7 +6758,7 @@ var XhImageElement = class extends XhElement {
6574
6758
  src: { converter: STRING_CONVERTER$59 },
6575
6759
  alt: { converter: STRING_CONVERTER$59 },
6576
6760
  fallbackDelay: {
6577
- converter: NUMBER_CONVERTER$37,
6761
+ converter: NUMBER_CONVERTER$38,
6578
6762
  attribute: "fallback-delay"
6579
6763
  }
6580
6764
  };
@@ -6631,7 +6815,7 @@ var XhImageElement = class extends XhElement {
6631
6815
  //#endregion
6632
6816
  //#region src/elements/image-cropper.ts
6633
6817
  const STRING_CONVERTER$58 = { fromAttribute: (v) => v ?? void 0 };
6634
- const NUMBER_CONVERTER$36 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
6818
+ const NUMBER_CONVERTER$37 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
6635
6819
  const BOOLEAN_CONVERTER$44 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
6636
6820
  /**
6637
6821
  * 裁切矩形写成逗号分隔的四个数:`x,y,width,height`。
@@ -6711,23 +6895,23 @@ var XhImageCropperElement = class extends XhElement {
6711
6895
  attribute: "default-value"
6712
6896
  },
6713
6897
  aspectRatio: {
6714
- converter: NUMBER_CONVERTER$36,
6898
+ converter: NUMBER_CONVERTER$37,
6715
6899
  attribute: "aspect-ratio"
6716
6900
  },
6717
6901
  minWidth: {
6718
- converter: NUMBER_CONVERTER$36,
6902
+ converter: NUMBER_CONVERTER$37,
6719
6903
  attribute: "min-width"
6720
6904
  },
6721
6905
  minHeight: {
6722
- converter: NUMBER_CONVERTER$36,
6906
+ converter: NUMBER_CONVERTER$37,
6723
6907
  attribute: "min-height"
6724
6908
  },
6725
- zoom: { converter: NUMBER_CONVERTER$36 },
6909
+ zoom: { converter: NUMBER_CONVERTER$37 },
6726
6910
  defaultZoom: {
6727
- converter: NUMBER_CONVERTER$36,
6911
+ converter: NUMBER_CONVERTER$37,
6728
6912
  attribute: "default-zoom"
6729
6913
  },
6730
- rotation: { converter: NUMBER_CONVERTER$36 },
6914
+ rotation: { converter: NUMBER_CONVERTER$37 },
6731
6915
  shape: { converter: STRING_CONVERTER$58 },
6732
6916
  disabled: { converter: BOOLEAN_CONVERTER$44 },
6733
6917
  readOnly: {
@@ -6824,7 +7008,7 @@ var XhImageCropperElement = class extends XhElement {
6824
7008
  //#endregion
6825
7009
  //#region src/elements/image-viewer.ts
6826
7010
  const BOOLEAN_CONVERTER$43 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
6827
- const NUMBER_CONVERTER$35 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
7011
+ const NUMBER_CONVERTER$36 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
6828
7012
  /**
6829
7013
  * `<xh-image-viewer>` —— Light-DOM 行为宿主,跑 image-viewer 机器:
6830
7014
  * 模态看片浮层,滚轮缩放、拖拽平移、旋转翻转与多图翻页。
@@ -6873,22 +7057,22 @@ var XhImageViewerElement = class extends XhElement {
6873
7057
  type: Boolean,
6874
7058
  attribute: "default-open"
6875
7059
  },
6876
- index: { converter: NUMBER_CONVERTER$35 },
7060
+ index: { converter: NUMBER_CONVERTER$36 },
6877
7061
  defaultIndex: {
6878
- converter: NUMBER_CONVERTER$35,
7062
+ converter: NUMBER_CONVERTER$36,
6879
7063
  attribute: "default-index"
6880
7064
  },
6881
7065
  loop: { converter: BOOLEAN_CONVERTER$43 },
6882
7066
  zoomStep: {
6883
- converter: NUMBER_CONVERTER$35,
7067
+ converter: NUMBER_CONVERTER$36,
6884
7068
  attribute: "zoom-step"
6885
7069
  },
6886
7070
  minScale: {
6887
- converter: NUMBER_CONVERTER$35,
7071
+ converter: NUMBER_CONVERTER$36,
6888
7072
  attribute: "min-scale"
6889
7073
  },
6890
7074
  maxScale: {
6891
- converter: NUMBER_CONVERTER$35,
7075
+ converter: NUMBER_CONVERTER$36,
6892
7076
  attribute: "max-scale"
6893
7077
  },
6894
7078
  closeOnEscape: {
@@ -7041,7 +7225,7 @@ var XhImageViewerElement = class extends XhElement {
7041
7225
  };
7042
7226
  //#endregion
7043
7227
  //#region src/elements/infinite-scroll.ts
7044
- const NUMBER_CONVERTER$34 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
7228
+ const NUMBER_CONVERTER$35 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
7045
7229
  const BOOLEAN_CONVERTER$42 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
7046
7230
  /**
7047
7231
  * `<xh-infinite-scroll>` —— 无限滚动行为宿主:摆在列表末尾的哨兵一进可视区就报「该取下一页了」。
@@ -7065,7 +7249,7 @@ var XhInfiniteScrollElement = class extends XhElement {
7065
7249
  meta: infiniteScrollMeta
7066
7250
  };
7067
7251
  static properties = {
7068
- distance: { converter: NUMBER_CONVERTER$34 },
7252
+ distance: { converter: NUMBER_CONVERTER$35 },
7069
7253
  disabled: { converter: BOOLEAN_CONVERTER$42 },
7070
7254
  loading: { converter: BOOLEAN_CONVERTER$42 },
7071
7255
  target: { attribute: false }
@@ -7102,7 +7286,7 @@ var XhInfiniteScrollElement = class extends XhElement {
7102
7286
  //#endregion
7103
7287
  //#region src/elements/json-viewer.ts
7104
7288
  const STRING_CONVERTER$57 = { fromAttribute: (v) => v ?? void 0 };
7105
- const NUMBER_CONVERTER$33 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
7289
+ const NUMBER_CONVERTER$34 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
7106
7290
  const BOOLEAN_CONVERTER$41 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
7107
7291
  const JSON_CONVERTER = { fromAttribute: (v) => {
7108
7292
  if (v == null) return void 0;
@@ -7141,6 +7325,10 @@ function reconcile(container, wanted) {
7141
7325
  function setText(el, text) {
7142
7326
  if (el.textContent !== text) el.textContent = text;
7143
7327
  }
7328
+ /** 此刻在场的那一档滚动层:树档是 tree,原文档是 text,两者都是 root 的直接子节点。 */
7329
+ function scrollLayerOf(root) {
7330
+ return root?.querySelector(":scope > [data-part=\"tree\"], :scope > [data-part=\"text\"]") ?? null;
7331
+ }
7144
7332
  /**
7145
7333
  * `<xh-json-viewer>` —— Light-DOM 行为宿主:作者只写一个 root 角色节点,
7146
7334
  * 元素跑 json-viewer 机器,把 value 摊成的每一行铺进 root 里。
@@ -7187,21 +7375,22 @@ var XhJsonViewerElement = class extends XhElement {
7187
7375
  expandedValue: { attribute: false },
7188
7376
  defaultExpandedValue: { attribute: false },
7189
7377
  defaultExpandedDepth: {
7190
- converter: NUMBER_CONVERTER$33,
7378
+ converter: NUMBER_CONVERTER$34,
7191
7379
  attribute: "default-expanded-depth"
7192
7380
  },
7193
7381
  maxStringLength: {
7194
- converter: NUMBER_CONVERTER$33,
7382
+ converter: NUMBER_CONVERTER$34,
7195
7383
  attribute: "max-string-length"
7196
7384
  },
7197
7385
  maxItems: {
7198
- converter: NUMBER_CONVERTER$33,
7386
+ converter: NUMBER_CONVERTER$34,
7199
7387
  attribute: "max-items"
7200
7388
  },
7201
7389
  sortKeys: {
7202
7390
  converter: BOOLEAN_CONVERTER$41,
7203
7391
  attribute: "sort-keys"
7204
7392
  },
7393
+ view: { attribute: "view" },
7205
7394
  loop: { converter: BOOLEAN_CONVERTER$41 },
7206
7395
  direction: {
7207
7396
  converter: STRING_CONVERTER$57,
@@ -7218,6 +7407,19 @@ var XhJsonViewerElement = class extends XhElement {
7218
7407
  }));
7219
7408
  };
7220
7409
  ctrl = new MachineController(this, jsonViewerMachine, () => this.machineProps());
7410
+ /**
7411
+ * 两档的自绘条:与滚动层同级挂在根上。两档互斥,交此刻在场的那个——
7412
+ * 两个容器都归本元素建,身上没有 data-xh-part,从 root 里现查。
7413
+ * 两条轴都摆:深层缩进往行首方向推、长字符串往行尾伸。
7414
+ */
7415
+ bars = new ScrollbarsController(this, {
7416
+ shell: () => this.getPart("root"),
7417
+ scrollable: () => scrollLayerOf(this.getPart("root")),
7418
+ axes: ["vertical", "horizontal"],
7419
+ props: () => ({ dir: this.direction })
7420
+ });
7421
+ /** 条子上一轮接的是哪一档的容器。 */
7422
+ wiredLayer = null;
7221
7423
  machineProps() {
7222
7424
  return {
7223
7425
  value: this.value,
@@ -7227,6 +7429,7 @@ var XhJsonViewerElement = class extends XhElement {
7227
7429
  maxStringLength: this.maxStringLength,
7228
7430
  maxItems: this.maxItems,
7229
7431
  sortKeys: this.sortKeys,
7432
+ view: this.view,
7230
7433
  loop: this.loop,
7231
7434
  dir: this.direction,
7232
7435
  size: this.size,
@@ -7236,6 +7439,7 @@ var XhJsonViewerElement = class extends XhElement {
7236
7439
  }
7237
7440
  /** 树容器与每一行都归本元素建,按路径留着复用。 */
7238
7441
  treeEl;
7442
+ textEl;
7239
7443
  rows = /* @__PURE__ */ new Map();
7240
7444
  /**
7241
7445
  * root 被移出本宿主时,铺在它里面的行也一并离场。浏览器此时不派 focusout,
@@ -7337,13 +7541,45 @@ var XhJsonViewerElement = class extends XhElement {
7337
7541
  if (!root) return;
7338
7542
  const api = connectJsonViewer(this.ctrl.service, wcNormalize);
7339
7543
  this.spreader.spread(root, api.getRootProps());
7544
+ if (api.view === "text") {
7545
+ const pre = this.textEl ?? (this.textEl = this.ownerDocument.createElement("pre"));
7546
+ this.adopt(root, pre, this.treeEl);
7547
+ this.spreader.spread(pre, api.getTextProps());
7548
+ setText(pre, api.text);
7549
+ this.rows.clear();
7550
+ this.syncBars();
7551
+ return;
7552
+ }
7340
7553
  const tree = this.treeEl ?? (this.treeEl = this.ownerDocument.createElement("div"));
7341
- if (root.firstChild !== tree || tree.nextSibling !== null) root.replaceChildren(tree);
7554
+ this.adopt(root, tree, this.textEl);
7342
7555
  this.spreader.spread(tree, api.getTreeProps());
7343
7556
  const children = groupByParent(api.visibleNodes);
7344
7557
  const alive = /* @__PURE__ */ new Set();
7345
7558
  this.paint(tree, children.get(null) ?? [], children, api, alive);
7346
7559
  for (const key of [...this.rows.keys()]) if (!alive.has(key)) this.rows.delete(key);
7560
+ this.syncBars();
7561
+ }
7562
+ /**
7563
+ * 把条子接到此刻在场的那一档容器上。
7564
+ * 机器的追踪器在本轮渲染之前就跑完了,这一轮换掉的容器它看不见;
7565
+ * 换了档就再催一轮,下一轮的追踪器才把滚动监听与容器标记挪过去。
7566
+ */
7567
+ syncBars() {
7568
+ this.bars.wire();
7569
+ const layer = scrollLayerOf(this.getPart("root"));
7570
+ if (layer === this.wiredLayer) return;
7571
+ this.wiredLayer = layer;
7572
+ this.requestUpdate();
7573
+ }
7574
+ /**
7575
+ * root 里只留这一档的容器:摘走另一档,作者写在里面的东西也一并清掉。
7576
+ * 自绘条同样挂在 root 上,按 scope 认出来留着——整份 replaceChildren 会把条子一起抹掉。
7577
+ * 已经就位的节点一个都不碰:移动一个节点等于把它摘下来再插回去,焦点在树里会掉回 body。
7578
+ */
7579
+ adopt(root, keep, drop) {
7580
+ drop?.remove();
7581
+ for (const child of [...root.children]) if (child !== keep && child.getAttribute("data-scope") !== "scrollbar") child.remove();
7582
+ if (root.firstChild !== keep) root.insertBefore(keep, root.firstChild);
7347
7583
  }
7348
7584
  };
7349
7585
  //#endregion
@@ -7664,7 +7900,7 @@ var XhListboxElement = class extends XhElement {
7664
7900
  //#endregion
7665
7901
  //#region src/elements/loading-bar.ts
7666
7902
  const STRING_CONVERTER$53 = { fromAttribute: (v) => v ?? void 0 };
7667
- const NUMBER_CONVERTER$32 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
7903
+ const NUMBER_CONVERTER$33 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
7668
7904
  const BOOLEAN_CONVERTER$39 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
7669
7905
  const HEIGHT_CONVERTER = { fromAttribute: (v) => {
7670
7906
  if (v == null || v === "") return void 0;
@@ -7704,9 +7940,9 @@ var XhLoadingBarElement = class extends XhElement {
7704
7940
  meta: loadingBarMeta
7705
7941
  };
7706
7942
  static properties = {
7707
- value: { converter: NUMBER_CONVERTER$32 },
7943
+ value: { converter: NUMBER_CONVERTER$33 },
7708
7944
  defaultValue: {
7709
- converter: NUMBER_CONVERTER$32,
7945
+ converter: NUMBER_CONVERTER$33,
7710
7946
  attribute: "default-value"
7711
7947
  },
7712
7948
  loading: { converter: BOOLEAN_CONVERTER$39 },
@@ -7715,12 +7951,12 @@ var XhLoadingBarElement = class extends XhElement {
7715
7951
  tone: { converter: STRING_CONVERTER$53 },
7716
7952
  trickle: { converter: BOOLEAN_CONVERTER$39 },
7717
7953
  trickleSpeed: {
7718
- converter: NUMBER_CONVERTER$32,
7954
+ converter: NUMBER_CONVERTER$33,
7719
7955
  attribute: "trickle-speed"
7720
7956
  },
7721
- minimum: { converter: NUMBER_CONVERTER$32 },
7957
+ minimum: { converter: NUMBER_CONVERTER$33 },
7722
7958
  fadeDuration: {
7723
- converter: NUMBER_CONVERTER$32,
7959
+ converter: NUMBER_CONVERTER$33,
7724
7960
  attribute: "fade-duration"
7725
7961
  },
7726
7962
  translations: { attribute: false }
@@ -7763,7 +7999,7 @@ var XhLoadingBarElement = class extends XhElement {
7763
7999
  };
7764
8000
  //#endregion
7765
8001
  //#region src/elements/log.ts
7766
- const NUMBER_CONVERTER$31 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
8002
+ const NUMBER_CONVERTER$32 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
7767
8003
  /**
7768
8004
  * `<xh-log>` —— Light-DOM 行为宿主:作者写 root/viewport/content/line 角色节点,
7769
8005
  * 元素把 connectLog 的产出打上去。行长出来时跟随滚动到底部,用户上滚后解除粘附,
@@ -7788,7 +8024,7 @@ var XhLogElement = class extends XhElement {
7788
8024
  meta: logMeta
7789
8025
  };
7790
8026
  static properties = {
7791
- rows: { converter: NUMBER_CONVERTER$31 },
8027
+ rows: { converter: NUMBER_CONVERTER$32 },
7792
8028
  loading: { type: Boolean },
7793
8029
  translations: { attribute: false }
7794
8030
  };
@@ -7850,7 +8086,7 @@ var XhLogElement = class extends XhElement {
7850
8086
  //#endregion
7851
8087
  //#region src/elements/marquee.ts
7852
8088
  const STRING_CONVERTER$52 = { fromAttribute: (v) => v ?? void 0 };
7853
- const NUMBER_CONVERTER$30 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
8089
+ const NUMBER_CONVERTER$31 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
7854
8090
  /**
7855
8091
  * `<xh-marquee>` —— Light-DOM 行为宿主,无状态机,把 connectMarquee 产出打到 root 与 content 上。
7856
8092
  *
@@ -7878,7 +8114,7 @@ var XhMarqueeElement = class extends XhElement {
7878
8114
  };
7879
8115
  static properties = {
7880
8116
  direction: { converter: STRING_CONVERTER$52 },
7881
- speed: { converter: NUMBER_CONVERTER$30 },
8117
+ speed: { converter: NUMBER_CONVERTER$31 },
7882
8118
  pauseOnHover: {
7883
8119
  type: Boolean,
7884
8120
  attribute: "pause-on-hover"
@@ -8028,7 +8264,7 @@ var XhMasonryElement = class extends XhElement {
8028
8264
  //#endregion
8029
8265
  //#region src/elements/mention.ts
8030
8266
  const STRING_CONVERTER$50 = { fromAttribute: (v) => v ?? void 0 };
8031
- const NUMBER_CONVERTER$29 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
8267
+ const NUMBER_CONVERTER$30 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
8032
8268
  const BOOLEAN_CONVERTER$37 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
8033
8269
  /**
8034
8270
  * `<xh-mention>` —— Light-DOM 行为宿主:作者写 root/input/positioner/content/item 角色节点,
@@ -8097,7 +8333,7 @@ var XhMentionElement = class extends XhElement {
8097
8333
  placeholder: { converter: STRING_CONVERTER$50 },
8098
8334
  loop: { converter: BOOLEAN_CONVERTER$37 },
8099
8335
  placement: { converter: STRING_CONVERTER$50 },
8100
- offset: { converter: NUMBER_CONVERTER$29 },
8336
+ offset: { converter: NUMBER_CONVERTER$30 },
8101
8337
  variant: { converter: STRING_CONVERTER$50 },
8102
8338
  tone: { converter: STRING_CONVERTER$50 },
8103
8339
  size: { converter: STRING_CONVERTER$50 }
@@ -8140,6 +8376,11 @@ var XhMentionElement = class extends XhElement {
8140
8376
  scope: this.mentionScope,
8141
8377
  onBuilt: (svc) => this.injectRefs(svc)
8142
8378
  });
8379
+ /** 候选列表的自绘条:与 content 同级挂在已经 fixed 的 positioner 上 */
8380
+ bars = new ScrollbarsController(this, {
8381
+ shell: () => this.getPart("positioner"),
8382
+ scrollable: () => this.getPart("content")
8383
+ });
8143
8384
  /** 作者声明的条目禁用,只认首见那一份;给了 collection 时用它,否则现读 */
8144
8385
  declaredDisabled = createDeclaredDisabled();
8145
8386
  machineProps() {
@@ -8177,7 +8418,7 @@ var XhMentionElement = class extends XhElement {
8177
8418
  return this.config.layerRegistry.register({
8178
8419
  kind: "popover",
8179
8420
  node: () => this.getPart("content"),
8180
- branches: () => [this.getPart("input")].filter(Boolean),
8421
+ branches: () => [this.getPart("input"), this.getPart("positioner")].filter(Boolean),
8181
8422
  isModal: () => false,
8182
8423
  setModal: () => {},
8183
8424
  surfaces: () => []
@@ -8232,6 +8473,7 @@ var XhMentionElement = class extends XhElement {
8232
8473
  this.exit.update(api.open);
8233
8474
  this.setPartHidden(this.getPart("content"), !this.exit.visible);
8234
8475
  if (this.ctrl.service.getStatus() === "Started") this.ctrl.service.send({ type: "ITEMS.SYNC" });
8476
+ this.bars.wire();
8235
8477
  }
8236
8478
  disconnectedCallback() {
8237
8479
  super.disconnectedCallback();
@@ -8244,7 +8486,7 @@ var XhMentionElement = class extends XhElement {
8244
8486
  //#endregion
8245
8487
  //#region src/elements/menu.ts
8246
8488
  const STRING_CONVERTER$49 = { fromAttribute: (v) => v ?? void 0 };
8247
- const NUMBER_CONVERTER$28 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
8489
+ const NUMBER_CONVERTER$29 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
8248
8490
  const BOOLEAN_CONVERTER$36 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
8249
8491
  /**
8250
8492
  * `<xh-menu>` —— Light-DOM 行为宿主:用户写 trigger/positioner/content/item/group/... 角色节点,
@@ -8285,7 +8527,7 @@ var XhMenuElement = class extends XhElement {
8285
8527
  attribute: "default-open"
8286
8528
  },
8287
8529
  placement: { converter: STRING_CONVERTER$49 },
8288
- offset: { converter: NUMBER_CONVERTER$28 },
8530
+ offset: { converter: NUMBER_CONVERTER$29 },
8289
8531
  loop: { converter: BOOLEAN_CONVERTER$36 },
8290
8532
  direction: {
8291
8533
  converter: STRING_CONVERTER$49,
@@ -8299,11 +8541,11 @@ var XhMenuElement = class extends XhElement {
8299
8541
  attribute: "open-on-hover"
8300
8542
  },
8301
8543
  hoverOpenDelay: {
8302
- converter: NUMBER_CONVERTER$28,
8544
+ converter: NUMBER_CONVERTER$29,
8303
8545
  attribute: "hover-open-delay"
8304
8546
  },
8305
8547
  hoverCloseDelay: {
8306
- converter: NUMBER_CONVERTER$28,
8548
+ converter: NUMBER_CONVERTER$29,
8307
8549
  attribute: "hover-close-delay"
8308
8550
  }
8309
8551
  };
@@ -8331,6 +8573,11 @@ var XhMenuElement = class extends XhElement {
8331
8573
  scope: this.menuScope,
8332
8574
  onBuilt: (svc) => this.injectRefs(svc)
8333
8575
  });
8576
+ /** 条目列表的自绘条:与 content 同级挂在已经 fixed 的 positioner 上 */
8577
+ bars = new ScrollbarsController(this, {
8578
+ shell: () => this.getPart("positioner"),
8579
+ scrollable: () => this.getPart("content")
8580
+ });
8334
8581
  /** 作者声明的条目禁用,只认首见那一份;给了 collection 时用它,否则现读 */
8335
8582
  declaredDisabled = createDeclaredDisabled();
8336
8583
  machineProps() {
@@ -8364,7 +8611,7 @@ var XhMenuElement = class extends XhElement {
8364
8611
  return this.config.layerRegistry.register({
8365
8612
  kind: "popover",
8366
8613
  node: () => this.getPart("content"),
8367
- branches: () => [this.getPart("trigger")].filter(Boolean),
8614
+ branches: () => [this.getPart("trigger"), this.getPart("positioner")].filter(Boolean),
8368
8615
  isModal: () => false,
8369
8616
  setModal: () => {},
8370
8617
  surfaces: () => []
@@ -8440,6 +8687,7 @@ var XhMenuElement = class extends XhElement {
8440
8687
  this.exit.track(content);
8441
8688
  this.exit.update(api.open);
8442
8689
  this.setPartHidden(content, !this.exit.visible);
8690
+ this.bars.wire();
8443
8691
  }
8444
8692
  disconnectedCallback() {
8445
8693
  super.disconnectedCallback();
@@ -8452,7 +8700,7 @@ var XhMenuElement = class extends XhElement {
8452
8700
  //#endregion
8453
8701
  //#region src/elements/menubar.ts
8454
8702
  const STRING_CONVERTER$48 = { fromAttribute: (v) => v ?? void 0 };
8455
- const NUMBER_CONVERTER$27 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
8703
+ const NUMBER_CONVERTER$28 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
8456
8704
  const BOOLEAN_CONVERTER$35 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
8457
8705
  /** 读角色节点的禁用声明,并摘掉作者写的原生 disabled,禁用态归一到 aria-disabled。 */
8458
8706
  function authorDisabled$1(el) {
@@ -8521,7 +8769,7 @@ var XhMenubarElement = class extends XhElement {
8521
8769
  disabled: { converter: BOOLEAN_CONVERTER$35 },
8522
8770
  typeahead: { converter: BOOLEAN_CONVERTER$35 },
8523
8771
  placement: { converter: STRING_CONVERTER$48 },
8524
- offset: { converter: NUMBER_CONVERTER$27 },
8772
+ offset: { converter: NUMBER_CONVERTER$28 },
8525
8773
  tone: { converter: STRING_CONVERTER$48 },
8526
8774
  size: { converter: STRING_CONVERTER$48 }
8527
8775
  };
@@ -8675,7 +8923,7 @@ var XhMenubarElement = class extends XhElement {
8675
8923
  //#endregion
8676
8924
  //#region src/elements/navigation-menu.ts
8677
8925
  const STRING_CONVERTER$47 = { fromAttribute: (v) => v ?? void 0 };
8678
- const NUMBER_CONVERTER$26 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
8926
+ const NUMBER_CONVERTER$27 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
8679
8927
  const BOOLEAN_CONVERTER$34 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
8680
8928
  /**
8681
8929
  * 作者写在角色节点上的布尔声明,三态读法:属性缺席 = false,="false" = false,其余 = true。
@@ -8747,11 +8995,11 @@ var XhNavigationMenuElement = class extends XhElement {
8747
8995
  },
8748
8996
  orientation: { converter: STRING_CONVERTER$47 },
8749
8997
  delayDuration: {
8750
- converter: NUMBER_CONVERTER$26,
8998
+ converter: NUMBER_CONVERTER$27,
8751
8999
  attribute: "delay-duration"
8752
9000
  },
8753
9001
  skipDelayDuration: {
8754
- converter: NUMBER_CONVERTER$26,
9002
+ converter: NUMBER_CONVERTER$27,
8755
9003
  attribute: "skip-delay-duration"
8756
9004
  },
8757
9005
  direction: {
@@ -8873,34 +9121,307 @@ var XhNavigationMenuElement = class extends XhElement {
8873
9121
  }
8874
9122
  };
8875
9123
  //#endregion
8876
- //#region src/elements/number-animation.ts
9124
+ //#region src/elements/notification.ts
8877
9125
  const STRING_CONVERTER$46 = { fromAttribute: (v) => v ?? void 0 };
8878
- const NUMBER_CONVERTER$25 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
9126
+ const NUMBER_CONVERTER$26 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
8879
9127
  const BOOLEAN_CONVERTER$33 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
8880
9128
  /**
8881
- * `<xh-number-animation>` —— Light-DOM 行为宿主:作者写一个 root 角色节点,
8882
- * 元素跑 number-animation 机器,逐帧把补间算出的数字格式化后写进那个节点。
8883
- *
8884
- * 参数改写分两路:改 `from` 是"换起点",数字当场落到新起点再重跑;
8885
- * `to` / `duration` / `easing` 是"换目标",从当前数字接着走,不跳回起点。
8886
- * 已经跑完停在 idle 时改 `to` 同样会重新跑起来,所以"数字跟着数据走"不必额外拨 `active`。
9129
+ * 这一摞对应哪个位置。属性缺席就交 undefined,由 connect 回落到队列的 placement。
9130
+ * 写坏了照原样交出去:它与九个位没有一个对得上,这摞就一直是空的——
9131
+ * 空得明显好过悄悄冒充另一个位置,把通知摆到作者没想到的角落。
9132
+ */
9133
+ function groupPlacement(el) {
9134
+ const raw = el.getAttribute("placement");
9135
+ return raw == null || raw === "" ? void 0 : raw;
9136
+ }
9137
+ /**
9138
+ * `<xh-notification>` —— Light-DOM 行为宿主:作者写 root 与若干 group 角色节点,
9139
+ * 元素跑 notification 机器并把 connect 产出打上去。每个 group 用 `placement` 属性声明自己是哪个位置,
9140
+ * 不写就落在队列的 placement 上。
8887
9141
  *
8888
- * 根是 role="status" aria-live 缺省写死 off:status 的隐含 aria-live 就是 polite,
8889
- * 一个每帧都在变的数字用 polite 会把读屏刷爆,要播报由作者把 live 开到 polite 或 assertive。
9142
+ * 单条通知的节点由作者按队列渲染(读 `items` 或听 `items-change`),元素不替作者生成:
9143
+ * 生成节点就等于收走模板控制权,图标、进度条、i18n 文案都再塞不进来。
9144
+ * 每条渲染成一个 `<xh-notification-item>`,它走完退场会冒泡一条 status-change,本元素据此把记录删掉。
8890
9145
  *
8891
- * @customElement xh-number-animation
8892
- * @attr {number} from - 起点,缺省 0
8893
- * @attr {number} to - 终点,缺省 0
8894
- * @attr {number} duration - 时长毫秒,缺省 1000;<=0 即一步到位
8895
- * @attr {'linear'|'ease-in'|'ease-out'|'ease-in-out'} easing - 缓动,缺省 linear
8896
- * @attr {number} precision - 小数位,缺省 0
8897
- * @attr {string} separator - 千位分隔符,缺省不分隔
8898
- * @attr {boolean} active - 是否在跑,缺省真;`active="false"` 停在当前值
8899
- * @attr {'sm'|'md'|'lg'} size - 尺寸,只改字号
8900
- * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气,决定数字用哪族颜色
8901
- * @attr {'off'|'polite'|'assertive'} live - 读屏播报档位,缺省 off
8902
- * @fires finish - 走到终点;detail `{ value: number }`
8903
- * @csspart root - 数字本身(承载 status 语义、data-state 与两个视觉轴);文字归元素写
9146
+ * @customElement xh-notification
9147
+ * @attr {'top-start'|'top'|'top-end'|'middle-start'|'middle'|'middle-end'|'bottom-start'|'bottom'|'bottom-end'} placement - 默认落位,默认 bottom-end
9148
+ * @attr {number} max - 每个位置最多同时留几条,超出挤掉最旧的;不给即不限
9149
+ * @attr {number} gap - 同一摞内的间距(px),默认 16
9150
+ * @attr {number} duration - 单条没写 duration 时的默认停留毫秒
9151
+ * @attr {number} remove-delay - 单条没写 remove-delay 时的默认退场窗口毫秒
9152
+ * @attr {boolean} pause-on-page-idle - 页面切到后台时按住计时,逐条下发
9153
+ * @fires items-change - 队列变化;detail 为 `{ items: NotificationRecord[] }`
9154
+ * @csspart root - 队列的作用域包装(display: contents,不占布局),承载 data-count / data-empty
9155
+ * @csspart group - role=region 的地标,某一个位置上的那一摞;可自带 placement 属性,承载 data-placement / data-count / data-empty 与间距
9156
+ */
9157
+ var XhNotificationElement = class extends XhElement {
9158
+ static partContract = {
9159
+ anatomy: notificationAnatomy,
9160
+ meta: notificationMeta
9161
+ };
9162
+ static properties = {
9163
+ items: { attribute: false },
9164
+ defaultItems: { attribute: false },
9165
+ placement: { converter: STRING_CONVERTER$46 },
9166
+ max: { converter: NUMBER_CONVERTER$26 },
9167
+ gap: { converter: NUMBER_CONVERTER$26 },
9168
+ duration: { converter: NUMBER_CONVERTER$26 },
9169
+ removeDelay: {
9170
+ converter: NUMBER_CONVERTER$26,
9171
+ attribute: "remove-delay"
9172
+ },
9173
+ pauseOnPageIdle: {
9174
+ converter: BOOLEAN_CONVERTER$33,
9175
+ attribute: "pause-on-page-idle"
9176
+ },
9177
+ translations: { attribute: false }
9178
+ };
9179
+ notify = (details) => {
9180
+ this.dispatchEvent(new CustomEvent("items-change", {
9181
+ detail: details,
9182
+ bubbles: true,
9183
+ composed: true
9184
+ }));
9185
+ };
9186
+ ctrl = new MachineController(this, notificationMachine, () => this.machineProps());
9187
+ machineProps() {
9188
+ return {
9189
+ items: this.items,
9190
+ defaultItems: this.defaultItems,
9191
+ placement: this.placement,
9192
+ max: this.max,
9193
+ gap: this.gap,
9194
+ duration: this.duration,
9195
+ removeDelay: this.removeDelay,
9196
+ pauseOnPageIdle: this.pauseOnPageIdle,
9197
+ translations: this.translations,
9198
+ onItemsChange: this.notify
9199
+ };
9200
+ }
9201
+ /**
9202
+ * 命令式入口共用的取法。机器要到进文档(hostConnected)才建:
9203
+ * 还没进文档就发通知是调用方的时序问题,明说好过把这条通知静默丢掉。
9204
+ */
9205
+ commands() {
9206
+ if (!this.ctrl.service) throw new Error("[xh] <xh-notification> 还没进文档,命令式接口此时不可用");
9207
+ return connectNotification(this.ctrl.service, wcNormalize);
9208
+ }
9209
+ /** 入队并返回 id;同 id 已存在则就地改写,位置不动(处理中转已完成走的就是这条)。 */
9210
+ create(options = {}) {
9211
+ return this.commands().create(options);
9212
+ }
9213
+ /**
9214
+ * 刻意不叫 `update`:那是 Lit 自己的渲染生命周期钩子,占用它会让宿主每次重渲
9215
+ * 都拐进这里来(还带着一个 changedProperties 当 id),组件当场不工作。
9216
+ * Vue 侧没有这层基类,composable 上仍叫 `update`。
9217
+ */
9218
+ updateItem(id, options) {
9219
+ this.commands().update(id, options);
9220
+ }
9221
+ dismiss(id) {
9222
+ this.commands().dismiss(id);
9223
+ }
9224
+ dismissAll() {
9225
+ this.commands().dismissAll();
9226
+ }
9227
+ /** max 之内、按加入先后排列的可见条目,已补齐默认值,可直接摊给 `<xh-notification-item>`。 */
9228
+ get visibleNotifications() {
9229
+ return this.commands().visibleNotifications;
9230
+ }
9231
+ /** 当前有条目的位置,按九宫格固定顺序。 */
9232
+ get placements() {
9233
+ return this.commands().placements;
9234
+ }
9235
+ get count() {
9236
+ return this.commands().count;
9237
+ }
9238
+ getItemsByPlacement(placement) {
9239
+ return this.commands().getItemsByPlacement(placement);
9240
+ }
9241
+ /**
9242
+ * 单条通知走完退场会冒泡上来:记录该从队列里删掉了。
9243
+ * 认元素名而不是只认事件名——avatar 之类的部件也派 status-change,且完全可能就摆在通知内部。
9244
+ */
9245
+ onItemStatus = (event) => {
9246
+ if (event.target?.tagName.toLowerCase() !== "xh-notification-item") return;
9247
+ const detail = event.detail;
9248
+ if (detail?.status !== "unmounted") return;
9249
+ if (this.ctrl.service?.getStatus() !== "Started") return;
9250
+ this.dismiss(detail.id);
9251
+ };
9252
+ connectedCallback() {
9253
+ super.connectedCallback();
9254
+ this.addEventListener("status-change", this.onItemStatus);
9255
+ }
9256
+ disconnectedCallback() {
9257
+ this.removeEventListener("status-change", this.onItemStatus);
9258
+ super.disconnectedCallback();
9259
+ }
9260
+ wire() {
9261
+ const api = connectNotification(this.ctrl.service, wcNormalize);
9262
+ const root = this.getPart("root");
9263
+ if (root) this.spreader.spread(root, api.getRootProps());
9264
+ for (const el of this.getParts("group")) this.spreader.spread(el, api.getGroupProps({ placement: groupPlacement(el) }));
9265
+ }
9266
+ };
9267
+ const ITEM_CONTRACT = {
9268
+ anatomy: notificationAnatomy,
9269
+ meta: {
9270
+ component: "notification",
9271
+ requiredParts: ["item"]
9272
+ }
9273
+ };
9274
+ /**
9275
+ * `<xh-notification-item>` —— 单条通知卡片:作者写 item/item-indicator/item-title/
9276
+ * item-description/item-action-trigger/item-close-trigger 角色节点,
9277
+ * 元素跑生命周期机器并把 connect 产出打上去。
9278
+ *
9279
+ * item 承载 role 与 aria-live:默认 status + polite(排队等读屏的空隙),
9280
+ * type="error" 换成 alert + assertive(打断当前朗读)。指针停在卡片上、
9281
+ * 或焦点落进卡片内部都会把倒计时按住,离开才接着走剩下的那一段。
9282
+ *
9283
+ * 退场窗口走完只把卡片收起、不删节点:作者写在里面的内容归作者,
9284
+ * 什么时候把这条从队列里删掉是 `<xh-notification>` 的事(它收本元素冒泡上去的 status-change)。
9285
+ *
9286
+ * @customElement xh-notification-item
9287
+ * @attr {string} id - 队列身份,`<xh-notification>` 按它寻址;不给就用实例自己的 scope id
9288
+ * @attr {string} title - 标题文案;作者没在 item-title 部件里写内容时由元素填入
9289
+ * @attr {string} description - 补充说明;作者没在 item-description 部件里写内容时由元素填入
9290
+ * @attr {'info'|'success'|'warning'|'error'|'loading'} type - 语气,默认 info;loading 不自动消失
9291
+ * @attr {number} duration - 停留毫秒,默认 5000;<=0 即关掉自动消失
9292
+ * @attr {number} remove-delay - 退场窗口毫秒,默认 200,留给退场动画
9293
+ * @attr {boolean} closable - 是否给可用的关闭按钮,默认 true;写 closable="false" 关掉
9294
+ * @attr {boolean} pause-on-page-idle - 页面切到后台时按住计时,默认关
9295
+ * @fires status-change - 生命周期落位;detail 为 `{ id: string, status: 'dismissing'|'unmounted' }`
9296
+ * @fires action - 操作按钮被按下;detail 为 `{ id: string }`
9297
+ * @csspart item - role=status(error 时 alert)的卡片,承载 data-type / data-tone / data-state / data-paused
9298
+ * @csspart item-indicator - 类型指示符;留空即由皮肤按 data-type 画一枚兜底字形
9299
+ * @csspart item-title - 标题,aria-labelledby 的目标
9300
+ * @csspart item-description - 补充说明,aria-describedby 的目标
9301
+ * @csspart item-action-trigger - 操作按钮:先发 action 再进入退场
9302
+ * @csspart item-close-trigger - 关闭按钮;closable=false 时转原生 disabled 并收起
9303
+ */
9304
+ var XhNotificationItemElement = class extends XhElement {
9305
+ static partContract = ITEM_CONTRACT;
9306
+ static properties = {
9307
+ itemId: {
9308
+ converter: STRING_CONVERTER$46,
9309
+ attribute: "id"
9310
+ },
9311
+ titleText: {
9312
+ converter: STRING_CONVERTER$46,
9313
+ attribute: "title"
9314
+ },
9315
+ description: { converter: STRING_CONVERTER$46 },
9316
+ type: { converter: STRING_CONVERTER$46 },
9317
+ duration: { converter: NUMBER_CONVERTER$26 },
9318
+ removeDelay: {
9319
+ converter: NUMBER_CONVERTER$26,
9320
+ attribute: "remove-delay"
9321
+ },
9322
+ closable: { converter: BOOLEAN_CONVERTER$33 },
9323
+ pauseOnPageIdle: {
9324
+ converter: BOOLEAN_CONVERTER$33,
9325
+ attribute: "pause-on-page-idle"
9326
+ },
9327
+ translations: { attribute: false }
9328
+ };
9329
+ notifyStatus = (details) => {
9330
+ this.dispatchEvent(new CustomEvent("status-change", {
9331
+ detail: details,
9332
+ bubbles: true,
9333
+ composed: true
9334
+ }));
9335
+ };
9336
+ notifyAction = (details) => {
9337
+ this.dispatchEvent(new CustomEvent("action", {
9338
+ detail: details,
9339
+ bubbles: true,
9340
+ composed: true
9341
+ }));
9342
+ };
9343
+ ctrl = new MachineController(this, toastMachine, () => this.machineProps(), { configName: "notification" });
9344
+ machineProps() {
9345
+ return {
9346
+ id: this.itemId,
9347
+ title: this.titleText,
9348
+ description: this.description,
9349
+ type: this.type,
9350
+ duration: this.duration,
9351
+ removeDelay: this.removeDelay,
9352
+ closable: this.closable,
9353
+ pauseOnPageIdle: this.pauseOnPageIdle,
9354
+ translations: this.translations,
9355
+ onStatusChange: this.notifyStatus,
9356
+ onAction: this.notifyAction
9357
+ };
9358
+ }
9359
+ /** 这个部件的文字归不归作者:头一回见到它时定案,之后不再改口。 */
9360
+ authorOwnsText = /* @__PURE__ */ new WeakMap();
9361
+ /**
9362
+ * 作者没往部件里写内容时,用 props 上的文案填进去。
9363
+ *
9364
+ * 归属只判一次:判完本轮就会把文字写进去,再回读分不清是作者写的还是自己写的,
9365
+ * 从那以后 title 属性改了也再刷不动(Vue 侧是响应式渲染,会跟着改,两侧就此分叉)。
9366
+ */
9367
+ fillText(el, text) {
9368
+ if (!el) return;
9369
+ let authored = this.authorOwnsText.get(el);
9370
+ if (authored === void 0) {
9371
+ authored = el.childElementCount > 0 || (el.textContent ?? "").trim() !== "";
9372
+ this.authorOwnsText.set(el, authored);
9373
+ }
9374
+ if (authored) return;
9375
+ const next = text ?? "";
9376
+ if (el.textContent !== next) el.textContent = next;
9377
+ }
9378
+ wire() {
9379
+ const api = connectNotificationItem(this.ctrl.service, wcNormalize);
9380
+ const put = (name, props) => {
9381
+ const el = this.getPart(name);
9382
+ if (el) this.spreader.spread(el, props);
9383
+ };
9384
+ put("item", api.getItemProps());
9385
+ put("item-indicator", api.getItemIndicatorProps());
9386
+ put("item-title", api.getItemTitleProps());
9387
+ put("item-description", api.getItemDescriptionProps());
9388
+ put("item-action-trigger", api.getItemActionTriggerProps());
9389
+ put("item-close-trigger", api.getItemCloseTriggerProps());
9390
+ this.fillText(this.getPart("item-title"), api.title);
9391
+ this.fillText(this.getPart("item-description"), api.description);
9392
+ this.setPartHidden(this.getPart("item"), api.status === "unmounted");
9393
+ this.setPartHidden(this.getPart("item-close-trigger"), !api.closable);
9394
+ }
9395
+ };
9396
+ //#endregion
9397
+ //#region src/elements/number-animation.ts
9398
+ const STRING_CONVERTER$45 = { fromAttribute: (v) => v ?? void 0 };
9399
+ const NUMBER_CONVERTER$25 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
9400
+ const BOOLEAN_CONVERTER$32 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
9401
+ /**
9402
+ * `<xh-number-animation>` —— Light-DOM 行为宿主:作者写一个 root 角色节点,
9403
+ * 元素跑 number-animation 机器,逐帧把补间算出的数字格式化后写进那个节点。
9404
+ *
9405
+ * 参数改写分两路:改 `from` 是"换起点",数字当场落到新起点再重跑;
9406
+ * 改 `to` / `duration` / `easing` 是"换目标",从当前数字接着走,不跳回起点。
9407
+ * 已经跑完停在 idle 时改 `to` 同样会重新跑起来,所以"数字跟着数据走"不必额外拨 `active`。
9408
+ *
9409
+ * 根是 role="status" 但 aria-live 缺省写死 off:status 的隐含 aria-live 就是 polite,
9410
+ * 一个每帧都在变的数字用 polite 会把读屏刷爆,要播报由作者把 live 开到 polite 或 assertive。
9411
+ *
9412
+ * @customElement xh-number-animation
9413
+ * @attr {number} from - 起点,缺省 0
9414
+ * @attr {number} to - 终点,缺省 0
9415
+ * @attr {number} duration - 时长毫秒,缺省 1000;<=0 即一步到位
9416
+ * @attr {'linear'|'ease-in'|'ease-out'|'ease-in-out'} easing - 缓动,缺省 linear
9417
+ * @attr {number} precision - 小数位,缺省 0
9418
+ * @attr {string} separator - 千位分隔符,缺省不分隔
9419
+ * @attr {boolean} active - 是否在跑,缺省真;`active="false"` 停在当前值
9420
+ * @attr {'sm'|'md'|'lg'} size - 尺寸,只改字号
9421
+ * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气,决定数字用哪族颜色
9422
+ * @attr {'off'|'polite'|'assertive'} live - 读屏播报档位,缺省 off
9423
+ * @fires finish - 走到终点;detail 为 `{ value: number }`
9424
+ * @csspart root - 数字本身(承载 status 语义、data-state 与两个视觉轴);文字归元素写
8904
9425
  */
8905
9426
  var XhNumberAnimationElement = class extends XhElement {
8906
9427
  static partContract = {
@@ -8911,13 +9432,13 @@ var XhNumberAnimationElement = class extends XhElement {
8911
9432
  from: { converter: NUMBER_CONVERTER$25 },
8912
9433
  to: { converter: NUMBER_CONVERTER$25 },
8913
9434
  duration: { converter: NUMBER_CONVERTER$25 },
8914
- easing: { converter: STRING_CONVERTER$46 },
9435
+ easing: { converter: STRING_CONVERTER$45 },
8915
9436
  precision: { converter: NUMBER_CONVERTER$25 },
8916
- separator: { converter: STRING_CONVERTER$46 },
8917
- active: { converter: BOOLEAN_CONVERTER$33 },
8918
- size: { converter: STRING_CONVERTER$46 },
8919
- tone: { converter: STRING_CONVERTER$46 },
8920
- live: { converter: STRING_CONVERTER$46 }
9437
+ separator: { converter: STRING_CONVERTER$45 },
9438
+ active: { converter: BOOLEAN_CONVERTER$32 },
9439
+ size: { converter: STRING_CONVERTER$45 },
9440
+ tone: { converter: STRING_CONVERTER$45 },
9441
+ live: { converter: STRING_CONVERTER$45 }
8921
9442
  };
8922
9443
  notify = (details) => {
8923
9444
  this.dispatchEvent(new CustomEvent("finish", {
@@ -8952,7 +9473,7 @@ var XhNumberAnimationElement = class extends XhElement {
8952
9473
  };
8953
9474
  //#endregion
8954
9475
  //#region src/elements/number-field.ts
8955
- const STRING_CONVERTER$45 = { fromAttribute: (v) => v ?? void 0 };
9476
+ const STRING_CONVERTER$44 = { fromAttribute: (v) => v ?? void 0 };
8956
9477
  const NUMBER_CONVERTER$24 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
8957
9478
  /**
8958
9479
  * `<xh-number-field>` —— Light-DOM 行为宿主:作者写 root/label/input/加减按钮四类角色节点,
@@ -8994,9 +9515,9 @@ var XhNumberFieldElement = class extends XhElement {
8994
9515
  meta: numberFieldMeta
8995
9516
  };
8996
9517
  static properties = {
8997
- value: { converter: STRING_CONVERTER$45 },
9518
+ value: { converter: STRING_CONVERTER$44 },
8998
9519
  defaultValue: {
8999
- converter: STRING_CONVERTER$45,
9520
+ converter: STRING_CONVERTER$44,
9000
9521
  attribute: "default-value"
9001
9522
  },
9002
9523
  min: { converter: NUMBER_CONVERTER$24 },
@@ -9013,7 +9534,7 @@ var XhNumberFieldElement = class extends XhElement {
9013
9534
  },
9014
9535
  required: { type: Boolean },
9015
9536
  invalid: { type: Boolean },
9016
- name: { converter: STRING_CONVERTER$45 },
9537
+ name: { converter: STRING_CONVERTER$44 },
9017
9538
  changeDelay: {
9018
9539
  converter: NUMBER_CONVERTER$24,
9019
9540
  attribute: "change-delay"
@@ -9022,9 +9543,9 @@ var XhNumberFieldElement = class extends XhElement {
9022
9543
  converter: NUMBER_CONVERTER$24,
9023
9544
  attribute: "change-interval"
9024
9545
  },
9025
- variant: { converter: STRING_CONVERTER$45 },
9026
- tone: { converter: STRING_CONVERTER$45 },
9027
- size: { converter: STRING_CONVERTER$45 },
9546
+ variant: { converter: STRING_CONVERTER$44 },
9547
+ tone: { converter: STRING_CONVERTER$44 },
9548
+ size: { converter: STRING_CONVERTER$44 },
9028
9549
  parse: { attribute: false },
9029
9550
  format: { attribute: false }
9030
9551
  };
@@ -9075,7 +9596,7 @@ var XhNumberFieldElement = class extends XhElement {
9075
9596
  };
9076
9597
  //#endregion
9077
9598
  //#region src/elements/page-header.ts
9078
- const STRING_CONVERTER$44 = { fromAttribute: (v) => v ?? void 0 };
9599
+ const STRING_CONVERTER$43 = { fromAttribute: (v) => v ?? void 0 };
9079
9600
  /**
9080
9601
  * `<xh-page-header>` —— Light-DOM 行为宿主,无状态机,把 connectPageHeader 产出打到各角色节点。
9081
9602
  * 除 root 外的部件全部可缺省:返回位、标题、副标题、操作、页脚按需摆。
@@ -9099,7 +9620,7 @@ var XhPageHeaderElement = class extends XhElement {
9099
9620
  meta: pageHeaderMeta
9100
9621
  };
9101
9622
  static properties = {
9102
- size: { converter: STRING_CONVERTER$44 },
9623
+ size: { converter: STRING_CONVERTER$43 },
9103
9624
  bordered: { type: Boolean }
9104
9625
  };
9105
9626
  wire() {
@@ -9122,7 +9643,7 @@ var XhPageHeaderElement = class extends XhElement {
9122
9643
  //#endregion
9123
9644
  //#region src/elements/pagination.ts
9124
9645
  const NUMBER_CONVERTER$23 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
9125
- const STRING_CONVERTER$43 = { fromAttribute: (v) => v ?? void 0 };
9646
+ const STRING_CONVERTER$42 = { fromAttribute: (v) => v ?? void 0 };
9126
9647
  /** 页码按钮自报的页数;缺失或空串一律给 NaN(见 wire 里的说明)。 */
9127
9648
  function itemPage(el) {
9128
9649
  const raw = el.getAttribute("value");
@@ -9148,11 +9669,18 @@ function itemPage(el) {
9148
9669
  * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气
9149
9670
  * @attr {'sm'|'md'|'lg'} size - 尺寸
9150
9671
  * @fires page-change - 页码变化;detail 为 `{ page: number, pageSize: number }`
9672
+ * @fires page-size-change - 每页条数变化;detail 为 `{ pageSize: number, page: number }`,页码是换算后的
9673
+ * @attr {string} placement - 省略位摊开后的落点,默认 bottom-start
9674
+ * @attr {number} offset - 浮层与省略位之间的间距(px),默认 8
9675
+ * @attr {number} open-delay - 指针停在省略位多久才摊开(ms),默认 200
9676
+ * @attr {number} close-delay - 指针离开后多久收起(ms),默认 300
9677
+ * @attr {number} default-page-size - 非受控初始每页条数,默认 10
9678
+ * @prop {number[]} pageSizeOptions - 可选的每页条数档位,默认 [10, 20, 50, 100]
9151
9679
  * @csspart root - nav 地标,承载 aria-label 与 data-empty
9152
9680
  * @csspart prev-trigger - 上一页;首页时转原生 disabled
9153
9681
  * @csspart next-trigger - 下一页;末页时转原生 disabled
9154
9682
  * @csspart item - 页码按钮,须自带 value 属性;当前页带 aria-current="page" 与 data-current
9155
- * @csspart ellipsis - 折叠掉的那几页的占位,对读屏隐藏
9683
+ * @csspart ellipsis - 折进去那几页的入口,须自带 side 属性(start / end);承载 data-side 与 aria-expanded
9156
9684
  */
9157
9685
  var XhPaginationElement = class extends XhElement {
9158
9686
  static partContract = {
@@ -9165,6 +9693,11 @@ var XhPaginationElement = class extends XhElement {
9165
9693
  converter: NUMBER_CONVERTER$23,
9166
9694
  attribute: "page-size"
9167
9695
  },
9696
+ defaultPageSize: {
9697
+ converter: NUMBER_CONVERTER$23,
9698
+ attribute: "default-page-size"
9699
+ },
9700
+ pageSizeOptions: { attribute: false },
9168
9701
  page: { converter: NUMBER_CONVERTER$23 },
9169
9702
  defaultPage: {
9170
9703
  converter: NUMBER_CONVERTER$23,
@@ -9175,13 +9708,29 @@ var XhPaginationElement = class extends XhElement {
9175
9708
  attribute: "sibling-count"
9176
9709
  },
9177
9710
  direction: {
9178
- converter: STRING_CONVERTER$43,
9711
+ converter: STRING_CONVERTER$42,
9179
9712
  attribute: "dir"
9180
9713
  },
9181
- tone: { converter: STRING_CONVERTER$43 },
9182
- size: { converter: STRING_CONVERTER$43 },
9183
- translations: { attribute: false }
9714
+ tone: { converter: STRING_CONVERTER$42 },
9715
+ size: { converter: STRING_CONVERTER$42 },
9716
+ translations: { attribute: false },
9717
+ placement: { converter: STRING_CONVERTER$42 },
9718
+ offset: { converter: NUMBER_CONVERTER$23 },
9719
+ openDelay: {
9720
+ converter: NUMBER_CONVERTER$23,
9721
+ attribute: "open-delay"
9722
+ },
9723
+ closeDelay: {
9724
+ converter: NUMBER_CONVERTER$23,
9725
+ attribute: "close-delay"
9726
+ }
9184
9727
  };
9728
+ idGen = createCounterIdGenerator();
9729
+ paginationScope = createScope(null, this.idGen);
9730
+ positionEngine = createPositionEngine();
9731
+ config = null;
9732
+ /** 退场闸门:收起从跟着展开态走改成跟着 presence 走,退场动画播完才真收。 */
9733
+ exit = null;
9185
9734
  notify = (details) => {
9186
9735
  this.dispatchEvent(new CustomEvent("page-change", {
9187
9736
  detail: details,
@@ -9189,11 +9738,69 @@ var XhPaginationElement = class extends XhElement {
9189
9738
  composed: true
9190
9739
  }));
9191
9740
  };
9192
- ctrl = new MachineController(this, paginationMachine, () => this.machineProps());
9741
+ notifyPageSize = (details) => {
9742
+ this.dispatchEvent(new CustomEvent("page-size-change", {
9743
+ detail: details,
9744
+ bubbles: true,
9745
+ composed: true
9746
+ }));
9747
+ };
9748
+ ctrl = new MachineController(this, paginationMachine, () => this.machineProps(), {
9749
+ scope: this.paginationScope,
9750
+ onBuilt: (svc) => this.injectRefs(svc)
9751
+ });
9752
+ /** 折叠页码列表的自绘条:与 content 同级挂在已经 fixed 的 positioner 上 */
9753
+ bars = new ScrollbarsController(this, {
9754
+ shell: () => this.getPart("positioner"),
9755
+ scrollable: () => this.getPart("content")
9756
+ });
9757
+ ensureConfig() {
9758
+ if (this.config) return;
9759
+ this.config = createRuntimeConfig({
9760
+ scope: this.paginationScope,
9761
+ idGenerator: this.idGen
9762
+ });
9763
+ }
9764
+ /** 此刻摊开的是哪个省略位的节点——它是定位锚点。 */
9765
+ openEllipsisEl(side) {
9766
+ if (!side) return null;
9767
+ for (const el of this.getParts("ellipsis")) if (el.getAttribute("data-side") === side) return el;
9768
+ return null;
9769
+ }
9770
+ registerLayer = () => {
9771
+ this.ensureConfig();
9772
+ return this.config.layerRegistry.register({
9773
+ kind: "popover",
9774
+ node: () => this.getPart("content"),
9775
+ branches: () => [...this.getParts("ellipsis"), this.getPart("positioner")].filter(Boolean),
9776
+ isModal: () => false,
9777
+ setModal: () => {},
9778
+ surfaces: () => []
9779
+ });
9780
+ };
9781
+ injectRefs(svc) {
9782
+ this.ensureConfig();
9783
+ svc.refs.set("config", this.config);
9784
+ svc.refs.set("registerLayer", this.registerLayer);
9785
+ svc.refs.set("position", this.positionEngine);
9786
+ svc.refs.set("getAnchorEl", () => this.openEllipsisEl(svc.context.get("openEllipsis")));
9787
+ svc.refs.set("getFloatingEl", () => this.getPart("positioner"));
9788
+ svc.refs.set("getContentEl", () => this.getPart("content"));
9789
+ }
9790
+ /**
9791
+ * 角色节点提前发现一次:常规发现要等首次 updated,那一刻 partMap 还空着,
9792
+ * 引擎挂不上,浮层会停在容器左上角。
9793
+ */
9794
+ connectedCallback() {
9795
+ this.refreshParts();
9796
+ super.connectedCallback();
9797
+ }
9193
9798
  machineProps() {
9194
9799
  return {
9195
9800
  count: this.count,
9196
9801
  pageSize: this.pageSize,
9802
+ defaultPageSize: this.defaultPageSize,
9803
+ pageSizeOptions: this.pageSizeOptions,
9197
9804
  page: this.page,
9198
9805
  defaultPage: this.defaultPage,
9199
9806
  siblingCount: this.siblingCount,
@@ -9201,7 +9808,12 @@ var XhPaginationElement = class extends XhElement {
9201
9808
  tone: this.tone,
9202
9809
  size: this.size,
9203
9810
  translations: this.translations,
9204
- onPageChange: this.notify
9811
+ placement: this.placement,
9812
+ offset: this.offset,
9813
+ openDelay: this.openDelay,
9814
+ closeDelay: this.closeDelay,
9815
+ onPageChange: this.notify,
9816
+ onPageSizeChange: this.notifyPageSize
9205
9817
  };
9206
9818
  }
9207
9819
  wire() {
@@ -9217,13 +9829,37 @@ var XhPaginationElement = class extends XhElement {
9217
9829
  const props = api.getItemProps({ page: itemPage(el) });
9218
9830
  this.spreader.spread(el, props);
9219
9831
  }
9220
- for (const el of this.getParts("ellipsis")) this.spreader.spread(el, api.getEllipsisProps());
9832
+ for (const el of this.getParts("ellipsis")) {
9833
+ const side = el.getAttribute("side") === "end" ? "end" : "start";
9834
+ this.spreader.spread(el, api.getEllipsisProps({ side }));
9835
+ }
9836
+ put("page-size-select", api.getPageSizeSelectProps());
9837
+ put("positioner", api.getPositionerProps());
9838
+ put("content", api.getContentProps());
9839
+ const content = this.getPart("content");
9840
+ this.ensureConfig();
9841
+ this.exit ??= createOverlayExit({
9842
+ config: this.config,
9843
+ open: api.openEllipsis != null,
9844
+ onExitComplete: () => this.requestUpdate()
9845
+ });
9846
+ this.exit.track(content);
9847
+ this.exit.update(api.openEllipsis != null);
9848
+ this.setPartHidden(content, !this.exit.visible);
9849
+ this.bars.wire();
9850
+ }
9851
+ disconnectedCallback() {
9852
+ super.disconnectedCallback();
9853
+ this.exit?.dispose();
9854
+ this.exit = null;
9855
+ this.setPartHidden(this.getPart("content"), true);
9856
+ this.config = null;
9221
9857
  }
9222
9858
  };
9223
9859
  //#endregion
9224
9860
  //#region src/elements/password-input.ts
9225
- const STRING_CONVERTER$42 = { fromAttribute: (v) => v ?? void 0 };
9226
- const BOOLEAN_CONVERTER$32 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
9861
+ const STRING_CONVERTER$41 = { fromAttribute: (v) => v ?? void 0 };
9862
+ const BOOLEAN_CONVERTER$31 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
9227
9863
  /**
9228
9864
  * `<xh-password-input>` —— Light-DOM 行为宿主:作者写 root/label/control/input/
9229
9865
  * visibility-trigger/caps-lock-indicator 六类角色节点,元素跑 password-input 机器并把 connect 产出打上去。
@@ -9268,32 +9904,32 @@ var XhPasswordInputElement = class extends XhElement {
9268
9904
  meta: passwordInputMeta
9269
9905
  };
9270
9906
  static properties = {
9271
- value: { converter: STRING_CONVERTER$42 },
9907
+ value: { converter: STRING_CONVERTER$41 },
9272
9908
  defaultValue: {
9273
- converter: STRING_CONVERTER$42,
9909
+ converter: STRING_CONVERTER$41,
9274
9910
  attribute: "default-value"
9275
9911
  },
9276
- visible: { converter: BOOLEAN_CONVERTER$32 },
9912
+ visible: { converter: BOOLEAN_CONVERTER$31 },
9277
9913
  defaultVisible: {
9278
- converter: BOOLEAN_CONVERTER$32,
9914
+ converter: BOOLEAN_CONVERTER$31,
9279
9915
  attribute: "default-visible"
9280
9916
  },
9281
- disabled: { converter: BOOLEAN_CONVERTER$32 },
9917
+ disabled: { converter: BOOLEAN_CONVERTER$31 },
9282
9918
  readOnly: {
9283
- converter: BOOLEAN_CONVERTER$32,
9919
+ converter: BOOLEAN_CONVERTER$31,
9284
9920
  attribute: "read-only"
9285
9921
  },
9286
- required: { converter: BOOLEAN_CONVERTER$32 },
9287
- invalid: { converter: BOOLEAN_CONVERTER$32 },
9288
- name: { converter: STRING_CONVERTER$42 },
9289
- placeholder: { converter: STRING_CONVERTER$42 },
9922
+ required: { converter: BOOLEAN_CONVERTER$31 },
9923
+ invalid: { converter: BOOLEAN_CONVERTER$31 },
9924
+ name: { converter: STRING_CONVERTER$41 },
9925
+ placeholder: { converter: STRING_CONVERTER$41 },
9290
9926
  autoComplete: {
9291
- converter: STRING_CONVERTER$42,
9927
+ converter: STRING_CONVERTER$41,
9292
9928
  attribute: "auto-complete"
9293
9929
  },
9294
- variant: { converter: STRING_CONVERTER$42 },
9295
- tone: { converter: STRING_CONVERTER$42 },
9296
- size: { converter: STRING_CONVERTER$42 },
9930
+ variant: { converter: STRING_CONVERTER$41 },
9931
+ tone: { converter: STRING_CONVERTER$41 },
9932
+ size: { converter: STRING_CONVERTER$41 },
9297
9933
  translations: { attribute: false }
9298
9934
  };
9299
9935
  notifyValue = (details) => {
@@ -9350,7 +9986,7 @@ var XhPasswordInputElement = class extends XhElement {
9350
9986
  };
9351
9987
  //#endregion
9352
9988
  //#region src/elements/pin-input.ts
9353
- const STRING_CONVERTER$41 = { fromAttribute: (v) => v ?? void 0 };
9989
+ const STRING_CONVERTER$40 = { fromAttribute: (v) => v ?? void 0 };
9354
9990
  const NUMBER_CONVERTER$22 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
9355
9991
  const ARRAY_CONVERTER$1 = { fromAttribute: (v) => v == null ? void 0 : [...v] };
9356
9992
  /** 作者写在格子上的下标。缺席或写坏了就退回文档序——手写 HTML 时把格子按顺序排下来本身就是声明。 */
@@ -9403,21 +10039,21 @@ var XhPinInputElement = class extends XhElement {
9403
10039
  attribute: "default-value"
9404
10040
  },
9405
10041
  length: { converter: NUMBER_CONVERTER$22 },
9406
- type: { converter: STRING_CONVERTER$41 },
9407
- pattern: { converter: STRING_CONVERTER$41 },
10042
+ type: { converter: STRING_CONVERTER$40 },
10043
+ pattern: { converter: STRING_CONVERTER$40 },
9408
10044
  mask: { type: Boolean },
9409
10045
  otp: { type: Boolean },
9410
- placeholder: { converter: STRING_CONVERTER$41 },
10046
+ placeholder: { converter: STRING_CONVERTER$40 },
9411
10047
  disabled: { type: Boolean },
9412
10048
  invalid: { type: Boolean },
9413
10049
  blurOnComplete: {
9414
10050
  type: Boolean,
9415
10051
  attribute: "blur-on-complete"
9416
10052
  },
9417
- name: { converter: STRING_CONVERTER$41 },
9418
- variant: { converter: STRING_CONVERTER$41 },
9419
- tone: { converter: STRING_CONVERTER$41 },
9420
- size: { converter: STRING_CONVERTER$41 },
10053
+ name: { converter: STRING_CONVERTER$40 },
10054
+ variant: { converter: STRING_CONVERTER$40 },
10055
+ tone: { converter: STRING_CONVERTER$40 },
10056
+ size: { converter: STRING_CONVERTER$40 },
9421
10057
  translations: { attribute: false }
9422
10058
  };
9423
10059
  notifyChange = (details) => {
@@ -9474,9 +10110,9 @@ var XhPinInputElement = class extends XhElement {
9474
10110
  };
9475
10111
  //#endregion
9476
10112
  //#region src/elements/popconfirm.ts
9477
- const STRING_CONVERTER$40 = { fromAttribute: (v) => v ?? void 0 };
10113
+ const STRING_CONVERTER$39 = { fromAttribute: (v) => v ?? void 0 };
9478
10114
  const NUMBER_CONVERTER$21 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
9479
- const BOOLEAN_CONVERTER$31 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
10115
+ const BOOLEAN_CONVERTER$30 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
9480
10116
  /**
9481
10117
  * `<xh-popconfirm>` —— Light-DOM 行为宿主:用户写 root/trigger/positioner/content/... 角色节点,
9482
10118
  * 元素跑 popover 机器(开合、定位、消解层、焦点域都在那里)并把 connectPopconfirm 产出打上去。
@@ -9513,22 +10149,22 @@ var XhPopconfirmElement = class extends XhElement {
9513
10149
  meta: popconfirmMeta
9514
10150
  };
9515
10151
  static properties = {
9516
- open: { converter: BOOLEAN_CONVERTER$31 },
10152
+ open: { converter: BOOLEAN_CONVERTER$30 },
9517
10153
  defaultOpen: {
9518
10154
  type: Boolean,
9519
10155
  attribute: "default-open"
9520
10156
  },
9521
- placement: { converter: STRING_CONVERTER$40 },
10157
+ placement: { converter: STRING_CONVERTER$39 },
9522
10158
  offset: { converter: NUMBER_CONVERTER$21 },
9523
10159
  closeOnEscape: {
9524
- converter: BOOLEAN_CONVERTER$31,
10160
+ converter: BOOLEAN_CONVERTER$30,
9525
10161
  attribute: "close-on-escape"
9526
10162
  },
9527
10163
  closeOnInteractOutside: {
9528
- converter: BOOLEAN_CONVERTER$31,
10164
+ converter: BOOLEAN_CONVERTER$30,
9529
10165
  attribute: "close-on-interact-outside"
9530
10166
  },
9531
- size: { converter: STRING_CONVERTER$40 }
10167
+ size: { converter: STRING_CONVERTER$39 }
9532
10168
  };
9533
10169
  idGen = createCounterIdGenerator();
9534
10170
  popconfirmScope = createScope(null, this.idGen);
@@ -9654,9 +10290,9 @@ var XhPopconfirmElement = class extends XhElement {
9654
10290
  };
9655
10291
  //#endregion
9656
10292
  //#region src/elements/popover.ts
9657
- const STRING_CONVERTER$39 = { fromAttribute: (v) => v ?? void 0 };
10293
+ const STRING_CONVERTER$38 = { fromAttribute: (v) => v ?? void 0 };
9658
10294
  const NUMBER_CONVERTER$20 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
9659
- const BOOLEAN_CONVERTER$30 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
10295
+ const BOOLEAN_CONVERTER$29 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
9660
10296
  /**
9661
10297
  * `<xh-popover>` —— Light-DOM 行为宿主:用户写 trigger/positioner/content/... 角色节点,
9662
10298
  * 元素跑 popover 机器并把 connect 产出打上去。浮层定位引擎在本元素里建好、经 refs 注入机器,
@@ -9686,23 +10322,23 @@ var XhPopoverElement = class extends XhElement {
9686
10322
  meta: popoverMeta
9687
10323
  };
9688
10324
  static properties = {
9689
- open: { converter: BOOLEAN_CONVERTER$30 },
10325
+ open: { converter: BOOLEAN_CONVERTER$29 },
9690
10326
  defaultOpen: {
9691
10327
  type: Boolean,
9692
10328
  attribute: "default-open"
9693
10329
  },
9694
- placement: { converter: STRING_CONVERTER$39 },
10330
+ placement: { converter: STRING_CONVERTER$38 },
9695
10331
  offset: { converter: NUMBER_CONVERTER$20 },
9696
- modal: { converter: BOOLEAN_CONVERTER$30 },
10332
+ modal: { converter: BOOLEAN_CONVERTER$29 },
9697
10333
  closeOnEscape: {
9698
- converter: BOOLEAN_CONVERTER$30,
10334
+ converter: BOOLEAN_CONVERTER$29,
9699
10335
  attribute: "close-on-escape"
9700
10336
  },
9701
10337
  closeOnInteractOutside: {
9702
- converter: BOOLEAN_CONVERTER$30,
10338
+ converter: BOOLEAN_CONVERTER$29,
9703
10339
  attribute: "close-on-interact-outside"
9704
10340
  },
9705
- size: { converter: STRING_CONVERTER$39 },
10341
+ size: { converter: STRING_CONVERTER$38 },
9706
10342
  translations: { attribute: false }
9707
10343
  };
9708
10344
  idGen = createCounterIdGenerator();
@@ -9722,6 +10358,11 @@ var XhPopoverElement = class extends XhElement {
9722
10358
  scope: this.popoverScope,
9723
10359
  onBuilt: (svc) => this.injectRefs(svc)
9724
10360
  });
10361
+ /** 面板内容的自绘条:与 content 同级挂在已经 fixed 的 positioner 上 */
10362
+ bars = new ScrollbarsController(this, {
10363
+ shell: () => this.getPart("positioner"),
10364
+ scrollable: () => this.getPart("content")
10365
+ });
9725
10366
  machineProps() {
9726
10367
  return {
9727
10368
  open: this.open,
@@ -9748,7 +10389,7 @@ var XhPopoverElement = class extends XhElement {
9748
10389
  return this.config.layerRegistry.register({
9749
10390
  kind: "popover",
9750
10391
  node: () => this.getPart("content"),
9751
- branches: () => [this.getPart("trigger")].filter(Boolean),
10392
+ branches: () => [this.getPart("trigger"), this.getPart("positioner")].filter(Boolean),
9752
10393
  isModal: () => this.modal ?? false,
9753
10394
  setModal: () => {},
9754
10395
  surfaces: () => []
@@ -9796,6 +10437,7 @@ var XhPopoverElement = class extends XhElement {
9796
10437
  this.exit.track(content);
9797
10438
  this.exit.update(api.open);
9798
10439
  if (content) this.setPartHidden(content, !this.exit.visible);
10440
+ this.bars.wire();
9799
10441
  }
9800
10442
  disconnectedCallback() {
9801
10443
  super.disconnectedCallback();
@@ -9807,9 +10449,9 @@ var XhPopoverElement = class extends XhElement {
9807
10449
  };
9808
10450
  //#endregion
9809
10451
  //#region src/elements/popselect.ts
9810
- const STRING_CONVERTER$38 = { fromAttribute: (v) => v ?? void 0 };
10452
+ const STRING_CONVERTER$37 = { fromAttribute: (v) => v ?? void 0 };
9811
10453
  const NUMBER_CONVERTER$19 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
9812
- const BOOLEAN_CONVERTER$29 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
10454
+ const BOOLEAN_CONVERTER$28 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
9813
10455
  /**
9814
10456
  * `<xh-popselect>` —— Light-DOM 行为宿主:作者写 root/trigger/positioner/content/item 角色节点,
9815
10457
  * 元素同时跑两台机器——浮层开合、定位、消解层与焦点域归 popover,选中集合与焦点锚点归 listbox——
@@ -9858,37 +10500,37 @@ var XhPopselectElement = class extends XhElement {
9858
10500
  };
9859
10501
  static properties = {
9860
10502
  collection: { attribute: false },
9861
- value: { converter: STRING_CONVERTER$38 },
10503
+ value: { converter: STRING_CONVERTER$37 },
9862
10504
  defaultValue: {
9863
- converter: STRING_CONVERTER$38,
10505
+ converter: STRING_CONVERTER$37,
9864
10506
  attribute: "default-value"
9865
10507
  },
9866
10508
  multiple: { type: Boolean },
9867
10509
  disabled: { type: Boolean },
9868
- loop: { converter: BOOLEAN_CONVERTER$29 },
9869
- typeahead: { converter: BOOLEAN_CONVERTER$29 },
10510
+ loop: { converter: BOOLEAN_CONVERTER$28 },
10511
+ typeahead: { converter: BOOLEAN_CONVERTER$28 },
9870
10512
  direction: {
9871
- converter: STRING_CONVERTER$38,
10513
+ converter: STRING_CONVERTER$37,
9872
10514
  attribute: "dir"
9873
10515
  },
9874
- open: { converter: BOOLEAN_CONVERTER$29 },
10516
+ open: { converter: BOOLEAN_CONVERTER$28 },
9875
10517
  defaultOpen: {
9876
10518
  type: Boolean,
9877
10519
  attribute: "default-open"
9878
10520
  },
9879
- placement: { converter: STRING_CONVERTER$38 },
10521
+ placement: { converter: STRING_CONVERTER$37 },
9880
10522
  offset: { converter: NUMBER_CONVERTER$19 },
9881
10523
  closeOnEscape: {
9882
- converter: BOOLEAN_CONVERTER$29,
10524
+ converter: BOOLEAN_CONVERTER$28,
9883
10525
  attribute: "close-on-escape"
9884
10526
  },
9885
10527
  closeOnInteractOutside: {
9886
- converter: BOOLEAN_CONVERTER$29,
10528
+ converter: BOOLEAN_CONVERTER$28,
9887
10529
  attribute: "close-on-interact-outside"
9888
10530
  },
9889
- variant: { converter: STRING_CONVERTER$38 },
9890
- tone: { converter: STRING_CONVERTER$38 },
9891
- size: { converter: STRING_CONVERTER$38 },
10531
+ variant: { converter: STRING_CONVERTER$37 },
10532
+ tone: { converter: STRING_CONVERTER$37 },
10533
+ size: { converter: STRING_CONVERTER$37 },
9892
10534
  translations: { attribute: false }
9893
10535
  };
9894
10536
  idGen = createCounterIdGenerator();
@@ -9916,6 +10558,11 @@ var XhPopselectElement = class extends XhElement {
9916
10558
  onBuilt: (svc) => this.injectRefs(svc)
9917
10559
  });
9918
10560
  listboxCtrl = new MachineController(this, listboxMachine, () => this.listboxProps(), { scope: this.popselectScope });
10561
+ /** 候选列表的自绘条:与 content 同级挂在已经 fixed 的 positioner 上 */
10562
+ bars = new ScrollbarsController(this, {
10563
+ shell: () => this.getPart("positioner"),
10564
+ scrollable: () => this.getPart("content")
10565
+ });
9919
10566
  /** 作者声明的条目禁用,只认首见那一份;没写即 undefined,交给 collection 定夺 */
9920
10567
  declaredDisabled = createDeclaredDisabled();
9921
10568
  popoverProps() {
@@ -9955,7 +10602,7 @@ var XhPopselectElement = class extends XhElement {
9955
10602
  return this.config.layerRegistry.register({
9956
10603
  kind: "popover",
9957
10604
  node: () => this.getPart("content"),
9958
- branches: () => [this.getPart("trigger")].filter(Boolean),
10605
+ branches: () => [this.getPart("trigger"), this.getPart("positioner")].filter(Boolean),
9959
10606
  isModal: () => false,
9960
10607
  setModal: () => {},
9961
10608
  surfaces: () => []
@@ -10039,6 +10686,7 @@ var XhPopselectElement = class extends XhElement {
10039
10686
  this.exit.track(content);
10040
10687
  this.exit.update(api.open);
10041
10688
  this.setPartHidden(content, !this.exit.visible);
10689
+ this.bars.wire();
10042
10690
  }
10043
10691
  disconnectedCallback() {
10044
10692
  super.disconnectedCallback();
@@ -10131,7 +10779,7 @@ var XhProgressElement = class extends XhElement {
10131
10779
  };
10132
10780
  //#endregion
10133
10781
  //#region src/elements/qr-code.ts
10134
- const STRING_CONVERTER$37 = { fromAttribute: (v) => v ?? void 0 };
10782
+ const STRING_CONVERTER$36 = { fromAttribute: (v) => v ?? void 0 };
10135
10783
  const SVG_NS = "http://www.w3.org/2000/svg";
10136
10784
  /** 本元素生成的几何节点的标记:作者写的节点不带它,重画时只清掉自己生成的那几个。 */
10137
10785
  const GEOM_ATTR = "data-xh-geom";
@@ -10176,20 +10824,20 @@ var XhQrCodeElement = class extends XhElement {
10176
10824
  }
10177
10825
  };
10178
10826
  static properties = {
10179
- value: { converter: STRING_CONVERTER$37 },
10180
- level: { converter: STRING_CONVERTER$37 },
10181
- label: { converter: STRING_CONVERTER$37 },
10827
+ value: { converter: STRING_CONVERTER$36 },
10828
+ level: { converter: STRING_CONVERTER$36 },
10829
+ label: { converter: STRING_CONVERTER$36 },
10182
10830
  pixelSize: {
10183
10831
  type: Number,
10184
10832
  attribute: "pixel-size"
10185
10833
  },
10186
10834
  margin: { type: Number },
10187
10835
  moduleShape: {
10188
- converter: STRING_CONVERTER$37,
10836
+ converter: STRING_CONVERTER$36,
10189
10837
  attribute: "module-shape"
10190
10838
  },
10191
10839
  eyeShape: {
10192
- converter: STRING_CONVERTER$37,
10840
+ converter: STRING_CONVERTER$36,
10193
10841
  attribute: "eye-shape"
10194
10842
  }
10195
10843
  };
@@ -10402,9 +11050,9 @@ var XhRadioGroupElement = class extends XhElement {
10402
11050
  };
10403
11051
  //#endregion
10404
11052
  //#region src/elements/rating.ts
10405
- const STRING_CONVERTER$36 = { fromAttribute: (v) => v ?? void 0 };
11053
+ const STRING_CONVERTER$35 = { fromAttribute: (v) => v ?? void 0 };
10406
11054
  const NUMBER_CONVERTER$18 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
10407
- const BOOLEAN_CONVERTER$28 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
11055
+ const BOOLEAN_CONVERTER$27 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
10408
11056
  /**
10409
11057
  * `<xh-rating>` —— Light-DOM 行为宿主:作者写 root/label/control 与若干 item 角色节点
10410
11058
  * (可选再写一个 hidden-input 参与表单提交),元素跑 rating 机器并把 connect 产出打上去。
@@ -10447,26 +11095,26 @@ var XhRatingElement = class extends XhElement {
10447
11095
  },
10448
11096
  count: { converter: NUMBER_CONVERTER$18 },
10449
11097
  allowHalf: {
10450
- converter: BOOLEAN_CONVERTER$28,
11098
+ converter: BOOLEAN_CONVERTER$27,
10451
11099
  attribute: "allow-half"
10452
11100
  },
10453
11101
  allowClear: {
10454
- converter: BOOLEAN_CONVERTER$28,
11102
+ converter: BOOLEAN_CONVERTER$27,
10455
11103
  attribute: "allow-clear"
10456
11104
  },
10457
- disabled: { converter: BOOLEAN_CONVERTER$28 },
11105
+ disabled: { converter: BOOLEAN_CONVERTER$27 },
10458
11106
  readOnly: {
10459
- converter: BOOLEAN_CONVERTER$28,
11107
+ converter: BOOLEAN_CONVERTER$27,
10460
11108
  attribute: "read-only"
10461
11109
  },
10462
- required: { converter: BOOLEAN_CONVERTER$28 },
10463
- name: { converter: STRING_CONVERTER$36 },
11110
+ required: { converter: BOOLEAN_CONVERTER$27 },
11111
+ name: { converter: STRING_CONVERTER$35 },
10464
11112
  direction: {
10465
- converter: STRING_CONVERTER$36,
11113
+ converter: STRING_CONVERTER$35,
10466
11114
  attribute: "dir"
10467
11115
  },
10468
- tone: { converter: STRING_CONVERTER$36 },
10469
- size: { converter: STRING_CONVERTER$36 }
11116
+ tone: { converter: STRING_CONVERTER$35 },
11117
+ size: { converter: STRING_CONVERTER$35 }
10470
11118
  };
10471
11119
  notifyValue = (details) => {
10472
11120
  this.dispatchEvent(new CustomEvent("value-change", {
@@ -10532,7 +11180,7 @@ var XhRatingElement = class extends XhElement {
10532
11180
  };
10533
11181
  //#endregion
10534
11182
  //#region src/elements/result.ts
10535
- const STRING_CONVERTER$35 = { fromAttribute: (v) => v ?? void 0 };
11183
+ const STRING_CONVERTER$34 = { fromAttribute: (v) => v ?? void 0 };
10536
11184
  /**
10537
11185
  * `<xh-result>` —— 结果页行为宿主,无状态机,把 connectResult 产出的属性打到角色节点上。
10538
11186
  *
@@ -10556,8 +11204,8 @@ var XhResultElement = class extends XhElement {
10556
11204
  meta: resultMeta
10557
11205
  };
10558
11206
  static properties = {
10559
- status: { converter: STRING_CONVERTER$35 },
10560
- size: { converter: STRING_CONVERTER$35 }
11207
+ status: { converter: STRING_CONVERTER$34 },
11208
+ size: { converter: STRING_CONVERTER$34 }
10561
11209
  };
10562
11210
  wire() {
10563
11211
  const props = {
@@ -10578,9 +11226,9 @@ var XhResultElement = class extends XhElement {
10578
11226
  };
10579
11227
  //#endregion
10580
11228
  //#region src/elements/scroll-area.ts
10581
- const STRING_CONVERTER$34 = { fromAttribute: (v) => v ?? void 0 };
11229
+ const STRING_CONVERTER$33 = { fromAttribute: (v) => v ?? void 0 };
10582
11230
  const NUMBER_CONVERTER$17 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
10583
- const BOOLEAN_CONVERTER$27 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
11231
+ const BOOLEAN_CONVERTER$26 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
10584
11232
  /**
10585
11233
  * `<xh-scroll-area>` —— Light-DOM 行为宿主:作者写 root/viewport/content 与两条 scrollbar
10586
11234
  * 角色节点,元素按轴各跑一台 scrollbar 机器并把 connect 产出打上去。
@@ -10597,8 +11245,8 @@ const BOOLEAN_CONVERTER$27 = { fromAttribute: (v) => v === null ? void 0 : v !==
10597
11245
  * 轨道与滑块按所在滚动条的轴向取几何,不必另写。这是挂载时的静态声明:运行期要换轴,换节点。
10598
11246
  *
10599
11247
  * @customElement xh-scroll-area
10600
- * @attr {'auto'|'always'|'scroll'|'hover'} type - 滚动条露面的时机,默认 hover
10601
- * @attr {number} hide-delay - 收起前的等待毫秒(type 为 scroll / hover 时生效),默认 600
11248
+ * @attr {'auto'|'always'|'scroll'|'hover'|'scroll-hover'} type - 滚动条露面的时机,默认 scroll-hover
11249
+ * @attr {number} hide-delay - 收起前的等待毫秒(type 为 scroll / hover / scroll-hover 时生效),默认 600
10602
11250
  * @attr {'horizontal'|'vertical'|'both'} orientation - 哪几条轴归本组件管,默认 both
10603
11251
  * @attr {'sm'|'md'|'lg'} size - 尺寸档,换的是滚动条厚度
10604
11252
  * @attr {'ltr'|'rtl'} dir - 排版方向,只改写横轴的滚动量正负与指针位移方向
@@ -10618,19 +11266,19 @@ var XhScrollAreaElement = class extends XhElement {
10618
11266
  delegates: [scrollbarAnatomy]
10619
11267
  };
10620
11268
  static properties = {
10621
- type: { converter: STRING_CONVERTER$34 },
11269
+ type: { converter: STRING_CONVERTER$33 },
10622
11270
  hideDelay: {
10623
11271
  converter: NUMBER_CONVERTER$17,
10624
11272
  attribute: "hide-delay"
10625
11273
  },
10626
- orientation: { converter: STRING_CONVERTER$34 },
10627
- size: { converter: STRING_CONVERTER$34 },
11274
+ orientation: { converter: STRING_CONVERTER$33 },
11275
+ size: { converter: STRING_CONVERTER$33 },
10628
11276
  direction: {
10629
- converter: STRING_CONVERTER$34,
11277
+ converter: STRING_CONVERTER$33,
10630
11278
  attribute: "dir"
10631
11279
  },
10632
11280
  forceVisible: {
10633
- converter: BOOLEAN_CONVERTER$27,
11281
+ converter: BOOLEAN_CONVERTER$26,
10634
11282
  attribute: "force-visible"
10635
11283
  }
10636
11284
  };
@@ -10695,9 +11343,9 @@ var XhScrollAreaElement = class extends XhElement {
10695
11343
  };
10696
11344
  //#endregion
10697
11345
  //#region src/elements/scrollbar.ts
10698
- const STRING_CONVERTER$33 = { fromAttribute: (v) => v ?? void 0 };
11346
+ const STRING_CONVERTER$32 = { fromAttribute: (v) => v ?? void 0 };
10699
11347
  const NUMBER_CONVERTER$16 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
10700
- const BOOLEAN_CONVERTER$26 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
11348
+ const BOOLEAN_CONVERTER$25 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
10701
11349
  /**
10702
11350
  * `<xh-scrollbar>` —— Light-DOM 行为宿主:作者写 root/track/thumb 三个角色节点,
10703
11351
  * 元素跑 scrollbar 机器并把 connect 产出打上去。
@@ -10716,8 +11364,8 @@ const BOOLEAN_CONVERTER$26 = { fromAttribute: (v) => v === null ? void 0 : v !==
10716
11364
  * @customElement xh-scrollbar
10717
11365
  * @attr {string} controls - 滚动容器的 id;没设 scrollable 属性时按它查节点,focusable 时同时落到 aria-controls
10718
11366
  * @attr {'horizontal'|'vertical'} orientation - 这条滚动条管哪条轴,默认 vertical
10719
- * @attr {'auto'|'always'|'scroll'|'hover'} type - 露面的时机,默认 hover
10720
- * @attr {number} hide-delay - 收起前的等待毫秒(type 为 scroll / hover 时生效),默认 600
11367
+ * @attr {'auto'|'always'|'scroll'|'hover'|'scroll-hover'} type - 露面的时机,默认 scroll-hover
11368
+ * @attr {number} hide-delay - 收起前的等待毫秒(type 为 scroll / hover / scroll-hover 时生效),默认 600
10721
11369
  * @attr {number} min-thumb-size - 滑块最短多少像素,默认 20
10722
11370
  * @attr {number} step - 方向键一步滚多少像素,默认 40
10723
11371
  * @attr {'sm'|'md'|'lg'} size - 尺寸档,换的是滚动条厚度
@@ -10742,9 +11390,9 @@ var XhScrollbarElement = class extends XhElement {
10742
11390
  meta: scrollbarMeta
10743
11391
  };
10744
11392
  static properties = {
10745
- controls: { converter: STRING_CONVERTER$33 },
10746
- orientation: { converter: STRING_CONVERTER$33 },
10747
- type: { converter: STRING_CONVERTER$33 },
11393
+ controls: { converter: STRING_CONVERTER$32 },
11394
+ orientation: { converter: STRING_CONVERTER$32 },
11395
+ type: { converter: STRING_CONVERTER$32 },
10748
11396
  hideDelay: {
10749
11397
  converter: NUMBER_CONVERTER$16,
10750
11398
  attribute: "hide-delay"
@@ -10754,16 +11402,16 @@ var XhScrollbarElement = class extends XhElement {
10754
11402
  attribute: "min-thumb-size"
10755
11403
  },
10756
11404
  step: { converter: NUMBER_CONVERTER$16 },
10757
- size: { converter: STRING_CONVERTER$33 },
10758
- disabled: { converter: BOOLEAN_CONVERTER$26 },
10759
- focusable: { converter: BOOLEAN_CONVERTER$26 },
10760
- gutter: { converter: BOOLEAN_CONVERTER$26 },
11405
+ size: { converter: STRING_CONVERTER$32 },
11406
+ disabled: { converter: BOOLEAN_CONVERTER$25 },
11407
+ focusable: { converter: BOOLEAN_CONVERTER$25 },
11408
+ gutter: { converter: BOOLEAN_CONVERTER$25 },
10761
11409
  forceVisible: {
10762
- converter: BOOLEAN_CONVERTER$26,
11410
+ converter: BOOLEAN_CONVERTER$25,
10763
11411
  attribute: "force-visible"
10764
11412
  },
10765
11413
  direction: {
10766
- converter: STRING_CONVERTER$33,
11414
+ converter: STRING_CONVERTER$32,
10767
11415
  attribute: "dir"
10768
11416
  },
10769
11417
  scrollable: { attribute: false },
@@ -10828,8 +11476,8 @@ var XhScrollbarElement = class extends XhElement {
10828
11476
  };
10829
11477
  //#endregion
10830
11478
  //#region src/elements/segmented.ts
10831
- const STRING_CONVERTER$32 = { fromAttribute: (v) => v ?? void 0 };
10832
- const BOOLEAN_CONVERTER$25 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
11479
+ const STRING_CONVERTER$31 = { fromAttribute: (v) => v ?? void 0 };
11480
+ const BOOLEAN_CONVERTER$24 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
10833
11481
  /**
10834
11482
  * `<xh-segmented>` —— Light-DOM 行为宿主:作者写 root 与若干 item 角色节点,
10835
11483
  * 元素跑 segmented 机器并把 connect 产出打上去。段须是原生 `<button>`
@@ -10867,28 +11515,28 @@ var XhSegmentedElement = class extends XhElement {
10867
11515
  };
10868
11516
  static properties = {
10869
11517
  collection: { attribute: false },
10870
- value: { converter: STRING_CONVERTER$32 },
11518
+ value: { converter: STRING_CONVERTER$31 },
10871
11519
  defaultValue: {
10872
- converter: STRING_CONVERTER$32,
11520
+ converter: STRING_CONVERTER$31,
10873
11521
  attribute: "default-value"
10874
11522
  },
10875
- disabled: { converter: BOOLEAN_CONVERTER$25 },
11523
+ disabled: { converter: BOOLEAN_CONVERTER$24 },
10876
11524
  readOnly: {
10877
- converter: BOOLEAN_CONVERTER$25,
11525
+ converter: BOOLEAN_CONVERTER$24,
10878
11526
  attribute: "read-only"
10879
11527
  },
10880
- invalid: { converter: BOOLEAN_CONVERTER$25 },
10881
- required: { converter: BOOLEAN_CONVERTER$25 },
10882
- name: { converter: STRING_CONVERTER$32 },
10883
- orientation: { converter: STRING_CONVERTER$32 },
11528
+ invalid: { converter: BOOLEAN_CONVERTER$24 },
11529
+ required: { converter: BOOLEAN_CONVERTER$24 },
11530
+ name: { converter: STRING_CONVERTER$31 },
11531
+ orientation: { converter: STRING_CONVERTER$31 },
10884
11532
  direction: {
10885
- converter: STRING_CONVERTER$32,
11533
+ converter: STRING_CONVERTER$31,
10886
11534
  attribute: "dir"
10887
11535
  },
10888
- loop: { converter: BOOLEAN_CONVERTER$25 },
10889
- block: { converter: BOOLEAN_CONVERTER$25 },
10890
- tone: { converter: STRING_CONVERTER$32 },
10891
- size: { converter: STRING_CONVERTER$32 }
11536
+ loop: { converter: BOOLEAN_CONVERTER$24 },
11537
+ block: { converter: BOOLEAN_CONVERTER$24 },
11538
+ tone: { converter: STRING_CONVERTER$31 },
11539
+ size: { converter: STRING_CONVERTER$31 }
10892
11540
  };
10893
11541
  declaredDisabled = /* @__PURE__ */ new WeakMap();
10894
11542
  /** 上一帧是否整组禁用:解禁当帧 DOM 上还留着机器写回的 aria-disabled,读不得。 */
@@ -10991,9 +11639,9 @@ var XhSegmentedElement = class extends XhElement {
10991
11639
  };
10992
11640
  //#endregion
10993
11641
  //#region src/elements/select.ts
10994
- const STRING_CONVERTER$31 = { fromAttribute: (v) => v ?? void 0 };
11642
+ const STRING_CONVERTER$30 = { fromAttribute: (v) => v ?? void 0 };
10995
11643
  const NUMBER_CONVERTER$15 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
10996
- const BOOLEAN_CONVERTER$24 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
11644
+ const BOOLEAN_CONVERTER$23 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
10997
11645
  /**
10998
11646
  * `<xh-select>` —— Light-DOM 行为宿主:用户写 root/trigger/value-text/positioner/content/item/...
10999
11647
  * 角色节点,元素跑 select 机器并把 connect 产出打上去。浮层定位引擎在本元素里建好、经 refs 注入机器,
@@ -11050,36 +11698,36 @@ var XhSelectElement = class extends XhElement {
11050
11698
  };
11051
11699
  static properties = {
11052
11700
  collection: { attribute: false },
11053
- value: { converter: STRING_CONVERTER$31 },
11701
+ value: { converter: STRING_CONVERTER$30 },
11054
11702
  defaultValue: {
11055
- converter: STRING_CONVERTER$31,
11703
+ converter: STRING_CONVERTER$30,
11056
11704
  attribute: "default-value"
11057
11705
  },
11058
- open: { converter: BOOLEAN_CONVERTER$24 },
11706
+ open: { converter: BOOLEAN_CONVERTER$23 },
11059
11707
  defaultOpen: {
11060
11708
  type: Boolean,
11061
11709
  attribute: "default-open"
11062
11710
  },
11063
11711
  disabled: { type: Boolean },
11064
11712
  readOnly: {
11065
- converter: BOOLEAN_CONVERTER$24,
11713
+ converter: BOOLEAN_CONVERTER$23,
11066
11714
  attribute: "read-only"
11067
11715
  },
11068
11716
  invalid: { type: Boolean },
11069
11717
  required: { type: Boolean },
11070
- name: { converter: STRING_CONVERTER$31 },
11071
- placeholder: { converter: STRING_CONVERTER$31 },
11072
- placement: { converter: STRING_CONVERTER$31 },
11718
+ name: { converter: STRING_CONVERTER$30 },
11719
+ placeholder: { converter: STRING_CONVERTER$30 },
11720
+ placement: { converter: STRING_CONVERTER$30 },
11073
11721
  offset: { converter: NUMBER_CONVERTER$15 },
11074
- loop: { converter: BOOLEAN_CONVERTER$24 },
11722
+ loop: { converter: BOOLEAN_CONVERTER$23 },
11075
11723
  multiple: { type: Boolean },
11076
11724
  direction: {
11077
- converter: STRING_CONVERTER$31,
11725
+ converter: STRING_CONVERTER$30,
11078
11726
  attribute: "dir"
11079
11727
  },
11080
- variant: { converter: STRING_CONVERTER$31 },
11081
- tone: { converter: STRING_CONVERTER$31 },
11082
- size: { converter: STRING_CONVERTER$31 },
11728
+ variant: { converter: STRING_CONVERTER$30 },
11729
+ tone: { converter: STRING_CONVERTER$30 },
11730
+ size: { converter: STRING_CONVERTER$30 },
11083
11731
  translations: { attribute: false },
11084
11732
  maxTagCount: {
11085
11733
  converter: NUMBER_CONVERTER$15,
@@ -11319,8 +11967,8 @@ var XhSeparatorElement = class extends XhElement {
11319
11967
  };
11320
11968
  //#endregion
11321
11969
  //#region src/elements/side-nav.ts
11322
- const STRING_CONVERTER$30 = { fromAttribute: (v) => v ?? void 0 };
11323
- const BOOLEAN_CONVERTER$23 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
11970
+ const STRING_CONVERTER$29 = { fromAttribute: (v) => v ?? void 0 };
11971
+ const BOOLEAN_CONVERTER$22 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
11324
11972
  /** 分支一系的归属容器;嵌套分支各认最近的那个。 */
11325
11973
  const BRANCH_SELECTOR$2 = "[data-xh-part=\"branch\"]";
11326
11974
  /** 分组一系的归属容器。 */
@@ -11361,21 +12009,21 @@ var XhSideNavElement = class extends XhElement {
11361
12009
  meta: sideNavMeta
11362
12010
  };
11363
12011
  static properties = {
11364
- value: { converter: STRING_CONVERTER$30 },
12012
+ value: { converter: STRING_CONVERTER$29 },
11365
12013
  defaultValue: {
11366
- converter: STRING_CONVERTER$30,
12014
+ converter: STRING_CONVERTER$29,
11367
12015
  attribute: "default-value"
11368
12016
  },
11369
- accordion: { converter: BOOLEAN_CONVERTER$23 },
11370
- collapsed: { converter: BOOLEAN_CONVERTER$23 },
12017
+ accordion: { converter: BOOLEAN_CONVERTER$22 },
12018
+ collapsed: { converter: BOOLEAN_CONVERTER$22 },
11371
12019
  collapsedPopout: {
11372
- converter: BOOLEAN_CONVERTER$23,
12020
+ converter: BOOLEAN_CONVERTER$22,
11373
12021
  attribute: "collapsed-popout"
11374
12022
  },
11375
- disabled: { converter: BOOLEAN_CONVERTER$23 },
11376
- loop: { converter: BOOLEAN_CONVERTER$23 },
12023
+ disabled: { converter: BOOLEAN_CONVERTER$22 },
12024
+ loop: { converter: BOOLEAN_CONVERTER$22 },
11377
12025
  direction: {
11378
- converter: STRING_CONVERTER$30,
12026
+ converter: STRING_CONVERTER$29,
11379
12027
  attribute: "dir"
11380
12028
  },
11381
12029
  collection: { attribute: false },
@@ -11526,8 +12174,8 @@ var XhSideNavElement = class extends XhElement {
11526
12174
  };
11527
12175
  //#endregion
11528
12176
  //#region src/elements/signature-pad.ts
11529
- const STRING_CONVERTER$29 = { fromAttribute: (v) => v ?? void 0 };
11530
- const BOOLEAN_CONVERTER$22 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
12177
+ const STRING_CONVERTER$28 = { fromAttribute: (v) => v ?? void 0 };
12178
+ const BOOLEAN_CONVERTER$21 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
11531
12179
  /**
11532
12180
  * `<xh-signature-pad>` —— Light-DOM 行为宿主:作者写 root / control / segment 三个必需角色节点
11533
12181
  * (可再写 label、guide、clear-trigger 与 hidden-input),元素跑 signature-pad 机器并把 connect 产出打上去。
@@ -11564,14 +12212,14 @@ var XhSignaturePadElement = class extends XhElement {
11564
12212
  meta: signaturePadMeta
11565
12213
  };
11566
12214
  static properties = {
11567
- disabled: { converter: BOOLEAN_CONVERTER$22 },
12215
+ disabled: { converter: BOOLEAN_CONVERTER$21 },
11568
12216
  readOnly: {
11569
- converter: BOOLEAN_CONVERTER$22,
12217
+ converter: BOOLEAN_CONVERTER$21,
11570
12218
  attribute: "read-only"
11571
12219
  },
11572
- required: { converter: BOOLEAN_CONVERTER$22 },
11573
- invalid: { converter: BOOLEAN_CONVERTER$22 },
11574
- name: { converter: STRING_CONVERTER$29 },
12220
+ required: { converter: BOOLEAN_CONVERTER$21 },
12221
+ invalid: { converter: BOOLEAN_CONVERTER$21 },
12222
+ name: { converter: STRING_CONVERTER$28 },
11575
12223
  drawing: { attribute: false },
11576
12224
  translations: { attribute: false }
11577
12225
  };
@@ -11657,8 +12305,8 @@ var XhSignaturePadElement = class extends XhElement {
11657
12305
  };
11658
12306
  //#endregion
11659
12307
  //#region src/elements/skeleton.ts
11660
- const STRING_CONVERTER$28 = { fromAttribute: (v) => v ?? void 0 };
11661
- const BOOLEAN_CONVERTER$21 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
12308
+ const STRING_CONVERTER$27 = { fromAttribute: (v) => v ?? void 0 };
12309
+ const BOOLEAN_CONVERTER$20 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
11662
12310
  /** 允许的形状名,作者写错时落回容器的默认值。 */
11663
12311
  const VARIANTS = [
11664
12312
  "text",
@@ -11688,8 +12336,8 @@ var XhSkeletonElement = class extends XhElement {
11688
12336
  meta: skeletonMeta
11689
12337
  };
11690
12338
  static properties = {
11691
- loading: { converter: BOOLEAN_CONVERTER$21 },
11692
- variant: { converter: STRING_CONVERTER$28 }
12339
+ loading: { converter: BOOLEAN_CONVERTER$20 },
12340
+ variant: { converter: STRING_CONVERTER$27 }
11693
12341
  };
11694
12342
  wire() {
11695
12343
  const api = connectSkeleton({
@@ -11703,9 +12351,9 @@ var XhSkeletonElement = class extends XhElement {
11703
12351
  };
11704
12352
  //#endregion
11705
12353
  //#region src/elements/slider.ts
11706
- const STRING_CONVERTER$27 = { fromAttribute: (v) => v ?? void 0 };
12354
+ const STRING_CONVERTER$26 = { fromAttribute: (v) => v ?? void 0 };
11707
12355
  const NUMBER_CONVERTER$14 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
11708
- const BOOLEAN_CONVERTER$20 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
12356
+ const BOOLEAN_CONVERTER$19 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
11709
12357
  /**
11710
12358
  * 值恒是数组,属性写成逗号分隔(单滑块 value="30",双滑块 value="20,80")。
11711
12359
  * 解析不出任何有限数就当没写:留下 NaN 会一路写进 aria-valuenow 与定位百分比。
@@ -11779,24 +12427,24 @@ var XhSliderElement = class extends XhElement {
11779
12427
  attribute: "min-steps-between-thumbs"
11780
12428
  },
11781
12429
  snapToMarks: {
11782
- converter: BOOLEAN_CONVERTER$20,
12430
+ converter: BOOLEAN_CONVERTER$19,
11783
12431
  attribute: "snap-to-marks"
11784
12432
  },
11785
12433
  marks: { attribute: false },
11786
- orientation: { converter: STRING_CONVERTER$27 },
12434
+ orientation: { converter: STRING_CONVERTER$26 },
11787
12435
  direction: {
11788
- converter: STRING_CONVERTER$27,
12436
+ converter: STRING_CONVERTER$26,
11789
12437
  attribute: "dir"
11790
12438
  },
11791
- disabled: { converter: BOOLEAN_CONVERTER$20 },
12439
+ disabled: { converter: BOOLEAN_CONVERTER$19 },
11792
12440
  readOnly: {
11793
- converter: BOOLEAN_CONVERTER$20,
12441
+ converter: BOOLEAN_CONVERTER$19,
11794
12442
  attribute: "read-only"
11795
12443
  },
11796
- invalid: { converter: BOOLEAN_CONVERTER$20 },
11797
- tone: { converter: STRING_CONVERTER$27 },
11798
- size: { converter: STRING_CONVERTER$27 },
11799
- name: { converter: STRING_CONVERTER$27 },
12444
+ invalid: { converter: BOOLEAN_CONVERTER$19 },
12445
+ tone: { converter: STRING_CONVERTER$26 },
12446
+ size: { converter: STRING_CONVERTER$26 },
12447
+ name: { converter: STRING_CONVERTER$26 },
11800
12448
  getValueText: { attribute: false }
11801
12449
  };
11802
12450
  idGen = createCounterIdGenerator();
@@ -11880,8 +12528,8 @@ var XhSliderElement = class extends XhElement {
11880
12528
  };
11881
12529
  //#endregion
11882
12530
  //#region src/elements/space.ts
11883
- const STRING_CONVERTER$26 = { fromAttribute: (v) => v ?? void 0 };
11884
- const BOOLEAN_CONVERTER$19 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
12531
+ const STRING_CONVERTER$25 = { fromAttribute: (v) => v ?? void 0 };
12532
+ const BOOLEAN_CONVERTER$18 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
11885
12533
  /**
11886
12534
  * `<xh-space>` —— Light-DOM 行为宿主,无状态机,把 connectSpace 产出打到 root 角色节点。
11887
12535
  * 排布参数原样落成 data-*,排布规则写在皮肤里。
@@ -11895,7 +12543,8 @@ const BOOLEAN_CONVERTER$19 = { fromAttribute: (v) => v === null ? void 0 : v !==
11895
12543
  * 根上不写 role:容器只做排布,里面装的是列表还是一组按钮由作者自己声明。
11896
12544
  *
11897
12545
  * @customElement xh-space
11898
- * @attr {'horizontal'|'vertical'} direction - 排布方向,缺省 horizontal
12546
+ * @attr {'horizontal'|'vertical'} orientation - 排布方向,缺省 horizontal
12547
+ * @attr {'horizontal'|'vertical'} direction - 排布方向的旧写法,两个都写时以 orientation 为准
11899
12548
  * @attr {'xs'|'sm'|'md'|'lg'|'xl'} gap - 子项间距档位,缺省 md,逐档对应一个间距令牌
11900
12549
  * @attr {'start'|'center'|'end'|'stretch'|'baseline'} align - 交叉轴对齐
11901
12550
  * @attr {'start'|'center'|'end'|'between'|'around'|'evenly'} justify - 主轴分布
@@ -11910,15 +12559,17 @@ var XhSpaceElement = class extends XhElement {
11910
12559
  meta: spaceMeta
11911
12560
  };
11912
12561
  static properties = {
11913
- direction: { converter: STRING_CONVERTER$26 },
11914
- gap: { converter: STRING_CONVERTER$26 },
11915
- align: { converter: STRING_CONVERTER$26 },
11916
- justify: { converter: STRING_CONVERTER$26 },
11917
- wrap: { converter: BOOLEAN_CONVERTER$19 },
11918
- inline: { converter: BOOLEAN_CONVERTER$19 }
12562
+ orientation: { converter: STRING_CONVERTER$25 },
12563
+ direction: { converter: STRING_CONVERTER$25 },
12564
+ gap: { converter: STRING_CONVERTER$25 },
12565
+ align: { converter: STRING_CONVERTER$25 },
12566
+ justify: { converter: STRING_CONVERTER$25 },
12567
+ wrap: { converter: BOOLEAN_CONVERTER$18 },
12568
+ inline: { converter: BOOLEAN_CONVERTER$18 }
11919
12569
  };
11920
12570
  wire() {
11921
12571
  const api = connectSpace({
12572
+ orientation: this.orientation,
11922
12573
  direction: this.direction,
11923
12574
  gap: this.gap,
11924
12575
  align: this.align,
@@ -11933,7 +12584,7 @@ var XhSpaceElement = class extends XhElement {
11933
12584
  };
11934
12585
  //#endregion
11935
12586
  //#region src/elements/spinner.ts
11936
- const STRING_CONVERTER$25 = { fromAttribute: (v) => v ?? void 0 };
12587
+ const STRING_CONVERTER$24 = { fromAttribute: (v) => v ?? void 0 };
11937
12588
  /**
11938
12589
  * `<xh-spinner>` —— 加载指示器宿主,无状态机,把活区语义与可及名字打到角色节点上。
11939
12590
  * 转圈图形由皮肤画在 root 的伪元素上,元素不生成任何结构。
@@ -11951,9 +12602,9 @@ var XhSpinnerElement = class extends XhElement {
11951
12602
  meta: spinnerMeta
11952
12603
  };
11953
12604
  static properties = {
11954
- label: { converter: STRING_CONVERTER$25 },
11955
- size: { converter: STRING_CONVERTER$25 },
11956
- tone: { converter: STRING_CONVERTER$25 },
12605
+ label: { converter: STRING_CONVERTER$24 },
12606
+ size: { converter: STRING_CONVERTER$24 },
12607
+ tone: { converter: STRING_CONVERTER$24 },
11957
12608
  translations: { attribute: false }
11958
12609
  };
11959
12610
  wire() {
@@ -11974,9 +12625,9 @@ var XhSpinnerElement = class extends XhElement {
11974
12625
  };
11975
12626
  //#endregion
11976
12627
  //#region src/elements/splitter.ts
11977
- const STRING_CONVERTER$24 = { fromAttribute: (v) => v ?? void 0 };
12628
+ const STRING_CONVERTER$23 = { fromAttribute: (v) => v ?? void 0 };
11978
12629
  const NUMBER_CONVERTER$13 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
11979
- const BOOLEAN_CONVERTER$18 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
12630
+ const BOOLEAN_CONVERTER$17 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
11980
12631
  /**
11981
12632
  * 布局是百分比数组,属性写成逗号分隔(两栏 sizes="30,70")。
11982
12633
  * 解析不出任何有限数就当没写:留下 NaN 会一路写进 aria-valuenow 与定位百分比。
@@ -12042,12 +12693,12 @@ var XhSplitterElement = class extends XhElement {
12042
12693
  attribute: "default-sizes"
12043
12694
  },
12044
12695
  panels: { converter: PANELS_CONVERTER },
12045
- orientation: { converter: STRING_CONVERTER$24 },
12696
+ orientation: { converter: STRING_CONVERTER$23 },
12046
12697
  direction: {
12047
- converter: STRING_CONVERTER$24,
12698
+ converter: STRING_CONVERTER$23,
12048
12699
  attribute: "dir"
12049
12700
  },
12050
- disabled: { converter: BOOLEAN_CONVERTER$18 },
12701
+ disabled: { converter: BOOLEAN_CONVERTER$17 },
12051
12702
  step: { converter: NUMBER_CONVERTER$13 },
12052
12703
  largeStep: {
12053
12704
  converter: NUMBER_CONVERTER$13,
@@ -12109,7 +12760,7 @@ var XhSplitterElement = class extends XhElement {
12109
12760
  };
12110
12761
  //#endregion
12111
12762
  //#region src/elements/statistic.ts
12112
- const STRING_CONVERTER$23 = { fromAttribute: (v) => v ?? void 0 };
12763
+ const STRING_CONVERTER$22 = { fromAttribute: (v) => v ?? void 0 };
12113
12764
  /**
12114
12765
  * `<xh-statistic>` —— Light-DOM 行为宿主,无状态机,把 connectStatistic 产出打到各角色节点。
12115
12766
  *
@@ -12133,8 +12784,8 @@ var XhStatisticElement = class extends XhElement {
12133
12784
  meta: statisticMeta
12134
12785
  };
12135
12786
  static properties = {
12136
- size: { converter: STRING_CONVERTER$23 },
12137
- tone: { converter: STRING_CONVERTER$23 }
12787
+ size: { converter: STRING_CONVERTER$22 },
12788
+ tone: { converter: STRING_CONVERTER$22 }
12138
12789
  };
12139
12790
  wire() {
12140
12791
  const props = {
@@ -12156,8 +12807,8 @@ var XhStatisticElement = class extends XhElement {
12156
12807
  //#endregion
12157
12808
  //#region src/elements/steps.ts
12158
12809
  const NUMBER_CONVERTER$12 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
12159
- const STRING_CONVERTER$22 = { fromAttribute: (v) => v ?? void 0 };
12160
- const BOOLEAN_CONVERTER$17 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
12810
+ const STRING_CONVERTER$21 = { fromAttribute: (v) => v ?? void 0 };
12811
+ const BOOLEAN_CONVERTER$16 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
12161
12812
  const ITEM_SELECTOR$3 = "[data-xh-part=\"item\"]";
12162
12813
  /** 角色节点自报的步序;缺失或空串一律给 NaN(与任何一步都不相等,绝不冒充当前步)。 */
12163
12814
  function stepIndexOf(el) {
@@ -12209,15 +12860,15 @@ var XhStepsElement = class extends XhElement {
12209
12860
  attribute: "default-step"
12210
12861
  },
12211
12862
  count: { converter: NUMBER_CONVERTER$12 },
12212
- orientation: { converter: STRING_CONVERTER$22 },
12213
- linear: { converter: BOOLEAN_CONVERTER$17 },
12214
- disabled: { converter: BOOLEAN_CONVERTER$17 },
12863
+ orientation: { converter: STRING_CONVERTER$21 },
12864
+ linear: { converter: BOOLEAN_CONVERTER$16 },
12865
+ disabled: { converter: BOOLEAN_CONVERTER$16 },
12215
12866
  direction: {
12216
- converter: STRING_CONVERTER$22,
12867
+ converter: STRING_CONVERTER$21,
12217
12868
  attribute: "dir"
12218
12869
  },
12219
- tone: { converter: STRING_CONVERTER$22 },
12220
- size: { converter: STRING_CONVERTER$22 }
12870
+ tone: { converter: STRING_CONVERTER$21 },
12871
+ size: { converter: STRING_CONVERTER$21 }
12221
12872
  };
12222
12873
  notify = (details) => {
12223
12874
  this.dispatchEvent(new CustomEvent("step-change", {
@@ -12378,8 +13029,9 @@ var XhSwitchElement = class extends XhElement {
12378
13029
  };
12379
13030
  //#endregion
12380
13031
  //#region src/elements/table.ts
12381
- const STRING_CONVERTER$21 = { fromAttribute: (v) => v ?? void 0 };
12382
- const BOOLEAN_CONVERTER$16 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
13032
+ const STRING_CONVERTER$20 = { fromAttribute: (v) => v ?? void 0 };
13033
+ const NUMBER_CONVERTER$11 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
13034
+ const BOOLEAN_CONVERTER$15 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
12383
13035
  /** 行系部件的归属容器:行内的把手与单元格向上找最近的那一行。 */
12384
13036
  const ROW_SELECTOR = "[data-xh-part=\"row\"]";
12385
13037
  /** 列系部件的归属容器:排序把手向上找最近的那个列标题。 */
@@ -12412,6 +13064,9 @@ const FOOTER_SELECTOR = "[data-xh-part=\"footer\"]";
12412
13064
  * @attr {'ltr'|'rtl'} dir - 文字方向,只对调左右方向键的展开/收起语义,默认 ltr
12413
13065
  * @attr {'sm'|'md'|'lg'} size - 密度:只换单元格的纵向内边距与字号,列宽不受影响
12414
13066
  * @fires sort-change - 排序链变化;detail 为 `{ value: { id, direction }[] }`
13067
+ * @fires column-preference-change - 列偏好变化;detail 为 `{ value: TableColumnPreference }`
13068
+ * @prop {TableColumnPreference} columnPreference - 列偏好(显隐/顺序/宽/冻结),给定即受控
13069
+ * @prop {TableColumnKind[]} prefixColumns - 要哪几列前缀列,按给定顺序插在最前面
12415
13070
  * @fires selection-change - 选中集合变化;detail 为 `{ value: string[] | 'all' }`
12416
13071
  * @fires expanded-change - 展开集合变化;detail 为 `{ value: string[] }`
12417
13072
  * @csspart root - role=grid 容器(rows 里有可展开的行时为 treegrid),报行列总数与多选声明
@@ -12445,11 +13100,19 @@ var XhTableElement = class extends XhElement {
12445
13100
  expanded: { attribute: false },
12446
13101
  defaultExpanded: { attribute: false },
12447
13102
  selectionMode: {
12448
- converter: STRING_CONVERTER$21,
13103
+ converter: STRING_CONVERTER$20,
12449
13104
  attribute: "selection-mode"
12450
13105
  },
13106
+ prefixColumns: { attribute: false },
13107
+ columnPreference: { attribute: false },
13108
+ defaultColumnPreference: { attribute: false },
13109
+ page: { converter: NUMBER_CONVERTER$11 },
13110
+ pageSize: {
13111
+ converter: NUMBER_CONVERTER$11,
13112
+ attribute: "page-size"
13113
+ },
12451
13114
  loading: { type: Boolean },
12452
- empty: { converter: BOOLEAN_CONVERTER$16 },
13115
+ empty: { converter: BOOLEAN_CONVERTER$15 },
12453
13116
  stickyHeader: {
12454
13117
  type: Boolean,
12455
13118
  attribute: "sticky-header"
@@ -12458,12 +13121,19 @@ var XhTableElement = class extends XhElement {
12458
13121
  borderless: { type: Boolean },
12459
13122
  ruled: { type: Boolean },
12460
13123
  footer: { type: Boolean },
12461
- loop: { converter: BOOLEAN_CONVERTER$16 },
13124
+ loop: { converter: BOOLEAN_CONVERTER$15 },
12462
13125
  direction: {
12463
- converter: STRING_CONVERTER$21,
13126
+ converter: STRING_CONVERTER$20,
12464
13127
  attribute: "dir"
12465
13128
  },
12466
- size: { converter: STRING_CONVERTER$21 }
13129
+ size: { converter: STRING_CONVERTER$20 }
13130
+ };
13131
+ notifyColumnPreference = (details) => {
13132
+ this.dispatchEvent(new CustomEvent("column-preference-change", {
13133
+ detail: details,
13134
+ bubbles: true,
13135
+ composed: true
13136
+ }));
12467
13137
  };
12468
13138
  notifySort = (details) => {
12469
13139
  this.dispatchEvent(new CustomEvent("sort-change", {
@@ -12498,6 +13168,12 @@ var XhTableElement = class extends XhElement {
12498
13168
  expanded: this.expanded,
12499
13169
  defaultExpanded: this.defaultExpanded,
12500
13170
  selectionMode: this.selectionMode,
13171
+ prefixColumns: this.prefixColumns,
13172
+ columnPreference: this.columnPreference,
13173
+ defaultColumnPreference: this.defaultColumnPreference,
13174
+ onColumnPreferenceChange: this.notifyColumnPreference,
13175
+ page: this.page,
13176
+ pageSize: this.pageSize,
12501
13177
  loading: this.loading ?? false,
12502
13178
  empty: this.empty,
12503
13179
  stickyHeader: this.stickyHeader ?? false,
@@ -12591,8 +13267,8 @@ var XhTableElement = class extends XhElement {
12591
13267
  };
12592
13268
  //#endregion
12593
13269
  //#region src/elements/tabs.ts
12594
- const STRING_CONVERTER$20 = { fromAttribute: (v) => v ?? void 0 };
12595
- const BOOLEAN_CONVERTER$15 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
13270
+ const STRING_CONVERTER$19 = { fromAttribute: (v) => v ?? void 0 };
13271
+ const BOOLEAN_CONVERTER$14 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
12596
13272
  /**
12597
13273
  * `<xh-tabs>` —— Light-DOM 行为宿主,跑 tabs 机器并把 connect 产出打到 root/list/trigger/content
12598
13274
  * 角色节点上。条目身份取作者写在 trigger/content 上的 value 属性,trigger 的禁用由部件自报。
@@ -12620,24 +13296,24 @@ var XhTabsElement = class extends XhElement {
12620
13296
  };
12621
13297
  static properties = {
12622
13298
  collection: { attribute: false },
12623
- value: { converter: STRING_CONVERTER$20 },
13299
+ value: { converter: STRING_CONVERTER$19 },
12624
13300
  defaultValue: {
12625
- converter: STRING_CONVERTER$20,
13301
+ converter: STRING_CONVERTER$19,
12626
13302
  attribute: "default-value"
12627
13303
  },
12628
- orientation: { converter: STRING_CONVERTER$20 },
13304
+ orientation: { converter: STRING_CONVERTER$19 },
12629
13305
  direction: {
12630
- converter: STRING_CONVERTER$20,
13306
+ converter: STRING_CONVERTER$19,
12631
13307
  attribute: "dir"
12632
13308
  },
12633
13309
  activationMode: {
12634
- converter: STRING_CONVERTER$20,
13310
+ converter: STRING_CONVERTER$19,
12635
13311
  attribute: "activation-mode"
12636
13312
  },
12637
- loop: { converter: BOOLEAN_CONVERTER$15 },
12638
- variant: { converter: STRING_CONVERTER$20 },
12639
- tone: { converter: STRING_CONVERTER$20 },
12640
- size: { converter: STRING_CONVERTER$20 }
13313
+ loop: { converter: BOOLEAN_CONVERTER$14 },
13314
+ variant: { converter: STRING_CONVERTER$19 },
13315
+ tone: { converter: STRING_CONVERTER$19 },
13316
+ size: { converter: STRING_CONVERTER$19 }
12641
13317
  };
12642
13318
  notify = (details) => {
12643
13319
  this.dispatchEvent(new CustomEvent("value-change", {
@@ -12695,8 +13371,8 @@ var XhTabsElement = class extends XhElement {
12695
13371
  };
12696
13372
  //#endregion
12697
13373
  //#region src/elements/tag.ts
12698
- const STRING_CONVERTER$19 = { fromAttribute: (v) => v ?? void 0 };
12699
- const BOOLEAN_CONVERTER$14 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
13374
+ const STRING_CONVERTER$18 = { fromAttribute: (v) => v ?? void 0 };
13375
+ const BOOLEAN_CONVERTER$13 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
12700
13376
  /**
12701
13377
  * `<xh-tag>` —— Light-DOM 行为宿主:作者写 root、label、close-trigger 角色节点,
12702
13378
  * 元素跑 tag 机器并把 connect 产出打上去。关闭钮须是原生 `<button>`
@@ -12721,14 +13397,14 @@ var XhTagElement = class extends XhElement {
12721
13397
  meta: tagMeta
12722
13398
  };
12723
13399
  static properties = {
12724
- variant: { converter: STRING_CONVERTER$19 },
12725
- tone: { converter: STRING_CONVERTER$19 },
12726
- size: { converter: STRING_CONVERTER$19 },
12727
- closable: { converter: BOOLEAN_CONVERTER$14 },
12728
- disabled: { converter: BOOLEAN_CONVERTER$14 },
12729
- open: { converter: BOOLEAN_CONVERTER$14 },
13400
+ variant: { converter: STRING_CONVERTER$18 },
13401
+ tone: { converter: STRING_CONVERTER$18 },
13402
+ size: { converter: STRING_CONVERTER$18 },
13403
+ closable: { converter: BOOLEAN_CONVERTER$13 },
13404
+ disabled: { converter: BOOLEAN_CONVERTER$13 },
13405
+ open: { converter: BOOLEAN_CONVERTER$13 },
12730
13406
  defaultOpen: {
12731
- converter: BOOLEAN_CONVERTER$14,
13407
+ converter: BOOLEAN_CONVERTER$13,
12732
13408
  attribute: "default-open"
12733
13409
  },
12734
13410
  translations: { attribute: false }
@@ -12768,9 +13444,9 @@ var XhTagElement = class extends XhElement {
12768
13444
  };
12769
13445
  //#endregion
12770
13446
  //#region src/elements/tags-input.ts
12771
- const STRING_CONVERTER$18 = { fromAttribute: (v) => v ?? void 0 };
12772
- const NUMBER_CONVERTER$11 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
12773
- const BOOLEAN_CONVERTER$13 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
13447
+ const STRING_CONVERTER$17 = { fromAttribute: (v) => v ?? void 0 };
13448
+ const NUMBER_CONVERTER$10 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
13449
+ const BOOLEAN_CONVERTER$12 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
12774
13450
  const ARRAY_CONVERTER = { fromAttribute: (v) => v == null ? void 0 : v.split(",").map((s) => s.trim()).filter((s) => s !== "") };
12775
13451
  /**
12776
13452
  * `<xh-tags-input>` —— Light-DOM 行为宿主:作者写 root/label/control/input/item 一族与
@@ -12827,39 +13503,39 @@ var XhTagsInputElement = class extends XhElement {
12827
13503
  attribute: "default-value"
12828
13504
  },
12829
13505
  inputValue: {
12830
- converter: STRING_CONVERTER$18,
13506
+ converter: STRING_CONVERTER$17,
12831
13507
  attribute: "input-value"
12832
13508
  },
12833
13509
  defaultInputValue: {
12834
- converter: STRING_CONVERTER$18,
13510
+ converter: STRING_CONVERTER$17,
12835
13511
  attribute: "default-input-value"
12836
13512
  },
12837
- max: { converter: NUMBER_CONVERTER$11 },
13513
+ max: { converter: NUMBER_CONVERTER$10 },
12838
13514
  allowOverflow: {
12839
- converter: BOOLEAN_CONVERTER$13,
13515
+ converter: BOOLEAN_CONVERTER$12,
12840
13516
  attribute: "allow-overflow"
12841
13517
  },
12842
- disabled: { converter: BOOLEAN_CONVERTER$13 },
13518
+ disabled: { converter: BOOLEAN_CONVERTER$12 },
12843
13519
  readOnly: {
12844
- converter: BOOLEAN_CONVERTER$13,
13520
+ converter: BOOLEAN_CONVERTER$12,
12845
13521
  attribute: "read-only"
12846
13522
  },
12847
- invalid: { converter: BOOLEAN_CONVERTER$13 },
12848
- name: { converter: STRING_CONVERTER$18 },
12849
- placeholder: { converter: STRING_CONVERTER$18 },
12850
- delimiter: { converter: STRING_CONVERTER$18 },
13523
+ invalid: { converter: BOOLEAN_CONVERTER$12 },
13524
+ name: { converter: STRING_CONVERTER$17 },
13525
+ placeholder: { converter: STRING_CONVERTER$17 },
13526
+ delimiter: { converter: STRING_CONVERTER$17 },
12851
13527
  addOnPaste: {
12852
- converter: BOOLEAN_CONVERTER$13,
13528
+ converter: BOOLEAN_CONVERTER$12,
12853
13529
  attribute: "add-on-paste"
12854
13530
  },
12855
- editable: { converter: BOOLEAN_CONVERTER$13 },
13531
+ editable: { converter: BOOLEAN_CONVERTER$12 },
12856
13532
  blurBehavior: {
12857
- converter: STRING_CONVERTER$18,
13533
+ converter: STRING_CONVERTER$17,
12858
13534
  attribute: "blur-behavior"
12859
13535
  },
12860
- variant: { converter: STRING_CONVERTER$18 },
12861
- tone: { converter: STRING_CONVERTER$18 },
12862
- size: { converter: STRING_CONVERTER$18 }
13536
+ variant: { converter: STRING_CONVERTER$17 },
13537
+ tone: { converter: STRING_CONVERTER$17 },
13538
+ size: { converter: STRING_CONVERTER$17 }
12863
13539
  };
12864
13540
  notifyValue = (details) => {
12865
13541
  this.dispatchEvent(new CustomEvent("value-change", {
@@ -12949,9 +13625,9 @@ var XhTagsInputElement = class extends XhElement {
12949
13625
  };
12950
13626
  //#endregion
12951
13627
  //#region src/elements/text-field.ts
12952
- const STRING_CONVERTER$17 = { fromAttribute: (v) => v ?? void 0 };
12953
- const NUMBER_CONVERTER$10 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
12954
- const BOOLEAN_CONVERTER$12 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
13628
+ const STRING_CONVERTER$16 = { fromAttribute: (v) => v ?? void 0 };
13629
+ const NUMBER_CONVERTER$9 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
13630
+ const BOOLEAN_CONVERTER$11 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
12955
13631
  /**
12956
13632
  * `<xh-text-field>` —— Light-DOM 行为宿主:作者写 root/label/input/clear-trigger 四类角色节点,
12957
13633
  * 元素跑 text-field 机器并把 connect 产出打上去。
@@ -12992,33 +13668,33 @@ var XhTextFieldElement = class extends XhElement {
12992
13668
  meta: textFieldMeta
12993
13669
  };
12994
13670
  static properties = {
12995
- value: { converter: STRING_CONVERTER$17 },
13671
+ value: { converter: STRING_CONVERTER$16 },
12996
13672
  defaultValue: {
12997
- converter: STRING_CONVERTER$17,
13673
+ converter: STRING_CONVERTER$16,
12998
13674
  attribute: "default-value"
12999
13675
  },
13000
- type: { converter: STRING_CONVERTER$17 },
13001
- placeholder: { converter: STRING_CONVERTER$17 },
13002
- disabled: { converter: BOOLEAN_CONVERTER$12 },
13676
+ type: { converter: STRING_CONVERTER$16 },
13677
+ placeholder: { converter: STRING_CONVERTER$16 },
13678
+ disabled: { converter: BOOLEAN_CONVERTER$11 },
13003
13679
  readOnly: {
13004
- converter: BOOLEAN_CONVERTER$12,
13680
+ converter: BOOLEAN_CONVERTER$11,
13005
13681
  attribute: "read-only"
13006
13682
  },
13007
- required: { converter: BOOLEAN_CONVERTER$12 },
13008
- invalid: { converter: BOOLEAN_CONVERTER$12 },
13009
- name: { converter: STRING_CONVERTER$17 },
13683
+ required: { converter: BOOLEAN_CONVERTER$11 },
13684
+ invalid: { converter: BOOLEAN_CONVERTER$11 },
13685
+ name: { converter: STRING_CONVERTER$16 },
13010
13686
  maxLength: {
13011
- converter: NUMBER_CONVERTER$10,
13687
+ converter: NUMBER_CONVERTER$9,
13012
13688
  attribute: "max-length"
13013
13689
  },
13014
- clearable: { converter: BOOLEAN_CONVERTER$12 },
13690
+ clearable: { converter: BOOLEAN_CONVERTER$11 },
13015
13691
  autoSize: {
13016
- converter: BOOLEAN_CONVERTER$12,
13692
+ converter: BOOLEAN_CONVERTER$11,
13017
13693
  attribute: "auto-size"
13018
13694
  },
13019
- variant: { converter: STRING_CONVERTER$17 },
13020
- tone: { converter: STRING_CONVERTER$17 },
13021
- size: { converter: STRING_CONVERTER$17 },
13695
+ variant: { converter: STRING_CONVERTER$16 },
13696
+ tone: { converter: STRING_CONVERTER$16 },
13697
+ size: { converter: STRING_CONVERTER$16 },
13022
13698
  translations: { attribute: false }
13023
13699
  };
13024
13700
  notify = (details) => {
@@ -13069,8 +13745,8 @@ var XhTextFieldElement = class extends XhElement {
13069
13745
  };
13070
13746
  //#endregion
13071
13747
  //#region src/elements/thread.ts
13072
- const STRING_CONVERTER$16 = { fromAttribute: (v) => v ?? void 0 };
13073
- const NUMBER_CONVERTER$9 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
13748
+ const STRING_CONVERTER$15 = { fromAttribute: (v) => v ?? void 0 };
13749
+ const NUMBER_CONVERTER$8 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
13074
13750
  /**
13075
13751
  * `<xh-thread>` —— Light-DOM 行为宿主:跑 thread 机器,把 connect 产出打到作者写的角色节点上。
13076
13752
  * 内容长高时跟随滚动到底部,用户上滚后解除粘附,滚回底部阈值内或按回到底部按钮时恢复。
@@ -13091,8 +13767,8 @@ var XhThreadElement = class extends XhElement {
13091
13767
  meta: threadMeta
13092
13768
  };
13093
13769
  static properties = {
13094
- status: { converter: STRING_CONVERTER$16 },
13095
- threshold: { converter: NUMBER_CONVERTER$9 },
13770
+ status: { converter: STRING_CONVERTER$15 },
13771
+ threshold: { converter: NUMBER_CONVERTER$8 },
13096
13772
  translations: { attribute: false }
13097
13773
  };
13098
13774
  idGen = createCounterIdGenerator();
@@ -13148,7 +13824,7 @@ var XhThreadElement = class extends XhElement {
13148
13824
  };
13149
13825
  //#endregion
13150
13826
  //#region src/elements/time.ts
13151
- const STRING_CONVERTER$15 = { fromAttribute: (v) => v ?? void 0 };
13827
+ const STRING_CONVERTER$14 = { fromAttribute: (v) => v ?? void 0 };
13152
13828
  /**
13153
13829
  * `<xh-time>` —— Light-DOM 行为宿主,无状态机,把 connectTime 产出打到 root 角色节点。
13154
13830
  *
@@ -13176,11 +13852,11 @@ var XhTimeElement = class extends XhElement {
13176
13852
  tags: { root: ["time"] }
13177
13853
  };
13178
13854
  static properties = {
13179
- value: { converter: STRING_CONVERTER$15 },
13180
- type: { converter: STRING_CONVERTER$15 },
13181
- format: { converter: STRING_CONVERTER$15 },
13182
- locale: { converter: STRING_CONVERTER$15 },
13183
- now: { converter: STRING_CONVERTER$15 }
13855
+ value: { converter: STRING_CONVERTER$14 },
13856
+ type: { converter: STRING_CONVERTER$14 },
13857
+ format: { converter: STRING_CONVERTER$14 },
13858
+ locale: { converter: STRING_CONVERTER$14 },
13859
+ now: { converter: STRING_CONVERTER$14 }
13184
13860
  };
13185
13861
  /** 上一次铺进 root 的那份文本。 */
13186
13862
  #painted;
@@ -13210,8 +13886,8 @@ var XhTimeElement = class extends XhElement {
13210
13886
  };
13211
13887
  //#endregion
13212
13888
  //#region src/elements/time-field.ts
13213
- const STRING_CONVERTER$14 = { fromAttribute: (v) => v ?? void 0 };
13214
- const BOOLEAN_CONVERTER$11 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
13889
+ const STRING_CONVERTER$13 = { fromAttribute: (v) => v ?? void 0 };
13890
+ const BOOLEAN_CONVERTER$10 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
13215
13891
  const HOUR_CYCLE_CONVERTER$1 = { fromAttribute: (v) => v === "12" ? 12 : v === "24" ? 24 : void 0 };
13216
13892
  const SEGMENT_TYPES$1 = [
13217
13893
  "hour",
@@ -13267,32 +13943,32 @@ var XhTimeFieldElement = class extends XhElement {
13267
13943
  meta: timeFieldMeta
13268
13944
  };
13269
13945
  static properties = {
13270
- value: { converter: STRING_CONVERTER$14 },
13946
+ value: { converter: STRING_CONVERTER$13 },
13271
13947
  defaultValue: {
13272
- converter: STRING_CONVERTER$14,
13948
+ converter: STRING_CONVERTER$13,
13273
13949
  attribute: "default-value"
13274
13950
  },
13275
- min: { converter: STRING_CONVERTER$14 },
13276
- max: { converter: STRING_CONVERTER$14 },
13277
- locale: { converter: STRING_CONVERTER$14 },
13951
+ min: { converter: STRING_CONVERTER$13 },
13952
+ max: { converter: STRING_CONVERTER$13 },
13953
+ locale: { converter: STRING_CONVERTER$13 },
13278
13954
  hourCycle: {
13279
13955
  converter: HOUR_CYCLE_CONVERTER$1,
13280
13956
  attribute: "hour-cycle"
13281
13957
  },
13282
- granularity: { converter: STRING_CONVERTER$14 },
13283
- disabled: { converter: BOOLEAN_CONVERTER$11 },
13958
+ granularity: { converter: STRING_CONVERTER$13 },
13959
+ disabled: { converter: BOOLEAN_CONVERTER$10 },
13284
13960
  readOnly: {
13285
- converter: BOOLEAN_CONVERTER$11,
13961
+ converter: BOOLEAN_CONVERTER$10,
13286
13962
  attribute: "read-only"
13287
13963
  },
13288
- invalid: { converter: BOOLEAN_CONVERTER$11 },
13964
+ invalid: { converter: BOOLEAN_CONVERTER$10 },
13289
13965
  translations: { attribute: false },
13290
- required: { converter: BOOLEAN_CONVERTER$11 },
13291
- name: { converter: STRING_CONVERTER$14 },
13292
- placeholder: { converter: STRING_CONVERTER$14 },
13293
- variant: { converter: STRING_CONVERTER$14 },
13294
- tone: { converter: STRING_CONVERTER$14 },
13295
- size: { converter: STRING_CONVERTER$14 }
13966
+ required: { converter: BOOLEAN_CONVERTER$10 },
13967
+ name: { converter: STRING_CONVERTER$13 },
13968
+ placeholder: { converter: STRING_CONVERTER$13 },
13969
+ variant: { converter: STRING_CONVERTER$13 },
13970
+ tone: { converter: STRING_CONVERTER$13 },
13971
+ size: { converter: STRING_CONVERTER$13 }
13296
13972
  };
13297
13973
  notifyChange = (details) => {
13298
13974
  this.dispatchEvent(new CustomEvent("value-change", {
@@ -13361,9 +14037,9 @@ var XhTimeFieldElement = class extends XhElement {
13361
14037
  };
13362
14038
  //#endregion
13363
14039
  //#region src/elements/time-picker.ts
13364
- const STRING_CONVERTER$13 = { fromAttribute: (v) => v ?? void 0 };
13365
- const NUMBER_CONVERTER$8 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
13366
- const BOOLEAN_CONVERTER$10 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
14040
+ const STRING_CONVERTER$12 = { fromAttribute: (v) => v ?? void 0 };
14041
+ const NUMBER_CONVERTER$7 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
14042
+ const BOOLEAN_CONVERTER$9 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
13367
14043
  const HOUR_CYCLE_CONVERTER = { fromAttribute: (v) => v === "12" ? 12 : v === "24" ? 24 : void 0 };
13368
14044
  const SEGMENT_TYPES = [
13369
14045
  "hour",
@@ -13445,41 +14121,41 @@ var XhTimePickerElement = class extends XhElement {
13445
14121
  meta: timePickerMeta
13446
14122
  };
13447
14123
  static properties = {
13448
- value: { converter: STRING_CONVERTER$13 },
14124
+ value: { converter: STRING_CONVERTER$12 },
13449
14125
  defaultValue: {
13450
- converter: STRING_CONVERTER$13,
14126
+ converter: STRING_CONVERTER$12,
13451
14127
  attribute: "default-value"
13452
14128
  },
13453
- open: { converter: BOOLEAN_CONVERTER$10 },
14129
+ open: { converter: BOOLEAN_CONVERTER$9 },
13454
14130
  defaultOpen: {
13455
14131
  type: Boolean,
13456
14132
  attribute: "default-open"
13457
14133
  },
13458
- min: { converter: STRING_CONVERTER$13 },
13459
- max: { converter: STRING_CONVERTER$13 },
13460
- locale: { converter: STRING_CONVERTER$13 },
14134
+ min: { converter: STRING_CONVERTER$12 },
14135
+ max: { converter: STRING_CONVERTER$12 },
14136
+ locale: { converter: STRING_CONVERTER$12 },
13461
14137
  hourCycle: {
13462
14138
  converter: HOUR_CYCLE_CONVERTER,
13463
14139
  attribute: "hour-cycle"
13464
14140
  },
13465
- granularity: { converter: STRING_CONVERTER$13 },
13466
- step: { converter: NUMBER_CONVERTER$8 },
14141
+ granularity: { converter: STRING_CONVERTER$12 },
14142
+ step: { converter: NUMBER_CONVERTER$7 },
13467
14143
  presets: { attribute: false },
13468
- disabled: { converter: BOOLEAN_CONVERTER$10 },
14144
+ disabled: { converter: BOOLEAN_CONVERTER$9 },
13469
14145
  readOnly: {
13470
- converter: BOOLEAN_CONVERTER$10,
14146
+ converter: BOOLEAN_CONVERTER$9,
13471
14147
  attribute: "read-only"
13472
14148
  },
13473
- invalid: { converter: BOOLEAN_CONVERTER$10 },
14149
+ invalid: { converter: BOOLEAN_CONVERTER$9 },
13474
14150
  translations: { attribute: false },
13475
14151
  isTimeUnavailable: { attribute: false },
13476
- required: { converter: BOOLEAN_CONVERTER$10 },
13477
- name: { converter: STRING_CONVERTER$13 },
13478
- variant: { converter: STRING_CONVERTER$13 },
13479
- tone: { converter: STRING_CONVERTER$13 },
13480
- size: { converter: STRING_CONVERTER$13 },
13481
- placement: { converter: STRING_CONVERTER$13 },
13482
- offset: { converter: NUMBER_CONVERTER$8 }
14152
+ required: { converter: BOOLEAN_CONVERTER$9 },
14153
+ name: { converter: STRING_CONVERTER$12 },
14154
+ variant: { converter: STRING_CONVERTER$12 },
14155
+ tone: { converter: STRING_CONVERTER$12 },
14156
+ size: { converter: STRING_CONVERTER$12 },
14157
+ placement: { converter: STRING_CONVERTER$12 },
14158
+ offset: { converter: NUMBER_CONVERTER$7 }
13483
14159
  };
13484
14160
  idGen = createCounterIdGenerator();
13485
14161
  pickerScope = createScope(null, this.idGen);
@@ -13558,6 +14234,7 @@ var XhTimePickerElement = class extends XhElement {
13558
14234
  svc.refs.set("registerLayer", this.registerLayer);
13559
14235
  svc.refs.set("position", this.positionEngine);
13560
14236
  svc.refs.set("getAnchorEl", () => this.getPart("control"));
14237
+ svc.refs.set("getTriggerEl", () => this.getPart("trigger"));
13561
14238
  svc.refs.set("getFloatingEl", () => this.getPart("positioner"));
13562
14239
  svc.refs.set("getContentEl", () => this.getPart("content"));
13563
14240
  }
@@ -13637,7 +14314,7 @@ var XhTimePickerElement = class extends XhElement {
13637
14314
  };
13638
14315
  //#endregion
13639
14316
  //#region src/elements/timeline.ts
13640
- const STRING_CONVERTER$12 = { fromAttribute: (v) => v ?? void 0 };
14317
+ const STRING_CONVERTER$11 = { fromAttribute: (v) => v ?? void 0 };
13641
14318
  const ITEM_SELECTOR$2 = "[data-xh-part=\"item\"]";
13642
14319
  /**
13643
14320
  * `<xh-timeline>` —— 事件流行为宿主,无状态机,把 connectTimeline 产出打到角色节点上。
@@ -13671,9 +14348,9 @@ var XhTimelineElement = class extends XhElement {
13671
14348
  meta: timelineMeta
13672
14349
  };
13673
14350
  static properties = {
13674
- orientation: { converter: STRING_CONVERTER$12 },
13675
- placement: { converter: STRING_CONVERTER$12 },
13676
- size: { converter: STRING_CONVERTER$12 }
14351
+ orientation: { converter: STRING_CONVERTER$11 },
14352
+ placement: { converter: STRING_CONVERTER$11 },
14353
+ size: { converter: STRING_CONVERTER$11 }
13677
14354
  };
13678
14355
  /**
13679
14356
  * 取角色节点所属条目的语气:tone 写在 item 节点上,圆点向上找自己的 item。
@@ -13709,9 +14386,9 @@ var XhTimelineElement = class extends XhElement {
13709
14386
  };
13710
14387
  //#endregion
13711
14388
  //#region src/elements/timer.ts
13712
- const STRING_CONVERTER$11 = { fromAttribute: (v) => v ?? void 0 };
13713
- const NUMBER_CONVERTER$7 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
13714
- const BOOLEAN_CONVERTER$9 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
14389
+ const STRING_CONVERTER$10 = { fromAttribute: (v) => v ?? void 0 };
14390
+ const NUMBER_CONVERTER$6 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
14391
+ const BOOLEAN_CONVERTER$8 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
13715
14392
  /** 条目没写段单位或写错时退回秒:秒是最常显示的那一段。 */
13716
14393
  const FALLBACK_UNIT = "seconds";
13717
14394
  /**
@@ -13750,20 +14427,20 @@ var XhTimerElement = class extends XhElement {
13750
14427
  };
13751
14428
  static properties = {
13752
14429
  startMs: {
13753
- converter: NUMBER_CONVERTER$7,
14430
+ converter: NUMBER_CONVERTER$6,
13754
14431
  attribute: "start-ms"
13755
14432
  },
13756
14433
  targetMs: {
13757
- converter: NUMBER_CONVERTER$7,
14434
+ converter: NUMBER_CONVERTER$6,
13758
14435
  attribute: "target-ms"
13759
14436
  },
13760
- countdown: { converter: BOOLEAN_CONVERTER$9 },
14437
+ countdown: { converter: BOOLEAN_CONVERTER$8 },
13761
14438
  autoStart: {
13762
- converter: BOOLEAN_CONVERTER$9,
14439
+ converter: BOOLEAN_CONVERTER$8,
13763
14440
  attribute: "auto-start"
13764
14441
  },
13765
- interval: { converter: NUMBER_CONVERTER$7 },
13766
- size: { converter: STRING_CONVERTER$11 },
14442
+ interval: { converter: NUMBER_CONVERTER$6 },
14443
+ size: { converter: STRING_CONVERTER$10 },
13767
14444
  translations: { attribute: false }
13768
14445
  };
13769
14446
  notifyTick = (details) => {
@@ -13833,24 +14510,23 @@ var XhTimerElement = class extends XhElement {
13833
14510
  };
13834
14511
  //#endregion
13835
14512
  //#region src/elements/toast.ts
13836
- const STRING_CONVERTER$10 = { fromAttribute: (v) => v ?? void 0 };
13837
- const NUMBER_CONVERTER$6 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
13838
- const BOOLEAN_CONVERTER$8 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
14513
+ const STRING_CONVERTER$9 = { fromAttribute: (v) => v ?? void 0 };
14514
+ const NUMBER_CONVERTER$5 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
14515
+ const BOOLEAN_CONVERTER$7 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
13839
14516
  /**
13840
- * `<xh-toast>` —— Light-DOM 行为宿主:作者写 root/title/description/action-trigger/close-trigger
14517
+ * `<xh-toast>` —— Light-DOM 行为宿主:作者写 root/title/action-trigger/close-trigger
13841
14518
  * 角色节点,元素跑 toast 机器并把 connect 产出打上去。
13842
14519
  *
13843
14520
  * root 承载 role 与 aria-live:默认 status + polite(排队等读屏的空隙),
13844
- * type="error" 换成 alert + assertive(打断当前朗读)。指针停在通知上、
13845
- * 或焦点落进通知内部都会把倒计时按住,离开才接着走剩下的那一段。
14521
+ * type="error" 换成 alert + assertive(打断当前朗读)。指针停在条子上、
14522
+ * 或焦点落进条子内部都会把倒计时按住,离开才接着走剩下的那一段。
13846
14523
  *
13847
14524
  * 退场窗口走完只把 root 收起、不删节点:作者写在里面的内容归作者,
13848
- * 什么时候把这条从队列里删掉是 `<xh-toaster>` 的事(它收本元素冒泡上去的 status-change)。
14525
+ * 什么时候把这条从队列里删掉是全局服务的事(它收本元素冒泡上去的 status-change)。
13849
14526
  *
13850
14527
  * @customElement xh-toast
13851
- * @attr {string} id - 队列身份,`<xh-toaster>` 按它寻址;不给就用实例自己的 scope id
14528
+ * @attr {string} id - 队列身份,全局服务按它寻址;不给就用实例自己的 scope id
13852
14529
  * @attr {string} title - 标题文案;作者没在 title 部件里写内容时由元素填入
13853
- * @attr {string} description - 补充说明;作者没在 description 部件里写内容时由元素填入
13854
14530
  * @attr {'info'|'success'|'warning'|'error'|'loading'} type - 语气,默认 info;loading 不自动消失
13855
14531
  * @attr {number} duration - 停留毫秒,默认 5000;<=0 即关掉自动消失
13856
14532
  * @attr {number} remove-delay - 退场窗口毫秒,默认 200,留给退场动画
@@ -13860,7 +14536,6 @@ const BOOLEAN_CONVERTER$8 = { fromAttribute: (v) => v === null ? void 0 : v !==
13860
14536
  * @fires action - 操作按钮被按下;detail 为 `{ id: string }`
13861
14537
  * @csspart root - role=status(error 时 alert)的容器,承载 data-type / data-tone / data-state / data-paused
13862
14538
  * @csspart title - 标题,aria-labelledby 的目标
13863
- * @csspart description - 补充说明,aria-describedby 的目标
13864
14539
  * @csspart action-trigger - 操作按钮:先发 action 再进入退场
13865
14540
  * @csspart close-trigger - 关闭按钮;closable=false 时转原生 disabled 并收起
13866
14541
  */
@@ -13871,23 +14546,22 @@ var XhToastElement = class extends XhElement {
13871
14546
  };
13872
14547
  static properties = {
13873
14548
  toastId: {
13874
- converter: STRING_CONVERTER$10,
14549
+ converter: STRING_CONVERTER$9,
13875
14550
  attribute: "id"
13876
14551
  },
13877
14552
  titleText: {
13878
- converter: STRING_CONVERTER$10,
14553
+ converter: STRING_CONVERTER$9,
13879
14554
  attribute: "title"
13880
14555
  },
13881
- description: { converter: STRING_CONVERTER$10 },
13882
- type: { converter: STRING_CONVERTER$10 },
13883
- duration: { converter: NUMBER_CONVERTER$6 },
14556
+ type: { converter: STRING_CONVERTER$9 },
14557
+ duration: { converter: NUMBER_CONVERTER$5 },
13884
14558
  removeDelay: {
13885
- converter: NUMBER_CONVERTER$6,
14559
+ converter: NUMBER_CONVERTER$5,
13886
14560
  attribute: "remove-delay"
13887
14561
  },
13888
- closable: { converter: BOOLEAN_CONVERTER$8 },
14562
+ closable: { converter: BOOLEAN_CONVERTER$7 },
13889
14563
  pauseOnPageIdle: {
13890
- converter: BOOLEAN_CONVERTER$8,
14564
+ converter: BOOLEAN_CONVERTER$7,
13891
14565
  attribute: "pause-on-page-idle"
13892
14566
  },
13893
14567
  translations: { attribute: false }
@@ -13911,7 +14585,6 @@ var XhToastElement = class extends XhElement {
13911
14585
  return {
13912
14586
  id: this.toastId,
13913
14587
  title: this.titleText,
13914
- description: this.description,
13915
14588
  type: this.type,
13916
14589
  duration: this.duration,
13917
14590
  removeDelay: this.removeDelay,
@@ -13949,160 +14622,14 @@ var XhToastElement = class extends XhElement {
13949
14622
  };
13950
14623
  put("root", api.getRootProps());
13951
14624
  put("title", api.getTitleProps());
13952
- put("description", api.getDescriptionProps());
13953
14625
  put("action-trigger", api.getActionTriggerProps());
13954
14626
  put("close-trigger", api.getCloseTriggerProps());
13955
14627
  this.fillText(this.getPart("title"), api.title);
13956
- this.fillText(this.getPart("description"), api.description);
13957
14628
  this.setPartHidden(this.getPart("root"), api.status === "unmounted");
13958
14629
  this.setPartHidden(this.getPart("close-trigger"), !api.closable);
13959
14630
  }
13960
14631
  };
13961
14632
  //#endregion
13962
- //#region src/elements/toaster.ts
13963
- const STRING_CONVERTER$9 = { fromAttribute: (v) => v ?? void 0 };
13964
- const NUMBER_CONVERTER$5 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
13965
- const BOOLEAN_CONVERTER$7 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
13966
- /**
13967
- * 这一摞对应哪个位置。属性缺席就交 undefined,由 connect 回落到 toaster 的 placement。
13968
- * 写坏了照原样交出去:它与九个位没有一个对得上,这摞就一直是空的——
13969
- * 空得明显好过悄悄冒充另一个位置,把通知摆到作者没想到的角落。
13970
- */
13971
- function groupPlacement(el) {
13972
- const raw = el.getAttribute("placement");
13973
- return raw == null || raw === "" ? void 0 : raw;
13974
- }
13975
- /**
13976
- * `<xh-toaster>` —— Light-DOM 行为宿主:作者写 root 与若干 group 角色节点,
13977
- * 元素跑 toaster 机器并把 connect 产出打上去。每个 group 用 `placement` 属性声明自己是哪个位置,
13978
- * 不写就落在 toaster 的 placement 上。
13979
- *
13980
- * 单条通知的节点由作者按队列渲染(读 `visibleToasts` 或听 `toasts-change`),元素不替作者生成:
13981
- * 生成节点就等于收走模板控制权,图标、进度条、i18n 文案都再塞不进来。
13982
- * 每条渲染成一个 `<xh-toast>`,它走完退场会冒泡一条 status-change,本元素据此把记录删掉。
13983
- *
13984
- * @customElement xh-toaster
13985
- * @attr {'top-start'|'top'|'top-end'|'middle-start'|'middle'|'middle-end'|'bottom-start'|'bottom'|'bottom-end'} placement - 默认落位,默认 bottom-end
13986
- * @attr {number} max - 每个位置最多同时留几条,超出挤掉最旧的;不给即不限
13987
- * @attr {number} gap - 同一摞内的间距(px),默认 16
13988
- * @attr {number} duration - 单条没写 duration 时的默认停留毫秒
13989
- * @attr {number} remove-delay - 单条没写 remove-delay 时的默认退场窗口毫秒
13990
- * @attr {boolean} pause-on-page-idle - 页面切到后台时按住计时,逐条下发
13991
- * @fires toasts-change - 队列变化;detail 为 `{ toasts: ToastRecord[] }`
13992
- * @csspart root - role=region 的地标容器,承载 data-count / data-empty
13993
- * @csspart group - 某一个位置上的那一摞,可自带 placement 属性;承载 data-placement / data-count / data-empty 与间距
13994
- */
13995
- var XhToasterElement = class extends XhElement {
13996
- static partContract = {
13997
- anatomy: toasterAnatomy,
13998
- meta: toasterMeta
13999
- };
14000
- static properties = {
14001
- toasts: { attribute: false },
14002
- defaultToasts: { attribute: false },
14003
- placement: { converter: STRING_CONVERTER$9 },
14004
- max: { converter: NUMBER_CONVERTER$5 },
14005
- gap: { converter: NUMBER_CONVERTER$5 },
14006
- duration: { converter: NUMBER_CONVERTER$5 },
14007
- removeDelay: {
14008
- converter: NUMBER_CONVERTER$5,
14009
- attribute: "remove-delay"
14010
- },
14011
- pauseOnPageIdle: {
14012
- converter: BOOLEAN_CONVERTER$7,
14013
- attribute: "pause-on-page-idle"
14014
- },
14015
- translations: { attribute: false }
14016
- };
14017
- notify = (details) => {
14018
- this.dispatchEvent(new CustomEvent("toasts-change", {
14019
- detail: details,
14020
- bubbles: true,
14021
- composed: true
14022
- }));
14023
- };
14024
- ctrl = new MachineController(this, toasterMachine, () => this.machineProps());
14025
- machineProps() {
14026
- return {
14027
- toasts: this.toasts,
14028
- defaultToasts: this.defaultToasts,
14029
- placement: this.placement,
14030
- max: this.max,
14031
- gap: this.gap,
14032
- duration: this.duration,
14033
- removeDelay: this.removeDelay,
14034
- pauseOnPageIdle: this.pauseOnPageIdle,
14035
- translations: this.translations,
14036
- onToastsChange: this.notify
14037
- };
14038
- }
14039
- /**
14040
- * 命令式入口共用的取法。机器要到进文档(hostConnected)才建:
14041
- * 还没进文档就发通知是调用方的时序问题,明说好过把这条通知静默丢掉。
14042
- */
14043
- commands() {
14044
- if (!this.ctrl.service) throw new Error("[xh] <xh-toaster> 还没进文档,命令式接口此时不可用");
14045
- return connectToaster(this.ctrl.service, wcNormalize);
14046
- }
14047
- /** 入队并返回 id;同 id 已存在则就地改写,位置不动(loading 转 success 走的就是这条)。 */
14048
- create(options = {}) {
14049
- return this.commands().create(options);
14050
- }
14051
- /**
14052
- * 刻意不叫 `update`:那是 Lit 自己的渲染生命周期钩子,占用它会让宿主每次重渲
14053
- * 都拐进这里来(还带着一个 changedProperties 当 id),组件当场不工作。
14054
- * Vue 侧没有这层基类,composable 上仍叫 `update`。
14055
- */
14056
- updateToast(id, options) {
14057
- this.commands().update(id, options);
14058
- }
14059
- dismiss(id) {
14060
- this.commands().dismiss(id);
14061
- }
14062
- dismissAll() {
14063
- this.commands().dismissAll();
14064
- }
14065
- /** max 之内、按加入先后排列的可见条目,已补齐默认值,可直接摊给 `<xh-toast>`。 */
14066
- get visibleToasts() {
14067
- return this.commands().visibleToasts;
14068
- }
14069
- /** 当前有条目的位置,按九宫格固定顺序。 */
14070
- get placements() {
14071
- return this.commands().placements;
14072
- }
14073
- get count() {
14074
- return this.commands().count;
14075
- }
14076
- getToastsByPlacement(placement) {
14077
- return this.commands().getToastsByPlacement(placement);
14078
- }
14079
- /**
14080
- * 单条通知走完退场会冒泡上来:记录该从队列里删掉了。
14081
- * 认元素名而不是只认事件名——avatar 之类的部件也派 status-change,且完全可能就摆在通知内部。
14082
- */
14083
- onToastStatus = (event) => {
14084
- if (event.target?.tagName.toLowerCase() !== "xh-toast") return;
14085
- const detail = event.detail;
14086
- if (detail?.status !== "unmounted") return;
14087
- if (this.ctrl.service?.getStatus() !== "Started") return;
14088
- this.dismiss(detail.id);
14089
- };
14090
- connectedCallback() {
14091
- super.connectedCallback();
14092
- this.addEventListener("status-change", this.onToastStatus);
14093
- }
14094
- disconnectedCallback() {
14095
- this.removeEventListener("status-change", this.onToastStatus);
14096
- super.disconnectedCallback();
14097
- }
14098
- wire() {
14099
- const api = connectToaster(this.ctrl.service, wcNormalize);
14100
- const root = this.getPart("root");
14101
- if (root) this.spreader.spread(root, api.getRootProps());
14102
- for (const el of this.getParts("group")) this.spreader.spread(el, api.getGroupProps({ placement: groupPlacement(el) }));
14103
- }
14104
- };
14105
- //#endregion
14106
14633
  //#region src/elements/toggle.ts
14107
14634
  /**
14108
14635
  * `<xh-toggle>` —— Light-DOM 行为宿主,跑 toggle 机器并把 connect 产出打到 root 角色节点。
@@ -14178,6 +14705,7 @@ const BOOLEAN_CONVERTER$6 = { fromAttribute: (v) => v === null ? void 0 : v !==
14178
14705
  * @attr {boolean} multiple - 允许多项同时选中,默认关闭
14179
14706
  * @attr {boolean} disabled - 整组禁用
14180
14707
  * @attr {boolean} disallow-empty - 不许把值点空(最后一个选中项摘不掉)
14708
+ * @attr {'sm'|'md'|'lg'} size - 尺寸
14181
14709
  * @attr {'horizontal'|'vertical'} orientation - 视觉排布,默认 horizontal;方向键四个恒响应,与它无关
14182
14710
  * @attr {'ltr'|'rtl'} dir - 文字方向,只改写左右方向键语义,默认 ltr
14183
14711
  * @attr {boolean} loop - 方向键走到尽头回绕,默认开启
@@ -14204,6 +14732,7 @@ var XhToggleGroupElement = class extends XhElement {
14204
14732
  converter: BOOLEAN_CONVERTER$6,
14205
14733
  attribute: "disallow-empty"
14206
14734
  },
14735
+ size: { converter: STRING_CONVERTER$8 },
14207
14736
  orientation: { converter: STRING_CONVERTER$8 },
14208
14737
  direction: {
14209
14738
  converter: STRING_CONVERTER$8,
@@ -14234,6 +14763,7 @@ var XhToggleGroupElement = class extends XhElement {
14234
14763
  multiple: this.multiple,
14235
14764
  disabled: this.disabled,
14236
14765
  disallowEmpty: this.disallowEmpty,
14766
+ size: this.size,
14237
14767
  orientation: this.orientation,
14238
14768
  dir: this.direction,
14239
14769
  loop: this.loop,
@@ -14982,7 +15512,9 @@ const BRANCH_SELECTOR$1 = "[data-xh-part=\"branch\"]";
14982
15512
  * 树数据与展开/选中集合都是数组,属性表达不了,只能走 property(`el.collection = [...]`)。
14983
15513
  *
14984
15514
  * @customElement xh-tree
14985
- * @attr {'single'|'multiple'} selection-mode - 选择模式,默认 single
15515
+ * @attr {boolean} multiple - 复选,默认关闭
15516
+ * @attr {'horizontal'|'vertical'} leaf-orientation - 末端那一层怎么排,默认 vertical;horizontal 让子节点全是叶子的那层并排铺开
15517
+ * @attr {'single'|'multiple'} selection-mode - 选择模式的旧写法,默认 single;与 multiple 同时给时以它为准
14986
15518
  * @attr {boolean} cascade - multiple 下父子级联勾选(整枝传导/半选/禁用冻结),默认 false
14987
15519
  * @attr {string} checked-strategy - 级联下对外值的收敛策略:child(默认)/ parent / all
14988
15520
  * @attr {boolean} expand-on-click - 点分支行顺带展开/收起,默认开;写 expand-on-click="false" 关掉
@@ -15018,6 +15550,11 @@ var XhTreeElement = class extends XhElement {
15018
15550
  defaultExpandedValue: { attribute: false },
15019
15551
  selection: { attribute: false },
15020
15552
  defaultSelection: { attribute: false },
15553
+ multiple: { converter: BOOLEAN_CONVERTER$2 },
15554
+ leafOrientation: {
15555
+ converter: STRING_CONVERTER$3,
15556
+ attribute: "leaf-orientation"
15557
+ },
15021
15558
  selectionMode: {
15022
15559
  converter: STRING_CONVERTER$3,
15023
15560
  attribute: "selection-mode"
@@ -15061,8 +15598,10 @@ var XhTreeElement = class extends XhElement {
15061
15598
  defaultExpandedValue: this.defaultExpandedValue,
15062
15599
  selection: this.selection,
15063
15600
  defaultSelection: this.defaultSelection,
15601
+ multiple: this.multiple,
15064
15602
  selectionMode: this.selectionMode,
15065
15603
  cascade: this.cascade,
15604
+ leafOrientation: this.leafOrientation,
15066
15605
  checkedStrategy: this.checkedStrategy,
15067
15606
  expandOnClick: this.expandOnClick,
15068
15607
  disabled: this.disabled ?? false,
@@ -15266,6 +15805,17 @@ var XhTreeSelectElement = class extends XhElement {
15266
15805
  scope: this.treeSelectScope,
15267
15806
  onBuilt: (svc) => this.injectRefs(svc)
15268
15807
  });
15808
+ /**
15809
+ * 树的自绘条:与 content 同级挂在已经 fixed 的 positioner 上。
15810
+ * 两条轴都摆——深层节点靠缩进往行末推,横向溢出与纵向一样是常态;
15811
+ * 横条的正负按排版方向算,而组件不读计算样式,把作者写的那份显式交过去。
15812
+ */
15813
+ bars = new ScrollbarsController(this, {
15814
+ shell: () => this.getPart("positioner"),
15815
+ scrollable: () => this.getPart("content"),
15816
+ axes: ["vertical", "horizontal"],
15817
+ props: () => ({ dir: this.direction })
15818
+ });
15269
15819
  machineProps() {
15270
15820
  return {
15271
15821
  collection: this.collection,
@@ -15308,7 +15858,7 @@ var XhTreeSelectElement = class extends XhElement {
15308
15858
  return this.config.layerRegistry.register({
15309
15859
  kind: "popover",
15310
15860
  node: () => this.getPart("content"),
15311
- branches: () => [this.getPart("trigger")].filter(Boolean),
15861
+ branches: () => [this.getPart("trigger"), this.getPart("positioner")].filter(Boolean),
15312
15862
  isModal: () => false,
15313
15863
  setModal: () => {},
15314
15864
  surfaces: () => []
@@ -15403,6 +15953,7 @@ var XhTreeSelectElement = class extends XhElement {
15403
15953
  this.exit.update(api.open);
15404
15954
  this.setPartHidden(this.getPart("content"), !this.exit.visible);
15405
15955
  for (const el of this.getParts("branch-content")) this.setPartHidden(el, !api.isExpanded(this.nodeOf(el, BRANCH_SELECTOR).value));
15956
+ this.bars.wire();
15406
15957
  }
15407
15958
  disconnectedCallback() {
15408
15959
  super.disconnectedCallback();
@@ -15752,6 +16303,8 @@ function defineXhElements() {
15752
16303
  defineElement("xh-menu", XhMenuElement, version);
15753
16304
  defineElement("xh-menubar", XhMenubarElement, version);
15754
16305
  defineElement("xh-navigation-menu", XhNavigationMenuElement, version);
16306
+ defineElement("xh-notification", XhNotificationElement, version);
16307
+ defineElement("xh-notification-item", XhNotificationItemElement, version);
15755
16308
  defineElement("xh-pagination", XhPaginationElement, version);
15756
16309
  defineElement("xh-pin-input", XhPinInputElement, version);
15757
16310
  defineElement("xh-popover", XhPopoverElement, version);
@@ -15781,7 +16334,6 @@ function defineXhElements() {
15781
16334
  defineElement("xh-timeline", XhTimelineElement, version);
15782
16335
  defineElement("xh-timer", XhTimerElement, version);
15783
16336
  defineElement("xh-toast", XhToastElement, version);
15784
- defineElement("xh-toaster", XhToasterElement, version);
15785
16337
  defineElement("xh-toggle", XhToggleElement, version);
15786
16338
  defineElement("xh-toggle-group", XhToggleGroupElement, version);
15787
16339
  defineElement("xh-toolbar", XhToolbarElement, version);
@@ -15801,6 +16353,6 @@ function defineXhElements() {
15801
16353
  }
15802
16354
  }
15803
16355
  //#endregion
15804
- export { XhAccordionElement, XhAlertElement, XhAnchorElement, XhAvatarElement, XhBadgeElement, XhBreadcrumbElement, XhButtonElement, XhCalendarElement, XhCarouselElement, XhCascaderElement, XhCheckboxElement, XhCheckboxGroupElement, XhClipboardElement, XhCodeBlockElement, XhCollapsibleElement, XhColorPickerElement, XhComboboxElement, XhComposerElement, XhConfigElement, XhContextMenuElement, XhDateFieldElement, XhDatePickerElement, XhDialogElement, XhDownloadTriggerElement, XhDrawerElement, XhEditableElement, XhEmptyStateElement, XhFieldElement, XhFieldsetElement, XhFileUploadElement, XhFloatingPanelElement, XhFormElement, XhHeatmapElement, XhHotkeysElement, XhHoverCardElement, XhIconElement, XhImageCropperElement, XhImageElement, XhImageViewerElement, XhJsonViewerElement, XhListboxElement, XhLoadingBarElement, XhMasonryElement, XhMenuElement, XhMenubarElement, XhNavigationMenuElement, XhNumberFieldElement, XhPaginationElement, XhPasswordInputElement, XhPinInputElement, XhPopoverElement, XhProgressElement, XhRadioGroupElement, XhRatingElement, XhScrollAreaElement, XhScrollbarElement, XhSegmentedElement, XhSelectElement, XhSeparatorElement, XhSideNavElement, XhSignaturePadElement, XhSkeletonElement, XhSliderElement, XhSpaceElement, XhSpinnerElement, XhSplitterElement, XhStepsElement, XhSwitchElement, XhTableElement, XhTabsElement, XhTagElement, XhTagsInputElement, XhTextFieldElement, XhThreadElement, XhTimeFieldElement, XhTimePickerElement, XhTimerElement, XhToastElement, XhToasterElement, XhToggleElement, XhToggleGroupElement, XhToolbarElement, XhTooltipElement, XhTourElement, XhTransferElement, XhTreeElement, XhTreeSelectElement, XhVirtualizerElement, defineXhElements };
16356
+ export { XhAccordionElement, XhAlertElement, XhAnchorElement, XhAvatarElement, XhBadgeElement, XhBreadcrumbElement, XhButtonElement, XhCalendarElement, XhCarouselElement, XhCascaderElement, XhCheckboxElement, XhCheckboxGroupElement, XhClipboardElement, XhCodeBlockElement, XhCollapsibleElement, XhColorPickerElement, XhComboboxElement, XhComposerElement, XhConfigElement, XhContextMenuElement, XhDateFieldElement, XhDatePickerElement, XhDialogElement, XhDownloadTriggerElement, XhDrawerElement, XhEditableElement, XhEmptyStateElement, XhFieldElement, XhFieldsetElement, XhFileUploadElement, XhFloatingPanelElement, XhFormElement, XhHeatmapElement, XhHotkeysElement, XhHoverCardElement, XhIconElement, XhImageCropperElement, XhImageElement, XhImageViewerElement, XhJsonViewerElement, XhListboxElement, XhLoadingBarElement, XhMasonryElement, XhMenuElement, XhMenubarElement, XhNavigationMenuElement, XhNotificationElement, XhNotificationItemElement, XhNumberFieldElement, XhPaginationElement, XhPasswordInputElement, XhPinInputElement, XhPopoverElement, XhProgressElement, XhRadioGroupElement, XhRatingElement, XhScrollAreaElement, XhScrollbarElement, XhSegmentedElement, XhSelectElement, XhSeparatorElement, XhSideNavElement, XhSignaturePadElement, XhSkeletonElement, XhSliderElement, XhSpaceElement, XhSpinnerElement, XhSplitterElement, XhStepsElement, XhSwitchElement, XhTableElement, XhTabsElement, XhTagElement, XhTagsInputElement, XhTextFieldElement, XhThreadElement, XhTimeFieldElement, XhTimePickerElement, XhTimerElement, XhToastElement, XhToggleElement, XhToggleGroupElement, XhToolbarElement, XhTooltipElement, XhTourElement, XhTransferElement, XhTreeElement, XhTreeSelectElement, XhVirtualizerElement, defineXhElements };
15805
16357
 
15806
16358
  //# sourceMappingURL=define.js.map