@xihan-ui/web-components 1.0.0-alpha.0 → 1.0.0-alpha.2

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,11 +1,12 @@
1
- import { a as discoverParts, i as containsPart, o as wcNormalize, r as createSpreader, t as MachineController } from "./machine-controller-Bnr5jbhz.js";
1
+ import { a as containsPart, i as PART_ATTR, o as discoverParts, r as createSpreader, s as wcNormalize, t as MachineController } from "./machine-controller-B1dE9_NF.js";
2
2
  import { t as defineElement } from "./registry-DR6I2_zF.js";
3
- import { n as version, t as XhReactiveElement } from "./element-xjYY5Oe2.js";
3
+ import { n as version, t as XhReactiveElement } from "./element-BHyfNDKE.js";
4
4
  import { DIAGNOSTIC_CODES, createCounterIdGenerator, createRuntimeConfig, createScope, getDiagnostics, reportDiagnostic } from "@xihan-ui/kernel";
5
5
  import { ITEM_VALUE_ATTR, declaredItemDisabled, isItemDisabled } from "@xihan-ui/behavior";
6
- import { accordionAnatomy, accordionMachine, accordionMeta, affixAnatomy, affixMachine, affixMeta, alertAnatomy, alertMachine, alertMeta, anchorAnatomy, anchorMachine, anchorMeta, avatarAnatomy, avatarGroupAnatomy, avatarGroupMeta, avatarMachine, avatarMeta, backTopAnatomy, backTopMachine, backTopMeta, badgeAnatomy, badgeMeta, breadcrumbAnatomy, breadcrumbMeta, 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, connectDrawer, connectDynamicInput, connectEditable, connectEllipsis, connectEmptyState, connectField, connectFileUpload, connectFlex, connectFloatButton, connectForm, connectGradientText, connectGrid, connectHighlight, connectHoverCard, connectIcon, connectIconWrapper, connectImage, connectInfiniteScroll, connectLayout, connectList, connectListbox, connectLoadingBar, connectLog, connectMarquee, connectMention, connectMenu, connectMenubar, connectNavigationMenu, connectNumberAnimation, connectNumberField, connectPageHeader, connectPagination, connectPinInput, connectPopconfirm, connectPopover, connectPopselect, connectProgress, connectQrCode, connectRadioGroup, connectRating, connectResult, connectScrollArea, connectSelect, connectSeparator, connectSkeleton, connectSlider, connectSpinner, connectSplitter, connectStatistic, connectSteps, connectSwitch, connectTable, connectTabs, connectTagsInput, connectTextField, connectThread, connectTime, connectTimeField, connectTimePicker, connectTimeline, 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, dialogAnatomy, dialogMachine, dialogMeta, drawerAnatomy, drawerMachine, drawerMeta, dynamicInputAnatomy, dynamicInputMachine, dynamicInputMeta, editableAnatomy, editableMachine, editableMeta, ellipsisAnatomy, ellipsisMachine, ellipsisMeta, emptyStateAnatomy, emptyStateMeta, fieldAnatomy, fieldMeta, fileUploadAnatomy, fileUploadMachine, fileUploadMeta, flexAnatomy, flexMeta, floatButtonAnatomy, floatButtonMeta, formAnatomy, formMachine, formMeta, gradientTextAnatomy, gradientTextMeta, gridAnatomy, gridMeta, highlightAnatomy, highlightMeta, hoverCardAnatomy, hoverCardMachine, hoverCardMeta, iconAnatomy, iconMeta, iconWrapperAnatomy, iconWrapperMeta, imageAnatomy, imageMachine, imageMeta, infiniteScrollAnatomy, infiniteScrollMachine, infiniteScrollMeta, layoutAnatomy, layoutMachine, layoutMeta, listAnatomy, listMeta, listboxAnatomy, listboxMachine, listboxMeta, loadingBarAnatomy, loadingBarMachine, loadingBarMeta, logAnatomy, logMeta, marqueeAnatomy, marqueeMeta, mentionAnatomy, mentionMachine, mentionMeta, menuAnatomy, menuMachine, menuMeta, menubarAnatomy, menubarMachine, menubarMeta, navigationMenuAnatomy, navigationMenuMachine, navigationMenuMeta, numberAnimationAnatomy, numberAnimationMachine, numberAnimationMeta, numberFieldAnatomy, numberFieldMachine, numberFieldMeta, pageHeaderAnatomy, pageHeaderMeta, paginationAnatomy, paginationMachine, paginationMeta, pinInputAnatomy, pinInputMachine, pinInputMeta, popconfirmAnatomy, popconfirmMeta, popoverAnatomy, popoverMachine, popoverMeta, popselectAnatomy, popselectMeta, progressAnatomy, progressMeta, qrCodeAnatomy, qrCodeMeta, radioGroupAnatomy, radioGroupMachine, radioGroupMeta, ratingAnatomy, ratingMachine, ratingMeta, resultAnatomy, resultMeta, scrollAreaAnatomy, scrollAreaMachine, scrollAreaMeta, selectAnatomy, selectMachine, selectMeta, separatorAnatomy, separatorMeta, skeletonAnatomy, skeletonMeta, sliderAnatomy, sliderMachine, sliderMeta, spinnerAnatomy, spinnerMeta, splitterAnatomy, splitterMachine, splitterMeta, statisticAnatomy, statisticMeta, stepsAnatomy, stepsMachine, stepsMeta, switchAnatomy, switchMachine, switchMeta, tableAnatomy, tableMachine, tableMeta, tabsAnatomy, tabsMachine, tabsMeta, tagsInputAnatomy, tagsInputMachine, tagsInputMeta, textFieldAnatomy, textFieldMachine, textFieldMeta, threadAnatomy, threadMachine, threadMeta, timeAnatomy, timeFieldAnatomy, timeFieldMachine, timeFieldMeta, timeMeta, timePickerAnatomy, timePickerMachine, timePickerMeta, timelineAnatomy, timelineMeta, 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";
6
+ import { 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, 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, connectDrawer, connectDynamicInput, connectEditable, connectEllipsis, connectEmptyState, connectField, connectFileUpload, connectFlex, connectFloatButton, connectForm, connectGradientText, connectGrid, connectHighlight, connectHoverCard, connectIcon, connectIconWrapper, connectImage, connectImageViewer, connectInfiniteScroll, connectLayout, connectList, connectListbox, connectLoadingBar, connectLog, connectMarquee, connectMention, connectMenu, connectMenubar, connectNavigationMenu, connectNumberAnimation, connectNumberField, connectPageHeader, connectPagination, connectPinInput, connectPopconfirm, connectPopover, connectPopselect, connectProgress, connectQrCode, connectRadioGroup, connectRating, connectResult, connectScrollArea, connectSelect, connectSeparator, connectSideNav, connectSkeleton, connectSlider, connectSpinner, connectSplitter, connectStatistic, connectSteps, connectSwitch, connectTable, connectTabs, connectTagsInput, connectTextField, connectThread, connectTime, connectTimeField, connectTimePicker, connectTimeline, 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, dialogAnatomy, dialogMachine, dialogMeta, drawerAnatomy, drawerMachine, drawerMeta, dynamicInputAnatomy, dynamicInputMachine, dynamicInputMeta, editableAnatomy, editableMachine, editableMeta, ellipsisAnatomy, ellipsisMachine, ellipsisMeta, emptyStateAnatomy, emptyStateMeta, fieldAnatomy, fieldMeta, fileUploadAnatomy, fileUploadMachine, fileUploadMeta, flexAnatomy, flexMeta, floatButtonAnatomy, floatButtonMeta, formAnatomy, formMachine, formMeta, gradientTextAnatomy, gradientTextMeta, gridAnatomy, gridMeta, highlightAnatomy, highlightMeta, hoverCardAnatomy, hoverCardMachine, hoverCardMeta, iconAnatomy, iconMeta, iconWrapperAnatomy, iconWrapperMeta, imageAnatomy, imageMachine, imageMeta, imageViewerAnatomy, imageViewerCounterText, imageViewerMachine, imageViewerMeta, infiniteScrollAnatomy, infiniteScrollMachine, infiniteScrollMeta, layoutAnatomy, layoutMachine, layoutMeta, listAnatomy, listMeta, listboxAnatomy, listboxMachine, listboxMeta, loadingBarAnatomy, loadingBarMachine, loadingBarMeta, logAnatomy, logMeta, marqueeAnatomy, marqueeMeta, mentionAnatomy, mentionMachine, mentionMeta, menuAnatomy, menuMachine, menuMeta, menubarAnatomy, menubarMachine, menubarMeta, navigationMenuAnatomy, navigationMenuMachine, navigationMenuMeta, numberAnimationAnatomy, numberAnimationMachine, numberAnimationMeta, numberFieldAnatomy, numberFieldMachine, numberFieldMeta, pageHeaderAnatomy, pageHeaderMeta, paginationAnatomy, paginationMachine, paginationMeta, pinInputAnatomy, pinInputMachine, pinInputMeta, popconfirmAnatomy, popconfirmMeta, popoverAnatomy, popoverMachine, popoverMeta, popselectAnatomy, popselectInitialFocus, popselectMeta, progressAnatomy, progressMeta, qrCodeAnatomy, qrCodeMeta, radioGroupAnatomy, radioGroupMachine, radioGroupMeta, ratingAnatomy, ratingMachine, ratingMeta, resultAnatomy, resultMeta, scrollAreaAnatomy, scrollAreaMachine, scrollAreaMeta, selectAnatomy, selectMachine, selectMeta, separatorAnatomy, separatorMeta, sideNavAnatomy, sideNavMachine, sideNavMeta, skeletonAnatomy, skeletonMeta, sliderAnatomy, sliderMachine, sliderMeta, spinnerAnatomy, spinnerMeta, splitterAnatomy, splitterMachine, splitterMeta, statisticAnatomy, statisticMeta, stepsAnatomy, stepsMachine, stepsMeta, switchAnatomy, switchMachine, switchMeta, tableAnatomy, tableMachine, tableMeta, tabsAnatomy, tabsMachine, tabsMeta, tagsInputAnatomy, tagsInputMachine, tagsInputMeta, textFieldAnatomy, textFieldMachine, textFieldMeta, threadAnatomy, threadMachine, threadMeta, timeAnatomy, timeFieldAnatomy, timeFieldMachine, timeFieldMeta, timeMeta, timePickerAnatomy, timePickerMachine, timePickerMeta, timelineAnatomy, timelineMeta, 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";
7
7
  import { createPositionEngine } from "@xihan-ui/position";
8
8
  import { createHighlighter } from "@xihan-ui/code-highlight";
9
+ import { attachCssExit, createPresence } from "@xihan-ui/behavior/presence";
9
10
  //#region src/dom/part-contract.ts
10
11
  /**
11
12
  * 比对已发现的角色节点与契约:缺必需 part 报 error,出现解剖外的 part 名报 warn。
@@ -302,7 +303,7 @@ var XhAccordionElement = class extends XhElement {
302
303
  };
303
304
  //#endregion
304
305
  //#region src/elements/affix.ts
305
- const NUMBER_CONVERTER$49 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
306
+ const NUMBER_CONVERTER$50 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
306
307
  /**
307
308
  * `<xh-affix>` —— 吸附行为宿主:滚过判定线就把 content 钉在滚动容器可视区的边上。
308
309
  *
@@ -325,11 +326,11 @@ var XhAffixElement = class extends XhElement {
325
326
  };
326
327
  static properties = {
327
328
  topOffset: {
328
- converter: NUMBER_CONVERTER$49,
329
+ converter: NUMBER_CONVERTER$50,
329
330
  attribute: "offset-top"
330
331
  },
331
332
  bottomOffset: {
332
- converter: NUMBER_CONVERTER$49,
333
+ converter: NUMBER_CONVERTER$50,
333
334
  attribute: "offset-bottom"
334
335
  },
335
336
  target: { attribute: false }
@@ -430,9 +431,9 @@ var XhAlertElement = class extends XhElement {
430
431
  };
431
432
  //#endregion
432
433
  //#region src/elements/anchor.ts
433
- const STRING_CONVERTER$79 = { fromAttribute: (v) => v ?? void 0 };
434
- const NUMBER_CONVERTER$48 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
435
- const BOOLEAN_CONVERTER$50 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
434
+ const STRING_CONVERTER$80 = { fromAttribute: (v) => v ?? void 0 };
435
+ const NUMBER_CONVERTER$49 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
436
+ const BOOLEAN_CONVERTER$52 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
436
437
  /**
437
438
  * `<xh-anchor>` —— 锚点导航行为宿主,激活项由机器的滚动观察器结算,
438
439
  * 目标区块按 link 上的 value 属性(或 targets 清单)里的 id 现查。
@@ -463,20 +464,20 @@ var XhAnchorElement = class extends XhElement {
463
464
  meta: anchorMeta
464
465
  };
465
466
  static properties = {
466
- value: { converter: STRING_CONVERTER$79 },
467
+ value: { converter: STRING_CONVERTER$80 },
467
468
  defaultValue: {
468
- converter: STRING_CONVERTER$79,
469
+ converter: STRING_CONVERTER$80,
469
470
  attribute: "default-value"
470
471
  },
471
- offset: { converter: NUMBER_CONVERTER$48 },
472
- smooth: { converter: BOOLEAN_CONVERTER$50 },
473
- orientation: { converter: STRING_CONVERTER$79 },
472
+ offset: { converter: NUMBER_CONVERTER$49 },
473
+ smooth: { converter: BOOLEAN_CONVERTER$52 },
474
+ orientation: { converter: STRING_CONVERTER$80 },
474
475
  direction: {
475
- converter: STRING_CONVERTER$79,
476
+ converter: STRING_CONVERTER$80,
476
477
  attribute: "dir"
477
478
  },
478
- tone: { converter: STRING_CONVERTER$79 },
479
- size: { converter: STRING_CONVERTER$79 },
479
+ tone: { converter: STRING_CONVERTER$80 },
480
+ size: { converter: STRING_CONVERTER$80 },
480
481
  targets: { attribute: false },
481
482
  translations: { attribute: false },
482
483
  scrollElement: { attribute: false }
@@ -531,7 +532,7 @@ var XhAnchorElement = class extends XhElement {
531
532
  };
532
533
  //#endregion
533
534
  //#region src/elements/avatar.ts
534
- const STRING_CONVERTER$78 = { fromAttribute: (v) => v ?? void 0 };
535
+ const STRING_CONVERTER$79 = { fromAttribute: (v) => v ?? void 0 };
535
536
  /**
536
537
  * `<xh-avatar>` —— 头像行为宿主,src/alt 写进 image 节点,加载成败回送机器,image 与 fallback 互斥显隐。
537
538
  *
@@ -550,9 +551,9 @@ var XhAvatarElement = class extends XhElement {
550
551
  meta: avatarMeta
551
552
  };
552
553
  static properties = {
553
- src: { converter: STRING_CONVERTER$78 },
554
- alt: { converter: STRING_CONVERTER$78 },
555
- size: { converter: STRING_CONVERTER$78 }
554
+ src: { converter: STRING_CONVERTER$79 },
555
+ alt: { converter: STRING_CONVERTER$79 },
556
+ size: { converter: STRING_CONVERTER$79 }
556
557
  };
557
558
  notify = (details) => {
558
559
  this.dispatchEvent(new CustomEvent("status-change", {
@@ -631,8 +632,8 @@ var XhAvatarGroupElement = class extends XhElement {
631
632
  };
632
633
  //#endregion
633
634
  //#region src/elements/back-top.ts
634
- const STRING_CONVERTER$77 = { fromAttribute: (v) => v ?? void 0 };
635
- const NUMBER_CONVERTER$47 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
635
+ const STRING_CONVERTER$78 = { fromAttribute: (v) => v ?? void 0 };
636
+ const NUMBER_CONVERTER$48 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
636
637
  /**
637
638
  * `<xh-back-top>` —— 回到顶部行为宿主:滚动量过线时露出按钮,点它滚回顶部。
638
639
  *
@@ -656,12 +657,12 @@ var XhBackTopElement = class extends XhElement {
656
657
  };
657
658
  static properties = {
658
659
  visibilityHeight: {
659
- converter: NUMBER_CONVERTER$47,
660
+ converter: NUMBER_CONVERTER$48,
660
661
  attribute: "visibility-height"
661
662
  },
662
- behavior: { converter: STRING_CONVERTER$77 },
663
- tone: { converter: STRING_CONVERTER$77 },
664
- size: { converter: STRING_CONVERTER$77 },
663
+ behavior: { converter: STRING_CONVERTER$78 },
664
+ tone: { converter: STRING_CONVERTER$78 },
665
+ size: { converter: STRING_CONVERTER$78 },
665
666
  translations: { attribute: false },
666
667
  target: { attribute: false }
667
668
  };
@@ -732,7 +733,7 @@ var XhBadgeElement = class extends XhElement {
732
733
  };
733
734
  //#endregion
734
735
  //#region src/elements/breadcrumb.ts
735
- const STRING_CONVERTER$76 = { fromAttribute: (v) => v ?? void 0 };
736
+ const STRING_CONVERTER$77 = { fromAttribute: (v) => v ?? void 0 };
736
737
  /** 读作者写在角色节点上的布尔声明:属性缺席或 ="false" 为假,其余为真。 */
737
738
  function authorFlag$1(el, name) {
738
739
  const raw = el.getAttribute(name);
@@ -762,11 +763,11 @@ var XhBreadcrumbElement = class extends XhElement {
762
763
  };
763
764
  static properties = {
764
765
  direction: {
765
- converter: STRING_CONVERTER$76,
766
+ converter: STRING_CONVERTER$77,
766
767
  attribute: "dir"
767
768
  },
768
- tone: { converter: STRING_CONVERTER$76 },
769
- size: { converter: STRING_CONVERTER$76 },
769
+ tone: { converter: STRING_CONVERTER$77 },
770
+ size: { converter: STRING_CONVERTER$77 },
770
771
  translations: { attribute: false }
771
772
  };
772
773
  wire() {
@@ -872,7 +873,7 @@ var XhButtonGroupElement = class extends XhElement {
872
873
  };
873
874
  //#endregion
874
875
  //#region src/elements/calendar.ts
875
- const STRING_CONVERTER$75 = { fromAttribute: (v) => v ?? void 0 };
876
+ const STRING_CONVERTER$76 = { fromAttribute: (v) => v ?? void 0 };
876
877
  /**
877
878
  * `<xh-calendar>` —— 日历行为宿主。
878
879
  *
@@ -916,32 +917,32 @@ var XhCalendarElement = class extends XhElement {
916
917
  meta: calendarMeta
917
918
  };
918
919
  static properties = {
919
- value: { converter: STRING_CONVERTER$75 },
920
+ value: { converter: STRING_CONVERTER$76 },
920
921
  defaultValue: {
921
- converter: STRING_CONVERTER$75,
922
+ converter: STRING_CONVERTER$76,
922
923
  attribute: "default-value"
923
924
  },
924
925
  selectionMode: {
925
- converter: STRING_CONVERTER$75,
926
+ converter: STRING_CONVERTER$76,
926
927
  attribute: "selection-mode"
927
928
  },
928
929
  focusedValue: {
929
- converter: STRING_CONVERTER$75,
930
+ converter: STRING_CONVERTER$76,
930
931
  attribute: "focused-value"
931
932
  },
932
933
  defaultFocusedValue: {
933
- converter: STRING_CONVERTER$75,
934
+ converter: STRING_CONVERTER$76,
934
935
  attribute: "default-focused-value"
935
936
  },
936
- min: { converter: STRING_CONVERTER$75 },
937
- max: { converter: STRING_CONVERTER$75 },
938
- locale: { converter: STRING_CONVERTER$75 },
937
+ min: { converter: STRING_CONVERTER$76 },
938
+ max: { converter: STRING_CONVERTER$76 },
939
+ locale: { converter: STRING_CONVERTER$76 },
939
940
  timeZone: {
940
- converter: STRING_CONVERTER$75,
941
+ converter: STRING_CONVERTER$76,
941
942
  attribute: "time-zone"
942
943
  },
943
944
  weekdayFormat: {
944
- converter: STRING_CONVERTER$75,
945
+ converter: STRING_CONVERTER$76,
945
946
  attribute: "weekday-format"
946
947
  },
947
948
  disabled: { type: Boolean },
@@ -1089,9 +1090,9 @@ var XhCardElement = class extends XhElement {
1089
1090
  };
1090
1091
  //#endregion
1091
1092
  //#region src/elements/carousel.ts
1092
- const STRING_CONVERTER$74 = { fromAttribute: (v) => v ?? void 0 };
1093
- const NUMBER_CONVERTER$46 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
1094
- const BOOLEAN_CONVERTER$49 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
1093
+ const STRING_CONVERTER$75 = { fromAttribute: (v) => v ?? void 0 };
1094
+ const NUMBER_CONVERTER$47 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
1095
+ const BOOLEAN_CONVERTER$51 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
1095
1096
  /**
1096
1097
  * autoplay 布尔或毫秒两用:缺席 = undefined,`autoplay` / `autoplay="true"` = 默认间隔,
1097
1098
  * `autoplay="false"` = 关,`autoplay="3000"` = 3 秒一张,念不成数的串按开着处理。
@@ -1145,35 +1146,35 @@ var XhCarouselElement = class extends XhElement {
1145
1146
  meta: carouselMeta
1146
1147
  };
1147
1148
  static properties = {
1148
- page: { converter: NUMBER_CONVERTER$46 },
1149
+ page: { converter: NUMBER_CONVERTER$47 },
1149
1150
  defaultPage: {
1150
- converter: NUMBER_CONVERTER$46,
1151
+ converter: NUMBER_CONVERTER$47,
1151
1152
  attribute: "default-page"
1152
1153
  },
1153
1154
  slideCount: {
1154
- converter: NUMBER_CONVERTER$46,
1155
+ converter: NUMBER_CONVERTER$47,
1155
1156
  attribute: "slide-count"
1156
1157
  },
1157
1158
  slidesPerPage: {
1158
- converter: NUMBER_CONVERTER$46,
1159
+ converter: NUMBER_CONVERTER$47,
1159
1160
  attribute: "slides-per-page"
1160
1161
  },
1161
1162
  slidesPerMove: {
1162
- converter: NUMBER_CONVERTER$46,
1163
+ converter: NUMBER_CONVERTER$47,
1163
1164
  attribute: "slides-per-move"
1164
1165
  },
1165
- orientation: { converter: STRING_CONVERTER$74 },
1166
+ orientation: { converter: STRING_CONVERTER$75 },
1166
1167
  direction: {
1167
- converter: STRING_CONVERTER$74,
1168
+ converter: STRING_CONVERTER$75,
1168
1169
  attribute: "dir"
1169
1170
  },
1170
- loop: { converter: BOOLEAN_CONVERTER$49 },
1171
+ loop: { converter: BOOLEAN_CONVERTER$51 },
1171
1172
  autoplay: { converter: AUTOPLAY_CONVERTER },
1172
1173
  allowPointerDrag: {
1173
- converter: BOOLEAN_CONVERTER$49,
1174
+ converter: BOOLEAN_CONVERTER$51,
1174
1175
  attribute: "allow-pointer-drag"
1175
1176
  },
1176
- spacing: { converter: STRING_CONVERTER$74 },
1177
+ spacing: { converter: STRING_CONVERTER$75 },
1177
1178
  translations: { attribute: false }
1178
1179
  };
1179
1180
  notify = (details) => {
@@ -1223,9 +1224,9 @@ var XhCarouselElement = class extends XhElement {
1223
1224
  };
1224
1225
  //#endregion
1225
1226
  //#region src/elements/cascader.ts
1226
- const STRING_CONVERTER$73 = { fromAttribute: (v) => v ?? void 0 };
1227
- const NUMBER_CONVERTER$45 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
1228
- const BOOLEAN_CONVERTER$48 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
1227
+ const STRING_CONVERTER$74 = { fromAttribute: (v) => v ?? void 0 };
1228
+ const NUMBER_CONVERTER$46 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
1229
+ const BOOLEAN_CONVERTER$50 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
1229
1230
  /** 条目一系的归属容器:文本与勾选标记向上找最近的那个条目。 */
1230
1231
  const ITEM_SELECTOR$4 = "[data-xh-part=\"item\"]";
1231
1232
  /**
@@ -1251,6 +1252,9 @@ const ITEM_SELECTOR$4 = "[data-xh-part=\"item\"]";
1251
1252
  * @attr {'click'|'hover'} expand-trigger - 子列由点还是悬停展开,默认 click
1252
1253
  * @attr {boolean} change-on-select - 中间层(分支)也能落值
1253
1254
  * @attr {boolean} multiple - 多选:选中后浮层不收起,焦点留在列里
1255
+ * @attr {boolean} searchable - 开启搜索:input 部件可用,输入后整条路径连缀过滤、候选替换列视图
1256
+ * @attr {boolean} cascade - 多选下父子级联勾选(整枝传导/半选/禁用冻结),默认 false
1257
+ * @attr {string} checked-strategy - 级联下对外值的收敛策略:child(默认)/ parent / all
1254
1258
  * @attr {boolean} disabled - 整个控件禁用:trigger 用原生 disabled,浮层展不开
1255
1259
  * @attr {boolean} read-only - 只读:浮层照常展开、列照常浏览,但选中值改不动、也清不掉
1256
1260
  * @attr {boolean} invalid - 校验失败标注
@@ -1272,7 +1276,11 @@ const ITEM_SELECTOR$4 = "[data-xh-part=\"item\"]";
1272
1276
  * @csspart indicator - 展开指示符(aria-hidden,data-state 随开合)
1273
1277
  * @csspart clear-trigger - 清空按钮,须是原生 button;不占 Tab 位且对读屏隐藏
1274
1278
  * @csspart positioner - 浮层定位容器,坐标由引擎写成内联样式
1275
- * @csspart content - 浮层壳(焦点域与消解层的根节点),键盘在此收口,收起时带 hidden
1279
+ * @csspart content - 浮层壳(焦点域与消解层的根节点),键盘在此收口,收起时带 hidden;根列没有条目时带 data-empty
1280
+ * @csspart input - 搜索框(content 顶部);没开 searchable 时带 hidden。上下键走候选、Enter 选中、Escape 先清词
1281
+ * @csspart search-list - 候选列表容器;不在搜索视图时带 hidden,无候选时带 data-empty
1282
+ * @csspart search-item - 一条候选,须用 value 属性写整条路径的 JSON 数组串(如 value='["a","b"]');词换了不匹配的带 hidden
1283
+ * @csspart empty - 空态占位:搜索无候选或 collection 为空时露面,其余时候带 hidden。标记里没写就由元素在 content 末尾补一个并填缺省文案;写了就用作者那份,文案也归作者
1276
1284
  * @csspart column - role=listbox 的一列,须自带 level 属性标识它是第几列;砍掉时带 hidden
1277
1285
  * @csspart item - role=option 的条目,须自带 value 属性标识身份;不在当前列里时带 hidden
1278
1286
  * @csspart item-text - 条目文本
@@ -1287,36 +1295,43 @@ var XhCascaderElement = class extends XhElement {
1287
1295
  collection: { attribute: false },
1288
1296
  value: { attribute: false },
1289
1297
  defaultValue: { attribute: false },
1290
- open: { converter: BOOLEAN_CONVERTER$48 },
1298
+ open: { converter: BOOLEAN_CONVERTER$50 },
1291
1299
  defaultOpen: {
1292
1300
  type: Boolean,
1293
1301
  attribute: "default-open"
1294
1302
  },
1295
1303
  expandTrigger: {
1296
- converter: STRING_CONVERTER$73,
1304
+ converter: STRING_CONVERTER$74,
1297
1305
  attribute: "expand-trigger"
1298
1306
  },
1299
1307
  changeOnSelect: {
1300
- converter: BOOLEAN_CONVERTER$48,
1308
+ converter: BOOLEAN_CONVERTER$50,
1301
1309
  attribute: "change-on-select"
1302
1310
  },
1303
1311
  multiple: { type: Boolean },
1312
+ searchable: { type: Boolean },
1313
+ cascade: { type: Boolean },
1314
+ checkedStrategy: {
1315
+ converter: STRING_CONVERTER$74,
1316
+ attribute: "checked-strategy"
1317
+ },
1304
1318
  disabled: { type: Boolean },
1305
1319
  readOnly: {
1306
- converter: BOOLEAN_CONVERTER$48,
1320
+ converter: BOOLEAN_CONVERTER$50,
1307
1321
  attribute: "read-only"
1308
1322
  },
1309
- invalid: { converter: BOOLEAN_CONVERTER$48 },
1310
- variant: { converter: STRING_CONVERTER$73 },
1311
- tone: { converter: STRING_CONVERTER$73 },
1312
- size: { converter: STRING_CONVERTER$73 },
1313
- placeholder: { converter: STRING_CONVERTER$73 },
1314
- separator: { converter: STRING_CONVERTER$73 },
1315
- placement: { converter: STRING_CONVERTER$73 },
1316
- offset: { converter: NUMBER_CONVERTER$45 },
1317
- loop: { converter: BOOLEAN_CONVERTER$48 },
1323
+ invalid: { converter: BOOLEAN_CONVERTER$50 },
1324
+ variant: { converter: STRING_CONVERTER$74 },
1325
+ tone: { converter: STRING_CONVERTER$74 },
1326
+ size: { converter: STRING_CONVERTER$74 },
1327
+ placeholder: { converter: STRING_CONVERTER$74 },
1328
+ separator: { converter: STRING_CONVERTER$74 },
1329
+ translations: { attribute: false },
1330
+ placement: { converter: STRING_CONVERTER$74 },
1331
+ offset: { converter: NUMBER_CONVERTER$46 },
1332
+ loop: { converter: BOOLEAN_CONVERTER$50 },
1318
1333
  direction: {
1319
- converter: STRING_CONVERTER$73,
1334
+ converter: STRING_CONVERTER$74,
1320
1335
  attribute: "dir"
1321
1336
  }
1322
1337
  };
@@ -1326,6 +1341,8 @@ var XhCascaderElement = class extends XhElement {
1326
1341
  config = null;
1327
1342
  /** value-text 是否归元素填:首次见到该节点时定,之后不再回读(回读到的会是自己写的字)。 */
1328
1343
  ownsValueText = /* @__PURE__ */ new WeakMap();
1344
+ /** 空态占位的文案是否归元素填,判定同 ownsValueText。 */
1345
+ ownsEmptyText = /* @__PURE__ */ new WeakMap();
1329
1346
  notifyValue = (details) => {
1330
1347
  this.dispatchEvent(new CustomEvent("value-change", {
1331
1348
  detail: details,
@@ -1354,6 +1371,9 @@ var XhCascaderElement = class extends XhElement {
1354
1371
  expandTrigger: this.expandTrigger,
1355
1372
  changeOnSelect: this.changeOnSelect ?? false,
1356
1373
  multiple: this.multiple ?? false,
1374
+ searchable: this.searchable ?? false,
1375
+ cascade: this.cascade,
1376
+ checkedStrategy: this.checkedStrategy,
1357
1377
  disabled: this.disabled ?? false,
1358
1378
  readOnly: this.readOnly ?? false,
1359
1379
  invalid: this.invalid ?? false,
@@ -1366,6 +1386,7 @@ var XhCascaderElement = class extends XhElement {
1366
1386
  offset: this.offset,
1367
1387
  loop: this.loop,
1368
1388
  dir: this.direction,
1389
+ translations: this.translations,
1369
1390
  onValueChange: this.notifyValue,
1370
1391
  onOpenChange: this.notifyOpen
1371
1392
  };
@@ -1434,16 +1455,30 @@ var XhCascaderElement = class extends XhElement {
1434
1455
  stripNativeDisabled(el) {
1435
1456
  if (el.hasAttribute("disabled")) el.removeAttribute("disabled");
1436
1457
  }
1437
- /** 把整条路径的文字填进 value-text;首次见到该节点时若已有内容则判为归作者,之后一概不碰。 */
1438
- fillValueText(el, text) {
1439
- let owned = this.ownsValueText.get(el);
1458
+ /** 把文字填进角色节点;首次见到该节点时若已有内容则判为归作者,之后一概不碰。 */
1459
+ fillOwnedText(owns, el, text) {
1460
+ let owned = owns.get(el);
1440
1461
  if (owned === void 0) {
1441
1462
  owned = (el.textContent ?? "").trim() === "";
1442
- this.ownsValueText.set(el, owned);
1463
+ owns.set(el, owned);
1443
1464
  }
1444
1465
  if (!owned || el.textContent === text) return;
1445
1466
  el.textContent = text;
1446
1467
  }
1468
+ /**
1469
+ * 取空态占位;标记里没写就在 content 末尾补一个,位置与 Vue 侧一致。
1470
+ * 作者写了就用作者那份,只接线不新建。补出来的节点下一轮由 discoverParts 收进 partMap。
1471
+ */
1472
+ ensureEmpty() {
1473
+ const existing = this.getPart("empty");
1474
+ if (existing) return existing;
1475
+ const content = this.getPart("content");
1476
+ if (!content) return null;
1477
+ const el = this.ownerDocument.createElement("div");
1478
+ el.setAttribute(PART_ATTR, "empty");
1479
+ content.append(el);
1480
+ return el;
1481
+ }
1447
1482
  wire() {
1448
1483
  const api = connectCascader(this.ctrl.service, wcNormalize);
1449
1484
  const put = (name, props) => {
@@ -1457,10 +1492,28 @@ var XhCascaderElement = class extends XhElement {
1457
1492
  put("clear-trigger", api.getClearTriggerProps());
1458
1493
  put("positioner", api.getPositionerProps());
1459
1494
  put("content", api.getContentProps());
1495
+ put("input", api.getInputProps());
1496
+ put("search-list", api.getSearchListProps());
1497
+ const empty = this.ensureEmpty();
1498
+ if (empty) {
1499
+ this.spreader.spread(empty, api.getEmptyProps());
1500
+ this.fillOwnedText(this.ownsEmptyText, empty, api.searching ? api.translations.noMatch : api.translations.empty);
1501
+ }
1502
+ for (const el of this.getParts("search-item")) {
1503
+ const raw = el.getAttribute("value") ?? "[]";
1504
+ let path = [];
1505
+ try {
1506
+ const parsed = JSON.parse(raw);
1507
+ if (Array.isArray(parsed)) path = parsed.map(String);
1508
+ } catch {
1509
+ path = [];
1510
+ }
1511
+ this.spreader.spread(el, api.getSearchItemProps({ path }));
1512
+ }
1460
1513
  const valueText = this.getPart("value-text");
1461
1514
  if (valueText) {
1462
1515
  this.spreader.spread(valueText, api.getValueTextProps());
1463
- this.fillValueText(valueText, api.displayText);
1516
+ this.fillOwnedText(this.ownsValueText, valueText, api.displayText);
1464
1517
  }
1465
1518
  this.getParts("column").forEach((el, position) => {
1466
1519
  this.spreader.spread(el, api.getColumnProps({ level: this.levelOf(el, position) }));
@@ -1496,6 +1549,8 @@ var XhCascaderElement = class extends XhElement {
1496
1549
  * @fires checked-change - checked 状态变化;detail 为 `{ checked: boolean }`
1497
1550
  * @csspart root - role=checkbox 的按钮(承载 aria-checked / data-state)
1498
1551
  * @csspart indicator - 选中标记
1552
+ * @attr {string} name - 表单字段名;给了 hidden-input 才参与提交
1553
+ * @csspart hidden-input - type=hidden 的表单出口,省略该节点即不参与表单
1499
1554
  */
1500
1555
  var XhCheckboxElement = class extends XhElement {
1501
1556
  static partContract = {
@@ -1509,6 +1564,8 @@ var XhCheckboxElement = class extends XhElement {
1509
1564
  converter: { fromAttribute: (v) => v === null ? void 0 : v === "indeterminate" ? "indeterminate" : v !== "false" }
1510
1565
  },
1511
1566
  disabled: { type: Boolean },
1567
+ name: { converter: { fromAttribute: (v) => v ?? void 0 } },
1568
+ value: { converter: { fromAttribute: (v) => v ?? void 0 } },
1512
1569
  tone: {},
1513
1570
  size: {}
1514
1571
  };
@@ -1527,6 +1584,8 @@ var XhCheckboxElement = class extends XhElement {
1527
1584
  disabled: this.disabled ?? false,
1528
1585
  tone: this.tone,
1529
1586
  size: this.size,
1587
+ name: this.name,
1588
+ value: this.value,
1530
1589
  onCheckedChange: this.notify
1531
1590
  };
1532
1591
  }
@@ -1536,6 +1595,8 @@ var XhCheckboxElement = class extends XhElement {
1536
1595
  if (root) this.spreader.spread(root, api.getRootProps());
1537
1596
  const indicator = this.getPart("indicator");
1538
1597
  if (indicator) this.spreader.spread(indicator, api.getIndicatorProps());
1598
+ const hidden = this.getPart("hidden-input");
1599
+ if (hidden) this.spreader.spread(hidden, api.getHiddenInputProps());
1539
1600
  }
1540
1601
  };
1541
1602
  //#endregion
@@ -1555,12 +1616,12 @@ function createDeclaredDisabled() {
1555
1616
  }
1556
1617
  //#endregion
1557
1618
  //#region src/elements/checkbox-group.ts
1558
- const STRING_CONVERTER$72 = { fromAttribute: (v) => v ?? void 0 };
1559
- const BOOLEAN_CONVERTER$47 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
1619
+ const STRING_CONVERTER$73 = { fromAttribute: (v) => v ?? void 0 };
1620
+ const BOOLEAN_CONVERTER$49 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
1560
1621
  const LIST_CONVERTER = { fromAttribute: (v) => v === null ? void 0 : v.split(",").map((s) => s.trim()).filter(Boolean) };
1561
1622
  /**
1562
1623
  * `<xh-checkbox-group>` —— Light-DOM 行为宿主:作者写 root/label 与若干 item 角色节点,
1563
- * 每个 item 内自带 item-hidden-input/item-control/item-text,元素跑 checkbox-group 机器
1624
+ * 每个 item 内自带 hidden-input/indicator/item-text,元素跑 checkbox-group 机器
1564
1625
  * 并把 connect 产出打上去。条目身份取自条目节点上的 value 属性。
1565
1626
  *
1566
1627
  * 不做 roving tabindex:组内每一项都是独立的 Tab 停靠点(禁用项也保留),容器自己不占位。
@@ -1578,9 +1639,9 @@ const LIST_CONVERTER = { fromAttribute: (v) => v === null ? void 0 : v.split(","
1578
1639
  * @csspart root - role=group 容器
1579
1640
  * @csspart label - 组标题(aria-labelledby 目标)
1580
1641
  * @csspart item - role=checkbox 条目,作者用 value 属性声明身份
1581
- * @csspart item-control - 条目的视觉方框(对读屏隐藏)
1642
+ * @csspart indicator - 条目的视觉方框(对读屏隐藏)
1582
1643
  * @csspart item-text - 条目文本,条目的可及名来源
1583
- * @csspart item-hidden-input - 条目的表单影子输入(必须是原生 input)
1644
+ * @csspart hidden-input - 条目的表单影子输入(必须是原生 input)
1584
1645
  * @csspart trigger - 全选/半选的父复选框,须写在 root 之内
1585
1646
  */
1586
1647
  var XhCheckboxGroupElement = class extends XhElement {
@@ -1599,14 +1660,14 @@ var XhCheckboxGroupElement = class extends XhElement {
1599
1660
  converter: LIST_CONVERTER,
1600
1661
  attribute: "item-values"
1601
1662
  },
1602
- disabled: { converter: BOOLEAN_CONVERTER$47 },
1663
+ disabled: { converter: BOOLEAN_CONVERTER$49 },
1603
1664
  readOnly: {
1604
- converter: BOOLEAN_CONVERTER$47,
1665
+ converter: BOOLEAN_CONVERTER$49,
1605
1666
  attribute: "read-only"
1606
1667
  },
1607
- invalid: { converter: BOOLEAN_CONVERTER$47 },
1608
- orientation: { converter: STRING_CONVERTER$72 },
1609
- name: { converter: STRING_CONVERTER$72 }
1668
+ invalid: { converter: BOOLEAN_CONVERTER$49 },
1669
+ orientation: { converter: STRING_CONVERTER$73 },
1670
+ name: { converter: STRING_CONVERTER$73 }
1610
1671
  };
1611
1672
  /** 条目自身 disabled 声明的快照,整组禁用期间 DOM 上的 aria-disabled 不可信。 */
1612
1673
  declaredDisabled = /* @__PURE__ */ new WeakMap();
@@ -1685,8 +1746,8 @@ var XhCheckboxGroupElement = class extends XhElement {
1685
1746
  for (const el of this.getParts("item")) {
1686
1747
  const item = this.itemProps(el);
1687
1748
  this.spreader.spread(el, api.getItemProps(item));
1688
- for (const input of this.partsIn(el, "item-hidden-input")) this.spreadHiddenInput(input, api.getItemHiddenInputProps(item));
1689
- for (const control of this.partsIn(el, "item-control")) this.spreader.spread(control, api.getItemControlProps(item));
1749
+ for (const input of this.partsIn(el, "hidden-input")) this.spreadHiddenInput(input, api.getHiddenInputProps(item));
1750
+ for (const control of this.partsIn(el, "indicator")) this.spreader.spread(control, api.getIndicatorProps(item));
1690
1751
  for (const text of this.partsIn(el, "item-text")) this.spreader.spread(text, api.getItemTextProps(item));
1691
1752
  }
1692
1753
  this.wasGroupDisabled = !!this.disabled;
@@ -1694,8 +1755,8 @@ var XhCheckboxGroupElement = class extends XhElement {
1694
1755
  };
1695
1756
  //#endregion
1696
1757
  //#region src/elements/clipboard.ts
1697
- const STRING_CONVERTER$71 = { fromAttribute: (v) => v ?? void 0 };
1698
- const NUMBER_CONVERTER$44 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
1758
+ const STRING_CONVERTER$72 = { fromAttribute: (v) => v ?? void 0 };
1759
+ const NUMBER_CONVERTER$45 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
1699
1760
  /**
1700
1761
  * `<xh-clipboard>` —— Light-DOM 行为宿主,跑 clipboard 机器并把 connect 产出打到角色节点上。
1701
1762
  *
@@ -1722,8 +1783,8 @@ var XhClipboardElement = class extends XhElement {
1722
1783
  meta: clipboardMeta
1723
1784
  };
1724
1785
  static properties = {
1725
- value: { converter: STRING_CONVERTER$71 },
1726
- timeout: { converter: NUMBER_CONVERTER$44 }
1786
+ value: { converter: STRING_CONVERTER$72 },
1787
+ timeout: { converter: NUMBER_CONVERTER$45 }
1727
1788
  };
1728
1789
  notifyStatus = (details) => {
1729
1790
  this.dispatchEvent(new CustomEvent("status-change", {
@@ -1770,8 +1831,8 @@ var XhClipboardElement = class extends XhElement {
1770
1831
  //#region src/elements/code-block.ts
1771
1832
  /** 默认着色实现全元素共用一份:它无状态,没必要每个块建一个。 */
1772
1833
  const defaultHighlighter = createHighlighter();
1773
- const STRING_CONVERTER$70 = { fromAttribute: (v) => v ?? void 0 };
1774
- const BOOLEAN_CONVERTER$46 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
1834
+ const STRING_CONVERTER$71 = { fromAttribute: (v) => v ?? void 0 };
1835
+ const BOOLEAN_CONVERTER$48 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
1775
1836
  /**
1776
1837
  * `<xh-code-block>` —— Light-DOM 行为宿主,无状态机:wire 时算出 connectCodeBlock 的产出,
1777
1838
  * 打到四类角色节点上。显示的代码文本由作者写在 code 角色节点里,元素不改其子节点。
@@ -1793,14 +1854,14 @@ var XhCodeBlockElement = class extends XhElement {
1793
1854
  meta: codeBlockMeta
1794
1855
  };
1795
1856
  static properties = {
1796
- code: { converter: STRING_CONVERTER$70 },
1857
+ code: { converter: STRING_CONVERTER$71 },
1797
1858
  codeLang: {
1798
- converter: STRING_CONVERTER$70,
1859
+ converter: STRING_CONVERTER$71,
1799
1860
  attribute: "code-lang"
1800
1861
  },
1801
- complete: { converter: BOOLEAN_CONVERTER$46 },
1862
+ complete: { converter: BOOLEAN_CONVERTER$48 },
1802
1863
  highlightWhileStreaming: {
1803
- converter: BOOLEAN_CONVERTER$46,
1864
+ converter: BOOLEAN_CONVERTER$48,
1804
1865
  attribute: "highlight-while-streaming"
1805
1866
  }
1806
1867
  };
@@ -1915,9 +1976,9 @@ var XhCollapsibleElement = class extends XhElement {
1915
1976
  };
1916
1977
  //#endregion
1917
1978
  //#region src/elements/color-picker.ts
1918
- const STRING_CONVERTER$69 = { fromAttribute: (v) => v ?? void 0 };
1919
- const NUMBER_CONVERTER$43 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
1920
- const BOOLEAN_CONVERTER$45 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
1979
+ const STRING_CONVERTER$70 = { fromAttribute: (v) => v ?? void 0 };
1980
+ const NUMBER_CONVERTER$44 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
1981
+ const BOOLEAN_CONVERTER$47 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
1921
1982
  /** 预设色板写成逗号分隔(swatches="#ff0000,#00ff00"),空串当没写。 */
1922
1983
  const STRING_LIST_CONVERTER = { fromAttribute: (v) => {
1923
1984
  if (v == null || v.trim() === "") return void 0;
@@ -1949,6 +2010,7 @@ const STRING_LIST_CONVERTER = { fromAttribute: (v) => {
1949
2010
  * @attr {'ltr'|'rtl'} dir - 文字方向,只改写横轴上左右两键与指针的语义,默认 ltr
1950
2011
  * @attr {string} placement - 首选放置位,默认 bottom-start;避让后的实际位写在 data-placement 上
1951
2012
  * @attr {number} offset - 浮层与锚点的间距(px)
2013
+ * @attr {string} name - 表单字段名;给了 hidden-input 才带 name 并参与提交
1952
2014
  * @fires value-change - 颜色变化;detail 为 `{ value: string }`
1953
2015
  * @fires open-change - open 状态变化;detail 为 `{ open: boolean }`
1954
2016
  * @csspart root - 组件根容器(承载 data-state/data-disabled/data-readonly)
@@ -1967,6 +2029,7 @@ const STRING_LIST_CONVERTER = { fromAttribute: (v) => {
1967
2029
  * @csspart eye-dropper-trigger - 屏幕取色按钮,须是原生 button;环境不支持时自动禁用
1968
2030
  * @csspart swatch-group - role=group 的预设色板容器
1969
2031
  * @csspart swatch-item - 预设色板一格,须是原生 button 且自带 value 属性
2032
+ * @csspart hidden-input - type=hidden 的表单出口,值是当前颜色串;作者不写这个部件就不参与提交
1970
2033
  */
1971
2034
  var XhColorPickerElement = class extends XhElement {
1972
2035
  static partContract = {
@@ -1974,30 +2037,31 @@ var XhColorPickerElement = class extends XhElement {
1974
2037
  meta: colorPickerMeta
1975
2038
  };
1976
2039
  static properties = {
1977
- value: { converter: STRING_CONVERTER$69 },
2040
+ value: { converter: STRING_CONVERTER$70 },
1978
2041
  defaultValue: {
1979
- converter: STRING_CONVERTER$69,
2042
+ converter: STRING_CONVERTER$70,
1980
2043
  attribute: "default-value"
1981
2044
  },
1982
- format: { converter: STRING_CONVERTER$69 },
1983
- open: { converter: BOOLEAN_CONVERTER$45 },
2045
+ format: { converter: STRING_CONVERTER$70 },
2046
+ open: { converter: BOOLEAN_CONVERTER$47 },
1984
2047
  defaultOpen: {
1985
2048
  type: Boolean,
1986
2049
  attribute: "default-open"
1987
2050
  },
1988
- disabled: { converter: BOOLEAN_CONVERTER$45 },
2051
+ disabled: { converter: BOOLEAN_CONVERTER$47 },
1989
2052
  readOnly: {
1990
- converter: BOOLEAN_CONVERTER$45,
2053
+ converter: BOOLEAN_CONVERTER$47,
1991
2054
  attribute: "read-only"
1992
2055
  },
1993
- alpha: { converter: BOOLEAN_CONVERTER$45 },
2056
+ alpha: { converter: BOOLEAN_CONVERTER$47 },
1994
2057
  swatches: { converter: STRING_LIST_CONVERTER },
2058
+ name: { converter: STRING_CONVERTER$70 },
1995
2059
  direction: {
1996
- converter: STRING_CONVERTER$69,
2060
+ converter: STRING_CONVERTER$70,
1997
2061
  attribute: "dir"
1998
2062
  },
1999
- placement: { converter: STRING_CONVERTER$69 },
2000
- offset: { converter: NUMBER_CONVERTER$43 },
2063
+ placement: { converter: STRING_CONVERTER$70 },
2064
+ offset: { converter: NUMBER_CONVERTER$44 },
2001
2065
  translations: { attribute: false }
2002
2066
  };
2003
2067
  idGen = createCounterIdGenerator();
@@ -2033,6 +2097,7 @@ var XhColorPickerElement = class extends XhElement {
2033
2097
  readOnly: this.readOnly ?? false,
2034
2098
  alpha: this.alpha ?? false,
2035
2099
  swatches: this.swatches,
2100
+ name: this.name,
2036
2101
  dir: this.direction,
2037
2102
  placement: this.placement,
2038
2103
  offset: this.offset,
@@ -2111,6 +2176,7 @@ var XhColorPickerElement = class extends XhElement {
2111
2176
  put("area-thumb", api.getAreaThumbProps());
2112
2177
  put("eye-dropper-trigger", api.getEyeDropperTriggerProps());
2113
2178
  put("swatch-group", api.getSwatchGroupProps());
2179
+ put("hidden-input", api.getHiddenInputProps());
2114
2180
  const valueText = this.getPart("value-text");
2115
2181
  if (valueText) {
2116
2182
  this.spreader.spread(valueText, api.getValueTextProps());
@@ -2136,9 +2202,9 @@ var XhColorPickerElement = class extends XhElement {
2136
2202
  };
2137
2203
  //#endregion
2138
2204
  //#region src/elements/combobox.ts
2139
- const STRING_CONVERTER$68 = { fromAttribute: (v) => v ?? void 0 };
2140
- const NUMBER_CONVERTER$42 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
2141
- const BOOLEAN_CONVERTER$44 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
2205
+ const STRING_CONVERTER$69 = { fromAttribute: (v) => v ?? void 0 };
2206
+ const NUMBER_CONVERTER$43 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
2207
+ const BOOLEAN_CONVERTER$46 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
2142
2208
  /**
2143
2209
  * `<xh-combobox>` —— Light-DOM 行为宿主:作者写 root/label/control/input/trigger/positioner/content/item/...
2144
2210
  * 角色节点,元素跑 combobox 机器并把 connect 产出打上去。浮层定位引擎在本元素里建好、经 refs 注入机器,
@@ -2186,6 +2252,8 @@ const BOOLEAN_CONVERTER$44 = { fromAttribute: (v) => v === null ? void 0 : v !==
2186
2252
  * @csspart item-indicator - 候选选中标记(aria-hidden)
2187
2253
  * @csspart item-group - role=group 分组容器,须自带 value 属性标识身份
2188
2254
  * @csspart item-group-label - 分组标题(本组 aria-labelledby 的目标)
2255
+ * @attr {string} name - 表单字段名;给了 hidden-input 才参与提交(多选按逗号拼成一串)
2256
+ * @csspart hidden-input - type=hidden 的表单出口,省略该节点即不参与表单
2189
2257
  * @csspart empty - 无匹配项提示;须放在 positioner 里当 content 的兄弟(列表内只允许 option 与 group)
2190
2258
  */
2191
2259
  var XhComboboxElement = class extends XhElement {
@@ -2195,20 +2263,21 @@ var XhComboboxElement = class extends XhElement {
2195
2263
  };
2196
2264
  static properties = {
2197
2265
  collection: { attribute: false },
2198
- value: { converter: STRING_CONVERTER$68 },
2266
+ name: { converter: STRING_CONVERTER$69 },
2267
+ value: { converter: STRING_CONVERTER$69 },
2199
2268
  defaultValue: {
2200
- converter: STRING_CONVERTER$68,
2269
+ converter: STRING_CONVERTER$69,
2201
2270
  attribute: "default-value"
2202
2271
  },
2203
2272
  inputValue: {
2204
- converter: STRING_CONVERTER$68,
2273
+ converter: STRING_CONVERTER$69,
2205
2274
  attribute: "input-value"
2206
2275
  },
2207
2276
  defaultInputValue: {
2208
- converter: STRING_CONVERTER$68,
2277
+ converter: STRING_CONVERTER$69,
2209
2278
  attribute: "default-input-value"
2210
2279
  },
2211
- open: { converter: BOOLEAN_CONVERTER$44 },
2280
+ open: { converter: BOOLEAN_CONVERTER$46 },
2212
2281
  defaultOpen: {
2213
2282
  type: Boolean,
2214
2283
  attribute: "default-open"
@@ -2216,12 +2285,12 @@ var XhComboboxElement = class extends XhElement {
2216
2285
  multiple: { type: Boolean },
2217
2286
  disabled: { type: Boolean },
2218
2287
  readOnly: {
2219
- converter: BOOLEAN_CONVERTER$44,
2288
+ converter: BOOLEAN_CONVERTER$46,
2220
2289
  attribute: "read-only"
2221
2290
  },
2222
- invalid: { converter: BOOLEAN_CONVERTER$44 },
2223
- loop: { converter: BOOLEAN_CONVERTER$44 },
2224
- placeholder: { converter: STRING_CONVERTER$68 },
2291
+ invalid: { converter: BOOLEAN_CONVERTER$46 },
2292
+ loop: { converter: BOOLEAN_CONVERTER$46 },
2293
+ placeholder: { converter: STRING_CONVERTER$69 },
2225
2294
  allowCustomValue: {
2226
2295
  type: Boolean,
2227
2296
  attribute: "allow-custom-value"
@@ -2231,14 +2300,14 @@ var XhComboboxElement = class extends XhElement {
2231
2300
  attribute: "open-on-click"
2232
2301
  },
2233
2302
  inputBehavior: {
2234
- converter: STRING_CONVERTER$68,
2303
+ converter: STRING_CONVERTER$69,
2235
2304
  attribute: "input-behavior"
2236
2305
  },
2237
- placement: { converter: STRING_CONVERTER$68 },
2238
- offset: { converter: NUMBER_CONVERTER$42 },
2239
- variant: { converter: STRING_CONVERTER$68 },
2240
- tone: { converter: STRING_CONVERTER$68 },
2241
- size: { converter: STRING_CONVERTER$68 }
2306
+ placement: { converter: STRING_CONVERTER$69 },
2307
+ offset: { converter: NUMBER_CONVERTER$43 },
2308
+ variant: { converter: STRING_CONVERTER$69 },
2309
+ tone: { converter: STRING_CONVERTER$69 },
2310
+ size: { converter: STRING_CONVERTER$69 }
2242
2311
  };
2243
2312
  idGen = createCounterIdGenerator();
2244
2313
  comboboxScope = createScope(null, this.idGen);
@@ -2285,6 +2354,7 @@ var XhComboboxElement = class extends XhElement {
2285
2354
  readOnly: this.readOnly ?? false,
2286
2355
  invalid: this.invalid ?? false,
2287
2356
  loop: this.loop,
2357
+ name: this.name,
2288
2358
  placeholder: this.placeholder,
2289
2359
  allowCustomValue: this.allowCustomValue ?? false,
2290
2360
  openOnClick: this.openOnClick ?? false,
@@ -2354,6 +2424,7 @@ var XhComboboxElement = class extends XhElement {
2354
2424
  put("positioner", api.getPositionerProps());
2355
2425
  put("content", api.getContentProps());
2356
2426
  put("empty", api.getEmptyProps());
2427
+ put("hidden-input", api.getHiddenInputProps());
2357
2428
  for (const el of this.getParts("item-group")) {
2358
2429
  const group = { value: el.getAttribute("value") ?? "" };
2359
2430
  this.spreader.spread(el, api.getItemGroupProps(group));
@@ -2379,8 +2450,8 @@ var XhComboboxElement = class extends XhElement {
2379
2450
  };
2380
2451
  //#endregion
2381
2452
  //#region src/elements/composer.ts
2382
- const STRING_CONVERTER$67 = { fromAttribute: (v) => v ?? void 0 };
2383
- const BOOLEAN_CONVERTER$43 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
2453
+ const STRING_CONVERTER$68 = { fromAttribute: (v) => v ?? void 0 };
2454
+ const BOOLEAN_CONVERTER$45 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
2384
2455
  /**
2385
2456
  * `<xh-composer>` —— Light-DOM 行为宿主:跑 composer 机器,把 connect 产出打到作者写的
2386
2457
  * root/input/submit-trigger 三类角色节点上。input 须是原生 `<textarea>`,值经 property 写、
@@ -2406,18 +2477,18 @@ var XhComposerElement = class extends XhElement {
2406
2477
  meta: composerMeta
2407
2478
  };
2408
2479
  static properties = {
2409
- value: { converter: STRING_CONVERTER$67 },
2480
+ value: { converter: STRING_CONVERTER$68 },
2410
2481
  defaultValue: {
2411
- converter: STRING_CONVERTER$67,
2482
+ converter: STRING_CONVERTER$68,
2412
2483
  attribute: "default-value"
2413
2484
  },
2414
- disabled: { converter: BOOLEAN_CONVERTER$43 },
2485
+ disabled: { converter: BOOLEAN_CONVERTER$45 },
2415
2486
  runStatus: {
2416
- converter: STRING_CONVERTER$67,
2487
+ converter: STRING_CONVERTER$68,
2417
2488
  attribute: "run-status"
2418
2489
  },
2419
2490
  submitOnEnter: {
2420
- converter: BOOLEAN_CONVERTER$43,
2491
+ converter: BOOLEAN_CONVERTER$45,
2421
2492
  attribute: "submit-on-enter"
2422
2493
  },
2423
2494
  translations: { attribute: false }
@@ -2459,9 +2530,9 @@ var XhComposerElement = class extends XhElement {
2459
2530
  };
2460
2531
  //#endregion
2461
2532
  //#region src/elements/context-menu.ts
2462
- const STRING_CONVERTER$66 = { fromAttribute: (v) => v ?? void 0 };
2463
- const NUMBER_CONVERTER$41 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
2464
- const BOOLEAN_CONVERTER$42 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
2533
+ const STRING_CONVERTER$67 = { fromAttribute: (v) => v ?? void 0 };
2534
+ const NUMBER_CONVERTER$42 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
2535
+ const BOOLEAN_CONVERTER$44 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
2465
2536
  /**
2466
2537
  * `<xh-context-menu>` —— Light-DOM 行为宿主:作者写 root/trigger/positioner/content 与若干
2467
2538
  * item / group / separator 角色节点,元素跑 context-menu 机器并把 connect 产出打上去。
@@ -2504,25 +2575,26 @@ var XhContextMenuElement = class extends XhElement {
2504
2575
  };
2505
2576
  static properties = {
2506
2577
  collection: { attribute: false },
2507
- open: { converter: BOOLEAN_CONVERTER$42 },
2578
+ open: { converter: BOOLEAN_CONVERTER$44 },
2508
2579
  defaultOpen: {
2509
2580
  type: Boolean,
2510
2581
  attribute: "default-open"
2511
2582
  },
2512
- placement: { converter: STRING_CONVERTER$66 },
2513
- offset: { converter: NUMBER_CONVERTER$41 },
2514
- loop: { converter: BOOLEAN_CONVERTER$42 },
2515
- typeahead: { converter: BOOLEAN_CONVERTER$42 },
2583
+ placement: { converter: STRING_CONVERTER$67 },
2584
+ offset: { converter: NUMBER_CONVERTER$42 },
2585
+ loop: { converter: BOOLEAN_CONVERTER$44 },
2586
+ typeahead: { converter: BOOLEAN_CONVERTER$44 },
2587
+ translations: { attribute: false },
2516
2588
  direction: {
2517
- converter: STRING_CONVERTER$66,
2589
+ converter: STRING_CONVERTER$67,
2518
2590
  attribute: "dir"
2519
2591
  },
2520
2592
  longPressDelay: {
2521
- converter: NUMBER_CONVERTER$41,
2593
+ converter: NUMBER_CONVERTER$42,
2522
2594
  attribute: "long-press-delay"
2523
2595
  },
2524
- tone: { converter: STRING_CONVERTER$66 },
2525
- size: { converter: STRING_CONVERTER$66 }
2596
+ tone: { converter: STRING_CONVERTER$67 },
2597
+ size: { converter: STRING_CONVERTER$67 }
2526
2598
  };
2527
2599
  idGen = createCounterIdGenerator();
2528
2600
  menuScope = createScope(null, this.idGen);
@@ -2557,6 +2629,7 @@ var XhContextMenuElement = class extends XhElement {
2557
2629
  offset: this.offset,
2558
2630
  loop: this.loop,
2559
2631
  typeahead: this.typeahead,
2632
+ translations: this.translations,
2560
2633
  dir: this.direction,
2561
2634
  longPressDelay: this.longPressDelay,
2562
2635
  tone: this.tone,
@@ -2589,6 +2662,7 @@ var XhContextMenuElement = class extends XhElement {
2589
2662
  svc.refs.set("registerLayer", this.registerLayer);
2590
2663
  svc.refs.set("position", this.positionEngine);
2591
2664
  svc.refs.set("getFloatingEl", () => this.getPart("positioner"));
2665
+ svc.refs.set("getTriggerEl", () => this.getPart("trigger"));
2592
2666
  svc.refs.set("getContentEl", () => this.getPart("content"));
2593
2667
  }
2594
2668
  /**
@@ -2652,9 +2726,9 @@ var XhContextMenuElement = class extends XhElement {
2652
2726
  };
2653
2727
  //#endregion
2654
2728
  //#region src/elements/countdown.ts
2655
- const STRING_CONVERTER$65 = { fromAttribute: (v) => v ?? void 0 };
2656
- const NUMBER_CONVERTER$40 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
2657
- const BOOLEAN_CONVERTER$41 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
2729
+ const STRING_CONVERTER$66 = { fromAttribute: (v) => v ?? void 0 };
2730
+ const NUMBER_CONVERTER$41 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
2731
+ const BOOLEAN_CONVERTER$43 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
2658
2732
  /**
2659
2733
  * `<xh-countdown>` —— Light-DOM 行为宿主:作者写一个 root 角色节点,
2660
2734
  * 元素跑 countdown 机器,逐帧把剩余毫秒按模板铺成时分秒写进那个节点。
@@ -2684,11 +2758,11 @@ var XhCountdownElement = class extends XhElement {
2684
2758
  meta: countdownMeta
2685
2759
  };
2686
2760
  static properties = {
2687
- value: { converter: NUMBER_CONVERTER$40 },
2688
- format: { converter: STRING_CONVERTER$65 },
2689
- active: { converter: BOOLEAN_CONVERTER$41 },
2690
- precision: { converter: NUMBER_CONVERTER$40 },
2691
- live: { converter: STRING_CONVERTER$65 }
2761
+ value: { converter: NUMBER_CONVERTER$41 },
2762
+ format: { converter: STRING_CONVERTER$66 },
2763
+ active: { converter: BOOLEAN_CONVERTER$43 },
2764
+ precision: { converter: NUMBER_CONVERTER$41 },
2765
+ live: { converter: STRING_CONVERTER$66 }
2692
2766
  };
2693
2767
  notify = (details) => {
2694
2768
  this.dispatchEvent(new CustomEvent("finish", {
@@ -2718,8 +2792,8 @@ var XhCountdownElement = class extends XhElement {
2718
2792
  };
2719
2793
  //#endregion
2720
2794
  //#region src/elements/date-field.ts
2721
- const STRING_CONVERTER$64 = { fromAttribute: (v) => v ?? void 0 };
2722
- const BOOLEAN_CONVERTER$40 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
2795
+ const STRING_CONVERTER$65 = { fromAttribute: (v) => v ?? void 0 };
2796
+ const BOOLEAN_CONVERTER$42 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
2723
2797
  /** 作者写在段位上的下标。缺席或写坏了就退回文档序——手写 HTML 时把段位按顺序排下来本身就是声明。 */
2724
2798
  function declaredIndex$4(el, position) {
2725
2799
  const raw = el.getAttribute("index");
@@ -2770,32 +2844,32 @@ var XhDateFieldElement = class extends XhElement {
2770
2844
  meta: dateFieldMeta
2771
2845
  };
2772
2846
  static properties = {
2773
- value: { converter: STRING_CONVERTER$64 },
2847
+ value: { converter: STRING_CONVERTER$65 },
2774
2848
  defaultValue: {
2775
- converter: STRING_CONVERTER$64,
2849
+ converter: STRING_CONVERTER$65,
2776
2850
  attribute: "default-value"
2777
2851
  },
2778
- min: { converter: STRING_CONVERTER$64 },
2779
- max: { converter: STRING_CONVERTER$64 },
2780
- locale: { converter: STRING_CONVERTER$64 },
2852
+ min: { converter: STRING_CONVERTER$65 },
2853
+ max: { converter: STRING_CONVERTER$65 },
2854
+ locale: { converter: STRING_CONVERTER$65 },
2781
2855
  timeZone: {
2782
- converter: STRING_CONVERTER$64,
2856
+ converter: STRING_CONVERTER$65,
2783
2857
  attribute: "time-zone"
2784
2858
  },
2785
- granularity: { converter: STRING_CONVERTER$64 },
2786
- disabled: { converter: BOOLEAN_CONVERTER$40 },
2859
+ granularity: { converter: STRING_CONVERTER$65 },
2860
+ disabled: { converter: BOOLEAN_CONVERTER$42 },
2787
2861
  readOnly: {
2788
- converter: BOOLEAN_CONVERTER$40,
2862
+ converter: BOOLEAN_CONVERTER$42,
2789
2863
  attribute: "read-only"
2790
2864
  },
2791
- invalid: { converter: BOOLEAN_CONVERTER$40 },
2792
- required: { converter: BOOLEAN_CONVERTER$40 },
2793
- name: { converter: STRING_CONVERTER$64 },
2865
+ invalid: { converter: BOOLEAN_CONVERTER$42 },
2866
+ required: { converter: BOOLEAN_CONVERTER$42 },
2867
+ name: { converter: STRING_CONVERTER$65 },
2794
2868
  placeholder: { attribute: false },
2795
2869
  translations: { attribute: false },
2796
- variant: { converter: STRING_CONVERTER$64 },
2797
- tone: { converter: STRING_CONVERTER$64 },
2798
- size: { converter: STRING_CONVERTER$64 }
2870
+ variant: { converter: STRING_CONVERTER$65 },
2871
+ tone: { converter: STRING_CONVERTER$65 },
2872
+ size: { converter: STRING_CONVERTER$65 }
2799
2873
  };
2800
2874
  notifyChange = (details) => {
2801
2875
  this.dispatchEvent(new CustomEvent("value-change", {
@@ -2849,9 +2923,9 @@ var XhDateFieldElement = class extends XhElement {
2849
2923
  };
2850
2924
  //#endregion
2851
2925
  //#region src/elements/date-picker.ts
2852
- const STRING_CONVERTER$63 = { fromAttribute: (v) => v ?? void 0 };
2853
- const NUMBER_CONVERTER$39 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
2854
- const BOOLEAN_CONVERTER$39 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
2926
+ const STRING_CONVERTER$64 = { fromAttribute: (v) => v ?? void 0 };
2927
+ const NUMBER_CONVERTER$40 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
2928
+ const BOOLEAN_CONVERTER$41 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
2855
2929
  /** 取作者写在段位上的 index,缺席或写坏了退回组内文档序。 */
2856
2930
  function declaredIndex$3(el, position) {
2857
2931
  const raw = el.getAttribute("index");
@@ -2909,6 +2983,9 @@ function declaredIndex$3(el, position) {
2909
2983
  * @csspart positioner - 浮层定位容器,坐标由引擎写成内联样式
2910
2984
  * @csspart content - role=dialog 浮层(消解层的根节点),收起时带 hidden
2911
2985
  * @csspart calendar - 内嵌日历的挂载点,同时充当日历的根节点
2986
+ * @csspart time-column - showTime 的时间列,须自带 unit 属性(hour/minute/second);没开时带 hidden
2987
+ * @csspart time-item - 时间选项,须自带 value 属性(两位补零串);点按把该单位写进值
2988
+ * @csspart confirm-trigger - showTime 的收口按钮;没开时带 hidden
2912
2989
  * @csspart header - 日历标题栏外壳(data-scope="calendar")
2913
2990
  * @csspart prev-trigger - 上一月;越过 min 时转原生 disabled
2914
2991
  * @csspart next-trigger - 下一月;越过 max 时转原生 disabled
@@ -2929,46 +3006,54 @@ var XhDatePickerElement = class extends XhElement {
2929
3006
  delegates: [dateFieldAnatomy, calendarAnatomy]
2930
3007
  };
2931
3008
  static properties = {
2932
- value: { converter: STRING_CONVERTER$63 },
3009
+ value: { converter: STRING_CONVERTER$64 },
2933
3010
  defaultValue: {
2934
- converter: STRING_CONVERTER$63,
3011
+ converter: STRING_CONVERTER$64,
2935
3012
  attribute: "default-value"
2936
3013
  },
2937
- open: { converter: BOOLEAN_CONVERTER$39 },
3014
+ open: { converter: BOOLEAN_CONVERTER$41 },
2938
3015
  defaultOpen: {
2939
3016
  type: Boolean,
2940
3017
  attribute: "default-open"
2941
3018
  },
2942
- min: { converter: STRING_CONVERTER$63 },
2943
- max: { converter: STRING_CONVERTER$63 },
2944
- locale: { converter: STRING_CONVERTER$63 },
3019
+ min: { converter: STRING_CONVERTER$64 },
3020
+ max: { converter: STRING_CONVERTER$64 },
3021
+ locale: { converter: STRING_CONVERTER$64 },
2945
3022
  timeZone: {
2946
- converter: STRING_CONVERTER$63,
3023
+ converter: STRING_CONVERTER$64,
2947
3024
  attribute: "time-zone"
2948
3025
  },
2949
3026
  selectionMode: {
2950
- converter: STRING_CONVERTER$63,
3027
+ converter: STRING_CONVERTER$64,
2951
3028
  attribute: "selection-mode"
2952
3029
  },
2953
- disabled: { converter: BOOLEAN_CONVERTER$39 },
3030
+ disabled: { converter: BOOLEAN_CONVERTER$41 },
2954
3031
  readOnly: {
2955
- converter: BOOLEAN_CONVERTER$39,
3032
+ converter: BOOLEAN_CONVERTER$41,
2956
3033
  attribute: "read-only"
2957
3034
  },
2958
- invalid: { converter: BOOLEAN_CONVERTER$39 },
2959
- required: { converter: BOOLEAN_CONVERTER$39 },
2960
- name: { converter: STRING_CONVERTER$63 },
3035
+ invalid: { converter: BOOLEAN_CONVERTER$41 },
3036
+ required: { converter: BOOLEAN_CONVERTER$41 },
3037
+ name: { converter: STRING_CONVERTER$64 },
2961
3038
  endName: {
2962
- converter: STRING_CONVERTER$63,
3039
+ converter: STRING_CONVERTER$64,
2963
3040
  attribute: "end-name"
2964
3041
  },
2965
3042
  translations: { attribute: false },
2966
- placement: { converter: STRING_CONVERTER$63 },
2967
- offset: { converter: NUMBER_CONVERTER$39 },
3043
+ placement: { converter: STRING_CONVERTER$64 },
3044
+ offset: { converter: NUMBER_CONVERTER$40 },
2968
3045
  closeOnSelect: {
2969
- converter: BOOLEAN_CONVERTER$39,
3046
+ converter: BOOLEAN_CONVERTER$41,
2970
3047
  attribute: "close-on-select"
2971
3048
  },
3049
+ showTime: {
3050
+ converter: BOOLEAN_CONVERTER$41,
3051
+ attribute: "show-time"
3052
+ },
3053
+ timeGranularity: {
3054
+ converter: STRING_CONVERTER$64,
3055
+ attribute: "time-granularity"
3056
+ },
2972
3057
  isDateUnavailable: { attribute: false }
2973
3058
  };
2974
3059
  idGen = createCounterIdGenerator();
@@ -3038,6 +3123,8 @@ var XhDatePickerElement = class extends XhElement {
3038
3123
  placement: this.placement,
3039
3124
  offset: this.offset,
3040
3125
  closeOnSelect: this.closeOnSelect,
3126
+ showTime: this.showTime,
3127
+ timeGranularity: this.timeGranularity,
3041
3128
  onValueChange: this.notifyValue,
3042
3129
  onOpenChange: this.notifyOpen,
3043
3130
  onFocusedValueChange: this.notifyFocus
@@ -3128,6 +3215,12 @@ var XhDatePickerElement = class extends XhElement {
3128
3215
  put("positioner", api.getPositionerProps());
3129
3216
  put("content", api.getContentProps());
3130
3217
  put("calendar", api.getCalendarProps());
3218
+ put("confirm-trigger", api.getConfirmTriggerProps());
3219
+ for (const el of this.getParts("time-column")) this.spreader.spread(el, api.getTimeColumnProps({ unit: el.getAttribute("unit") ?? "hour" }));
3220
+ for (const el of this.getParts("time-item")) this.spreader.spread(el, api.getTimeItemProps({
3221
+ unit: el.closest("[data-xh-part=\"time-column\"]")?.getAttribute("unit") ?? "hour",
3222
+ value: el.getAttribute("value") ?? ""
3223
+ }));
3131
3224
  const inputs = this.getParts("input");
3132
3225
  const owners = [inputs[0] ?? this, inputs[1]];
3133
3226
  const hiddenInputs = this.hiddenInputGroups(inputs);
@@ -3167,7 +3260,7 @@ var XhDatePickerElement = class extends XhElement {
3167
3260
  };
3168
3261
  //#endregion
3169
3262
  //#region src/elements/descriptions.ts
3170
- const STRING_CONVERTER$62 = { fromAttribute: (v) => v ?? void 0 };
3263
+ const STRING_CONVERTER$63 = { fromAttribute: (v) => v ?? void 0 };
3171
3264
  /**
3172
3265
  * `<xh-descriptions>` —— Light-DOM 行为宿主,无状态机,把 connectDescriptions 产出打到各角色节点。
3173
3266
  * 排版走 CSS Grid,columns 落成列数。
@@ -3193,8 +3286,8 @@ var XhDescriptionsElement = class extends XhElement {
3193
3286
  static properties = {
3194
3287
  columns: { type: Number },
3195
3288
  bordered: { type: Boolean },
3196
- placement: { converter: STRING_CONVERTER$62 },
3197
- size: { converter: STRING_CONVERTER$62 }
3289
+ placement: { converter: STRING_CONVERTER$63 },
3290
+ size: { converter: STRING_CONVERTER$63 }
3198
3291
  };
3199
3292
  wire() {
3200
3293
  const api = connectDescriptions({
@@ -3214,9 +3307,45 @@ var XhDescriptionsElement = class extends XhElement {
3214
3307
  }
3215
3308
  };
3216
3309
  //#endregion
3310
+ //#region src/overlay-exit.ts
3311
+ function createOverlayExit(options) {
3312
+ let disposed = false;
3313
+ let node = null;
3314
+ let detach;
3315
+ const presence = createPresence({
3316
+ config: options.config,
3317
+ open: options.open,
3318
+ onRenderedChange: (rendered) => {
3319
+ if (!rendered && !disposed) options.onExitComplete();
3320
+ }
3321
+ });
3322
+ return {
3323
+ get visible() {
3324
+ return !disposed && presence.rendered;
3325
+ },
3326
+ track(next) {
3327
+ if (disposed || next === node) return;
3328
+ node = next;
3329
+ detach?.();
3330
+ detach = next ? attachCssExit(next, presence) : void 0;
3331
+ },
3332
+ update(open) {
3333
+ if (!disposed) presence.update(open);
3334
+ },
3335
+ dispose() {
3336
+ if (disposed) return;
3337
+ disposed = true;
3338
+ detach?.();
3339
+ detach = void 0;
3340
+ node = null;
3341
+ presence.dispose();
3342
+ }
3343
+ };
3344
+ }
3345
+ //#endregion
3217
3346
  //#region src/elements/dialog.ts
3218
- const BOOLEAN_CONVERTER$38 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
3219
- const STRING_CONVERTER$61 = { fromAttribute: (v) => v ?? void 0 };
3347
+ const BOOLEAN_CONVERTER$40 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
3348
+ const STRING_CONVERTER$62 = { fromAttribute: (v) => v ?? void 0 };
3220
3349
  /**
3221
3350
  * `<xh-dialog>` —— Light-DOM 行为宿主,跑 dialog 机器并把 connect 产出打到角色节点上,
3222
3351
  * 关闭时用内联 style.display 隐藏浮层子树。
@@ -3244,26 +3373,27 @@ var XhDialogElement = class extends XhElement {
3244
3373
  meta: dialogMeta
3245
3374
  };
3246
3375
  static properties = {
3247
- open: { converter: BOOLEAN_CONVERTER$38 },
3376
+ open: { converter: BOOLEAN_CONVERTER$40 },
3248
3377
  defaultOpen: {
3249
3378
  type: Boolean,
3250
3379
  attribute: "default-open"
3251
3380
  },
3252
- modal: { converter: BOOLEAN_CONVERTER$38 },
3381
+ modal: { converter: BOOLEAN_CONVERTER$40 },
3253
3382
  closeOnEscape: {
3254
- converter: BOOLEAN_CONVERTER$38,
3383
+ converter: BOOLEAN_CONVERTER$40,
3255
3384
  attribute: "close-on-escape"
3256
3385
  },
3257
3386
  restoreFocus: {
3258
- converter: BOOLEAN_CONVERTER$38,
3387
+ converter: BOOLEAN_CONVERTER$40,
3259
3388
  attribute: "restore-focus"
3260
3389
  },
3261
- size: { converter: STRING_CONVERTER$61 }
3390
+ size: { converter: STRING_CONVERTER$62 }
3262
3391
  };
3263
3392
  idGen = createCounterIdGenerator();
3264
3393
  dialogScope = createScope(null, this.idGen);
3265
3394
  config = null;
3266
3395
  contentNode = null;
3396
+ exit = null;
3267
3397
  backdropNode = null;
3268
3398
  notify = (details) => {
3269
3399
  this.dispatchEvent(new CustomEvent("open-change", {
@@ -3295,6 +3425,16 @@ var XhDialogElement = class extends XhElement {
3295
3425
  idGenerator: this.idGen
3296
3426
  });
3297
3427
  }
3428
+ /** 退场闸门建一次;presence 不是响应式 cell,退场结束要显式排一次更新才轮得到收起。 */
3429
+ ensureExit() {
3430
+ this.ensureConfig();
3431
+ this.exit ??= createOverlayExit({
3432
+ config: this.config,
3433
+ open: this.ctrl.service.state.get() === "open",
3434
+ onExitComplete: () => this.requestUpdate()
3435
+ });
3436
+ return this.exit;
3437
+ }
3298
3438
  registerLayer = () => {
3299
3439
  this.ensureConfig();
3300
3440
  return this.config.layerRegistry.register({
@@ -3332,20 +3472,27 @@ var XhDialogElement = class extends XhElement {
3332
3472
  put("title", api.getTitleProps());
3333
3473
  put("description", api.getDescriptionProps());
3334
3474
  put("close-trigger", api.getCloseTriggerProps());
3475
+ const exit = this.ensureExit();
3476
+ exit.track(this.contentNode);
3477
+ exit.update(open);
3478
+ const visible = exit.visible;
3335
3479
  const positioner = this.getPart("positioner");
3336
- if (positioner) this.setPartHidden(positioner, !open);
3337
- if (this.backdropNode) this.setPartHidden(this.backdropNode, !open);
3338
- this.setPartHidden(this.contentNode, !open);
3480
+ if (positioner) this.setPartHidden(positioner, !visible);
3481
+ if (this.backdropNode) this.setPartHidden(this.backdropNode, !visible);
3482
+ this.setPartHidden(this.contentNode, !visible);
3339
3483
  }
3340
3484
  disconnectedCallback() {
3341
3485
  super.disconnectedCallback();
3486
+ this.exit?.dispose();
3487
+ this.exit = null;
3488
+ if (this.ctrl.service.state.get() !== "open") this.setPartHidden(this.contentNode, true);
3342
3489
  this.config = null;
3343
3490
  }
3344
3491
  };
3345
3492
  //#endregion
3346
3493
  //#region src/elements/drawer.ts
3347
- const BOOLEAN_CONVERTER$37 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
3348
- const STRING_CONVERTER$60 = { fromAttribute: (v) => v ?? void 0 };
3494
+ const BOOLEAN_CONVERTER$39 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
3495
+ const STRING_CONVERTER$61 = { fromAttribute: (v) => v ?? void 0 };
3349
3496
  /**
3350
3497
  * `<xh-drawer>` —— Light-DOM 行为宿主,跑 drawer 机器并把 connect 产出打到角色节点上,
3351
3498
  * 关闭时用内联 style.display 隐藏浮层子树。
@@ -3378,32 +3525,33 @@ var XhDrawerElement = class extends XhElement {
3378
3525
  meta: drawerMeta
3379
3526
  };
3380
3527
  static properties = {
3381
- open: { converter: BOOLEAN_CONVERTER$37 },
3528
+ open: { converter: BOOLEAN_CONVERTER$39 },
3382
3529
  defaultOpen: {
3383
3530
  type: Boolean,
3384
3531
  attribute: "default-open"
3385
3532
  },
3386
- modal: { converter: BOOLEAN_CONVERTER$37 },
3387
- side: { converter: STRING_CONVERTER$60 },
3533
+ modal: { converter: BOOLEAN_CONVERTER$39 },
3534
+ side: { converter: STRING_CONVERTER$61 },
3388
3535
  closeOnEscape: {
3389
- converter: BOOLEAN_CONVERTER$37,
3536
+ converter: BOOLEAN_CONVERTER$39,
3390
3537
  attribute: "close-on-escape"
3391
3538
  },
3392
3539
  closeOnInteractOutside: {
3393
- converter: BOOLEAN_CONVERTER$37,
3540
+ converter: BOOLEAN_CONVERTER$39,
3394
3541
  attribute: "close-on-interact-outside"
3395
3542
  },
3396
3543
  restoreFocus: {
3397
- converter: BOOLEAN_CONVERTER$37,
3544
+ converter: BOOLEAN_CONVERTER$39,
3398
3545
  attribute: "restore-focus"
3399
3546
  },
3400
- size: { converter: STRING_CONVERTER$60 },
3547
+ size: { converter: STRING_CONVERTER$61 },
3401
3548
  translations: { attribute: false }
3402
3549
  };
3403
3550
  idGen = createCounterIdGenerator();
3404
3551
  drawerScope = createScope(null, this.idGen);
3405
3552
  config = null;
3406
3553
  contentNode = null;
3554
+ exit = null;
3407
3555
  backdropNode = null;
3408
3556
  notify = (details) => {
3409
3557
  this.dispatchEvent(new CustomEvent("open-change", {
@@ -3438,6 +3586,16 @@ var XhDrawerElement = class extends XhElement {
3438
3586
  idGenerator: this.idGen
3439
3587
  });
3440
3588
  }
3589
+ /** 退场闸门建一次;presence 不是响应式 cell,退场结束要显式排一次更新才轮得到收起。 */
3590
+ ensureExit() {
3591
+ this.ensureConfig();
3592
+ this.exit ??= createOverlayExit({
3593
+ config: this.config,
3594
+ open: this.ctrl.service.state.get() === "open",
3595
+ onExitComplete: () => this.requestUpdate()
3596
+ });
3597
+ return this.exit;
3598
+ }
3441
3599
  registerLayer = () => {
3442
3600
  this.ensureConfig();
3443
3601
  return this.config.layerRegistry.register({
@@ -3476,20 +3634,27 @@ var XhDrawerElement = class extends XhElement {
3476
3634
  put("title", api.getTitleProps());
3477
3635
  put("description", api.getDescriptionProps());
3478
3636
  put("close-trigger", api.getCloseTriggerProps());
3637
+ const exit = this.ensureExit();
3638
+ exit.track(this.contentNode);
3639
+ exit.update(open);
3640
+ const visible = exit.visible;
3479
3641
  const positioner = this.getPart("positioner");
3480
- if (positioner) this.setPartHidden(positioner, !open);
3481
- if (this.backdropNode) this.setPartHidden(this.backdropNode, !open);
3482
- this.setPartHidden(this.contentNode, !open);
3642
+ if (positioner) this.setPartHidden(positioner, !visible);
3643
+ if (this.backdropNode) this.setPartHidden(this.backdropNode, !visible);
3644
+ this.setPartHidden(this.contentNode, !visible);
3483
3645
  }
3484
3646
  disconnectedCallback() {
3485
3647
  super.disconnectedCallback();
3648
+ this.exit?.dispose();
3649
+ this.exit = null;
3650
+ if (this.ctrl.service.state.get() !== "open") this.setPartHidden(this.contentNode, true);
3486
3651
  this.config = null;
3487
3652
  }
3488
3653
  };
3489
3654
  //#endregion
3490
3655
  //#region src/elements/dynamic-input.ts
3491
- const NUMBER_CONVERTER$38 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
3492
- const BOOLEAN_CONVERTER$36 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
3656
+ const NUMBER_CONVERTER$39 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
3657
+ const BOOLEAN_CONVERTER$38 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
3493
3658
  /** 作者写在行上的下标。缺席或写坏了就退回文档序——把行按顺序排下来本身就是声明。 */
3494
3659
  function declaredIndex$2(el, position) {
3495
3660
  const raw = el.getAttribute("index");
@@ -3531,11 +3696,11 @@ var XhDynamicInputElement = class extends XhElement {
3531
3696
  static properties = {
3532
3697
  value: { attribute: false },
3533
3698
  defaultValue: { attribute: false },
3534
- min: { converter: NUMBER_CONVERTER$38 },
3535
- max: { converter: NUMBER_CONVERTER$38 },
3699
+ min: { converter: NUMBER_CONVERTER$39 },
3700
+ max: { converter: NUMBER_CONVERTER$39 },
3536
3701
  createItem: { attribute: false },
3537
- movable: { converter: BOOLEAN_CONVERTER$36 },
3538
- disabled: { converter: BOOLEAN_CONVERTER$36 },
3702
+ movable: { converter: BOOLEAN_CONVERTER$38 },
3703
+ disabled: { converter: BOOLEAN_CONVERTER$38 },
3539
3704
  translations: { attribute: false }
3540
3705
  };
3541
3706
  notifyValue = (details) => {
@@ -3589,9 +3754,9 @@ var XhDynamicInputElement = class extends XhElement {
3589
3754
  };
3590
3755
  //#endregion
3591
3756
  //#region src/elements/editable.ts
3592
- const STRING_CONVERTER$59 = { fromAttribute: (v) => v ?? void 0 };
3593
- const NUMBER_CONVERTER$37 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
3594
- const BOOLEAN_CONVERTER$35 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
3757
+ const STRING_CONVERTER$60 = { fromAttribute: (v) => v ?? void 0 };
3758
+ const NUMBER_CONVERTER$38 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
3759
+ const BOOLEAN_CONVERTER$37 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
3595
3760
  /**
3596
3761
  * `<xh-editable>` —— Light-DOM 行为宿主:作者写 root/label/area/preview/input/control
3597
3762
  * 与三颗按钮的角色节点,元素跑 editable 机器并把 connect 产出打上去。
@@ -3640,42 +3805,42 @@ var XhEditableElement = class extends XhElement {
3640
3805
  meta: editableMeta
3641
3806
  };
3642
3807
  static properties = {
3643
- value: { converter: STRING_CONVERTER$59 },
3808
+ value: { converter: STRING_CONVERTER$60 },
3644
3809
  defaultValue: {
3645
- converter: STRING_CONVERTER$59,
3810
+ converter: STRING_CONVERTER$60,
3646
3811
  attribute: "default-value"
3647
3812
  },
3648
- edit: { converter: BOOLEAN_CONVERTER$35 },
3813
+ edit: { converter: BOOLEAN_CONVERTER$37 },
3649
3814
  defaultEdit: {
3650
- converter: BOOLEAN_CONVERTER$35,
3815
+ converter: BOOLEAN_CONVERTER$37,
3651
3816
  attribute: "default-edit"
3652
3817
  },
3653
- placeholder: { converter: STRING_CONVERTER$59 },
3654
- disabled: { converter: BOOLEAN_CONVERTER$35 },
3818
+ placeholder: { converter: STRING_CONVERTER$60 },
3819
+ disabled: { converter: BOOLEAN_CONVERTER$37 },
3655
3820
  readOnly: {
3656
- converter: BOOLEAN_CONVERTER$35,
3821
+ converter: BOOLEAN_CONVERTER$37,
3657
3822
  attribute: "read-only"
3658
3823
  },
3659
- invalid: { converter: BOOLEAN_CONVERTER$35 },
3824
+ invalid: { converter: BOOLEAN_CONVERTER$37 },
3660
3825
  maxLength: {
3661
- converter: NUMBER_CONVERTER$37,
3826
+ converter: NUMBER_CONVERTER$38,
3662
3827
  attribute: "max-length"
3663
3828
  },
3664
- name: { converter: STRING_CONVERTER$59 },
3829
+ name: { converter: STRING_CONVERTER$60 },
3665
3830
  submitMode: {
3666
- converter: STRING_CONVERTER$59,
3831
+ converter: STRING_CONVERTER$60,
3667
3832
  attribute: "submit-mode"
3668
3833
  },
3669
3834
  activationMode: {
3670
- converter: STRING_CONVERTER$59,
3835
+ converter: STRING_CONVERTER$60,
3671
3836
  attribute: "activation-mode"
3672
3837
  },
3673
3838
  selectOnFocus: {
3674
- converter: BOOLEAN_CONVERTER$35,
3839
+ converter: BOOLEAN_CONVERTER$37,
3675
3840
  attribute: "select-on-focus"
3676
3841
  },
3677
3842
  autoResize: {
3678
- converter: BOOLEAN_CONVERTER$35,
3843
+ converter: BOOLEAN_CONVERTER$37,
3679
3844
  attribute: "auto-resize"
3680
3845
  }
3681
3846
  };
@@ -3784,7 +3949,7 @@ var XhEditableElement = class extends XhElement {
3784
3949
  };
3785
3950
  //#endregion
3786
3951
  //#region src/elements/ellipsis.ts
3787
- const NUMBER_CONVERTER$36 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
3952
+ const NUMBER_CONVERTER$37 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
3788
3953
  const TRISTATE_CONVERTER$1 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
3789
3954
  /**
3790
3955
  * `<xh-ellipsis>` —— 省略行为宿主:把一段文字夹在给定行数内,并如实报出它有没有被裁掉。
@@ -3812,7 +3977,7 @@ var XhEllipsisElement = class extends XhElement {
3812
3977
  meta: ellipsisMeta
3813
3978
  };
3814
3979
  static properties = {
3815
- lines: { converter: NUMBER_CONVERTER$36 },
3980
+ lines: { converter: NUMBER_CONVERTER$37 },
3816
3981
  expandable: { type: Boolean },
3817
3982
  expanded: { converter: TRISTATE_CONVERTER$1 },
3818
3983
  defaultExpanded: {
@@ -3858,7 +4023,7 @@ var XhEllipsisElement = class extends XhElement {
3858
4023
  };
3859
4024
  //#endregion
3860
4025
  //#region src/elements/empty-state.ts
3861
- const STRING_CONVERTER$58 = { fromAttribute: (v) => v ?? void 0 };
4026
+ const STRING_CONVERTER$59 = { fromAttribute: (v) => v ?? void 0 };
3862
4027
  /**
3863
4028
  * `<xh-empty-state>` —— 空状态行为宿主,无状态机,把 connectEmptyState 产出的属性打到角色节点上。
3864
4029
  *
@@ -3880,8 +4045,8 @@ var XhEmptyStateElement = class extends XhElement {
3880
4045
  meta: emptyStateMeta
3881
4046
  };
3882
4047
  static properties = {
3883
- size: { converter: STRING_CONVERTER$58 },
3884
- live: { converter: STRING_CONVERTER$58 }
4048
+ size: { converter: STRING_CONVERTER$59 },
4049
+ live: { converter: STRING_CONVERTER$59 }
3885
4050
  };
3886
4051
  wire() {
3887
4052
  const api = connectEmptyState({
@@ -3901,7 +4066,7 @@ var XhEmptyStateElement = class extends XhElement {
3901
4066
  };
3902
4067
  //#endregion
3903
4068
  //#region src/elements/field.ts
3904
- const STRING_CONVERTER$57 = { fromAttribute: (v) => v ?? void 0 };
4069
+ const STRING_CONVERTER$58 = { fromAttribute: (v) => v ?? void 0 };
3905
4070
  /**
3906
4071
  * `<xh-field>` —— Light-DOM 行为宿主,无状态机,把 connectField 产出的 id 与 aria-* 打到
3907
4072
  * label/control/description/error-text 角色节点上,自动对齐 `for` 与描述链。控件本身由作者渲染。
@@ -3931,7 +4096,7 @@ var XhFieldElement = class extends XhElement {
3931
4096
  required: { type: Boolean },
3932
4097
  disabled: { type: Boolean },
3933
4098
  controlId: {
3934
- converter: STRING_CONVERTER$57,
4099
+ converter: STRING_CONVERTER$58,
3935
4100
  attribute: "control-id"
3936
4101
  }
3937
4102
  };
@@ -3957,9 +4122,9 @@ var XhFieldElement = class extends XhElement {
3957
4122
  };
3958
4123
  //#endregion
3959
4124
  //#region src/elements/file-upload.ts
3960
- const STRING_CONVERTER$56 = { fromAttribute: (v) => v ?? void 0 };
3961
- const NUMBER_CONVERTER$35 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
3962
- const BOOLEAN_CONVERTER$34 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
4125
+ const STRING_CONVERTER$57 = { fromAttribute: (v) => v ?? void 0 };
4126
+ const NUMBER_CONVERTER$36 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
4127
+ const BOOLEAN_CONVERTER$36 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
3963
4128
  /** 取作者写在条目上的 index,缺席或写坏了退回文档序。 */
3964
4129
  function declaredIndex$1(el, position) {
3965
4130
  const raw = el.getAttribute("index");
@@ -3991,7 +4156,11 @@ function declaredIndex$1(el, position) {
3991
4156
  * @attr {boolean} allow-drop - 是否接受拖拽投放,默认 true;写 allow-drop="false" 关掉
3992
4157
  * @attr {boolean} directory - 选目录而不是选文件(隐藏输入带 webkitdirectory)
3993
4158
  * @attr {'user'|'environment'} capture - 移动端直接调用摄像头/麦克风采集
4159
+ * @attr {boolean} auto-upload - 收下即自动开传(须配 upload 实现),默认 true;写 auto-upload="false" 关掉
3994
4160
  * @fires files-change - 列表变化;detail 为 `{ files: File[] }`
4161
+ * @fires remote-files-change - 远程附件列表变化;detail 为 `{ files: FileUploadRemoteFile[] }`
4162
+ * @fires upload-complete - 单个文件传完;detail 为 `{ file, url? }`
4163
+ * @fires upload-error - 单个文件传败;detail 为 `{ file, error }`
3995
4164
  * @fires file-accept - 本次收下了哪些;detail 为 `{ files: File[] }`
3996
4165
  * @fires file-reject - 本次拒了哪些、各自为什么;detail 为 `{ files: { file, reasons }[] }`
3997
4166
  * @csspart root - 组件根容器,承载 data-dragging / data-disabled / data-invalid / data-empty
@@ -4015,28 +4184,35 @@ var XhFileUploadElement = class XhFileUploadElement extends XhElement {
4015
4184
  static properties = {
4016
4185
  files: { attribute: false },
4017
4186
  defaultFiles: { attribute: false },
4018
- accept: { converter: STRING_CONVERTER$56 },
4187
+ remoteFiles: { attribute: false },
4188
+ defaultRemoteFiles: { attribute: false },
4189
+ upload: { attribute: false },
4190
+ autoUpload: {
4191
+ converter: BOOLEAN_CONVERTER$36,
4192
+ attribute: "auto-upload"
4193
+ },
4194
+ accept: { converter: STRING_CONVERTER$57 },
4019
4195
  maxFiles: {
4020
- converter: NUMBER_CONVERTER$35,
4196
+ converter: NUMBER_CONVERTER$36,
4021
4197
  attribute: "max-files"
4022
4198
  },
4023
4199
  maxFileSize: {
4024
- converter: NUMBER_CONVERTER$35,
4200
+ converter: NUMBER_CONVERTER$36,
4025
4201
  attribute: "max-file-size"
4026
4202
  },
4027
4203
  minFileSize: {
4028
- converter: NUMBER_CONVERTER$35,
4204
+ converter: NUMBER_CONVERTER$36,
4029
4205
  attribute: "min-file-size"
4030
4206
  },
4031
4207
  disabled: { type: Boolean },
4032
4208
  invalid: { type: Boolean },
4033
- name: { converter: STRING_CONVERTER$56 },
4209
+ name: { converter: STRING_CONVERTER$57 },
4034
4210
  allowDrop: {
4035
- converter: BOOLEAN_CONVERTER$34,
4211
+ converter: BOOLEAN_CONVERTER$36,
4036
4212
  attribute: "allow-drop"
4037
4213
  },
4038
4214
  directory: { type: Boolean },
4039
- capture: { converter: STRING_CONVERTER$56 },
4215
+ capture: { converter: STRING_CONVERTER$57 },
4040
4216
  translations: { attribute: false }
4041
4217
  };
4042
4218
  uploadScope = createScope(this, createCounterIdGenerator());
@@ -4061,11 +4237,36 @@ var XhFileUploadElement = class XhFileUploadElement extends XhElement {
4061
4237
  composed: true
4062
4238
  }));
4063
4239
  };
4240
+ notifyRemoteChange = (details) => {
4241
+ this.dispatchEvent(new CustomEvent("remote-files-change", {
4242
+ detail: details,
4243
+ bubbles: true,
4244
+ composed: true
4245
+ }));
4246
+ };
4247
+ notifyUploadComplete = (details) => {
4248
+ this.dispatchEvent(new CustomEvent("upload-complete", {
4249
+ detail: details,
4250
+ bubbles: true,
4251
+ composed: true
4252
+ }));
4253
+ };
4254
+ notifyUploadError = (details) => {
4255
+ this.dispatchEvent(new CustomEvent("upload-error", {
4256
+ detail: details,
4257
+ bubbles: true,
4258
+ composed: true
4259
+ }));
4260
+ };
4064
4261
  ctrl = new MachineController(this, fileUploadMachine, () => this.machineProps(), { scope: this.uploadScope });
4065
4262
  machineProps() {
4066
4263
  return {
4067
4264
  files: this.files,
4068
4265
  defaultFiles: this.defaultFiles,
4266
+ remoteFiles: this.remoteFiles,
4267
+ defaultRemoteFiles: this.defaultRemoteFiles,
4268
+ upload: this.upload,
4269
+ autoUpload: this.autoUpload,
4069
4270
  accept: this.accept,
4070
4271
  maxFiles: this.maxFiles,
4071
4272
  maxFileSize: this.maxFileSize,
@@ -4078,6 +4279,9 @@ var XhFileUploadElement = class XhFileUploadElement extends XhElement {
4078
4279
  capture: this.capture,
4079
4280
  translations: this.translations,
4080
4281
  onFilesChange: this.notifyChange,
4282
+ onRemoteFilesChange: this.notifyRemoteChange,
4283
+ onUploadComplete: this.notifyUploadComplete,
4284
+ onUploadError: this.notifyUploadError,
4081
4285
  onFileAccept: this.notifyAccept,
4082
4286
  onFileReject: this.notifyReject
4083
4287
  };
@@ -4222,8 +4426,8 @@ var XhFlexElement = class extends XhElement {
4222
4426
  };
4223
4427
  //#endregion
4224
4428
  //#region src/elements/float-button.ts
4225
- const STRING_CONVERTER$55 = { fromAttribute: (v) => v ?? void 0 };
4226
- const NUMBER_CONVERTER$34 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
4429
+ const STRING_CONVERTER$56 = { fromAttribute: (v) => v ?? void 0 };
4430
+ const NUMBER_CONVERTER$35 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
4227
4431
  const TRISTATE_CONVERTER = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
4228
4432
  /**
4229
4433
  * `<xh-float-button>` —— 悬浮按钮行为宿主:一颗钉在视口一角的触发器,展开一组动作。
@@ -4261,11 +4465,11 @@ var XhFloatButtonElement = class extends XhElement {
4261
4465
  attribute: "default-open"
4262
4466
  },
4263
4467
  disabled: { type: Boolean },
4264
- placement: { converter: STRING_CONVERTER$55 },
4265
- offset: { converter: NUMBER_CONVERTER$34 },
4266
- shape: { converter: STRING_CONVERTER$55 },
4468
+ placement: { converter: STRING_CONVERTER$56 },
4469
+ offset: { converter: NUMBER_CONVERTER$35 },
4470
+ shape: { converter: STRING_CONVERTER$56 },
4267
4471
  expandTrigger: {
4268
- converter: STRING_CONVERTER$55,
4472
+ converter: STRING_CONVERTER$56,
4269
4473
  attribute: "expand-trigger"
4270
4474
  },
4271
4475
  translations: { attribute: false }
@@ -4313,8 +4517,8 @@ var XhFloatButtonElement = class extends XhElement {
4313
4517
  };
4314
4518
  //#endregion
4315
4519
  //#region src/elements/form.ts
4316
- const STRING_CONVERTER$54 = { fromAttribute: (v) => v ?? void 0 };
4317
- const BOOLEAN_CONVERTER$33 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
4520
+ const STRING_CONVERTER$55 = { fromAttribute: (v) => v ?? void 0 };
4521
+ const BOOLEAN_CONVERTER$35 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
4318
4522
  /**
4319
4523
  * 字段容器与摘要条目自报的字段名,取作者写的 `value` 属性。
4320
4524
  *
@@ -4344,6 +4548,9 @@ function fieldNameOf(el) {
4344
4548
  *
4345
4549
  * @customElement xh-form
4346
4550
  * @attr {string} validate-on - 校验时机:submit(默认)/ blur / change
4551
+ * @attr {string} layout - 排布:vertical(默认)/ horizontal(标签左置两列)/ inline(横排一行流)
4552
+ * @attr {string} label-width - horizontal 下标签列宽(CSS 长度),整表统一对齐
4553
+ * @attr {string} label-align - horizontal 下标签对齐缘:end(默认,贴控件)/ start
4347
4554
  * @attr {boolean} disabled - 整个表单禁用:提交、重置、写值一概不发生,两颗按钮带原生 disabled
4348
4555
  * @attr {boolean} read-only - 只读:写值与重置不发生,但仍可提交
4349
4556
  * @fires values-change - 值表变化;detail 为 `{ values }`
@@ -4351,7 +4558,8 @@ function fieldNameOf(el) {
4351
4558
  * @fires submit - 校验通过才派发;detail 为 `{ values }`
4352
4559
  * @fires invalid - 校验不通过时派发;detail 为 `{ errors, values }`
4353
4560
  * @csspart root - 表单根容器,必须是原生 `<form>`(承载 data-state/data-disabled/data-readonly/data-invalid)
4354
- * @csspart field-group - 单个字段的容器,须自带 value 属性标识字段名;带 id 供摘要链接指向
4561
+ * @csspart field-group - 单个字段的容器,须自带 value 属性标识字段名;带 id 供摘要链接指向。
4562
+ * 组里的 `<xh-field>` 由表单驱动 invalid/required/disabled,作者显式设的会被顶掉
4355
4563
  * @csspart error-summary - role=alert 的错误汇总,提交失败且仍有错误时才显形
4356
4564
  * @csspart error-summary-item - 摘要里的一条,须是原生 `<a>` 且自带 value 属性标识字段名;无对应错误时带 hidden
4357
4565
  * @csspart submit-trigger - 提交键,须是原生 button(连接层写成 type=submit)
@@ -4368,13 +4576,24 @@ var XhFormElement = class extends XhElement {
4368
4576
  errors: { attribute: false },
4369
4577
  defaultErrors: { attribute: false },
4370
4578
  validate: { attribute: false },
4579
+ rules: { attribute: false },
4580
+ validateMessages: { attribute: false },
4371
4581
  validateOn: {
4372
- converter: STRING_CONVERTER$54,
4582
+ converter: STRING_CONVERTER$55,
4373
4583
  attribute: "validate-on"
4374
4584
  },
4375
- disabled: { converter: BOOLEAN_CONVERTER$33 },
4585
+ layout: { converter: STRING_CONVERTER$55 },
4586
+ labelWidth: {
4587
+ converter: STRING_CONVERTER$55,
4588
+ attribute: "label-width"
4589
+ },
4590
+ labelAlign: {
4591
+ converter: STRING_CONVERTER$55,
4592
+ attribute: "label-align"
4593
+ },
4594
+ disabled: { converter: BOOLEAN_CONVERTER$35 },
4376
4595
  readOnly: {
4377
- converter: BOOLEAN_CONVERTER$33,
4596
+ converter: BOOLEAN_CONVERTER$35,
4378
4597
  attribute: "read-only"
4379
4598
  }
4380
4599
  };
@@ -4414,7 +4633,12 @@ var XhFormElement = class extends XhElement {
4414
4633
  errors: this.errors,
4415
4634
  defaultErrors: this.defaultErrors,
4416
4635
  validate: this.validate,
4636
+ rules: this.rules,
4637
+ validateMessages: this.validateMessages,
4417
4638
  validateOn: this.validateOn,
4639
+ layout: this.layout,
4640
+ labelWidth: this.labelWidth,
4641
+ labelAlign: this.labelAlign,
4418
4642
  disabled: this.disabled ?? false,
4419
4643
  readOnly: this.readOnly ?? false,
4420
4644
  onValuesChange: this.notifyValues,
@@ -4486,7 +4710,15 @@ var XhFormElement = class extends XhElement {
4486
4710
  put("error-summary", api.getErrorSummaryProps());
4487
4711
  put("submit-trigger", api.getSubmitTriggerProps());
4488
4712
  put("reset-trigger", api.getResetTriggerProps());
4489
- for (const el of this.getParts("field-group")) this.spreader.spread(el, api.getFieldGroupProps({ name: fieldNameOf(el) }));
4713
+ for (const el of this.getParts("field-group")) {
4714
+ const name = fieldNameOf(el);
4715
+ this.spreader.spread(el, api.getFieldGroupProps({ name }));
4716
+ for (const field of el.querySelectorAll("xh-field")) {
4717
+ field.invalid = api.isFieldInvalid(name);
4718
+ field.required = api.isFieldRequired(name) || void 0;
4719
+ field.disabled = api.disabled || void 0;
4720
+ }
4721
+ }
4490
4722
  for (const el of this.getParts("error-summary-item")) {
4491
4723
  this.spreader.spread(el, api.getErrorSummaryItemProps({ name: fieldNameOf(el) }));
4492
4724
  this.setPartHidden(el, api.getFieldError(fieldNameOf(el)) === void 0);
@@ -4496,7 +4728,7 @@ var XhFormElement = class extends XhElement {
4496
4728
  };
4497
4729
  //#endregion
4498
4730
  //#region src/elements/gradient-text.ts
4499
- const STRING_CONVERTER$53 = { fromAttribute: (v) => v ?? void 0 };
4731
+ const STRING_CONVERTER$54 = { fromAttribute: (v) => v ?? void 0 };
4500
4732
  /**
4501
4733
  * `<xh-gradient-text>` —— Light-DOM 行为宿主,无状态机,把 connectGradientText 产出打到 root 角色节点。
4502
4734
  *
@@ -4517,9 +4749,9 @@ var XhGradientTextElement = class extends XhElement {
4517
4749
  meta: gradientTextMeta
4518
4750
  };
4519
4751
  static properties = {
4520
- from: { converter: STRING_CONVERTER$53 },
4521
- to: { converter: STRING_CONVERTER$53 },
4522
- direction: { converter: STRING_CONVERTER$53 }
4752
+ from: { converter: STRING_CONVERTER$54 },
4753
+ to: { converter: STRING_CONVERTER$54 },
4754
+ direction: { converter: STRING_CONVERTER$54 }
4523
4755
  };
4524
4756
  wire() {
4525
4757
  const api = connectGradientText({
@@ -4533,7 +4765,7 @@ var XhGradientTextElement = class extends XhElement {
4533
4765
  };
4534
4766
  //#endregion
4535
4767
  //#region src/elements/grid.ts
4536
- const STRING_CONVERTER$52 = { fromAttribute: (v) => v ?? void 0 };
4768
+ const STRING_CONVERTER$53 = { fromAttribute: (v) => v ?? void 0 };
4537
4769
  /**
4538
4770
  * 列数写整数就是各档同一个列数(`cols="3"`),写 JSON 对象就是逐档的列数
4539
4771
  * (`cols='{"base":1,"md":3}'`)。解析不出对象时当没写:落一个半截对象进去,
@@ -4582,9 +4814,9 @@ var XhGridElement = class extends XhElement {
4582
4814
  };
4583
4815
  static properties = {
4584
4816
  cols: { converter: COLS_CONVERTER },
4585
- gap: { converter: STRING_CONVERTER$52 },
4586
- align: { converter: STRING_CONVERTER$52 },
4587
- justify: { converter: STRING_CONVERTER$52 }
4817
+ gap: { converter: STRING_CONVERTER$53 },
4818
+ align: { converter: STRING_CONVERTER$53 },
4819
+ justify: { converter: STRING_CONVERTER$53 }
4588
4820
  };
4589
4821
  wire() {
4590
4822
  const api = connectGrid({
@@ -4606,7 +4838,7 @@ var XhGridElement = class extends XhElement {
4606
4838
  };
4607
4839
  //#endregion
4608
4840
  //#region src/elements/highlight.ts
4609
- const STRING_CONVERTER$51 = { fromAttribute: (v) => v ?? void 0 };
4841
+ const STRING_CONVERTER$52 = { fromAttribute: (v) => v ?? void 0 };
4610
4842
  /**
4611
4843
  * `<xh-highlight>` —— Light-DOM 行为宿主,无状态机,把 text 按 keyword 切段铺进 root。
4612
4844
  *
@@ -4632,8 +4864,8 @@ var XhHighlightElement = class extends XhElement {
4632
4864
  meta: highlightMeta
4633
4865
  };
4634
4866
  static properties = {
4635
- text: { converter: STRING_CONVERTER$51 },
4636
- keyword: { converter: STRING_CONVERTER$51 },
4867
+ text: { converter: STRING_CONVERTER$52 },
4868
+ keyword: { converter: STRING_CONVERTER$52 },
4637
4869
  caseSensitive: {
4638
4870
  type: Boolean,
4639
4871
  attribute: "case-sensitive"
@@ -4681,13 +4913,13 @@ var XhHighlightElement = class extends XhElement {
4681
4913
  };
4682
4914
  //#endregion
4683
4915
  //#region src/elements/hover-card.ts
4684
- const STRING_CONVERTER$50 = { fromAttribute: (v) => v ?? void 0 };
4685
- const NUMBER_CONVERTER$33 = { fromAttribute: (v) => {
4916
+ const STRING_CONVERTER$51 = { fromAttribute: (v) => v ?? void 0 };
4917
+ const NUMBER_CONVERTER$34 = { fromAttribute: (v) => {
4686
4918
  if (v === null) return void 0;
4687
4919
  const n = Number(v);
4688
4920
  return Number.isFinite(n) ? n : void 0;
4689
4921
  } };
4690
- const BOOLEAN_CONVERTER$32 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
4922
+ const BOOLEAN_CONVERTER$34 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
4691
4923
  /**
4692
4924
  * `<xh-hover-card>` —— Light-DOM 行为宿主:作者写 root/trigger/positioner/content/arrow 角色节点,
4693
4925
  * 元素跑 hover-card 机器并把 connect 产出打上去。
@@ -4720,27 +4952,27 @@ var XhHoverCardElement = class extends XhElement {
4720
4952
  meta: hoverCardMeta
4721
4953
  };
4722
4954
  static properties = {
4723
- open: { converter: BOOLEAN_CONVERTER$32 },
4955
+ open: { converter: BOOLEAN_CONVERTER$34 },
4724
4956
  defaultOpen: {
4725
4957
  type: Boolean,
4726
4958
  attribute: "default-open"
4727
4959
  },
4728
- placement: { converter: STRING_CONVERTER$50 },
4729
- offset: { converter: NUMBER_CONVERTER$33 },
4960
+ placement: { converter: STRING_CONVERTER$51 },
4961
+ offset: { converter: NUMBER_CONVERTER$34 },
4730
4962
  openDelay: {
4731
- converter: NUMBER_CONVERTER$33,
4963
+ converter: NUMBER_CONVERTER$34,
4732
4964
  attribute: "open-delay"
4733
4965
  },
4734
4966
  closeDelay: {
4735
- converter: NUMBER_CONVERTER$33,
4967
+ converter: NUMBER_CONVERTER$34,
4736
4968
  attribute: "close-delay"
4737
4969
  },
4738
4970
  direction: {
4739
- converter: STRING_CONVERTER$50,
4971
+ converter: STRING_CONVERTER$51,
4740
4972
  attribute: "dir"
4741
4973
  },
4742
4974
  disabled: { type: Boolean },
4743
- size: { converter: STRING_CONVERTER$50 }
4975
+ size: { converter: STRING_CONVERTER$51 }
4744
4976
  };
4745
4977
  idGen = createCounterIdGenerator();
4746
4978
  hoverCardScope = createScope(null, this.idGen);
@@ -4828,7 +5060,7 @@ var XhHoverCardElement = class extends XhElement {
4828
5060
  };
4829
5061
  //#endregion
4830
5062
  //#region src/elements/icon.ts
4831
- const STRING_CONVERTER$49 = { fromAttribute: (v) => v ?? void 0 };
5063
+ const STRING_CONVERTER$50 = { fromAttribute: (v) => v ?? void 0 };
4832
5064
  const SVG_NS$1 = "http://www.w3.org/2000/svg";
4833
5065
  /** 自带可及名字的控件;图标落在它们里面时名字该写在控件上。 */
4834
5066
  const NAMED_CONTROLS = "button, a[href], [role=\"button\"], [role=\"link\"], [role=\"menuitem\"], [role=\"tab\"], [role=\"option\"]";
@@ -4869,10 +5101,10 @@ var XhIconElement = class extends XhElement {
4869
5101
  }
4870
5102
  };
4871
5103
  static properties = {
4872
- label: { converter: STRING_CONVERTER$49 },
4873
- size: { converter: STRING_CONVERTER$49 },
4874
- weight: { converter: STRING_CONVERTER$49 },
4875
- tone: { converter: STRING_CONVERTER$49 },
5104
+ label: { converter: STRING_CONVERTER$50 },
5105
+ size: { converter: STRING_CONVERTER$50 },
5106
+ weight: { converter: STRING_CONVERTER$50 },
5107
+ tone: { converter: STRING_CONVERTER$50 },
4876
5108
  icon: { attribute: false }
4877
5109
  };
4878
5110
  /** 一个 glyph 节点归谁,首次见到时定死。 */
@@ -4995,8 +5227,8 @@ var XhIconWrapperElement = class extends XhElement {
4995
5227
  };
4996
5228
  //#endregion
4997
5229
  //#region src/elements/image.ts
4998
- const STRING_CONVERTER$48 = { fromAttribute: (v) => v ?? void 0 };
4999
- const NUMBER_CONVERTER$32 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
5230
+ const STRING_CONVERTER$49 = { fromAttribute: (v) => v ?? void 0 };
5231
+ const NUMBER_CONVERTER$33 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
5000
5232
  /**
5001
5233
  * `<xh-image>` —— Light-DOM 行为宿主:作者写 root/image/fallback 角色节点,
5002
5234
  * 元素跑 image 机器并把 connect 产出打上去。图片来源由宿主的 src/alt 写进 image 节点,
@@ -5020,10 +5252,10 @@ var XhImageElement = class extends XhElement {
5020
5252
  meta: imageMeta
5021
5253
  };
5022
5254
  static properties = {
5023
- src: { converter: STRING_CONVERTER$48 },
5024
- alt: { converter: STRING_CONVERTER$48 },
5255
+ src: { converter: STRING_CONVERTER$49 },
5256
+ alt: { converter: STRING_CONVERTER$49 },
5025
5257
  fallbackDelay: {
5026
- converter: NUMBER_CONVERTER$32,
5258
+ converter: NUMBER_CONVERTER$33,
5027
5259
  attribute: "fallback-delay"
5028
5260
  }
5029
5261
  };
@@ -5078,9 +5310,226 @@ var XhImageElement = class extends XhElement {
5078
5310
  }
5079
5311
  };
5080
5312
  //#endregion
5313
+ //#region src/elements/image-viewer.ts
5314
+ const BOOLEAN_CONVERTER$33 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
5315
+ const NUMBER_CONVERTER$32 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
5316
+ /**
5317
+ * `<xh-image-viewer>` —— Light-DOM 行为宿主,跑 image-viewer 机器:
5318
+ * 模态看片浮层,滚轮缩放、拖拽平移、旋转翻转与多图翻页。
5319
+ *
5320
+ * @customElement xh-image-viewer
5321
+ * @attr {boolean} open - 受控开合;缺省该属性即非受控
5322
+ * @attr {boolean} default-open - 非受控初始为打开
5323
+ * @attr {number} index - 受控下标(0 起)
5324
+ * @attr {number} default-index - 非受控初始下标,默认 0
5325
+ * @attr {boolean} loop - 前后翻页到头回绕,默认 true;写 loop="false" 关掉
5326
+ * @attr {number} zoom-step - 缩放步长(加法),默认 0.5
5327
+ * @attr {number} min-scale - 缩放下限,默认 0.25
5328
+ * @attr {number} max-scale - 缩放上限,默认 8
5329
+ * @attr {boolean} close-on-escape - Esc 关闭,默认 true
5330
+ * @attr {boolean} close-on-interact-outside - 点遮罩关闭,默认 true
5331
+ * @attr {boolean} restore-focus - 关闭后把焦点归还触发元素,默认 true
5332
+ * @fires open-change - open 状态变化;detail 为 `{ open: boolean }`
5333
+ * @fires index-change - 下标变化;detail 为 `{ index: number }`
5334
+ * @csspart trigger - 触发按钮
5335
+ * @csspart backdrop - 遮罩层
5336
+ * @csspart positioner - 浮层定位容器
5337
+ * @csspart content - 看片容器(role=dialog + aria-modal;方向键翻页在这里)
5338
+ * @csspart viewport - 手势视口(滚轮缩放、拖拽平移)
5339
+ * @csspart image - 当前那张图(src/alt/transform 由元素代填)
5340
+ * @csspart toolbar - 工具条容器
5341
+ * @csspart zoom-in-trigger - 放大
5342
+ * @csspart zoom-out-trigger - 缩小
5343
+ * @csspart rotate-left-trigger - 左转 90°
5344
+ * @csspart rotate-right-trigger - 右转 90°
5345
+ * @csspart flip-horizontal-trigger - 水平翻转
5346
+ * @csspart flip-vertical-trigger - 垂直翻转
5347
+ * @csspart reset-trigger - 变换归零
5348
+ * @csspart prev-trigger - 上一张
5349
+ * @csspart next-trigger - 下一张
5350
+ * @csspart counter - 「第 n / 共 m」计数(元素代填)
5351
+ * @csspart close-trigger - 关闭
5352
+ */
5353
+ var XhImageViewerElement = class extends XhElement {
5354
+ static partContract = {
5355
+ anatomy: imageViewerAnatomy,
5356
+ meta: imageViewerMeta
5357
+ };
5358
+ static properties = {
5359
+ open: { converter: BOOLEAN_CONVERTER$33 },
5360
+ defaultOpen: {
5361
+ type: Boolean,
5362
+ attribute: "default-open"
5363
+ },
5364
+ index: { converter: NUMBER_CONVERTER$32 },
5365
+ defaultIndex: {
5366
+ converter: NUMBER_CONVERTER$32,
5367
+ attribute: "default-index"
5368
+ },
5369
+ loop: { converter: BOOLEAN_CONVERTER$33 },
5370
+ zoomStep: {
5371
+ converter: NUMBER_CONVERTER$32,
5372
+ attribute: "zoom-step"
5373
+ },
5374
+ minScale: {
5375
+ converter: NUMBER_CONVERTER$32,
5376
+ attribute: "min-scale"
5377
+ },
5378
+ maxScale: {
5379
+ converter: NUMBER_CONVERTER$32,
5380
+ attribute: "max-scale"
5381
+ },
5382
+ closeOnEscape: {
5383
+ converter: BOOLEAN_CONVERTER$33,
5384
+ attribute: "close-on-escape"
5385
+ },
5386
+ closeOnInteractOutside: {
5387
+ converter: BOOLEAN_CONVERTER$33,
5388
+ attribute: "close-on-interact-outside"
5389
+ },
5390
+ restoreFocus: {
5391
+ converter: BOOLEAN_CONVERTER$33,
5392
+ attribute: "restore-focus"
5393
+ },
5394
+ items: { attribute: false },
5395
+ translations: { attribute: false }
5396
+ };
5397
+ idGen = createCounterIdGenerator();
5398
+ viewerScope = createScope(null, this.idGen);
5399
+ config = null;
5400
+ contentNode = null;
5401
+ exit = null;
5402
+ backdropNode = null;
5403
+ /** counter 的文本归属:首帧为空才代填,作者写过内容就不碰。 */
5404
+ counterOwned = null;
5405
+ notifyOpen = (details) => {
5406
+ this.dispatchEvent(new CustomEvent("open-change", {
5407
+ detail: details,
5408
+ bubbles: true,
5409
+ composed: true
5410
+ }));
5411
+ };
5412
+ notifyIndex = (details) => {
5413
+ this.dispatchEvent(new CustomEvent("index-change", {
5414
+ detail: details,
5415
+ bubbles: true,
5416
+ composed: true
5417
+ }));
5418
+ };
5419
+ ctrl = new MachineController(this, imageViewerMachine, () => this.machineProps(), {
5420
+ scope: this.viewerScope,
5421
+ onBuilt: (svc) => this.injectRefs(svc)
5422
+ });
5423
+ machineProps() {
5424
+ return {
5425
+ items: this.items,
5426
+ open: this.open,
5427
+ defaultOpen: this.defaultOpen ?? false,
5428
+ index: this.index,
5429
+ defaultIndex: this.defaultIndex,
5430
+ loop: this.loop,
5431
+ zoomStep: this.zoomStep,
5432
+ minScale: this.minScale,
5433
+ maxScale: this.maxScale,
5434
+ closeOnEscape: this.closeOnEscape,
5435
+ closeOnInteractOutside: this.closeOnInteractOutside,
5436
+ restoreFocus: this.restoreFocus,
5437
+ translations: this.translations,
5438
+ onOpenChange: this.notifyOpen,
5439
+ onIndexChange: this.notifyIndex
5440
+ };
5441
+ }
5442
+ ensureConfig() {
5443
+ if (this.config) return;
5444
+ this.config = createRuntimeConfig({
5445
+ scope: this.viewerScope,
5446
+ idGenerator: this.idGen
5447
+ });
5448
+ }
5449
+ /** 退场闸门建一次;presence 不是响应式 cell,退场结束要显式排一次更新才轮得到收起。 */
5450
+ ensureExit() {
5451
+ this.ensureConfig();
5452
+ this.exit ??= createOverlayExit({
5453
+ config: this.config,
5454
+ open: this.ctrl.service.state.get() === "open",
5455
+ onExitComplete: () => this.requestUpdate()
5456
+ });
5457
+ return this.exit;
5458
+ }
5459
+ registerLayer = () => {
5460
+ this.ensureConfig();
5461
+ return this.config.layerRegistry.register({
5462
+ kind: "modal",
5463
+ node: () => this.contentNode,
5464
+ branches: () => [],
5465
+ isModal: () => true,
5466
+ setModal: () => {},
5467
+ surfaces: () => [this.backdropNode].filter(Boolean)
5468
+ });
5469
+ };
5470
+ injectRefs(svc) {
5471
+ this.ensureConfig();
5472
+ svc.refs.set("config", this.config);
5473
+ svc.refs.set("registerLayer", this.registerLayer);
5474
+ svc.refs.set("getContentEl", () => this.contentNode);
5475
+ }
5476
+ wire() {
5477
+ const svc = this.ctrl.service;
5478
+ const api = connectImageViewer(svc, wcNormalize);
5479
+ const open = svc.state.get() === "open";
5480
+ this.contentNode = this.getPart("content");
5481
+ this.backdropNode = this.getPart("backdrop");
5482
+ const put = (name, props) => {
5483
+ const el = this.getPart(name);
5484
+ if (el) this.spreader.spread(el, props);
5485
+ };
5486
+ put("trigger", api.getTriggerProps());
5487
+ put("backdrop", api.getBackdropProps());
5488
+ put("positioner", api.getPositionerProps());
5489
+ put("content", api.getContentProps());
5490
+ put("viewport", api.getViewportProps());
5491
+ put("image", api.getImageProps());
5492
+ put("toolbar", api.getToolbarProps());
5493
+ put("zoom-in-trigger", api.getZoomInTriggerProps());
5494
+ put("zoom-out-trigger", api.getZoomOutTriggerProps());
5495
+ put("rotate-left-trigger", api.getRotateLeftTriggerProps());
5496
+ put("rotate-right-trigger", api.getRotateRightTriggerProps());
5497
+ put("flip-horizontal-trigger", api.getFlipHorizontalTriggerProps());
5498
+ put("flip-vertical-trigger", api.getFlipVerticalTriggerProps());
5499
+ put("reset-trigger", api.getResetTriggerProps());
5500
+ put("prev-trigger", api.getPrevTriggerProps());
5501
+ put("next-trigger", api.getNextTriggerProps());
5502
+ put("counter", api.getCounterProps());
5503
+ put("close-trigger", api.getCloseTriggerProps());
5504
+ const counter = this.getPart("counter");
5505
+ if (counter) {
5506
+ if (this.counterOwned === null) this.counterOwned = (counter.textContent ?? "").trim() === "";
5507
+ if (this.counterOwned) {
5508
+ const text = imageViewerCounterText(this.translations, api.index, api.count);
5509
+ if (counter.textContent !== text) counter.textContent = text;
5510
+ }
5511
+ }
5512
+ const exit = this.ensureExit();
5513
+ exit.track(this.contentNode);
5514
+ exit.update(open);
5515
+ const visible = exit.visible;
5516
+ const positioner = this.getPart("positioner");
5517
+ if (positioner) this.setPartHidden(positioner, !visible);
5518
+ if (this.backdropNode) this.setPartHidden(this.backdropNode, !visible);
5519
+ this.setPartHidden(this.contentNode, !visible);
5520
+ }
5521
+ disconnectedCallback() {
5522
+ super.disconnectedCallback();
5523
+ this.exit?.dispose();
5524
+ this.exit = null;
5525
+ if (this.ctrl.service.state.get() !== "open") this.setPartHidden(this.contentNode, true);
5526
+ this.config = null;
5527
+ }
5528
+ };
5529
+ //#endregion
5081
5530
  //#region src/elements/infinite-scroll.ts
5082
5531
  const NUMBER_CONVERTER$31 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
5083
- const BOOLEAN_CONVERTER$31 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
5532
+ const BOOLEAN_CONVERTER$32 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
5084
5533
  /**
5085
5534
  * `<xh-infinite-scroll>` —— 无限滚动行为宿主:摆在列表末尾的哨兵一进可视区就报「该取下一页了」。
5086
5535
  *
@@ -5104,8 +5553,8 @@ var XhInfiniteScrollElement = class extends XhElement {
5104
5553
  };
5105
5554
  static properties = {
5106
5555
  distance: { converter: NUMBER_CONVERTER$31 },
5107
- disabled: { converter: BOOLEAN_CONVERTER$31 },
5108
- loading: { converter: BOOLEAN_CONVERTER$31 },
5556
+ disabled: { converter: BOOLEAN_CONVERTER$32 },
5557
+ loading: { converter: BOOLEAN_CONVERTER$32 },
5109
5558
  target: { attribute: false }
5110
5559
  };
5111
5560
  notify = () => {
@@ -5139,7 +5588,7 @@ var XhInfiniteScrollElement = class extends XhElement {
5139
5588
  };
5140
5589
  //#endregion
5141
5590
  //#region src/elements/layout.ts
5142
- const STRING_CONVERTER$47 = { fromAttribute: (v) => v ?? void 0 };
5591
+ const STRING_CONVERTER$48 = { fromAttribute: (v) => v ?? void 0 };
5143
5592
  /**
5144
5593
  * `<xh-layout>` —— 页面骨架的 Light-DOM 行为宿主,跑 layout 机器并把 connect 产出打到
5145
5594
  * root/header/sider/content/footer/sider-trigger 角色节点。
@@ -5185,15 +5634,15 @@ var XhLayoutElement = class extends XhElement {
5185
5634
  },
5186
5635
  siderWidth: {
5187
5636
  attribute: "sider-width",
5188
- converter: STRING_CONVERTER$47
5637
+ converter: STRING_CONVERTER$48
5189
5638
  },
5190
5639
  siderCollapsedWidth: {
5191
5640
  attribute: "sider-collapsed-width",
5192
- converter: STRING_CONVERTER$47
5641
+ converter: STRING_CONVERTER$48
5193
5642
  },
5194
5643
  siderPlacement: {
5195
5644
  attribute: "sider-placement",
5196
- converter: STRING_CONVERTER$47
5645
+ converter: STRING_CONVERTER$48
5197
5646
  },
5198
5647
  headerFixed: {
5199
5648
  type: Boolean,
@@ -5242,7 +5691,7 @@ var XhLayoutElement = class extends XhElement {
5242
5691
  };
5243
5692
  //#endregion
5244
5693
  //#region src/elements/list.ts
5245
- const STRING_CONVERTER$46 = { fromAttribute: (v) => v ?? void 0 };
5694
+ const STRING_CONVERTER$47 = { fromAttribute: (v) => v ?? void 0 };
5246
5695
  /**
5247
5696
  * `<xh-list>` —— Light-DOM 行为宿主,无状态机,把 connectList 产出打到各角色节点。
5248
5697
  * 除 root 外的部件全部可缺省:空列表、只有一行标题的条目都是合法形态。
@@ -5272,7 +5721,7 @@ var XhListElement = class extends XhElement {
5272
5721
  bordered: { type: Boolean },
5273
5722
  hoverable: { type: Boolean },
5274
5723
  split: { type: Boolean },
5275
- size: { converter: STRING_CONVERTER$46 }
5724
+ size: { converter: STRING_CONVERTER$47 }
5276
5725
  };
5277
5726
  wire() {
5278
5727
  const api = connectList({
@@ -5296,8 +5745,8 @@ var XhListElement = class extends XhElement {
5296
5745
  };
5297
5746
  //#endregion
5298
5747
  //#region src/elements/listbox.ts
5299
- const STRING_CONVERTER$45 = { fromAttribute: (v) => v ?? void 0 };
5300
- const BOOLEAN_CONVERTER$30 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
5748
+ const STRING_CONVERTER$46 = { fromAttribute: (v) => v ?? void 0 };
5749
+ const BOOLEAN_CONVERTER$31 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
5301
5750
  /**
5302
5751
  * `<xh-listbox>` —— Light-DOM 行为宿主:作者写 root/label/content 与若干 item 角色节点,
5303
5752
  * 元素跑 listbox 机器并把 connect 产出打上去。条目身份取自条目节点上的 value 属性,
@@ -5339,24 +5788,24 @@ var XhListboxElement = class extends XhElement {
5339
5788
  };
5340
5789
  static properties = {
5341
5790
  collection: { attribute: false },
5342
- value: { converter: STRING_CONVERTER$45 },
5791
+ value: { converter: STRING_CONVERTER$46 },
5343
5792
  defaultValue: {
5344
- converter: STRING_CONVERTER$45,
5793
+ converter: STRING_CONVERTER$46,
5345
5794
  attribute: "default-value"
5346
5795
  },
5347
5796
  multiple: { type: Boolean },
5348
5797
  selectionMode: {
5349
- converter: STRING_CONVERTER$45,
5798
+ converter: STRING_CONVERTER$46,
5350
5799
  attribute: "selection-mode"
5351
5800
  },
5352
5801
  disabled: { type: Boolean },
5353
- loop: { converter: BOOLEAN_CONVERTER$30 },
5802
+ loop: { converter: BOOLEAN_CONVERTER$31 },
5354
5803
  direction: {
5355
- converter: STRING_CONVERTER$45,
5804
+ converter: STRING_CONVERTER$46,
5356
5805
  attribute: "dir"
5357
5806
  },
5358
- orientation: { converter: STRING_CONVERTER$45 },
5359
- typeahead: { converter: BOOLEAN_CONVERTER$30 }
5807
+ orientation: { converter: STRING_CONVERTER$46 },
5808
+ typeahead: { converter: BOOLEAN_CONVERTER$31 }
5360
5809
  };
5361
5810
  declaredDisabled = /* @__PURE__ */ new WeakMap();
5362
5811
  /** 上一帧是否整列禁用:解禁当帧 DOM 上还留着机器写回的 aria-disabled,读不得。 */
@@ -5454,9 +5903,9 @@ var XhListboxElement = class extends XhElement {
5454
5903
  };
5455
5904
  //#endregion
5456
5905
  //#region src/elements/loading-bar.ts
5457
- const STRING_CONVERTER$44 = { fromAttribute: (v) => v ?? void 0 };
5906
+ const STRING_CONVERTER$45 = { fromAttribute: (v) => v ?? void 0 };
5458
5907
  const NUMBER_CONVERTER$30 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
5459
- const BOOLEAN_CONVERTER$29 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
5908
+ const BOOLEAN_CONVERTER$30 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
5460
5909
  const HEIGHT_CONVERTER = { fromAttribute: (v) => {
5461
5910
  if (v == null || v === "") return void 0;
5462
5911
  const px = Number(v);
@@ -5500,11 +5949,11 @@ var XhLoadingBarElement = class extends XhElement {
5500
5949
  converter: NUMBER_CONVERTER$30,
5501
5950
  attribute: "default-value"
5502
5951
  },
5503
- loading: { converter: BOOLEAN_CONVERTER$29 },
5952
+ loading: { converter: BOOLEAN_CONVERTER$30 },
5504
5953
  height: { converter: HEIGHT_CONVERTER },
5505
- color: { converter: STRING_CONVERTER$44 },
5506
- tone: { converter: STRING_CONVERTER$44 },
5507
- trickle: { converter: BOOLEAN_CONVERTER$29 },
5954
+ color: { converter: STRING_CONVERTER$45 },
5955
+ tone: { converter: STRING_CONVERTER$45 },
5956
+ trickle: { converter: BOOLEAN_CONVERTER$30 },
5508
5957
  trickleSpeed: {
5509
5958
  converter: NUMBER_CONVERTER$30,
5510
5959
  attribute: "trickle-speed"
@@ -5640,7 +6089,7 @@ var XhLogElement = class extends XhElement {
5640
6089
  };
5641
6090
  //#endregion
5642
6091
  //#region src/elements/marquee.ts
5643
- const STRING_CONVERTER$43 = { fromAttribute: (v) => v ?? void 0 };
6092
+ const STRING_CONVERTER$44 = { fromAttribute: (v) => v ?? void 0 };
5644
6093
  const NUMBER_CONVERTER$28 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
5645
6094
  /**
5646
6095
  * `<xh-marquee>` —— Light-DOM 行为宿主,无状态机,把 connectMarquee 产出打到 root 与 content 上。
@@ -5668,7 +6117,7 @@ var XhMarqueeElement = class extends XhElement {
5668
6117
  meta: marqueeMeta
5669
6118
  };
5670
6119
  static properties = {
5671
- direction: { converter: STRING_CONVERTER$43 },
6120
+ direction: { converter: STRING_CONVERTER$44 },
5672
6121
  speed: { converter: NUMBER_CONVERTER$28 },
5673
6122
  pauseOnHover: {
5674
6123
  type: Boolean,
@@ -5696,9 +6145,9 @@ var XhMarqueeElement = class extends XhElement {
5696
6145
  };
5697
6146
  //#endregion
5698
6147
  //#region src/elements/mention.ts
5699
- const STRING_CONVERTER$42 = { fromAttribute: (v) => v ?? void 0 };
6148
+ const STRING_CONVERTER$43 = { fromAttribute: (v) => v ?? void 0 };
5700
6149
  const NUMBER_CONVERTER$27 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
5701
- const BOOLEAN_CONVERTER$28 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
6150
+ const BOOLEAN_CONVERTER$29 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
5702
6151
  /**
5703
6152
  * `<xh-mention>` —— Light-DOM 行为宿主:作者写 root/input/positioner/content/item 角色节点,
5704
6153
  * 元素跑 mention 机器并把 connect 产出打上去。浮层定位引擎在本元素里建好、经 refs 注入机器,
@@ -5747,22 +6196,22 @@ var XhMentionElement = class extends XhElement {
5747
6196
  collection: { attribute: false },
5748
6197
  translations: { attribute: false },
5749
6198
  triggerPrefix: {
5750
- converter: STRING_CONVERTER$42,
6199
+ converter: STRING_CONVERTER$43,
5751
6200
  attribute: "prefix"
5752
6201
  },
5753
- value: { converter: STRING_CONVERTER$42 },
6202
+ value: { converter: STRING_CONVERTER$43 },
5754
6203
  defaultValue: {
5755
- converter: STRING_CONVERTER$42,
6204
+ converter: STRING_CONVERTER$43,
5756
6205
  attribute: "default-value"
5757
6206
  },
5758
6207
  disabled: { type: Boolean },
5759
- placeholder: { converter: STRING_CONVERTER$42 },
5760
- loop: { converter: BOOLEAN_CONVERTER$28 },
5761
- placement: { converter: STRING_CONVERTER$42 },
6208
+ placeholder: { converter: STRING_CONVERTER$43 },
6209
+ loop: { converter: BOOLEAN_CONVERTER$29 },
6210
+ placement: { converter: STRING_CONVERTER$43 },
5762
6211
  offset: { converter: NUMBER_CONVERTER$27 },
5763
- variant: { converter: STRING_CONVERTER$42 },
5764
- tone: { converter: STRING_CONVERTER$42 },
5765
- size: { converter: STRING_CONVERTER$42 }
6212
+ variant: { converter: STRING_CONVERTER$43 },
6213
+ tone: { converter: STRING_CONVERTER$43 },
6214
+ size: { converter: STRING_CONVERTER$43 }
5766
6215
  };
5767
6216
  idGen = createCounterIdGenerator();
5768
6217
  mentionScope = createScope(null, this.idGen);
@@ -5890,9 +6339,9 @@ var XhMentionElement = class extends XhElement {
5890
6339
  };
5891
6340
  //#endregion
5892
6341
  //#region src/elements/menu.ts
5893
- const STRING_CONVERTER$41 = { fromAttribute: (v) => v ?? void 0 };
6342
+ const STRING_CONVERTER$42 = { fromAttribute: (v) => v ?? void 0 };
5894
6343
  const NUMBER_CONVERTER$26 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
5895
- const BOOLEAN_CONVERTER$27 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
6344
+ const BOOLEAN_CONVERTER$28 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
5896
6345
  /**
5897
6346
  * `<xh-menu>` —— Light-DOM 行为宿主:用户写 trigger/positioner/content/item/... 角色节点,
5898
6347
  * 元素跑 menu 机器并把 connect 产出打上去。浮层定位引擎在本元素里建好、经 refs 注入机器,
@@ -5924,20 +6373,33 @@ var XhMenuElement = class extends XhElement {
5924
6373
  };
5925
6374
  static properties = {
5926
6375
  collection: { attribute: false },
5927
- open: { converter: BOOLEAN_CONVERTER$27 },
6376
+ open: { converter: BOOLEAN_CONVERTER$28 },
5928
6377
  defaultOpen: {
5929
6378
  type: Boolean,
5930
6379
  attribute: "default-open"
5931
6380
  },
5932
- placement: { converter: STRING_CONVERTER$41 },
6381
+ placement: { converter: STRING_CONVERTER$42 },
5933
6382
  offset: { converter: NUMBER_CONVERTER$26 },
5934
- loop: { converter: BOOLEAN_CONVERTER$27 },
6383
+ loop: { converter: BOOLEAN_CONVERTER$28 },
5935
6384
  direction: {
5936
- converter: STRING_CONVERTER$41,
6385
+ converter: STRING_CONVERTER$42,
5937
6386
  attribute: "dir"
5938
6387
  },
5939
- tone: { converter: STRING_CONVERTER$41 },
5940
- size: { converter: STRING_CONVERTER$41 }
6388
+ tone: { converter: STRING_CONVERTER$42 },
6389
+ size: { converter: STRING_CONVERTER$42 },
6390
+ submenu: { converter: BOOLEAN_CONVERTER$28 },
6391
+ openOnHover: {
6392
+ converter: BOOLEAN_CONVERTER$28,
6393
+ attribute: "open-on-hover"
6394
+ },
6395
+ hoverOpenDelay: {
6396
+ converter: NUMBER_CONVERTER$26,
6397
+ attribute: "hover-open-delay"
6398
+ },
6399
+ hoverCloseDelay: {
6400
+ converter: NUMBER_CONVERTER$26,
6401
+ attribute: "hover-close-delay"
6402
+ }
5941
6403
  };
5942
6404
  idGen = createCounterIdGenerator();
5943
6405
  menuScope = createScope(null, this.idGen);
@@ -5974,6 +6436,10 @@ var XhMenuElement = class extends XhElement {
5974
6436
  dir: this.direction,
5975
6437
  tone: this.tone,
5976
6438
  size: this.size,
6439
+ submenu: this.submenu,
6440
+ openOnHover: this.openOnHover,
6441
+ hoverOpenDelay: this.hoverOpenDelay,
6442
+ hoverCloseDelay: this.hoverCloseDelay,
5977
6443
  onOpenChange: this.notifyOpen,
5978
6444
  onSelect: this.notifySelect
5979
6445
  };
@@ -6033,7 +6499,9 @@ var XhMenuElement = class extends XhElement {
6033
6499
  const el = this.getPart(name);
6034
6500
  if (el) this.spreader.spread(el, props);
6035
6501
  };
6036
- put("trigger", api.getTriggerProps());
6502
+ const triggerEl = this.getPart("trigger");
6503
+ if (this.submenu && triggerEl) this.spreader.spread(triggerEl, api.getSubmenuTriggerProps({ value: triggerEl.getAttribute("value") ?? "" }));
6504
+ else put("trigger", api.getTriggerProps());
6037
6505
  put("positioner", api.getPositionerProps());
6038
6506
  put("content", api.getContentProps());
6039
6507
  put("arrow", api.getArrowProps());
@@ -6055,9 +6523,9 @@ var XhMenuElement = class extends XhElement {
6055
6523
  };
6056
6524
  //#endregion
6057
6525
  //#region src/elements/menubar.ts
6058
- const STRING_CONVERTER$40 = { fromAttribute: (v) => v ?? void 0 };
6526
+ const STRING_CONVERTER$41 = { fromAttribute: (v) => v ?? void 0 };
6059
6527
  const NUMBER_CONVERTER$25 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
6060
- const BOOLEAN_CONVERTER$26 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
6528
+ const BOOLEAN_CONVERTER$27 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
6061
6529
  /** 读角色节点的禁用声明,并摘掉作者写的原生 disabled,禁用态归一到 aria-disabled。 */
6062
6530
  function authorDisabled$1(el) {
6063
6531
  const disabled = isItemDisabled(el);
@@ -6107,23 +6575,23 @@ var XhMenubarElement = class extends XhElement {
6107
6575
  };
6108
6576
  static properties = {
6109
6577
  collection: { attribute: false },
6110
- value: { converter: STRING_CONVERTER$40 },
6578
+ value: { converter: STRING_CONVERTER$41 },
6111
6579
  defaultValue: {
6112
- converter: STRING_CONVERTER$40,
6580
+ converter: STRING_CONVERTER$41,
6113
6581
  attribute: "default-value"
6114
6582
  },
6115
- orientation: { converter: STRING_CONVERTER$40 },
6116
- loop: { converter: BOOLEAN_CONVERTER$26 },
6583
+ orientation: { converter: STRING_CONVERTER$41 },
6584
+ loop: { converter: BOOLEAN_CONVERTER$27 },
6117
6585
  direction: {
6118
- converter: STRING_CONVERTER$40,
6586
+ converter: STRING_CONVERTER$41,
6119
6587
  attribute: "dir"
6120
6588
  },
6121
- disabled: { converter: BOOLEAN_CONVERTER$26 },
6122
- typeahead: { converter: BOOLEAN_CONVERTER$26 },
6123
- placement: { converter: STRING_CONVERTER$40 },
6589
+ disabled: { converter: BOOLEAN_CONVERTER$27 },
6590
+ typeahead: { converter: BOOLEAN_CONVERTER$27 },
6591
+ placement: { converter: STRING_CONVERTER$41 },
6124
6592
  offset: { converter: NUMBER_CONVERTER$25 },
6125
- tone: { converter: STRING_CONVERTER$40 },
6126
- size: { converter: STRING_CONVERTER$40 }
6593
+ tone: { converter: STRING_CONVERTER$41 },
6594
+ size: { converter: STRING_CONVERTER$41 }
6127
6595
  };
6128
6596
  idGen = createCounterIdGenerator();
6129
6597
  barScope = createScope(null, this.idGen);
@@ -6257,9 +6725,9 @@ var XhMenubarElement = class extends XhElement {
6257
6725
  };
6258
6726
  //#endregion
6259
6727
  //#region src/elements/navigation-menu.ts
6260
- const STRING_CONVERTER$39 = { fromAttribute: (v) => v ?? void 0 };
6728
+ const STRING_CONVERTER$40 = { fromAttribute: (v) => v ?? void 0 };
6261
6729
  const NUMBER_CONVERTER$24 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
6262
- const BOOLEAN_CONVERTER$25 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
6730
+ const BOOLEAN_CONVERTER$26 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
6263
6731
  /**
6264
6732
  * 作者写在角色节点上的布尔声明,三态读法:属性缺席 = false,="false" = false,其余 = true。
6265
6733
  */
@@ -6319,12 +6787,12 @@ var XhNavigationMenuElement = class extends XhElement {
6319
6787
  };
6320
6788
  static properties = {
6321
6789
  collection: { attribute: false },
6322
- value: { converter: STRING_CONVERTER$39 },
6790
+ value: { converter: STRING_CONVERTER$40 },
6323
6791
  defaultValue: {
6324
- converter: STRING_CONVERTER$39,
6792
+ converter: STRING_CONVERTER$40,
6325
6793
  attribute: "default-value"
6326
6794
  },
6327
- orientation: { converter: STRING_CONVERTER$39 },
6795
+ orientation: { converter: STRING_CONVERTER$40 },
6328
6796
  delayDuration: {
6329
6797
  converter: NUMBER_CONVERTER$24,
6330
6798
  attribute: "delay-duration"
@@ -6334,12 +6802,12 @@ var XhNavigationMenuElement = class extends XhElement {
6334
6802
  attribute: "skip-delay-duration"
6335
6803
  },
6336
6804
  direction: {
6337
- converter: STRING_CONVERTER$39,
6805
+ converter: STRING_CONVERTER$40,
6338
6806
  attribute: "dir"
6339
6807
  },
6340
- loop: { converter: BOOLEAN_CONVERTER$25 },
6341
- tone: { converter: STRING_CONVERTER$39 },
6342
- size: { converter: STRING_CONVERTER$39 },
6808
+ loop: { converter: BOOLEAN_CONVERTER$26 },
6809
+ tone: { converter: STRING_CONVERTER$40 },
6810
+ size: { converter: STRING_CONVERTER$40 },
6343
6811
  translations: { attribute: false }
6344
6812
  };
6345
6813
  idGen = createCounterIdGenerator();
@@ -6412,9 +6880,9 @@ var XhNavigationMenuElement = class extends XhElement {
6412
6880
  };
6413
6881
  //#endregion
6414
6882
  //#region src/elements/number-animation.ts
6415
- const STRING_CONVERTER$38 = { fromAttribute: (v) => v ?? void 0 };
6883
+ const STRING_CONVERTER$39 = { fromAttribute: (v) => v ?? void 0 };
6416
6884
  const NUMBER_CONVERTER$23 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
6417
- const BOOLEAN_CONVERTER$24 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
6885
+ const BOOLEAN_CONVERTER$25 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
6418
6886
  /**
6419
6887
  * `<xh-number-animation>` —— Light-DOM 行为宿主:作者写一个 root 角色节点,
6420
6888
  * 元素跑 number-animation 机器,逐帧把补间算出的数字格式化后写进那个节点。
@@ -6449,13 +6917,13 @@ var XhNumberAnimationElement = class extends XhElement {
6449
6917
  from: { converter: NUMBER_CONVERTER$23 },
6450
6918
  to: { converter: NUMBER_CONVERTER$23 },
6451
6919
  duration: { converter: NUMBER_CONVERTER$23 },
6452
- easing: { converter: STRING_CONVERTER$38 },
6920
+ easing: { converter: STRING_CONVERTER$39 },
6453
6921
  precision: { converter: NUMBER_CONVERTER$23 },
6454
- separator: { converter: STRING_CONVERTER$38 },
6455
- active: { converter: BOOLEAN_CONVERTER$24 },
6456
- size: { converter: STRING_CONVERTER$38 },
6457
- tone: { converter: STRING_CONVERTER$38 },
6458
- live: { converter: STRING_CONVERTER$38 }
6922
+ separator: { converter: STRING_CONVERTER$39 },
6923
+ active: { converter: BOOLEAN_CONVERTER$25 },
6924
+ size: { converter: STRING_CONVERTER$39 },
6925
+ tone: { converter: STRING_CONVERTER$39 },
6926
+ live: { converter: STRING_CONVERTER$39 }
6459
6927
  };
6460
6928
  notify = (details) => {
6461
6929
  this.dispatchEvent(new CustomEvent("finish", {
@@ -6490,7 +6958,7 @@ var XhNumberAnimationElement = class extends XhElement {
6490
6958
  };
6491
6959
  //#endregion
6492
6960
  //#region src/elements/number-field.ts
6493
- const STRING_CONVERTER$37 = { fromAttribute: (v) => v ?? void 0 };
6961
+ const STRING_CONVERTER$38 = { fromAttribute: (v) => v ?? void 0 };
6494
6962
  const NUMBER_CONVERTER$22 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
6495
6963
  /**
6496
6964
  * `<xh-number-field>` —— Light-DOM 行为宿主:作者写 root/label/input/加减按钮四类角色节点,
@@ -6529,9 +6997,9 @@ var XhNumberFieldElement = class extends XhElement {
6529
6997
  meta: numberFieldMeta
6530
6998
  };
6531
6999
  static properties = {
6532
- value: { converter: STRING_CONVERTER$37 },
7000
+ value: { converter: STRING_CONVERTER$38 },
6533
7001
  defaultValue: {
6534
- converter: STRING_CONVERTER$37,
7002
+ converter: STRING_CONVERTER$38,
6535
7003
  attribute: "default-value"
6536
7004
  },
6537
7005
  min: { converter: NUMBER_CONVERTER$22 },
@@ -6548,7 +7016,7 @@ var XhNumberFieldElement = class extends XhElement {
6548
7016
  },
6549
7017
  required: { type: Boolean },
6550
7018
  invalid: { type: Boolean },
6551
- name: { converter: STRING_CONVERTER$37 },
7019
+ name: { converter: STRING_CONVERTER$38 },
6552
7020
  changeDelay: {
6553
7021
  converter: NUMBER_CONVERTER$22,
6554
7022
  attribute: "change-delay"
@@ -6557,9 +7025,9 @@ var XhNumberFieldElement = class extends XhElement {
6557
7025
  converter: NUMBER_CONVERTER$22,
6558
7026
  attribute: "change-interval"
6559
7027
  },
6560
- variant: { converter: STRING_CONVERTER$37 },
6561
- tone: { converter: STRING_CONVERTER$37 },
6562
- size: { converter: STRING_CONVERTER$37 }
7028
+ variant: { converter: STRING_CONVERTER$38 },
7029
+ tone: { converter: STRING_CONVERTER$38 },
7030
+ size: { converter: STRING_CONVERTER$38 }
6563
7031
  };
6564
7032
  notify = (details) => {
6565
7033
  this.dispatchEvent(new CustomEvent("value-change", {
@@ -6605,7 +7073,7 @@ var XhNumberFieldElement = class extends XhElement {
6605
7073
  };
6606
7074
  //#endregion
6607
7075
  //#region src/elements/page-header.ts
6608
- const STRING_CONVERTER$36 = { fromAttribute: (v) => v ?? void 0 };
7076
+ const STRING_CONVERTER$37 = { fromAttribute: (v) => v ?? void 0 };
6609
7077
  /**
6610
7078
  * `<xh-page-header>` —— Light-DOM 行为宿主,无状态机,把 connectPageHeader 产出打到各角色节点。
6611
7079
  * 除 root 外的部件全部可缺省:返回位、标题、副标题、操作、页脚按需摆。
@@ -6629,7 +7097,7 @@ var XhPageHeaderElement = class extends XhElement {
6629
7097
  meta: pageHeaderMeta
6630
7098
  };
6631
7099
  static properties = {
6632
- size: { converter: STRING_CONVERTER$36 },
7100
+ size: { converter: STRING_CONVERTER$37 },
6633
7101
  bordered: { type: Boolean }
6634
7102
  };
6635
7103
  wire() {
@@ -6652,7 +7120,7 @@ var XhPageHeaderElement = class extends XhElement {
6652
7120
  //#endregion
6653
7121
  //#region src/elements/pagination.ts
6654
7122
  const NUMBER_CONVERTER$21 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
6655
- const STRING_CONVERTER$35 = { fromAttribute: (v) => v ?? void 0 };
7123
+ const STRING_CONVERTER$36 = { fromAttribute: (v) => v ?? void 0 };
6656
7124
  /** 页码按钮自报的页数;缺失或空串一律给 NaN(见 wire 里的说明)。 */
6657
7125
  function itemPage(el) {
6658
7126
  const raw = el.getAttribute("value");
@@ -6705,11 +7173,11 @@ var XhPaginationElement = class extends XhElement {
6705
7173
  attribute: "sibling-count"
6706
7174
  },
6707
7175
  direction: {
6708
- converter: STRING_CONVERTER$35,
7176
+ converter: STRING_CONVERTER$36,
6709
7177
  attribute: "dir"
6710
7178
  },
6711
- tone: { converter: STRING_CONVERTER$35 },
6712
- size: { converter: STRING_CONVERTER$35 },
7179
+ tone: { converter: STRING_CONVERTER$36 },
7180
+ size: { converter: STRING_CONVERTER$36 },
6713
7181
  translations: { attribute: false }
6714
7182
  };
6715
7183
  notify = (details) => {
@@ -6752,7 +7220,7 @@ var XhPaginationElement = class extends XhElement {
6752
7220
  };
6753
7221
  //#endregion
6754
7222
  //#region src/elements/pin-input.ts
6755
- const STRING_CONVERTER$34 = { fromAttribute: (v) => v ?? void 0 };
7223
+ const STRING_CONVERTER$35 = { fromAttribute: (v) => v ?? void 0 };
6756
7224
  const NUMBER_CONVERTER$20 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
6757
7225
  const ARRAY_CONVERTER$1 = { fromAttribute: (v) => v == null ? void 0 : [...v] };
6758
7226
  /** 作者写在格子上的下标。缺席或写坏了就退回文档序——手写 HTML 时把格子按顺序排下来本身就是声明。 */
@@ -6804,20 +7272,20 @@ var XhPinInputElement = class extends XhElement {
6804
7272
  attribute: "default-value"
6805
7273
  },
6806
7274
  length: { converter: NUMBER_CONVERTER$20 },
6807
- type: { converter: STRING_CONVERTER$34 },
7275
+ type: { converter: STRING_CONVERTER$35 },
6808
7276
  mask: { type: Boolean },
6809
7277
  otp: { type: Boolean },
6810
- placeholder: { converter: STRING_CONVERTER$34 },
7278
+ placeholder: { converter: STRING_CONVERTER$35 },
6811
7279
  disabled: { type: Boolean },
6812
7280
  invalid: { type: Boolean },
6813
7281
  blurOnComplete: {
6814
7282
  type: Boolean,
6815
7283
  attribute: "blur-on-complete"
6816
7284
  },
6817
- name: { converter: STRING_CONVERTER$34 },
6818
- variant: { converter: STRING_CONVERTER$34 },
6819
- tone: { converter: STRING_CONVERTER$34 },
6820
- size: { converter: STRING_CONVERTER$34 },
7285
+ name: { converter: STRING_CONVERTER$35 },
7286
+ variant: { converter: STRING_CONVERTER$35 },
7287
+ tone: { converter: STRING_CONVERTER$35 },
7288
+ size: { converter: STRING_CONVERTER$35 },
6821
7289
  translations: { attribute: false }
6822
7290
  };
6823
7291
  notifyChange = (details) => {
@@ -6873,9 +7341,9 @@ var XhPinInputElement = class extends XhElement {
6873
7341
  };
6874
7342
  //#endregion
6875
7343
  //#region src/elements/popconfirm.ts
6876
- const STRING_CONVERTER$33 = { fromAttribute: (v) => v ?? void 0 };
7344
+ const STRING_CONVERTER$34 = { fromAttribute: (v) => v ?? void 0 };
6877
7345
  const NUMBER_CONVERTER$19 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
6878
- const BOOLEAN_CONVERTER$23 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
7346
+ const BOOLEAN_CONVERTER$24 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
6879
7347
  /**
6880
7348
  * `<xh-popconfirm>` —— Light-DOM 行为宿主:用户写 root/trigger/positioner/content/... 角色节点,
6881
7349
  * 元素跑 popover 机器(开合、定位、消解层、焦点域都在那里)并把 connectPopconfirm 产出打上去。
@@ -6893,7 +7361,9 @@ const BOOLEAN_CONVERTER$23 = { fromAttribute: (v) => v === null ? void 0 : v !==
6893
7361
  * @attr {boolean} close-on-interact-outside - 层外交互关闭,默认 true;写 "false" 关掉
6894
7362
  * @attr {'sm'|'md'|'lg'} size - 尺寸
6895
7363
  * @fires open-change - open 状态变化;detail 为 `{ open: boolean }`
6896
- * @fires confirm - 点了确认按钮;随后浮层收起
7364
+ * @fires confirm - 点了确认按钮;随后浮层收起。异步门走 confirmAction 属性:
7365
+ * 事件拿不到监听函数的返回值,给元素赋 `confirmAction = () => Promise` 即挂起确认门
7366
+ * (浮层等兑现才收、确认按钮转圈,落空留在原地),confirm 事件照发只作通知
6897
7367
  * @fires cancel - 点了取消按钮;随后浮层收起
6898
7368
  * @csspart root - 框住触发器的根容器,承载 data-state
6899
7369
  * @csspart trigger - 触发按钮(aria-haspopup/aria-expanded/aria-controls 所在),同时是定位锚点
@@ -6910,22 +7380,22 @@ var XhPopconfirmElement = class extends XhElement {
6910
7380
  meta: popconfirmMeta
6911
7381
  };
6912
7382
  static properties = {
6913
- open: { converter: BOOLEAN_CONVERTER$23 },
7383
+ open: { converter: BOOLEAN_CONVERTER$24 },
6914
7384
  defaultOpen: {
6915
7385
  type: Boolean,
6916
7386
  attribute: "default-open"
6917
7387
  },
6918
- placement: { converter: STRING_CONVERTER$33 },
7388
+ placement: { converter: STRING_CONVERTER$34 },
6919
7389
  offset: { converter: NUMBER_CONVERTER$19 },
6920
7390
  closeOnEscape: {
6921
- converter: BOOLEAN_CONVERTER$23,
7391
+ converter: BOOLEAN_CONVERTER$24,
6922
7392
  attribute: "close-on-escape"
6923
7393
  },
6924
7394
  closeOnInteractOutside: {
6925
- converter: BOOLEAN_CONVERTER$23,
7395
+ converter: BOOLEAN_CONVERTER$24,
6926
7396
  attribute: "close-on-interact-outside"
6927
7397
  },
6928
- size: { converter: STRING_CONVERTER$33 }
7398
+ size: { converter: STRING_CONVERTER$34 }
6929
7399
  };
6930
7400
  idGen = createCounterIdGenerator();
6931
7401
  popconfirmScope = createScope(null, this.idGen);
@@ -6938,18 +7408,25 @@ var XhPopconfirmElement = class extends XhElement {
6938
7408
  composed: true
6939
7409
  }));
6940
7410
  };
7411
+ /** 异步确认的挂起布尔;变化时重打属性。 */
7412
+ pendingState = false;
6941
7413
  intents = {
6942
7414
  onConfirm: () => {
6943
7415
  this.dispatchEvent(new CustomEvent("confirm", {
6944
7416
  bubbles: true,
6945
7417
  composed: true
6946
7418
  }));
7419
+ return this.confirmAction?.();
6947
7420
  },
6948
7421
  onCancel: () => {
6949
7422
  this.dispatchEvent(new CustomEvent("cancel", {
6950
7423
  bubbles: true,
6951
7424
  composed: true
6952
7425
  }));
7426
+ },
7427
+ onPendingChange: (next) => {
7428
+ this.pendingState = next;
7429
+ this.requestUpdate();
6953
7430
  }
6954
7431
  };
6955
7432
  ctrl = new MachineController(this, popoverMachine, () => this.machineProps(), {
@@ -7005,7 +7482,10 @@ var XhPopconfirmElement = class extends XhElement {
7005
7482
  super.connectedCallback();
7006
7483
  }
7007
7484
  wire() {
7008
- const api = connectPopconfirm(this.ctrl.service, this.intents, wcNormalize);
7485
+ const api = connectPopconfirm(this.ctrl.service, {
7486
+ ...this.intents,
7487
+ pending: this.pendingState
7488
+ }, wcNormalize);
7009
7489
  const put = (name, props) => {
7010
7490
  const el = this.getPart(name);
7011
7491
  if (el) this.spreader.spread(el, props);
@@ -7028,9 +7508,9 @@ var XhPopconfirmElement = class extends XhElement {
7028
7508
  };
7029
7509
  //#endregion
7030
7510
  //#region src/elements/popover.ts
7031
- const STRING_CONVERTER$32 = { fromAttribute: (v) => v ?? void 0 };
7511
+ const STRING_CONVERTER$33 = { fromAttribute: (v) => v ?? void 0 };
7032
7512
  const NUMBER_CONVERTER$18 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
7033
- const BOOLEAN_CONVERTER$22 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
7513
+ const BOOLEAN_CONVERTER$23 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
7034
7514
  /**
7035
7515
  * `<xh-popover>` —— Light-DOM 行为宿主:用户写 trigger/positioner/content/... 角色节点,
7036
7516
  * 元素跑 popover 机器并把 connect 产出打上去。浮层定位引擎在本元素里建好、经 refs 注入机器,
@@ -7060,23 +7540,23 @@ var XhPopoverElement = class extends XhElement {
7060
7540
  meta: popoverMeta
7061
7541
  };
7062
7542
  static properties = {
7063
- open: { converter: BOOLEAN_CONVERTER$22 },
7543
+ open: { converter: BOOLEAN_CONVERTER$23 },
7064
7544
  defaultOpen: {
7065
7545
  type: Boolean,
7066
7546
  attribute: "default-open"
7067
7547
  },
7068
- placement: { converter: STRING_CONVERTER$32 },
7548
+ placement: { converter: STRING_CONVERTER$33 },
7069
7549
  offset: { converter: NUMBER_CONVERTER$18 },
7070
- modal: { converter: BOOLEAN_CONVERTER$22 },
7550
+ modal: { converter: BOOLEAN_CONVERTER$23 },
7071
7551
  closeOnEscape: {
7072
- converter: BOOLEAN_CONVERTER$22,
7552
+ converter: BOOLEAN_CONVERTER$23,
7073
7553
  attribute: "close-on-escape"
7074
7554
  },
7075
7555
  closeOnInteractOutside: {
7076
- converter: BOOLEAN_CONVERTER$22,
7556
+ converter: BOOLEAN_CONVERTER$23,
7077
7557
  attribute: "close-on-interact-outside"
7078
7558
  },
7079
- size: { converter: STRING_CONVERTER$32 },
7559
+ size: { converter: STRING_CONVERTER$33 },
7080
7560
  translations: { attribute: false }
7081
7561
  };
7082
7562
  idGen = createCounterIdGenerator();
@@ -7168,9 +7648,9 @@ var XhPopoverElement = class extends XhElement {
7168
7648
  };
7169
7649
  //#endregion
7170
7650
  //#region src/elements/popselect.ts
7171
- const STRING_CONVERTER$31 = { fromAttribute: (v) => v ?? void 0 };
7651
+ const STRING_CONVERTER$32 = { fromAttribute: (v) => v ?? void 0 };
7172
7652
  const NUMBER_CONVERTER$17 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
7173
- const BOOLEAN_CONVERTER$21 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
7653
+ const BOOLEAN_CONVERTER$22 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
7174
7654
  /**
7175
7655
  * `<xh-popselect>` —— Light-DOM 行为宿主:作者写 root/trigger/positioner/content/item 角色节点,
7176
7656
  * 元素同时跑两台机器——浮层开合、定位、消解层与焦点域归 popover,选中集合与焦点锚点归 listbox——
@@ -7217,37 +7697,37 @@ var XhPopselectElement = class extends XhElement {
7217
7697
  };
7218
7698
  static properties = {
7219
7699
  collection: { attribute: false },
7220
- value: { converter: STRING_CONVERTER$31 },
7700
+ value: { converter: STRING_CONVERTER$32 },
7221
7701
  defaultValue: {
7222
- converter: STRING_CONVERTER$31,
7702
+ converter: STRING_CONVERTER$32,
7223
7703
  attribute: "default-value"
7224
7704
  },
7225
7705
  multiple: { type: Boolean },
7226
7706
  disabled: { type: Boolean },
7227
- loop: { converter: BOOLEAN_CONVERTER$21 },
7228
- typeahead: { converter: BOOLEAN_CONVERTER$21 },
7707
+ loop: { converter: BOOLEAN_CONVERTER$22 },
7708
+ typeahead: { converter: BOOLEAN_CONVERTER$22 },
7229
7709
  direction: {
7230
- converter: STRING_CONVERTER$31,
7710
+ converter: STRING_CONVERTER$32,
7231
7711
  attribute: "dir"
7232
7712
  },
7233
- open: { converter: BOOLEAN_CONVERTER$21 },
7713
+ open: { converter: BOOLEAN_CONVERTER$22 },
7234
7714
  defaultOpen: {
7235
7715
  type: Boolean,
7236
7716
  attribute: "default-open"
7237
7717
  },
7238
- placement: { converter: STRING_CONVERTER$31 },
7718
+ placement: { converter: STRING_CONVERTER$32 },
7239
7719
  offset: { converter: NUMBER_CONVERTER$17 },
7240
7720
  closeOnEscape: {
7241
- converter: BOOLEAN_CONVERTER$21,
7721
+ converter: BOOLEAN_CONVERTER$22,
7242
7722
  attribute: "close-on-escape"
7243
7723
  },
7244
7724
  closeOnInteractOutside: {
7245
- converter: BOOLEAN_CONVERTER$21,
7725
+ converter: BOOLEAN_CONVERTER$22,
7246
7726
  attribute: "close-on-interact-outside"
7247
7727
  },
7248
- variant: { converter: STRING_CONVERTER$31 },
7249
- tone: { converter: STRING_CONVERTER$31 },
7250
- size: { converter: STRING_CONVERTER$31 }
7728
+ variant: { converter: STRING_CONVERTER$32 },
7729
+ tone: { converter: STRING_CONVERTER$32 },
7730
+ size: { converter: STRING_CONVERTER$32 }
7251
7731
  };
7252
7732
  idGen = createCounterIdGenerator();
7253
7733
  popselectScope = createScope(null, this.idGen);
@@ -7325,6 +7805,7 @@ var XhPopselectElement = class extends XhElement {
7325
7805
  svc.refs.set("getAnchorEl", () => this.getPart("trigger"));
7326
7806
  svc.refs.set("getFloatingEl", () => this.getPart("positioner"));
7327
7807
  svc.refs.set("getContentEl", () => this.getPart("content"));
7808
+ svc.refs.set("getInitialFocusEl", () => popselectInitialFocus(this.listboxCtrl.service, this.getPart("content")));
7328
7809
  }
7329
7810
  /**
7330
7811
  * 角色节点提前发现一次:default-open 时 popover 机器在 hostConnected 当场进入 open,
@@ -7392,16 +7873,35 @@ var XhPopselectElement = class extends XhElement {
7392
7873
  //#endregion
7393
7874
  //#region src/elements/progress.ts
7394
7875
  /**
7395
- * `<xh-progress>` —— Light-DOM 行为宿主,无状态机,把 connectProgress 产出打到 root/track/range 角色节点。
7876
+ * `<xh-progress>` —— Light-DOM 行为宿主,无状态机,把 connectProgress 产出打到各角色节点。
7877
+ *
7878
+ * 线形写三层 div(root > track > range);环形要把 track 与 range 写成 `<circle>`、
7879
+ * 外面套一层 `<svg>` 当 canvas,环心的文字放进 label:
7880
+ *
7881
+ * ```html
7882
+ * <xh-progress variant="circle" value="60">
7883
+ * <div data-part="root">
7884
+ * <svg data-part="canvas"><circle data-part="track" /><circle data-part="range" /></svg>
7885
+ * <div data-part="label">60%</div>
7886
+ * </div>
7887
+ * </xh-progress>
7888
+ * ```
7396
7889
  *
7397
7890
  * @customElement xh-progress
7398
7891
  * @attr {number} value - 当前进度值,越界会被夹到 [0, max],默认 0
7399
7892
  * @attr {number} max - 满值上限,默认 100
7893
+ * @attr {'line'|'circle'|'dashboard'} variant - 形态,默认 line
7894
+ * @attr {number} stroke-width - 环的线宽(viewBox 单位),默认 6;只对 circle / dashboard 生效
7895
+ * @attr {number} gap-degree - 缺口角度,默认 75;只对 dashboard 生效
7896
+ * @attr {'top'|'right'|'bottom'|'left'} gap-position - 缺口朝向,默认 bottom;只对 dashboard 生效
7897
+ * @attr {string} value-text - 读屏播报的文字,覆盖默认的数值播报
7400
7898
  * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气
7401
- * @attr {'sm'|'md'|'lg'} size - 尺寸
7899
+ * @attr {'sm'|'md'|'lg'} size - 尺寸:线形改厚度,环形改直径
7402
7900
  * @csspart root - role=progressbar 的容器(承载 aria-valuenow/aria-valuemax/data-state)
7403
- * @csspart track - 进度轨道(满长背景)
7404
- * @csspart range - 已完成区段,长度按百分比写成内联 inline-size
7901
+ * @csspart canvas - 承载环的 svg(线形不用)
7902
+ * @csspart track - 进度轨道:线形是满长背景,环形是整段弧
7903
+ * @csspart range - 已完成区段:线形写内联 inline-size,环形写 stroke-dashoffset
7904
+ * @csspart label - 环心那一块,写什么由使用者决定(线形不用)
7405
7905
  */
7406
7906
  var XhProgressElement = class extends XhElement {
7407
7907
  static partContract = {
@@ -7411,6 +7911,17 @@ var XhProgressElement = class extends XhElement {
7411
7911
  static properties = {
7412
7912
  value: { type: Number },
7413
7913
  max: { type: Number },
7914
+ variant: {},
7915
+ strokeWidth: {
7916
+ type: Number,
7917
+ attribute: "stroke-width"
7918
+ },
7919
+ gapDegree: {
7920
+ type: Number,
7921
+ attribute: "gap-degree"
7922
+ },
7923
+ gapPosition: { attribute: "gap-position" },
7924
+ valueText: { attribute: "value-text" },
7414
7925
  tone: {},
7415
7926
  size: {}
7416
7927
  };
@@ -7418,23 +7929,28 @@ var XhProgressElement = class extends XhElement {
7418
7929
  const api = connectProgress({
7419
7930
  value: this.value,
7420
7931
  max: this.max,
7932
+ variant: this.variant,
7933
+ strokeWidth: this.strokeWidth,
7934
+ gapDegree: this.gapDegree,
7935
+ gapPosition: this.gapPosition,
7936
+ valueText: this.valueText,
7421
7937
  tone: this.tone,
7422
7938
  size: this.size
7423
7939
  }, wcNormalize);
7424
- const root = this.getPart("root");
7425
- if (root) this.spreader.spread(root, api.getRootProps());
7426
- const track = this.getPart("track");
7427
- if (track) this.spreader.spread(track, api.getTrackProps());
7428
- const range = this.getPart("range");
7429
- if (!range) return;
7430
- const { style, ...attrs } = api.getRangeProps();
7431
- this.spreader.spread(range, attrs);
7432
- range.style.inlineSize = style?.inlineSize ?? "";
7940
+ const put = (name, props) => {
7941
+ const el = this.getPart(name);
7942
+ if (el) this.spreader.spread(el, props);
7943
+ };
7944
+ put("root", api.getRootProps());
7945
+ put("canvas", api.getCanvasProps());
7946
+ put("track", api.getTrackProps());
7947
+ put("range", api.getRangeProps());
7948
+ put("label", api.getLabelProps());
7433
7949
  }
7434
7950
  };
7435
7951
  //#endregion
7436
7952
  //#region src/elements/qr-code.ts
7437
- const STRING_CONVERTER$30 = { fromAttribute: (v) => v ?? void 0 };
7953
+ const STRING_CONVERTER$31 = { fromAttribute: (v) => v ?? void 0 };
7438
7954
  const SVG_NS = "http://www.w3.org/2000/svg";
7439
7955
  /** 本元素生成的几何节点的标记:作者写的节点不带它,重画时只清掉自己生成的那几个。 */
7440
7956
  const GEOM_ATTR = "data-xh-geom";
@@ -7461,7 +7977,7 @@ function makeGeom(doc, tag, name) {
7461
7977
  * @customElement xh-qr-code
7462
7978
  * @attr {string} value - 要编码的内容,按 UTF-8 取字节走字节模式
7463
7979
  * @attr {'L'|'M'|'Q'|'H'} level - 纠错级别,缺省 M
7464
- * @attr {number} size - 像素边长,缺省 160
7980
+ * @attr {number} pixel-size - 像素边长,缺省 160
7465
7981
  * @attr {number} margin - 静区宽度(模块数),缺省 4
7466
7982
  * @attr {string} label - 可及名字,缺省用 value
7467
7983
  * @attr {'square'|'dot'|'rounded'} module-shape - 码点形状,缺省 square
@@ -7479,17 +7995,20 @@ var XhQrCodeElement = class extends XhElement {
7479
7995
  }
7480
7996
  };
7481
7997
  static properties = {
7482
- value: { converter: STRING_CONVERTER$30 },
7483
- level: { converter: STRING_CONVERTER$30 },
7484
- label: { converter: STRING_CONVERTER$30 },
7485
- size: { type: Number },
7998
+ value: { converter: STRING_CONVERTER$31 },
7999
+ level: { converter: STRING_CONVERTER$31 },
8000
+ label: { converter: STRING_CONVERTER$31 },
8001
+ pixelSize: {
8002
+ type: Number,
8003
+ attribute: "pixel-size"
8004
+ },
7486
8005
  margin: { type: Number },
7487
8006
  moduleShape: {
7488
- converter: STRING_CONVERTER$30,
8007
+ converter: STRING_CONVERTER$31,
7489
8008
  attribute: "module-shape"
7490
8009
  },
7491
8010
  eyeShape: {
7492
- converter: STRING_CONVERTER$30,
8011
+ converter: STRING_CONVERTER$31,
7493
8012
  attribute: "eye-shape"
7494
8013
  }
7495
8014
  };
@@ -7502,7 +8021,7 @@ var XhQrCodeElement = class extends XhElement {
7502
8021
  const api = connectQrCode({
7503
8022
  value: this.value,
7504
8023
  level: this.level,
7505
- size: this.size,
8024
+ pixelSize: this.pixelSize,
7506
8025
  margin: this.margin,
7507
8026
  label: this.label,
7508
8027
  moduleShape: this.moduleShape,
@@ -7690,9 +8209,9 @@ var XhRadioGroupElement = class extends XhElement {
7690
8209
  };
7691
8210
  //#endregion
7692
8211
  //#region src/elements/rating.ts
7693
- const STRING_CONVERTER$29 = { fromAttribute: (v) => v ?? void 0 };
8212
+ const STRING_CONVERTER$30 = { fromAttribute: (v) => v ?? void 0 };
7694
8213
  const NUMBER_CONVERTER$16 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
7695
- const BOOLEAN_CONVERTER$20 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
8214
+ const BOOLEAN_CONVERTER$21 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
7696
8215
  /**
7697
8216
  * `<xh-rating>` —— Light-DOM 行为宿主:作者写 root/label/control 与若干 item 角色节点
7698
8217
  * (可选再写一个 hidden-input 参与表单提交),元素跑 rating 机器并把 connect 产出打上去。
@@ -7705,6 +8224,7 @@ const BOOLEAN_CONVERTER$20 = { fromAttribute: (v) => v === null ? void 0 : v !==
7705
8224
  * @attr {number} default-value - 非受控初值,缺省 0(还没评)
7706
8225
  * @attr {number} count - 星星颗数,默认 5
7707
8226
  * @attr {boolean} allow-half - 允许半颗星:档位从 1 变成 0.5
8227
+ * @attr {boolean} allow-clear - 再点当前档位清零,键盘最低档再往下也清;默认开,写 "false" 关
7708
8228
  * @attr {boolean} disabled - 整个不可交互:整条带子退出 Tab 序列,指针与键盘都不认
7709
8229
  * @attr {boolean} read-only - 只读:仍可聚焦与朗读,但改不动,也没有悬停预览
7710
8230
  * @attr {boolean} required - 必填标注;表单影子据此参与原生校验
@@ -7734,22 +8254,26 @@ var XhRatingElement = class extends XhElement {
7734
8254
  },
7735
8255
  count: { converter: NUMBER_CONVERTER$16 },
7736
8256
  allowHalf: {
7737
- converter: BOOLEAN_CONVERTER$20,
8257
+ converter: BOOLEAN_CONVERTER$21,
7738
8258
  attribute: "allow-half"
7739
8259
  },
7740
- disabled: { converter: BOOLEAN_CONVERTER$20 },
8260
+ allowClear: {
8261
+ converter: BOOLEAN_CONVERTER$21,
8262
+ attribute: "allow-clear"
8263
+ },
8264
+ disabled: { converter: BOOLEAN_CONVERTER$21 },
7741
8265
  readOnly: {
7742
- converter: BOOLEAN_CONVERTER$20,
8266
+ converter: BOOLEAN_CONVERTER$21,
7743
8267
  attribute: "read-only"
7744
8268
  },
7745
- required: { converter: BOOLEAN_CONVERTER$20 },
7746
- name: { converter: STRING_CONVERTER$29 },
8269
+ required: { converter: BOOLEAN_CONVERTER$21 },
8270
+ name: { converter: STRING_CONVERTER$30 },
7747
8271
  direction: {
7748
- converter: STRING_CONVERTER$29,
8272
+ converter: STRING_CONVERTER$30,
7749
8273
  attribute: "dir"
7750
8274
  },
7751
- tone: { converter: STRING_CONVERTER$29 },
7752
- size: { converter: STRING_CONVERTER$29 }
8275
+ tone: { converter: STRING_CONVERTER$30 },
8276
+ size: { converter: STRING_CONVERTER$30 }
7753
8277
  };
7754
8278
  notifyValue = (details) => {
7755
8279
  this.dispatchEvent(new CustomEvent("value-change", {
@@ -7772,6 +8296,7 @@ var XhRatingElement = class extends XhElement {
7772
8296
  defaultValue: this.defaultValue,
7773
8297
  count: this.count,
7774
8298
  allowHalf: this.allowHalf ?? false,
8299
+ allowClear: this.allowClear,
7775
8300
  disabled: this.disabled ?? false,
7776
8301
  readOnly: this.readOnly ?? false,
7777
8302
  required: this.required ?? false,
@@ -7814,7 +8339,7 @@ var XhRatingElement = class extends XhElement {
7814
8339
  };
7815
8340
  //#endregion
7816
8341
  //#region src/elements/result.ts
7817
- const STRING_CONVERTER$28 = { fromAttribute: (v) => v ?? void 0 };
8342
+ const STRING_CONVERTER$29 = { fromAttribute: (v) => v ?? void 0 };
7818
8343
  /**
7819
8344
  * `<xh-result>` —— 结果页行为宿主,无状态机,把 connectResult 产出的属性打到角色节点上。
7820
8345
  *
@@ -7838,8 +8363,8 @@ var XhResultElement = class extends XhElement {
7838
8363
  meta: resultMeta
7839
8364
  };
7840
8365
  static properties = {
7841
- status: { converter: STRING_CONVERTER$28 },
7842
- size: { converter: STRING_CONVERTER$28 }
8366
+ status: { converter: STRING_CONVERTER$29 },
8367
+ size: { converter: STRING_CONVERTER$29 }
7843
8368
  };
7844
8369
  wire() {
7845
8370
  const api = connectResult({
@@ -7859,7 +8384,7 @@ var XhResultElement = class extends XhElement {
7859
8384
  };
7860
8385
  //#endregion
7861
8386
  //#region src/elements/scroll-area.ts
7862
- const STRING_CONVERTER$27 = { fromAttribute: (v) => v ?? void 0 };
8387
+ const STRING_CONVERTER$28 = { fromAttribute: (v) => v ?? void 0 };
7863
8388
  const NUMBER_CONVERTER$15 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
7864
8389
  /**
7865
8390
  * `<xh-scroll-area>` —— Light-DOM 行为宿主:作者写 root/viewport/content/scrollbar/thumb/corner
@@ -7894,14 +8419,14 @@ var XhScrollAreaElement = class extends XhElement {
7894
8419
  meta: scrollAreaMeta
7895
8420
  };
7896
8421
  static properties = {
7897
- type: { converter: STRING_CONVERTER$27 },
8422
+ type: { converter: STRING_CONVERTER$28 },
7898
8423
  scrollHideDelay: {
7899
8424
  converter: NUMBER_CONVERTER$15,
7900
8425
  attribute: "scroll-hide-delay"
7901
8426
  },
7902
- orientation: { converter: STRING_CONVERTER$27 },
8427
+ orientation: { converter: STRING_CONVERTER$28 },
7903
8428
  direction: {
7904
- converter: STRING_CONVERTER$27,
8429
+ converter: STRING_CONVERTER$28,
7905
8430
  attribute: "dir"
7906
8431
  }
7907
8432
  };
@@ -7955,9 +8480,9 @@ var XhScrollAreaElement = class extends XhElement {
7955
8480
  };
7956
8481
  //#endregion
7957
8482
  //#region src/elements/select.ts
7958
- const STRING_CONVERTER$26 = { fromAttribute: (v) => v ?? void 0 };
8483
+ const STRING_CONVERTER$27 = { fromAttribute: (v) => v ?? void 0 };
7959
8484
  const NUMBER_CONVERTER$14 = { fromAttribute: (v) => v === null ? void 0 : Number(v) };
7960
- const BOOLEAN_CONVERTER$19 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
8485
+ const BOOLEAN_CONVERTER$20 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
7961
8486
  /**
7962
8487
  * `<xh-select>` —— Light-DOM 行为宿主:用户写 root/trigger/value-text/positioner/content/item/...
7963
8488
  * 角色节点,元素跑 select 机器并把 connect 产出打上去。浮层定位引擎在本元素里建好、经 refs 注入机器,
@@ -7973,6 +8498,8 @@ const BOOLEAN_CONVERTER$19 = { fromAttribute: (v) => v === null ? void 0 : v !==
7973
8498
  * @attr {boolean} open - 受控开合;缺省该属性即非受控
7974
8499
  * @attr {boolean} default-open - 非受控初始为展开
7975
8500
  * @attr {boolean} disabled - 整个控件禁用:trigger 用原生 disabled,表单影子不参与提交
8501
+ * @attr {boolean} invalid - 校验错误态:trigger 标红并输出 aria-invalid
8502
+ * @attr {number} max-tag-count - 多选标签最多摆几个,其余折进 api 的 overflowCount;缺省全摆
7976
8503
  * @attr {boolean} required - 原生表单校验:无选中值时提交被拦下;多选下的门槛是至少选中一项
7977
8504
  * @attr {string} name - 表单字段名;给定后表单影子才带 name 并参与提交
7978
8505
  * @attr {string} placeholder - 无选中时 value-text 显示的占位文字
@@ -7991,6 +8518,10 @@ const BOOLEAN_CONVERTER$19 = { fromAttribute: (v) => v === null ? void 0 : v !==
7991
8518
  * @csspart trigger - 触发按钮(aria-haspopup=listbox/aria-expanded/aria-controls 所在),同时是定位锚点,须是原生 button
7992
8519
  * @csspart value-text - 选中项文本的显示位;留空即由元素填入 displayText,作者写了内容则归作者
7993
8520
  * @csspart indicator - 展开指示符(aria-hidden,data-state 随开合)
8521
+ * @csspart control - 触发器与清空按钮的收纳容器兼定位基准;清空钮据此嵌进触发器右端、悬停时替换展开指示符
8522
+ * @csspart clear-trigger - 清空按钮:trigger 的兄弟节点(放进 control 即内嵌形态),没选中或禁用时带 hidden;可及名走 translations.clear
8523
+ * @csspart tag - 多选标签,须自带 value 属性标识选中值;放触发器里是纯展示,放外面配 tag-remove 可删
8524
+ * @csspart tag-remove - 标签删除按钮,须放在 tag 里;点按摘掉所在标签的选中值,可及名走 translations.removeTag
7994
8525
  * @csspart positioner - 浮层定位容器,坐标由引擎写成内联样式
7995
8526
  * @csspart content - role=listbox 容器(焦点域与消解层的根节点,键盘在此收口),收起时带 hidden
7996
8527
  * @csspart item - role=option 条目,须自带 value 属性标识身份;禁用写 aria-disabled="true"
@@ -8005,31 +8536,37 @@ var XhSelectElement = class extends XhElement {
8005
8536
  };
8006
8537
  static properties = {
8007
8538
  collection: { attribute: false },
8008
- value: { converter: STRING_CONVERTER$26 },
8539
+ value: { converter: STRING_CONVERTER$27 },
8009
8540
  defaultValue: {
8010
- converter: STRING_CONVERTER$26,
8541
+ converter: STRING_CONVERTER$27,
8011
8542
  attribute: "default-value"
8012
8543
  },
8013
- open: { converter: BOOLEAN_CONVERTER$19 },
8544
+ open: { converter: BOOLEAN_CONVERTER$20 },
8014
8545
  defaultOpen: {
8015
8546
  type: Boolean,
8016
8547
  attribute: "default-open"
8017
8548
  },
8018
8549
  disabled: { type: Boolean },
8550
+ invalid: { type: Boolean },
8019
8551
  required: { type: Boolean },
8020
- name: { converter: STRING_CONVERTER$26 },
8021
- placeholder: { converter: STRING_CONVERTER$26 },
8022
- placement: { converter: STRING_CONVERTER$26 },
8552
+ name: { converter: STRING_CONVERTER$27 },
8553
+ placeholder: { converter: STRING_CONVERTER$27 },
8554
+ placement: { converter: STRING_CONVERTER$27 },
8023
8555
  offset: { converter: NUMBER_CONVERTER$14 },
8024
- loop: { converter: BOOLEAN_CONVERTER$19 },
8556
+ loop: { converter: BOOLEAN_CONVERTER$20 },
8025
8557
  multiple: { type: Boolean },
8026
8558
  direction: {
8027
- converter: STRING_CONVERTER$26,
8559
+ converter: STRING_CONVERTER$27,
8028
8560
  attribute: "dir"
8029
8561
  },
8030
- variant: { converter: STRING_CONVERTER$26 },
8031
- tone: { converter: STRING_CONVERTER$26 },
8032
- size: { converter: STRING_CONVERTER$26 }
8562
+ variant: { converter: STRING_CONVERTER$27 },
8563
+ tone: { converter: STRING_CONVERTER$27 },
8564
+ size: { converter: STRING_CONVERTER$27 },
8565
+ translations: { attribute: false },
8566
+ maxTagCount: {
8567
+ converter: NUMBER_CONVERTER$14,
8568
+ attribute: "max-tag-count"
8569
+ }
8033
8570
  };
8034
8571
  idGen = createCounterIdGenerator();
8035
8572
  selectScope = createScope(null, this.idGen);
@@ -8067,6 +8604,7 @@ var XhSelectElement = class extends XhElement {
8067
8604
  open: this.open,
8068
8605
  defaultOpen: this.defaultOpen ?? false,
8069
8606
  disabled: this.disabled ?? false,
8607
+ invalid: this.invalid ?? false,
8070
8608
  required: this.required ?? false,
8071
8609
  name: this.name,
8072
8610
  placeholder: this.placeholder,
@@ -8078,6 +8616,8 @@ var XhSelectElement = class extends XhElement {
8078
8616
  variant: this.variant,
8079
8617
  tone: this.tone,
8080
8618
  size: this.size,
8619
+ translations: this.translations,
8620
+ maxTagCount: this.maxTagCount,
8081
8621
  onValueChange: this.notifyValue,
8082
8622
  onOpenChange: this.notifyOpen
8083
8623
  };
@@ -8177,8 +8717,15 @@ var XhSelectElement = class extends XhElement {
8177
8717
  };
8178
8718
  put("root", api.getRootProps());
8179
8719
  put("label", api.getLabelProps());
8720
+ put("control", api.getControlProps());
8180
8721
  put("trigger", api.getTriggerProps());
8181
8722
  put("indicator", api.getIndicatorProps());
8723
+ put("clear-trigger", api.getClearTriggerProps());
8724
+ for (const el of this.getParts("tag")) this.spreader.spread(el, api.getTagProps({ value: el.getAttribute("value") ?? "" }));
8725
+ for (const el of this.getParts("tag-remove")) {
8726
+ const owner = el.closest("[data-xh-part=\"tag\"]");
8727
+ this.spreader.spread(el, api.getTagRemoveProps({ value: owner?.getAttribute("value") ?? "" }));
8728
+ }
8182
8729
  put("positioner", api.getPositionerProps());
8183
8730
  put("content", api.getContentProps());
8184
8731
  const valueText = this.getPart("value-text");
@@ -8237,6 +8784,175 @@ var XhSeparatorElement = class extends XhElement {
8237
8784
  }
8238
8785
  };
8239
8786
  //#endregion
8787
+ //#region src/elements/side-nav.ts
8788
+ const STRING_CONVERTER$26 = { fromAttribute: (v) => v ?? void 0 };
8789
+ const BOOLEAN_CONVERTER$19 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
8790
+ /** 分支一系的归属容器;嵌套分支各认最近的那个。 */
8791
+ const BRANCH_SELECTOR$2 = "[data-xh-part=\"branch\"]";
8792
+ /** 分组一系的归属容器。 */
8793
+ const GROUP_SELECTOR = "[data-xh-part=\"group\"]";
8794
+ /**
8795
+ * `<xh-side-nav>` —— Light-DOM 行为宿主:管理后台侧栏导航。
8796
+ * 作者写 root/list 与若干 branch / link 角色节点,元素跑 side-nav 机器并把 connect 产出打上去。
8797
+ * 节点身份取自节点上的 value 属性;href 与禁用查 `collection` 这份树数据。
8798
+ *
8799
+ * @customElement xh-side-nav
8800
+ * @attr {string} value - 受控选中的叶子;缺省该属性即非受控
8801
+ * @attr {string} default-value - 非受控初始选中
8802
+ * @attr {boolean} accordion - 同层手风琴:展开一枝收起同层其余,默认 false
8803
+ * @attr {boolean} collapsed - 折叠成图标栏(内嵌展开整体收起、文字由皮肤藏掉;顶层分支换装浮层弹出)
8804
+ * @attr {boolean} collapsed-popout - 折叠态下顶层分支是否弹出子级面板,默认 true
8805
+ * @attr {boolean} disabled - 整个侧栏禁用
8806
+ * @attr {boolean} loop - 上下键走到首尾回绕,默认关
8807
+ * @attr {'ltr'|'rtl'} dir - 文字方向,只对调左右方向键的展开/收起语义,默认 ltr
8808
+ * @fires value-change - 选中变化;detail 为 `{ value: string | null }`
8809
+ * @fires expanded-change - 展开集合变化;detail 为 `{ value: string[] }`
8810
+ * @csspart root - nav 地标根容器(aria-label 由 translations.root 给)
8811
+ * @csspart list - 顶层列表容器
8812
+ * @csspart group - role=group 分组,须自带 value 属性
8813
+ * @csspart group-label - 分组标题(aria-labelledby 目标)
8814
+ * @csspart branch - 分支行容器,须自带 value 属性;它裹着自己的 branch-content
8815
+ * @csspart branch-trigger - 展开/收起按钮(aria-expanded / aria-controls)
8816
+ * @csspart branch-text - 行文字载体,折叠成图标栏时隐藏
8817
+ * @csspart branch-indicator - 展开方向指示符(aria-hidden)
8818
+ * @csspart branch-content - 内嵌子层容器,收起时隐藏
8819
+ * @csspart link - 去处链接,须自带 value 属性;选中输出 aria-current="page"
8820
+ * @csspart link-text - 链接文字载体,折叠成图标栏时隐藏
8821
+ */
8822
+ var XhSideNavElement = class extends XhElement {
8823
+ static partContract = {
8824
+ anatomy: sideNavAnatomy,
8825
+ meta: sideNavMeta
8826
+ };
8827
+ static properties = {
8828
+ value: { converter: STRING_CONVERTER$26 },
8829
+ defaultValue: {
8830
+ converter: STRING_CONVERTER$26,
8831
+ attribute: "default-value"
8832
+ },
8833
+ accordion: { converter: BOOLEAN_CONVERTER$19 },
8834
+ collapsed: { converter: BOOLEAN_CONVERTER$19 },
8835
+ collapsedPopout: {
8836
+ converter: BOOLEAN_CONVERTER$19,
8837
+ attribute: "collapsed-popout"
8838
+ },
8839
+ disabled: { converter: BOOLEAN_CONVERTER$19 },
8840
+ loop: { converter: BOOLEAN_CONVERTER$19 },
8841
+ direction: {
8842
+ converter: STRING_CONVERTER$26,
8843
+ attribute: "dir"
8844
+ },
8845
+ collection: { attribute: false },
8846
+ expandedValue: { attribute: false },
8847
+ defaultExpandedValue: { attribute: false },
8848
+ translations: { attribute: false }
8849
+ };
8850
+ notifyValue = (details) => {
8851
+ this.dispatchEvent(new CustomEvent("value-change", {
8852
+ detail: details,
8853
+ bubbles: true,
8854
+ composed: true
8855
+ }));
8856
+ };
8857
+ notifyExpanded = (details) => {
8858
+ this.dispatchEvent(new CustomEvent("expanded-change", {
8859
+ detail: details,
8860
+ bubbles: true,
8861
+ composed: true
8862
+ }));
8863
+ };
8864
+ idGen = createCounterIdGenerator();
8865
+ navScope = createScope(null, this.idGen);
8866
+ positionEngine = createPositionEngine();
8867
+ config = null;
8868
+ ctrl = new MachineController(this, sideNavMachine, () => this.machineProps(), {
8869
+ scope: this.navScope,
8870
+ onBuilt: (svc) => this.injectRefs(svc)
8871
+ });
8872
+ machineProps() {
8873
+ return {
8874
+ collection: this.collection,
8875
+ value: this.value,
8876
+ defaultValue: this.defaultValue,
8877
+ expandedValue: this.expandedValue,
8878
+ defaultExpandedValue: this.defaultExpandedValue,
8879
+ accordion: this.accordion,
8880
+ collapsed: this.collapsed,
8881
+ collapsedPopout: this.collapsedPopout,
8882
+ disabled: this.disabled,
8883
+ loop: this.loop,
8884
+ dir: this.direction,
8885
+ translations: this.translations,
8886
+ onValueChange: this.notifyValue,
8887
+ onExpandedChange: this.notifyExpanded
8888
+ };
8889
+ }
8890
+ ensureConfig() {
8891
+ if (this.config) return;
8892
+ this.config = createRuntimeConfig({
8893
+ scope: this.navScope,
8894
+ idGenerator: this.idGen
8895
+ });
8896
+ }
8897
+ /** 当前弹出分支名下的角色节点:按归属分支的 value 现查。 */
8898
+ findPopoutPart(svc, name) {
8899
+ const v = svc.context.get("popoutValue");
8900
+ if (v == null) return null;
8901
+ for (const el of this.getParts(name)) if (this.nodeOf(el, BRANCH_SELECTOR$2).value === v) return el;
8902
+ return null;
8903
+ }
8904
+ registerLayer = () => {
8905
+ this.ensureConfig();
8906
+ const svc = this.ctrl.service;
8907
+ return this.config.layerRegistry.register({
8908
+ kind: "popover",
8909
+ node: () => this.findPopoutPart(svc, "branch-content"),
8910
+ branches: () => [this.findPopoutPart(svc, "branch-trigger")].filter(Boolean),
8911
+ isModal: () => false,
8912
+ setModal: () => {},
8913
+ surfaces: () => []
8914
+ });
8915
+ };
8916
+ injectRefs(svc) {
8917
+ this.ensureConfig();
8918
+ svc.refs.set("config", this.config);
8919
+ svc.refs.set("registerLayer", this.registerLayer);
8920
+ svc.refs.set("position", this.positionEngine);
8921
+ svc.refs.set("getPopoutAnchorEl", () => this.findPopoutPart(svc, "branch-trigger"));
8922
+ svc.refs.set("getPopoutContentEl", () => this.findPopoutPart(svc, "branch-content"));
8923
+ }
8924
+ nodeOf(el, selector) {
8925
+ const owner = el.closest(selector);
8926
+ return { value: (owner && owner !== this && this.contains(owner) ? owner : el).getAttribute("value") ?? "" };
8927
+ }
8928
+ disconnectedCallback() {
8929
+ super.disconnectedCallback();
8930
+ this.config = null;
8931
+ }
8932
+ wire() {
8933
+ const api = connectSideNav(this.ctrl.service, wcNormalize);
8934
+ const put = (name, props) => {
8935
+ const el = this.getPart(name);
8936
+ if (el) this.spreader.spread(el, props);
8937
+ };
8938
+ put("root", api.getRootProps());
8939
+ put("list", api.getListProps());
8940
+ const putAll = (name, selector, get) => {
8941
+ for (const el of this.getParts(name)) this.spreader.spread(el, get(this.nodeOf(el, selector)));
8942
+ };
8943
+ putAll("group", GROUP_SELECTOR, (node) => api.getGroupProps(node));
8944
+ putAll("group-label", GROUP_SELECTOR, (node) => api.getGroupLabelProps(node));
8945
+ putAll("branch", BRANCH_SELECTOR$2, (node) => api.getBranchProps(node));
8946
+ putAll("branch-trigger", BRANCH_SELECTOR$2, (node) => api.getBranchTriggerProps(node));
8947
+ putAll("branch-indicator", BRANCH_SELECTOR$2, (node) => api.getBranchIndicatorProps(node));
8948
+ for (const el of this.getParts("branch-text")) this.spreader.spread(el, api.getBranchTextProps());
8949
+ for (const el of this.getParts("link-text")) this.spreader.spread(el, api.getLinkTextProps());
8950
+ putAll("branch-content", BRANCH_SELECTOR$2, (node) => api.getBranchContentProps(node));
8951
+ putAll("link", "[data-xh-part=\"link\"]", (node) => api.getLinkProps(node));
8952
+ for (const el of this.getParts("branch-content")) this.setPartHidden(el, el.hasAttribute("hidden"));
8953
+ }
8954
+ };
8955
+ //#endregion
8240
8956
  //#region src/elements/skeleton.ts
8241
8957
  const STRING_CONVERTER$25 = { fromAttribute: (v) => v ?? void 0 };
8242
8958
  const BOOLEAN_CONVERTER$18 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
@@ -8315,6 +9031,7 @@ const NUMBER_LIST_CONVERTER$1 = { fromAttribute: (v) => {
8315
9031
  * @attr {number} step - 方向键与吸附网格的步长,默认 1
8316
9032
  * @attr {number} large-step - PageUp/PageDown 的步长,默认 10 倍 step
8317
9033
  * @attr {number} min-steps-between-thumbs - 相邻滑块至少隔几格,默认 0
9034
+ * @attr {boolean} snap-to-marks - 只认刻度落点:拖动、点按与键盘都吸到最近/下一档刻度;刻度表经 marks property 赋
8318
9035
  * @attr {'horizontal'|'vertical'} orientation - 轨道朝向,默认 horizontal
8319
9036
  * @attr {'ltr'|'rtl'} dir - 文字方向,只改写水平轨道上左右两键与指针的语义,默认 ltr
8320
9037
  * @attr {boolean} disabled - 禁用:拇指退出 Tab 序列、推不动、不参与表单提交
@@ -8330,6 +9047,9 @@ const NUMBER_LIST_CONVERTER$1 = { fromAttribute: (v) => {
8330
9047
  * @csspart control - 指针命中区,按下即跳到落点并接管拖动
8331
9048
  * @csspart track - 轨道本体,值与坐标的换算以它的矩形为准
8332
9049
  * @csspart range - 已选区间,起止由内联逻辑属性给出
9050
+ * @csspart marks - 刻度容器
9051
+ * @csspart mark - 刻度点(纯装饰),须自带 value 属性;落进已选区间带 data-active
9052
+ * @csspart mark-label - 刻度文案,须自带 value 属性;点按把最近的滑块跳到这一档
8333
9053
  * @csspart thumb - role=slider 的拇指,键盘交互全在它身上;多滑块须写 index 属性
8334
9054
  * @csspart hidden-input - 拇指内的表单影子(须是原生 input)
8335
9055
  */
@@ -8355,6 +9075,11 @@ var XhSliderElement = class extends XhElement {
8355
9075
  converter: NUMBER_CONVERTER$13,
8356
9076
  attribute: "min-steps-between-thumbs"
8357
9077
  },
9078
+ snapToMarks: {
9079
+ converter: BOOLEAN_CONVERTER$17,
9080
+ attribute: "snap-to-marks"
9081
+ },
9082
+ marks: { attribute: false },
8358
9083
  orientation: { converter: STRING_CONVERTER$24 },
8359
9084
  direction: {
8360
9085
  converter: STRING_CONVERTER$24,
@@ -8400,6 +9125,8 @@ var XhSliderElement = class extends XhElement {
8400
9125
  step: this.step,
8401
9126
  largeStep: this.largeStep,
8402
9127
  minStepsBetweenThumbs: this.minStepsBetweenThumbs,
9128
+ marks: this.marks,
9129
+ snapToMarks: this.snapToMarks,
8403
9130
  orientation: this.orientation,
8404
9131
  dir: this.direction,
8405
9132
  disabled: this.disabled ?? false,
@@ -8438,6 +9165,9 @@ var XhSliderElement = class extends XhElement {
8438
9165
  put("control", api.getControlProps());
8439
9166
  put("track", api.getTrackProps());
8440
9167
  put("range", api.getRangeProps());
9168
+ put("marks", api.getMarksProps());
9169
+ for (const el of this.getParts("mark")) this.spreader.spread(el, api.getMarkProps({ value: Number(el.getAttribute("value")) }));
9170
+ for (const el of this.getParts("mark-label")) this.spreader.spread(el, api.getMarkLabelProps({ value: Number(el.getAttribute("value")) }));
8441
9171
  for (const el of this.getParts("thumb")) {
8442
9172
  const index = this.thumbIndex(el);
8443
9173
  this.spreader.spread(el, api.getThumbProps(index));
@@ -8491,7 +9221,7 @@ const STRING_CONVERTER$22 = { fromAttribute: (v) => v ?? void 0 };
8491
9221
  const NUMBER_CONVERTER$12 = { fromAttribute: (v) => v == null || v === "" ? void 0 : Number(v) };
8492
9222
  const BOOLEAN_CONVERTER$16 = { fromAttribute: (v) => v === null ? void 0 : v !== "false" };
8493
9223
  /**
8494
- * 布局是百分比数组,属性写成逗号分隔(两栏 size="30,70")。
9224
+ * 布局是百分比数组,属性写成逗号分隔(两栏 sizes="30,70")。
8495
9225
  * 解析不出任何有限数就当没写:留下 NaN 会一路写进 aria-valuenow 与定位百分比。
8496
9226
  */
8497
9227
  const NUMBER_LIST_CONVERTER = { fromAttribute: (v) => {
@@ -8529,16 +9259,16 @@ const PANELS_CONVERTER = { fromAttribute: (v) => {
8529
9259
  * 第 index 条分隔条坐在第 index 与第 index+1 块面板之间,调整的是前一块。
8530
9260
  *
8531
9261
  * @customElement xh-splitter
8532
- * @attr {string} size - 受控布局,逗号分隔的百分比(如 "30,70");缺省该属性即非受控
8533
- * @attr {string} default-size - 非受控初值,同样逗号分隔;缺省时按面板数等分
9262
+ * @attr {string} sizes - 受控布局,逗号分隔的百分比(如 "30,70");缺省该属性即非受控
9263
+ * @attr {string} default-sizes - 非受控初值,同样逗号分隔;缺省时按面板数等分
8534
9264
  * @attr {string} panels - 逐块约束的 JSON 数组:id / min / max / collapsible / collapsedSize
8535
9265
  * @attr {'horizontal'|'vertical'} orientation - 面板排布轴,默认 horizontal(并排)
8536
9266
  * @attr {'ltr'|'rtl'} dir - 文字方向,只对调水平排布下左右两键与指针位移的正负,默认 ltr
8537
9267
  * @attr {boolean} disabled - 禁用:分隔条退出 Tab 序列、拖不动也推不动
8538
9268
  * @attr {number} step - 方向键的步长(百分比),默认 1
8539
9269
  * @attr {number} large-step - Shift + 方向键的步长(百分比),默认 10
8540
- * @fires size-change - 布局变化(拖动途中会连发);detail 为 `{ size: number[] }`
8541
- * @fires size-change-end - 一次拖拽收尾发一次;detail 为 `{ size: number[], index: number }`
9270
+ * @fires sizes-change - 布局变化(拖动途中会连发);detail 为 `{ sizes: number[] }`
9271
+ * @fires sizes-change-end - 一次拖拽收尾发一次;detail 为 `{ sizes: number[], index: number }`
8542
9272
  * @csspart root - 承载 data-orientation / data-disabled / data-dragging 的容器,矩形以它为准
8543
9273
  * @csspart panel - 一块面板;尺寸由内联 flex-basis 给出,折叠时带 data-collapsed
8544
9274
  * @csspart resize-trigger - role=separator 的分隔条,指针与键盘交互全在它身上
@@ -8549,10 +9279,10 @@ var XhSplitterElement = class extends XhElement {
8549
9279
  meta: splitterMeta
8550
9280
  };
8551
9281
  static properties = {
8552
- size: { converter: NUMBER_LIST_CONVERTER },
8553
- defaultSize: {
9282
+ sizes: { converter: NUMBER_LIST_CONVERTER },
9283
+ defaultSizes: {
8554
9284
  converter: NUMBER_LIST_CONVERTER,
8555
- attribute: "default-size"
9285
+ attribute: "default-sizes"
8556
9286
  },
8557
9287
  panels: { converter: PANELS_CONVERTER },
8558
9288
  orientation: { converter: STRING_CONVERTER$22 },
@@ -8570,14 +9300,14 @@ var XhSplitterElement = class extends XhElement {
8570
9300
  idGen = createCounterIdGenerator();
8571
9301
  splitterScope = createScope(null, this.idGen);
8572
9302
  notifySize = (details) => {
8573
- this.dispatchEvent(new CustomEvent("size-change", {
9303
+ this.dispatchEvent(new CustomEvent("sizes-change", {
8574
9304
  detail: details,
8575
9305
  bubbles: true,
8576
9306
  composed: true
8577
9307
  }));
8578
9308
  };
8579
9309
  notifySizeEnd = (details) => {
8580
- this.dispatchEvent(new CustomEvent("size-change-end", {
9310
+ this.dispatchEvent(new CustomEvent("sizes-change-end", {
8581
9311
  detail: details,
8582
9312
  bubbles: true,
8583
9313
  composed: true
@@ -8589,16 +9319,16 @@ var XhSplitterElement = class extends XhElement {
8589
9319
  });
8590
9320
  machineProps() {
8591
9321
  return {
8592
- size: this.size,
8593
- defaultSize: this.defaultSize,
9322
+ sizes: this.sizes,
9323
+ defaultSizes: this.defaultSizes,
8594
9324
  panels: this.panels,
8595
9325
  orientation: this.orientation,
8596
9326
  dir: this.direction,
8597
9327
  disabled: this.disabled ?? false,
8598
9328
  step: this.step,
8599
9329
  largeStep: this.largeStep,
8600
- onSizeChange: this.notifySize,
8601
- onSizeChangeEnd: this.notifySizeEnd
9330
+ onSizesChange: this.notifySize,
9331
+ onSizesChangeEnd: this.notifySizeEnd
8602
9332
  };
8603
9333
  }
8604
9334
  injectRefs(svc) {
@@ -8812,11 +9542,14 @@ var XhStepsElement = class extends XhElement {
8812
9542
  * @attr {boolean} checked - 受控开合;缺省该属性即非受控
8813
9543
  * @attr {boolean} default-checked - 非受控初始为选中
8814
9544
  * @attr {boolean} disabled - 禁用
9545
+ * @attr {boolean} loading - 提交中:交互挂起、滑块转圈,仍可聚焦(aria-busy)
8815
9546
  * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气
8816
9547
  * @attr {'sm'|'md'|'lg'} size - 尺寸
8817
9548
  * @fires checked-change - checked 状态变化;detail 为 `{ checked: boolean }`
8818
9549
  * @csspart root - role=switch 的按钮(承载 aria-checked / data-state)
8819
9550
  * @csspart thumb - 滑块
9551
+ * @attr {string} name - 表单字段名;给了 hidden-input 才参与提交
9552
+ * @csspart hidden-input - type=hidden 的表单出口,省略该节点即不参与表单
8820
9553
  */
8821
9554
  var XhSwitchElement = class extends XhElement {
8822
9555
  static partContract = {
@@ -8830,6 +9563,9 @@ var XhSwitchElement = class extends XhElement {
8830
9563
  attribute: "default-checked"
8831
9564
  },
8832
9565
  disabled: { type: Boolean },
9566
+ loading: { type: Boolean },
9567
+ name: { converter: { fromAttribute: (v) => v ?? void 0 } },
9568
+ value: { converter: { fromAttribute: (v) => v ?? void 0 } },
8833
9569
  tone: {},
8834
9570
  size: {}
8835
9571
  };
@@ -8846,8 +9582,11 @@ var XhSwitchElement = class extends XhElement {
8846
9582
  checked: this.checked,
8847
9583
  defaultChecked: this.defaultChecked ?? false,
8848
9584
  disabled: this.disabled ?? false,
9585
+ loading: this.loading ?? false,
8849
9586
  tone: this.tone,
8850
9587
  size: this.size,
9588
+ name: this.name,
9589
+ value: this.value,
8851
9590
  onCheckedChange: this.notify
8852
9591
  };
8853
9592
  }
@@ -8857,6 +9596,8 @@ var XhSwitchElement = class extends XhElement {
8857
9596
  if (root) this.spreader.spread(root, api.getRootProps());
8858
9597
  const thumb = this.getPart("thumb");
8859
9598
  if (thumb) this.spreader.spread(thumb, api.getThumbProps());
9599
+ const hidden = this.getPart("hidden-input");
9600
+ if (hidden) this.spreader.spread(hidden, api.getHiddenInputProps());
8860
9601
  }
8861
9602
  };
8862
9603
  //#endregion
@@ -8907,7 +9648,7 @@ const FOOTER_SELECTOR = "[data-xh-part=\"footer\"]";
8907
9648
  * @csspart sort-trigger - 排序把手,自占一个 Tab 位;按住 Shift 点是追加到排序链
8908
9649
  * @csspart expand-trigger - 展开把手(aria-hidden 且不占 Tab 位,键盘那一路由左右方向键承担)
8909
9650
  * @csspart expanded-row - role=row 详情行,须自带 value 属性与它所属的数据行配对,内部须放一个 cell 承载详情;收起时 hidden
8910
- * @csspart empty-state - 空态节点,表体为空且不在加载时显形
9651
+ * @csspart empty - 空态节点,表体为空且不在加载时显形
8911
9652
  * @csspart loading-state - 加载态节点,表体为空且正在加载时显形
8912
9653
  */
8913
9654
  var XhTableElement = class extends XhElement {
@@ -9028,9 +9769,9 @@ var XhTableElement = class extends XhElement {
9028
9769
  put("header", api.getHeaderProps());
9029
9770
  put("body", api.getBodyProps());
9030
9771
  put("footer", api.getFooterProps());
9031
- const emptyProps = api.getEmptyStateProps();
9772
+ const emptyProps = api.getEmptyProps();
9032
9773
  const loadingProps = api.getLoadingStateProps();
9033
- put("empty-state", emptyProps);
9774
+ put("empty", emptyProps);
9034
9775
  put("loading-state", loadingProps);
9035
9776
  const putAll = (name, get) => {
9036
9777
  for (const el of this.getParts(name)) this.spreader.spread(el, get(el));
@@ -9059,7 +9800,7 @@ var XhTableElement = class extends XhElement {
9059
9800
  putAll("expanded-row", (el) => api.getExpandedRowProps({ value: el.getAttribute("value") ?? "" }));
9060
9801
  for (const el of this.getParts("row")) if (el.hasAttribute("disabled")) el.removeAttribute("disabled");
9061
9802
  for (const el of this.getParts("expanded-row")) this.setPartHidden(el, !api.isExpanded(el.getAttribute("value") ?? ""));
9062
- this.setPartHidden(this.getPart("empty-state"), !!emptyProps.hidden);
9803
+ this.setPartHidden(this.getPart("empty"), !!emptyProps.hidden);
9063
9804
  this.setPartHidden(this.getPart("loading-state"), !!loadingProps.hidden);
9064
9805
  }
9065
9806
  };
@@ -9374,6 +10115,7 @@ const BOOLEAN_CONVERTER$11 = { fromAttribute: (v) => v === null ? void 0 : v !==
9374
10115
  * @attr {string} name - 表单字段名;给了才参与提交
9375
10116
  * @attr {number} max-length - 字符数上限;同时落成原生 maxlength 与机器侧截断
9376
10117
  * @attr {boolean} clearable - 开启清空:清空按钮显出并在有值时可用,Escape 接管
10118
+ * @attr {boolean} auto-size - 多行宿主(input 部件写成 textarea)的自动高度;行数界限对象经 autoSize property 赋
9377
10119
  * @attr {'outline'|'subtle'|'ghost'} variant - 视觉变体
9378
10120
  * @attr {'brand'|'neutral'|'success'|'warning'|'danger'|'info'} tone - 语气
9379
10121
  * @attr {'sm'|'md'|'lg'} size - 尺寸
@@ -9408,6 +10150,10 @@ var XhTextFieldElement = class extends XhElement {
9408
10150
  attribute: "max-length"
9409
10151
  },
9410
10152
  clearable: { converter: BOOLEAN_CONVERTER$11 },
10153
+ autoSize: {
10154
+ converter: BOOLEAN_CONVERTER$11,
10155
+ attribute: "auto-size"
10156
+ },
9411
10157
  variant: { converter: STRING_CONVERTER$16 },
9412
10158
  tone: { converter: STRING_CONVERTER$16 },
9413
10159
  size: { converter: STRING_CONVERTER$16 }
@@ -9432,6 +10178,7 @@ var XhTextFieldElement = class extends XhElement {
9432
10178
  name: this.name,
9433
10179
  maxLength: this.maxLength,
9434
10180
  clearable: this.clearable ?? false,
10181
+ autoSize: this.autoSize,
9435
10182
  variant: this.variant,
9436
10183
  tone: this.tone,
9437
10184
  size: this.size,
@@ -9446,7 +10193,10 @@ var XhTextFieldElement = class extends XhElement {
9446
10193
  };
9447
10194
  put("root", api.getRootProps());
9448
10195
  put("label", api.getLabelProps());
9449
- put("input", api.getInputProps());
10196
+ const inputEl = this.getPart("input");
10197
+ const host = inputEl?.tagName === "TEXTAREA" ? "textarea" : "input";
10198
+ put("input", api.getInputProps({ as: host }));
10199
+ if (host === "textarea" && inputEl) autoSizeTextarea(inputEl, api.autoSize);
9450
10200
  put("clear-trigger", api.getClearTriggerProps());
9451
10201
  this.setPartHidden(this.getPart("clear-trigger"), !api.clearable);
9452
10202
  }
@@ -9768,7 +10518,7 @@ function declaredUnit(el, position) {
9768
10518
  }
9769
10519
  /**
9770
10520
  * `<xh-time-picker>` —— Light-DOM 行为宿主:作者写 root/label/control/input(多个)/trigger/
9771
- * clear-trigger/positioner/content/column(多个)/option(多个)/hidden-input 角色节点,
10521
+ * clear-trigger/positioner/content/column(多个)/item(多个)/hidden-input 角色节点,
9772
10522
  * 元素跑 time-picker 机器并把 connect 产出打上去。浮层定位引擎在本元素里建好、经 refs 注入机器,
9773
10523
  * 锚点取 control(浮层因此与整个输入行对齐),被定位的浮层取 positioner。
9774
10524
  *
@@ -9806,7 +10556,7 @@ function declaredUnit(el, position) {
9806
10556
  * @csspart positioner - 浮层定位容器,坐标由引擎写成内联样式
9807
10557
  * @csspart content - 浮层容器(消解层与焦点域的根节点),收起时带 hidden
9808
10558
  * @csspart column - role=listbox 的一列,可自带 unit 属性声明单位,缺省按文档序
9809
- * @csspart option - role=option 的一格,须自带 value 属性(两位补零的显示串)
10559
+ * @csspart item - role=option 的一格,须自带 value 属性(两位补零的显示串)
9810
10560
  * @csspart hidden-input - type=hidden 的表单出口,值是完整 ISO 串
9811
10561
  */
9812
10562
  var XhTimePickerElement = class extends XhElement {
@@ -9958,13 +10708,13 @@ var XhTimePickerElement = class extends XhElement {
9958
10708
  const unit = declaredUnit(columnEl, position);
9959
10709
  this.spreader.spread(columnEl, api.getColumnProps({ unit }));
9960
10710
  this.setPartHidden(columnEl, !api.columns.some((column) => column.unit === unit));
9961
- for (const optionEl of this.getParts("option").filter((el) => columnEl.contains(el))) {
9962
- const value = optionEl.getAttribute("value") ?? "";
9963
- this.spreader.spread(optionEl, api.getOptionProps({
10711
+ for (const itemEl of this.getParts("item").filter((el) => columnEl.contains(el))) {
10712
+ const value = itemEl.getAttribute("value") ?? "";
10713
+ this.spreader.spread(itemEl, api.getItemProps({
9964
10714
  unit,
9965
10715
  value
9966
10716
  }));
9967
- this.fillText(optionEl, value);
10717
+ this.fillText(itemEl, value);
9968
10718
  }
9969
10719
  });
9970
10720
  this.setPartHidden(this.getPart("content"), !api.open);
@@ -10734,6 +11484,7 @@ const BOOLEAN_CONVERTER$4 = { fromAttribute: (v) => v === null ? void 0 : v !==
10734
11484
  * @attr {boolean} close-on-interact-outside - 层外交互关闭,默认 false;写 "true" 打开
10735
11485
  * @attr {boolean} show-backdrop - 画遮罩,默认 true;写 show-backdrop="false" 关掉
10736
11486
  * @attr {number} spotlight-padding - 高亮框在目标四周留出的空白(px),默认 8
11487
+ * @attr {boolean} auto-scroll - 展开与换步时自动把目标滚进视口(nearest),默认 true;写 auto-scroll="false" 关掉
10737
11488
  * @fires open-change - open 状态变化;detail 为 `{ open: boolean }`
10738
11489
  * @fires step-change - 步序变化;detail 为 `{ step: number }`
10739
11490
  * @fires complete - 末步再按下一步;detail 为 `{ step: number }`
@@ -10786,6 +11537,10 @@ var XhTourElement = class extends XhElement {
10786
11537
  converter: NUMBER_CONVERTER$3,
10787
11538
  attribute: "spotlight-padding"
10788
11539
  },
11540
+ autoScroll: {
11541
+ converter: BOOLEAN_CONVERTER$4,
11542
+ attribute: "auto-scroll"
11543
+ },
10789
11544
  steps: { attribute: false },
10790
11545
  translations: { attribute: false }
10791
11546
  };
@@ -10825,6 +11580,7 @@ var XhTourElement = class extends XhElement {
10825
11580
  closeOnInteractOutside: this.closeOnInteractOutside,
10826
11581
  showBackdrop: this.showBackdrop,
10827
11582
  spotlightPadding: this.spotlightPadding,
11583
+ autoScroll: this.autoScroll,
10828
11584
  translations: this.translations,
10829
11585
  onOpenChange: this.notifyOpen,
10830
11586
  onStepChange: this.notifyStep,
@@ -10887,6 +11643,10 @@ var XhTourElement = class extends XhElement {
10887
11643
  wire() {
10888
11644
  this.wireWith(this.ctrl.service);
10889
11645
  }
11646
+ /** 重量高亮框与浮层位置:目标节点被外部改动(换位、变尺寸)后调它校准。 */
11647
+ remeasure() {
11648
+ this.ctrl?.service.send({ type: "GEOMETRY.SYNC" });
11649
+ }
10890
11650
  wireWith(svc) {
10891
11651
  const api = connectTour(svc, wcNormalize);
10892
11652
  this.contentNode = this.getPart("content");
@@ -10935,7 +11695,7 @@ const SIDES = ["source", "target"];
10935
11695
  /**
10936
11696
  * 读条目节点上作者写的原生 disabled,顺手摘掉。
10937
11697
  *
10938
- * 集合条目的禁用一律由 aria-disabled 表达(禁用声明的事实源是 items,不是标记):
11698
+ * 集合条目的禁用一律由 aria-disabled 表达(禁用声明的事实源是 collection,不是标记):
10939
11699
  * 原生禁用的节点不可聚焦、也收不到 click,「禁用项仍是方向键起点、仍挡得住点击」
10940
11700
  * 这两条在原生 disabled 下根本无从成立。摘掉之后禁用态由 connect 写回的 aria-disabled 承接。
10941
11701
  */
@@ -10947,7 +11707,7 @@ function stripNativeDisabled(el) {
10947
11707
  * root/source-panel/target-panel/panel-header/panel-title/panel-count/search/list/item/...
10948
11708
  * 角色节点,元素跑 transfer 机器并把 connect 产出打上去。
10949
11709
  *
10950
- * 条目全集由 `items` 属性(property)给出,它是标签与禁用的唯一事实源;
11710
+ * 条目全集由 `collection` 属性(property)给出,它是标签与禁用的唯一事实源;
10951
11711
  * **两侧面板各挂一份全集**,不属于本侧、或被搜索筛掉的那一份由元素打上 hidden,
10952
11712
  * 节点不卸载。条目身份取节点上的 `value` 属性,归哪一侧则取它落在哪个面板里。
10953
11713
  *
@@ -10956,8 +11716,8 @@ function stripNativeDisabled(el) {
10956
11716
  * 导航与勾选在事件那一刻按 data-scope+data-part 查活 DOM,依赖 connect 回写的 data-value,
10957
11717
  * 因此 wire 必须先于交互跑过(基类 updated 已保证)。
10958
11718
  *
10959
- * 集合类输入(items / value / selected / filter)都表达不成属性,只能走 property:
10960
- * `el.items = [...]`、`el.value = ['a']`。
11719
+ * 集合类输入(collection / value / selected / filter)都表达不成属性,只能走 property:
11720
+ * `el.collection = [...]`、`el.value = ['a']`。
10961
11721
  *
10962
11722
  * @customElement xh-transfer
10963
11723
  * @attr {boolean} searchable - 每侧带一个搜索框;关掉时搜索框仍在 DOM 里但带 hidden
@@ -10966,7 +11726,7 @@ function stripNativeDisabled(el) {
10966
11726
  * @attr {boolean} loop - 列表内方向键走到尽头回绕,默认 true;写 loop="false" 关掉
10967
11727
  * @attr {'ltr'|'rtl'} dir - 文字方向,决定列表内哪个横向方向键是"搬向对面",默认 ltr
10968
11728
  * @fires value-change - 落在右侧的值变化;detail 为 `{ value: string[] }`
10969
- * @fires selected-change - 勾选集合变化;detail 为 `{ selected: string[] }`
11729
+ * @fires selection-change - 勾选集合变化;detail 为 `{ selected: string[] }`
10970
11730
  * @csspart root - 组件根容器(承载 data-disabled/data-one-way)
10971
11731
  * @csspart source-panel - 左侧面板容器,其内的角色节点一律归左侧
10972
11732
  * @csspart target-panel - 右侧面板容器,其内的角色节点一律归右侧
@@ -10975,7 +11735,7 @@ function stripNativeDisabled(el) {
10975
11735
  * @csspart panel-count - 计数节点,只带 data-count / data-checked-count,文案由作者写
10976
11736
  * @csspart search - 本侧搜索框,须是原生 input;searchable 关掉时带 hidden
10977
11737
  * @csspart list - role=listbox 容器,键盘在此收口,也是 roving tabindex 的兜底位
10978
- * @csspart item - role=option 条目,须自带 value 属性标识身份;禁用写在 items 里,不写在节点上
11738
+ * @csspart item - role=option 条目,须自带 value 属性标识身份;禁用写在 collection 里,不写在节点上
10979
11739
  * @csspart item-text - 条目文本
10980
11740
  * @csspart item-checkbox - 条目勾选标记(aria-hidden);oneWay 下右侧的那一份带 hidden
10981
11741
  * @csspart select-all-trigger - 本侧全选格,须是原生 button;三态经 aria-checked 上报
@@ -10988,7 +11748,7 @@ var XhTransferElement = class extends XhElement {
10988
11748
  meta: transferMeta
10989
11749
  };
10990
11750
  static properties = {
10991
- items: { attribute: false },
11751
+ collection: { attribute: false },
10992
11752
  value: { attribute: false },
10993
11753
  defaultValue: { attribute: false },
10994
11754
  selected: { attribute: false },
@@ -11014,7 +11774,7 @@ var XhTransferElement = class extends XhElement {
11014
11774
  }));
11015
11775
  };
11016
11776
  notifySelected = (details) => {
11017
- this.dispatchEvent(new CustomEvent("selected-change", {
11777
+ this.dispatchEvent(new CustomEvent("selection-change", {
11018
11778
  detail: details,
11019
11779
  bubbles: true,
11020
11780
  composed: true
@@ -11023,7 +11783,7 @@ var XhTransferElement = class extends XhElement {
11023
11783
  ctrl = new MachineController(this, transferMachine, () => this.machineProps());
11024
11784
  machineProps() {
11025
11785
  return {
11026
- items: this.items,
11786
+ collection: this.collection,
11027
11787
  value: this.value,
11028
11788
  defaultValue: this.defaultValue,
11029
11789
  selected: this.selected,
@@ -11035,7 +11795,7 @@ var XhTransferElement = class extends XhElement {
11035
11795
  loop: this.loop,
11036
11796
  dir: this.direction,
11037
11797
  onValueChange: this.notifyValue,
11038
- onSelectedChange: this.notifySelected
11798
+ onSelectionChange: this.notifySelected
11039
11799
  };
11040
11800
  }
11041
11801
  /**
@@ -11120,6 +11880,8 @@ const BRANCH_SELECTOR$1 = "[data-xh-part=\"branch\"]";
11120
11880
  *
11121
11881
  * @customElement xh-tree
11122
11882
  * @attr {'single'|'multiple'} selection-mode - 选择模式,默认 single
11883
+ * @attr {boolean} cascade - multiple 下父子级联勾选(整枝传导/半选/禁用冻结),默认 false
11884
+ * @attr {string} checked-strategy - 级联下对外值的收敛策略:child(默认)/ parent / all
11123
11885
  * @attr {boolean} expand-on-click - 点分支行顺带展开/收起,默认开;写 expand-on-click="false" 关掉
11124
11886
  * @attr {boolean} disabled - 整棵树禁用:所有节点转 aria-disabled,键盘与点击都改不了展开与选中
11125
11887
  * @attr {boolean} loop - 上下键走到首尾回绕,默认关;写 loop="true" 打开
@@ -11155,6 +11917,11 @@ var XhTreeElement = class extends XhElement {
11155
11917
  converter: STRING_CONVERTER$3,
11156
11918
  attribute: "selection-mode"
11157
11919
  },
11920
+ cascade: { type: Boolean },
11921
+ checkedStrategy: {
11922
+ converter: STRING_CONVERTER$3,
11923
+ attribute: "checked-strategy"
11924
+ },
11158
11925
  expandOnClick: {
11159
11926
  converter: BOOLEAN_CONVERTER$2,
11160
11927
  attribute: "expand-on-click"
@@ -11190,6 +11957,8 @@ var XhTreeElement = class extends XhElement {
11190
11957
  selectedValue: this.selectedValue,
11191
11958
  defaultSelectedValue: this.defaultSelectedValue,
11192
11959
  selectionMode: this.selectionMode,
11960
+ cascade: this.cascade,
11961
+ checkedStrategy: this.checkedStrategy,
11193
11962
  expandOnClick: this.expandOnClick,
11194
11963
  disabled: this.disabled ?? false,
11195
11964
  loop: this.loop,
@@ -11274,6 +12043,8 @@ const BRANCH_SELECTOR = "[data-xh-part=\"branch\"]";
11274
12043
  * @attr {boolean} open - 受控开合;缺省该属性即非受控
11275
12044
  * @attr {boolean} default-open - 非受控初始为展开
11276
12045
  * @attr {boolean} multiple - 多选:选中后浮层不收起,焦点留在树里
12046
+ * @attr {boolean} cascade - 多选下父子级联勾选(整枝传导/半选/禁用冻结),默认 false
12047
+ * @attr {string} checked-strategy - 级联下对外值的收敛策略:child(默认)/ parent / all
11277
12048
  * @attr {boolean} disabled - 整个控件禁用:trigger 用原生 disabled,表单出口不参与提交
11278
12049
  * @attr {boolean} read-only - 只读:浮层照常展开、树照常浏览,但选中值改不动、也清不掉
11279
12050
  * @attr {boolean} invalid - 校验失败标注
@@ -11296,8 +12067,8 @@ const BRANCH_SELECTOR = "[data-xh-part=\"branch\"]";
11296
12067
  * @csspart indicator - 展开指示符(aria-hidden,data-state 随开合)
11297
12068
  * @csspart clear-trigger - 清空按钮,须是原生 button;不占 Tab 位且对读屏隐藏
11298
12069
  * @csspart positioner - 浮层定位容器,坐标由引擎写成内联样式
11299
- * @csspart content - 浮层壳(焦点域与消解层的根节点),收起时带 hidden
11300
- * @csspart tree - role=tree 容器,键盘在此收口,也是没有锚点时的 Tab 兜底位
12070
+ * @csspart content - 浮层壳(焦点域与消解层的根节点,键盘在此收口),收起时带 hidden
12071
+ * @csspart tree - role=tree 容器,没有锚点时的 Tab 兜底位与落焦点
11301
12072
  * @csspart item - role=treeitem 叶子,须自带 value 属性标识身份
11302
12073
  * @csspart item-text - 叶子文本
11303
12074
  * @csspart item-indicator - 叶子选中标记(aria-hidden)
@@ -11329,6 +12100,11 @@ var XhTreeSelectElement = class extends XhElement {
11329
12100
  attribute: "default-open"
11330
12101
  },
11331
12102
  multiple: { type: Boolean },
12103
+ cascade: { type: Boolean },
12104
+ checkedStrategy: {
12105
+ converter: STRING_CONVERTER$2,
12106
+ attribute: "checked-strategy"
12107
+ },
11332
12108
  disabled: { type: Boolean },
11333
12109
  readOnly: {
11334
12110
  converter: BOOLEAN_CONVERTER$1,
@@ -11339,6 +12115,7 @@ var XhTreeSelectElement = class extends XhElement {
11339
12115
  tone: { converter: STRING_CONVERTER$2 },
11340
12116
  size: { converter: STRING_CONVERTER$2 },
11341
12117
  placeholder: { converter: STRING_CONVERTER$2 },
12118
+ translations: { attribute: false },
11342
12119
  placement: { converter: STRING_CONVERTER$2 },
11343
12120
  offset: { converter: NUMBER_CONVERTER$2 },
11344
12121
  loop: { converter: BOOLEAN_CONVERTER$1 },
@@ -11389,6 +12166,8 @@ var XhTreeSelectElement = class extends XhElement {
11389
12166
  open: this.open,
11390
12167
  defaultOpen: this.defaultOpen ?? false,
11391
12168
  multiple: this.multiple ?? false,
12169
+ cascade: this.cascade,
12170
+ checkedStrategy: this.checkedStrategy,
11392
12171
  disabled: this.disabled ?? false,
11393
12172
  readOnly: this.readOnly ?? false,
11394
12173
  invalid: this.invalid ?? false,
@@ -11396,6 +12175,7 @@ var XhTreeSelectElement = class extends XhElement {
11396
12175
  tone: this.tone,
11397
12176
  size: this.size,
11398
12177
  placeholder: this.placeholder,
12178
+ translations: this.translations,
11399
12179
  placement: this.placement,
11400
12180
  offset: this.offset,
11401
12181
  loop: this.loop,
@@ -11831,6 +12611,7 @@ function defineXhElements() {
11831
12611
  defineElement("xh-hover-card", XhHoverCardElement, version);
11832
12612
  defineElement("xh-icon", XhIconElement, version);
11833
12613
  defineElement("xh-image", XhImageElement, version);
12614
+ defineElement("xh-image-viewer", XhImageViewerElement, version);
11834
12615
  defineElement("xh-listbox", XhListboxElement, version);
11835
12616
  defineElement("xh-loading-bar", XhLoadingBarElement, version);
11836
12617
  defineElement("xh-menu", XhMenuElement, version);
@@ -11846,6 +12627,7 @@ function defineXhElements() {
11846
12627
  defineElement("xh-scroll-area", XhScrollAreaElement, version);
11847
12628
  defineElement("xh-select", XhSelectElement, version);
11848
12629
  defineElement("xh-separator", XhSeparatorElement, version);
12630
+ defineElement("xh-side-nav", XhSideNavElement, version);
11849
12631
  defineElement("xh-slider", XhSliderElement, version);
11850
12632
  defineElement("xh-splitter", XhSplitterElement, version);
11851
12633
  defineElement("xh-statistic", XhStatisticElement, version);
@@ -11875,6 +12657,6 @@ function defineXhElements() {
11875
12657
  defineElement("xh-watermark", XhWatermarkElement, version);
11876
12658
  }
11877
12659
  //#endregion
11878
- export { XhAccordionElement, XhAlertElement, XhAnchorElement, XhAvatarElement, XhBadgeElement, XhBreadcrumbElement, XhButtonElement, XhCalendarElement, XhCarouselElement, XhCascaderElement, XhCheckboxElement, XhCheckboxGroupElement, XhClipboardElement, XhCodeBlockElement, XhCollapsibleElement, XhColorPickerElement, XhComboboxElement, XhComposerElement, XhContextMenuElement, XhDateFieldElement, XhDatePickerElement, XhDialogElement, XhDrawerElement, XhEditableElement, XhEmptyStateElement, XhFieldElement, XhFileUploadElement, XhFormElement, XhHoverCardElement, XhIconElement, XhImageElement, XhListboxElement, XhLoadingBarElement, XhMenuElement, XhMenubarElement, XhNavigationMenuElement, XhNumberFieldElement, XhPaginationElement, XhPinInputElement, XhPopoverElement, XhProgressElement, XhRadioGroupElement, XhRatingElement, XhScrollAreaElement, XhSelectElement, XhSeparatorElement, XhSkeletonElement, XhSliderElement, XhSpinnerElement, XhSplitterElement, XhStepsElement, XhSwitchElement, XhTableElement, XhTabsElement, XhTagsInputElement, XhTextFieldElement, XhThreadElement, XhTimeFieldElement, XhTimePickerElement, XhToastElement, XhToasterElement, XhToggleElement, XhToggleGroupElement, XhToolbarElement, XhTooltipElement, XhTourElement, XhTransferElement, XhTreeElement, XhTreeSelectElement, XhVirtualizerElement, defineXhElements };
12660
+ export { XhAccordionElement, XhAlertElement, XhAnchorElement, XhAvatarElement, XhBadgeElement, XhBreadcrumbElement, XhButtonElement, XhCalendarElement, XhCarouselElement, XhCascaderElement, XhCheckboxElement, XhCheckboxGroupElement, XhClipboardElement, XhCodeBlockElement, XhCollapsibleElement, XhColorPickerElement, XhComboboxElement, XhComposerElement, XhContextMenuElement, XhDateFieldElement, XhDatePickerElement, XhDialogElement, XhDrawerElement, XhEditableElement, XhEmptyStateElement, XhFieldElement, XhFileUploadElement, XhFormElement, XhHoverCardElement, XhIconElement, XhImageElement, XhImageViewerElement, XhListboxElement, XhLoadingBarElement, XhMenuElement, XhMenubarElement, XhNavigationMenuElement, XhNumberFieldElement, XhPaginationElement, XhPinInputElement, XhPopoverElement, XhProgressElement, XhRadioGroupElement, XhRatingElement, XhScrollAreaElement, XhSelectElement, XhSeparatorElement, XhSideNavElement, XhSkeletonElement, XhSliderElement, XhSpinnerElement, XhSplitterElement, XhStepsElement, XhSwitchElement, XhTableElement, XhTabsElement, XhTagsInputElement, XhTextFieldElement, XhThreadElement, XhTimeFieldElement, XhTimePickerElement, XhToastElement, XhToasterElement, XhToggleElement, XhToggleGroupElement, XhToolbarElement, XhTooltipElement, XhTourElement, XhTransferElement, XhTreeElement, XhTreeSelectElement, XhVirtualizerElement, defineXhElements };
11879
12661
 
11880
12662
  //# sourceMappingURL=define.js.map