@kne/system-layout 0.2.0-alpha.20 → 0.2.0-alpha.22

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.
@@ -32,7 +32,7 @@ function _extends() {
32
32
  }, _extends.apply(null, arguments);
33
33
  }
34
34
 
35
- var style$3 = {"kne-responsive-boundary":"kne-system-layout_VtEb1","kne-responsive-scroll":"kne-system-layout_UMzfg","layout":"kne-system-layout_sK89O","has-toolbar":"kne-system-layout_gyKfI","has-navbar":"kne-system-layout_X1wZG","menu":"kne-system-layout_-LpWn","open":"kne-system-layout_G-zuN","layer-menu":"kne-system-layout_6TCwG","ai-entry":"kne-system-layout_5qnw5","page":"kne-system-layout_HnwkM","page-content":"kne-system-layout_nyAa2","toolbar":"kne-system-layout_h8PAW","page-children":"kne-system-layout_OM1Q2","is-scroller":"kne-system-layout_6gjkS","is-mobile":"kne-system-layout_udBgQ","logo":"kne-system-layout_-T-Dc","menu-header":"kne-system-layout_LOrmu","menu-boundary-overlay":"kne-system-layout_-cMpV","is-portaled":"kne-system-layout_leFsD","logo-img":"kne-system-layout_2cRWf","expand-btn-wrapper":"kne-system-layout_5D-Oq","expand-btn-bg":"kne-system-layout_p4eOE","expand-btn":"kne-system-layout_8dzE7","menu-inner":"kne-system-layout_7wq3X","menu-list":"kne-system-layout_8gqbZ","username":"kne-system-layout_b7XeQ","user-description":"kne-system-layout_U0YTk","ai-dialog-window":"kne-system-layout_UAJc-","pulse-dialog-window":"kne-system-layout_VjIWn","page-dialog-outer":"kne-system-layout_I7Anv","page-dialog":"kne-system-layout_UhsFd","pulse-page-dialog":"kne-system-layout_H7slV","page-window-content":"kne-system-layout_2mdNn","ai-dialog-window-title":"kne-system-layout_33Tja","ai-dialog-window-content":"kne-system-layout_YmBhl"};
35
+ var style$3 = {"kne-responsive-boundary":"kne-system-layout_VtEb1","kne-responsive-scroll":"kne-system-layout_UMzfg","layout":"kne-system-layout_sK89O","has-toolbar":"kne-system-layout_gyKfI","has-navbar":"kne-system-layout_X1wZG","menu":"kne-system-layout_-LpWn","open":"kne-system-layout_G-zuN","layer-menu":"kne-system-layout_6TCwG","ai-entry":"kne-system-layout_5qnw5","page":"kne-system-layout_HnwkM","page-content":"kne-system-layout_nyAa2","toolbar":"kne-system-layout_h8PAW","page-children":"kne-system-layout_OM1Q2","is-scroller":"kne-system-layout_6gjkS","is-mobile":"kne-system-layout_udBgQ","logo":"kne-system-layout_-T-Dc","menu-header":"kne-system-layout_LOrmu","menu-boundary-overlay":"kne-system-layout_-cMpV","is-portaled":"kne-system-layout_leFsD","logo-img":"kne-system-layout_2cRWf","expand-btn-wrapper":"kne-system-layout_5D-Oq","expand-btn-bg":"kne-system-layout_p4eOE","expand-btn":"kne-system-layout_8dzE7","menu-inner":"kne-system-layout_7wq3X","menu-list":"kne-system-layout_8gqbZ","username":"kne-system-layout_b7XeQ","user-description":"kne-system-layout_U0YTk","ai-dialog-window":"kne-system-layout_UAJc-","pulse-dialog-window":"kne-system-layout_VjIWn","is-mobile-full":"kne-system-layout_tiNSQ","is-viewport":"kne-system-layout_UxwXs","ai-dialog-window-title":"kne-system-layout_33Tja","ai-dialog-window-content":"kne-system-layout_YmBhl","ai-boundary-overlay":"kne-system-layout_Nt0Rj","ai-entry-mobile":"kne-system-layout_ln2Ag","is-boundary":"kne-system-layout_dWwHX","page-dialog-outer":"kne-system-layout_I7Anv","page-dialog":"kne-system-layout_UhsFd","pulse-page-dialog":"kne-system-layout_H7slV","page-window-content":"kne-system-layout_2mdNn"};
36
36
 
37
37
  const UserCard = ({
38
38
  name,
@@ -579,6 +579,83 @@ const LayoutResponsiveScope = ({
579
579
  });
580
580
  };
581
581
  const LayoutMenuOpenKey = 'LAYOUT_MENU_OPEN';
582
+ const DRAG_THRESHOLD = 4;
583
+ const MobileAiEntry = ({
584
+ variant,
585
+ onOpen
586
+ }) => {
587
+ const btnRef = useRef(null);
588
+ const dragRef = useRef(null);
589
+ const [pos, setPos] = useState(null);
590
+ const handlePointerDown = event => {
591
+ const node = btnRef.current;
592
+ if (!node) {
593
+ return;
594
+ }
595
+ // 与 toolbar 一致:boundary 模式下相对定位容器为 offsetParent,viewport 模式下相对视口
596
+ const container = node.offsetParent;
597
+ const rect = node.getBoundingClientRect();
598
+ const refLeft = container ? container.getBoundingClientRect().left : 0;
599
+ const refTop = container ? container.getBoundingClientRect().top : 0;
600
+ dragRef.current = {
601
+ startX: event.clientX,
602
+ startY: event.clientY,
603
+ originLeft: rect.left - refLeft,
604
+ originTop: rect.top - refTop,
605
+ refWidth: container ? container.clientWidth : window.innerWidth,
606
+ refHeight: container ? container.clientHeight : window.innerHeight,
607
+ size: node.offsetWidth,
608
+ moved: false
609
+ };
610
+ node.setPointerCapture == null || node.setPointerCapture(event.pointerId);
611
+ };
612
+ const handlePointerMove = event => {
613
+ const drag = dragRef.current;
614
+ if (!drag) {
615
+ return;
616
+ }
617
+ const dx = event.clientX - drag.startX;
618
+ const dy = event.clientY - drag.startY;
619
+ if (Math.abs(dx) > DRAG_THRESHOLD || Math.abs(dy) > DRAG_THRESHOLD) {
620
+ drag.moved = true;
621
+ }
622
+ const maxLeft = Math.max(8, drag.refWidth - drag.size - 8);
623
+ const maxTop = Math.max(8, drag.refHeight - drag.size - 8);
624
+ setPos({
625
+ left: Math.min(Math.max(8, drag.originLeft + dx), maxLeft),
626
+ top: Math.min(Math.max(8, drag.originTop + dy), maxTop)
627
+ });
628
+ };
629
+ const handlePointerUp = event => {
630
+ var _btnRef$current;
631
+ const drag = dragRef.current;
632
+ dragRef.current = null;
633
+ (_btnRef$current = btnRef.current) == null || _btnRef$current.releasePointerCapture == null || _btnRef$current.releasePointerCapture(event.pointerId);
634
+ if (drag && !drag.moved) {
635
+ onOpen();
636
+ }
637
+ };
638
+ return /*#__PURE__*/jsx("div", {
639
+ ref: btnRef,
640
+ className: classnames('ai-entry-mobile', style$3['ai-entry-mobile'], {
641
+ [style$3['is-viewport']]: variant === 'viewport',
642
+ [style$3['is-boundary']]: variant !== 'viewport'
643
+ }),
644
+ style: pos ? {
645
+ left: `${pos.left}px`,
646
+ top: `${pos.top}px`,
647
+ right: 'auto',
648
+ bottom: 'auto'
649
+ } : undefined,
650
+ onPointerDown: handlePointerDown,
651
+ onPointerMove: handlePointerMove,
652
+ onPointerUp: handlePointerUp,
653
+ children: /*#__PURE__*/jsx(Icon, {
654
+ type: "system-prompt",
655
+ colorful: true
656
+ })
657
+ });
658
+ };
582
659
  const Layout = ({
583
660
  className,
584
661
  menu,
@@ -714,7 +791,7 @@ const Layout = ({
714
791
  deviceIsMobile && setMenuOpen(false);
715
792
  }
716
793
  }))
717
- }), _aiDialog && /*#__PURE__*/jsx("div", {
794
+ }), _aiDialog && !deviceIsMobile && /*#__PURE__*/jsx("div", {
718
795
  className: classnames('ai-entry', style$3['ai-entry']),
719
796
  onClick: () => {
720
797
  setAiType('small');
@@ -727,6 +804,61 @@ const Layout = ({
727
804
  })]
728
805
  });
729
806
  const portalMenu = useMenuPortal && menuPortalTarget;
807
+ const aiDialogWindow = _aiDialog && aiType === 'small' ? /*#__PURE__*/jsxs("div", {
808
+ className: classnames('ai-dialog-window', style$3['ai-dialog-window'], {
809
+ 'is-mobile-full': deviceIsMobile,
810
+ [style$3['is-mobile-full']]: deviceIsMobile,
811
+ [style$3['is-viewport']]: deviceIsMobile && !portalMenu
812
+ }),
813
+ children: [/*#__PURE__*/jsxs(Flex, {
814
+ className: classnames('ai-dialog-window-title', style$3['ai-dialog-window-title']),
815
+ children: [/*#__PURE__*/jsx("div", {
816
+ children: _aiDialog.title
817
+ }), /*#__PURE__*/jsxs(Flex, {
818
+ gap: 10,
819
+ children: [!deviceIsMobile && /*#__PURE__*/jsx(Icon, {
820
+ className: "btn",
821
+ type: "icon-a-Typeopen_in_full",
822
+ fontClassName: "system",
823
+ onClick: () => {
824
+ setAiType('inner');
825
+ }
826
+ }), /*#__PURE__*/jsx(Icon, {
827
+ className: "btn",
828
+ type: "icon-a-Typeclose",
829
+ fontClassName: "system",
830
+ onClick: () => {
831
+ setAiType('closed');
832
+ }
833
+ })]
834
+ })]
835
+ }), /*#__PURE__*/jsx(ErrorBoundary, {
836
+ children: /*#__PURE__*/jsx("div", {
837
+ className: classnames('ai-dialog-window-content', style$3['ai-dialog-window-content']),
838
+ children: _aiDialog.content
839
+ })
840
+ })]
841
+ }) : null;
842
+ const aiEntryMobile = deviceIsMobile && _aiDialog && aiType === 'closed' ? /*#__PURE__*/jsx(MobileAiEntry, {
843
+ variant: portalMenu ? 'boundary' : 'viewport',
844
+ onOpen: () => setAiType('small')
845
+ }) : null;
846
+
847
+ // portal 到 boundary(popup 挂载点)时,layout 上的 CSS 变量不会随 portal 继承,需要显式透传
848
+ const aiPortalVars = {
849
+ '--background': _background,
850
+ '--toolbar-height': deviceIsMobile && toolbarShow ? '72px' : '0px',
851
+ '--safe-area-inset-top': 'env(safe-area-inset-top)',
852
+ '--safe-area-inset-bottom': 'env(safe-area-inset-bottom)'
853
+ };
854
+ const aiOverlayContent = aiDialogWindow || aiEntryMobile ? /*#__PURE__*/jsxs(Fragment, {
855
+ children: [aiDialogWindow, aiEntryMobile]
856
+ }) : null;
857
+ const aiOverlay = !aiOverlayContent ? null : portalMenu ? /*#__PURE__*/createPortal(/*#__PURE__*/jsx("div", {
858
+ className: classnames('ai-boundary-overlay', style$3['ai-boundary-overlay']),
859
+ style: aiPortalVars,
860
+ children: aiOverlayContent
861
+ }), menuPortalTarget) : aiOverlayContent;
730
862
  return /*#__PURE__*/jsx(LayoutResponsiveScope, {
731
863
  boundaryRef: layoutBoundaryRef,
732
864
  scrollRef: pageScrollRef,
@@ -814,38 +946,8 @@ const Layout = ({
814
946
  })
815
947
  })]
816
948
  })
817
- }), _aiDialog && aiType === 'small' && /*#__PURE__*/jsxs("div", {
818
- className: classnames('ai-dialog-window', style$3['ai-dialog-window']),
819
- children: [/*#__PURE__*/jsxs(Flex, {
820
- className: classnames('ai-dialog-window-title', style$3['ai-dialog-window-title']),
821
- children: [/*#__PURE__*/jsx("div", {
822
- children: _aiDialog.title
823
- }), /*#__PURE__*/jsxs(Flex, {
824
- gap: 10,
825
- children: [/*#__PURE__*/jsx(Icon, {
826
- className: "btn",
827
- type: "icon-a-Typeopen_in_full",
828
- fontClassName: "system",
829
- onClick: () => {
830
- setAiType('inner');
831
- }
832
- }), /*#__PURE__*/jsx(Icon, {
833
- className: "btn",
834
- type: "icon-a-Typeclose",
835
- fontClassName: "system",
836
- onClick: () => {
837
- setAiType('closed');
838
- }
839
- })]
840
- })]
841
- }), /*#__PURE__*/jsx(ErrorBoundary, {
842
- children: /*#__PURE__*/jsx("div", {
843
- className: classnames('ai-dialog-window-content', style$3['ai-dialog-window-content']),
844
- children: _aiDialog.content
845
- })
846
- })]
847
949
  })]
848
- }), /*#__PURE__*/jsx(Toolbar, _extends({}, menu, {
950
+ }), aiOverlay, /*#__PURE__*/jsx(Toolbar, _extends({}, menu, {
849
951
  className: classnames(style$3['toolbar']),
850
952
  show: deviceIsMobile && toolbarShow,
851
953
  target: toolbarTarget