@laser-ui/components 0.0.5 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,16 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
4
4
 
5
+ ## [0.1.1](https://github.com/laser-ui/laser-ui/compare/v0.1.0...v0.1.1) (2023-09-13)
6
+
7
+ ### Bug Fixes
8
+
9
+ - **components:** fix `container` is null ([151da41](https://github.com/laser-ui/laser-ui/commit/151da41063f8e629ef18ece4d70c9a35cb38b2f8))
10
+
11
+ # [0.1.0](https://github.com/laser-ui/laser-ui/compare/v0.0.5...v0.1.0) (2023-09-12)
12
+
13
+ **Note:** Version bump only for package @laser-ui/components
14
+
5
15
  ## [0.0.5](https://github.com/laser-ui/laser-ui/compare/v0.0.4...v0.0.5) (2023-09-11)
6
16
 
7
17
  **Note:** Version bump only for package @laser-ui/components
package/README.md CHANGED
@@ -1,15 +1,15 @@
1
1
  <p align="center">
2
- <a href="//react-devui.com" rel="noopener" target="_blank"><img width="150" src="/packages/site/src/assets/logo.svg" alt="DevUI logo"></a>
2
+ <a href="//laser-ui.surge.sh/" rel="noopener" target="_blank"><img width="150" src="apps/site/public/logo.png" alt="logo"></a>
3
3
  </p>
4
4
 
5
- <h1 align="center">React DevUI</h1>
5
+ <h1 align="center">Laser UI</h1>
6
6
 
7
7
  <div align="center">
8
8
 
9
9
  <!-- prettier-ignore-start -->
10
- [![npm latest package](http://img.shields.io/npm/v/@react-devui/ui/latest.svg?style=flat-square)](https://www.npmjs.com/package/@react-devui/ui)
11
- [![npm bundle size](https://img.shields.io/bundlephobia/minzip/@react-devui/ui?style=flat-square)](https://bundlephobia.com/package/@react-devui/ui)
12
- [![gitHub workflow status](https://img.shields.io/github/actions/workflow/status/DevCloudFE/react-devui/main.yml?branch=main&style=flat-square)](https://github.com/DevCloudFE/react-devui/actions/workflows/main.yml)
10
+ [![npm latest package](http://img.shields.io/npm/v/@laser-ui/components/latest.svg?style=flat-square)](https://www.npmjs.com/package/@laser-ui/components)
11
+ [![npm bundle size](https://img.shields.io/bundlephobia/minzip/@laser-ui/components?style=flat-square)](https://bundlephobia.com/package/@laser-ui/components)
12
+ [![gitHub workflow status](https://img.shields.io/github/actions/workflow/status/laser-ui/laser-ui/main.yml?branch=main&style=flat-square)](https://github.com/laser-ui/laser-ui/actions/workflows/main.yml)
13
13
  <!-- prettier-ignore-end -->
14
14
 
15
15
  </div>
@@ -23,49 +23,48 @@ English | [简体中文](README.zh-CN.md)
23
23
  ## Installation
24
24
 
25
25
  ```bash
26
- yarn add @react-devui/ui @react-devui/icons @react-devui/hooks @react-devui/utils
26
+ npm install @laser-ui/components @laser-ui/hooks @laser-ui/themes @laser-ui/utils
27
27
  ```
28
28
 
29
29
  ## Getting Started
30
30
 
31
31
  ```tsx
32
- import type { DRootProps } from '@react-devui/ui';
32
+ import type { LContextIn } from '@laser-ui/components/context';
33
33
 
34
+ import { ConfigProvider, Root } from '@laser-ui/components';
34
35
  import { useMemo } from 'react';
35
36
 
36
- import { DRoot } from '@react-devui/ui';
37
-
38
37
  export default function App() {
39
- const rootContext = useMemo<DRootProps['context']>(
38
+ const lContext = useMemo<LContextIn>(
40
39
  () => ({
41
- layout: { pageScrollEl: '#app-main', contentResizeEl: '#app-content' },
40
+ layoutPageScrollEl: '#app-main',
41
+ layoutContentResizeEl: '#app-content',
42
42
  }),
43
- []
43
+ [],
44
44
  );
45
45
 
46
46
  return (
47
- <DRoot context={rootContext}>
48
- <main id="app-main" style={{ overflow: 'auto' }}>
49
- <section id="app-content" style={{ height: '200vh' }}>
50
- Some content...
51
- </section>
52
- </main>
53
- </DRoot>
47
+ <ConfigProvider context={lContext}>
48
+ <Root>
49
+ <main id="app-main" style={{ overflow: 'auto' }}>
50
+ <section id="app-content" style={{ height: '200vh' }}>
51
+ Some content...
52
+ </section>
53
+ </main>
54
+ </Root>
55
+ </ConfigProvider>
54
56
  );
55
57
  }
56
58
  ```
57
59
 
58
60
  ## Links
59
61
 
60
- - [react-devui.com](//react-devui.com)
61
- - [admin.react-devui.com](//admin.react-devui.com)
62
+ - [laser-ui.surge.sh](//laser-ui.surge.sh)
62
63
 
63
64
  ## Contributing
64
65
 
65
66
  Please read our [contributing guide](/CONTRIBUTING.md) first.
66
67
 
67
- Need unit test support (Jest) 🤝.
68
-
69
68
  ## License
70
69
 
71
- [![gitHub license](https://img.shields.io/github/license/DevCloudFE/react-devui?style=flat-square)](/LICENSE)
70
+ [![gitHub license](https://img.shields.io/github/license/laser-ui/laser-ui?style=flat-square)](/LICENSE)
package/affix/Affix.js CHANGED
@@ -1,55 +1,65 @@
1
1
  import { Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useEvent, useEventCallback, useIsomorphicLayoutEffect, useRefExtra, useResize } from '@laser-ui/hooks';
2
+ import { useEvent, useEventCallback, useMount, useRefExtra, useResize } from '@laser-ui/hooks';
3
3
  import { getOffsetToRoot, toPx } from '@laser-ui/utils';
4
4
  import { isFunction, isString, isUndefined } from 'lodash';
5
5
  import { cloneElement, forwardRef, useId, useImperativeHandle, useState } from 'react';
6
- import { useComponentProps, useLayout, useListenGlobalScrolling, useNamespace } from '../hooks';
6
+ import { useComponentProps, useJSS, useLayout, useListenGlobalScrolling, useNamespace } from '../hooks';
7
7
  export const Affix = forwardRef((props, ref) => {
8
8
  const { children, top = 0, target, zIndex } = useComponentProps('Affix', props);
9
9
  const namespace = useNamespace();
10
+ const sheet = useJSS();
10
11
  const { pageScrollRef, contentResizeRef } = useLayout();
11
12
  const uniqueId = useId();
12
13
  const affixRef = useRefExtra(() => document.querySelector(`[data-l-affix="${uniqueId}"]`));
13
- const referenceRef = useRefExtra(() => document.querySelector(`[data-l-affix-reference="${uniqueId}"]`));
14
+ const placeholderRef = useRefExtra(() => document.querySelector(`[data-l-affix-placeholder="${uniqueId}"]`));
14
15
  const targetRef = useRefExtra(isUndefined(target) ? () => pageScrollRef.current : target);
15
16
  const [sticky, setSticky] = useState(false);
16
- const [positionStyle, setPositionStyle] = useState();
17
17
  const updatePosition = useEventCallback(() => {
18
- const offsetEl = sticky ? referenceRef.current : affixRef.current;
19
- if (targetRef.current && offsetEl) {
18
+ if (affixRef.current && placeholderRef.current && targetRef.current) {
19
+ const offsetEl = sticky ? placeholderRef.current : affixRef.current;
20
20
  const offsetRect = offsetEl.getBoundingClientRect();
21
21
  const targetTop = getOffsetToRoot(targetRef.current);
22
22
  const distance = isString(top) ? toPx(top, true) : top;
23
- setSticky(Math.ceil(targetRef.current.scrollTop) + distance >= getOffsetToRoot(offsetEl) - targetTop);
24
- setPositionStyle({
25
- width: offsetRect.width,
26
- height: offsetRect.height,
27
- top: (isUndefined(target) ? targetTop : targetRef.current.getBoundingClientRect().top) + distance,
28
- left: offsetRect.left,
29
- });
23
+ const newSticky = Math.ceil(targetRef.current.scrollTop) + distance >= getOffsetToRoot(offsetEl) - targetTop;
24
+ setSticky(newSticky);
25
+ if (sheet.classes.position) {
26
+ affixRef.current.classList.toggle(sheet.classes.position, false);
27
+ }
28
+ if (newSticky) {
29
+ sheet.replaceRule('position', {
30
+ width: offsetRect.width,
31
+ height: offsetRect.height,
32
+ position: 'fixed',
33
+ top: (isUndefined(target) ? targetTop : targetRef.current.getBoundingClientRect().top) + distance,
34
+ left: offsetRect.left,
35
+ zIndex: zIndex !== null && zIndex !== void 0 ? zIndex : `var(--${namespace}-zindex-sticky)`,
36
+ });
37
+ affixRef.current.classList.toggle(sheet.classes.position, true);
38
+ placeholderRef.current.style.display = '';
39
+ }
40
+ else {
41
+ sheet.deleteRule('position');
42
+ placeholderRef.current.style.display = 'none';
43
+ }
30
44
  }
31
45
  });
32
- useIsomorphicLayoutEffect(() => {
46
+ useMount(() => {
33
47
  updatePosition();
34
- // eslint-disable-next-line react-hooks/exhaustive-deps
35
- }, []);
48
+ });
36
49
  const listenGlobalScrolling = useListenGlobalScrolling(updatePosition);
37
50
  useEvent(pageScrollRef, 'scroll', updatePosition, { passive: true }, listenGlobalScrolling);
38
51
  useEvent(targetRef, 'scroll', updatePosition, { passive: true }, listenGlobalScrolling || isUndefined(target));
39
- useResize(sticky ? referenceRef : affixRef, updatePosition);
52
+ useResize(sticky ? placeholderRef : affixRef, updatePosition);
40
53
  useResize(contentResizeRef, updatePosition);
41
54
  useImperativeHandle(ref, () => ({
42
55
  sticky,
43
56
  updatePosition,
44
57
  }), [sticky, updatePosition]);
45
- const render = (el) => (_jsxs(_Fragment, { children: [sticky &&
46
- cloneElement(el, {
47
- style: Object.assign(Object.assign({}, el.props.style), { visibility: 'hidden' }),
48
- 'aria-hidden': true,
49
- 'data-l-affix-reference': uniqueId,
50
- }), cloneElement(el, {
51
- style: sticky
52
- ? Object.assign(Object.assign(Object.assign({}, el.props.style), positionStyle), { position: 'fixed', zIndex: zIndex !== null && zIndex !== void 0 ? zIndex : `var(--${namespace}-zindex-sticky)` }) : el.props.style,
58
+ const render = (el) => (_jsxs(_Fragment, { children: [cloneElement(el, {
59
+ style: Object.assign(Object.assign({}, el.props.style), { visibility: 'hidden' }),
60
+ 'aria-hidden': true,
61
+ 'data-l-affix-placeholder': uniqueId,
62
+ }), cloneElement(el, {
53
63
  'data-l-affix': uniqueId,
54
64
  })] }));
55
65
  return isFunction(children) ? children(render) : render(children);
package/anchor/Anchor.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import { __rest } from "tslib";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useEvent, useEventCallback, useIsomorphicLayoutEffect, useRefExtra, useResize } from '@laser-ui/hooks';
3
+ import { useEvent, useEventCallback, useMount, useRefExtra, useResize } from '@laser-ui/hooks';
4
4
  import { getOffsetToRoot, scrollTo, toPx } from '@laser-ui/utils';
5
5
  import { isArray, isString, isUndefined } from 'lodash';
6
- import { Fragment, forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react';
6
+ import { Fragment, forwardRef, useImperativeHandle, useRef, useState } from 'react';
7
7
  import { CLASSES, DOT_INDICATOR, LINE_INDICATOR } from './vars';
8
8
  import { useComponentProps, useLayout, useListenGlobalScrolling, useStyled } from '../hooks';
9
9
  import { mergeCS } from '../utils';
@@ -11,14 +11,13 @@ function AnchorFC(props, ref) {
11
11
  const _a = useComponentProps('Anchor', props), { styleOverrides, styleProvider, list, page, distance: distanceProp = 0, scrollBehavior = 'instant', indicator = DOT_INDICATOR, onClick } = _a, restProps = __rest(_a, ["styleOverrides", "styleProvider", "list", "page", "distance", "scrollBehavior", "indicator", "onClick"]);
12
12
  const styled = useStyled(CLASSES, { anchor: styleProvider === null || styleProvider === void 0 ? void 0 : styleProvider.anchor }, styleOverrides);
13
13
  const { pageScrollRef, contentResizeRef } = useLayout();
14
+ const pageRef = useRefExtra(page !== null && page !== void 0 ? page : (() => pageScrollRef.current));
14
15
  const anchorRef = useRef(null);
15
16
  const indicatorRef = useRef(null);
16
- const activeLinkRef = useRef(null);
17
- const pageRef = useRefExtra(page !== null && page !== void 0 ? page : (() => pageScrollRef.current));
18
17
  const dataRef = useRef({});
19
18
  const [active, setActive] = useState(null);
20
19
  const updateAnchor = useEventCallback(() => {
21
- if (pageRef.current) {
20
+ if (pageRef.current && anchorRef.current && indicatorRef.current) {
22
21
  const pageTop = getOffsetToRoot(pageRef.current);
23
22
  let nearestEl;
24
23
  const reduceLinks = (arr) => {
@@ -44,19 +43,8 @@ function AnchorFC(props, ref) {
44
43
  reduceLinks(list);
45
44
  const href = nearestEl ? nearestEl[0] : null;
46
45
  setActive(href);
47
- }
48
- });
49
- useIsomorphicLayoutEffect(() => {
50
- updateAnchor();
51
- // eslint-disable-next-line react-hooks/exhaustive-deps
52
- }, []);
53
- const listenGlobalScrolling = useListenGlobalScrolling(updateAnchor);
54
- useEvent(pageRef, 'scroll', updateAnchor, { passive: true }, listenGlobalScrolling);
55
- useResize(contentResizeRef, updateAnchor);
56
- useEffect(() => {
57
- if (anchorRef.current && indicatorRef.current) {
58
- if (activeLinkRef.current) {
59
- const rect = activeLinkRef.current.getBoundingClientRect();
46
+ if (href) {
47
+ const rect = anchorRef.current.querySelector(`[data-l-href="${href}"]`).getBoundingClientRect();
60
48
  const top = rect.top - anchorRef.current.getBoundingClientRect().top + rect.height / 2;
61
49
  indicatorRef.current.style.cssText = `opacity:1;top:${top}px;`;
62
50
  }
@@ -65,6 +53,12 @@ function AnchorFC(props, ref) {
65
53
  }
66
54
  }
67
55
  });
56
+ useMount(() => {
57
+ updateAnchor();
58
+ });
59
+ const listenGlobalScrolling = useListenGlobalScrolling(updateAnchor);
60
+ useEvent(pageRef, 'scroll', updateAnchor, { passive: true }, listenGlobalScrolling);
61
+ useResize(contentResizeRef, updateAnchor);
68
62
  useImperativeHandle(ref, () => ({
69
63
  active,
70
64
  updateAnchor,
@@ -91,10 +85,9 @@ function AnchorFC(props, ref) {
91
85
  const linkNodes = (() => {
92
86
  const getNodes = (arr, level = 0) => arr.map((link) => {
93
87
  const { title: linkTitle, href: linkHref, target: linkTarget, children } = link;
94
- const isActive = linkHref === active;
95
88
  return (_jsxs(Fragment, { children: [_jsx("li", Object.assign({}, styled('anchor__link', {
96
- 'anchor__link.is-active': isActive,
97
- }), { ref: isActive ? activeLinkRef : undefined, children: _jsx("a", { style: { paddingLeft: 16 + level * 16 }, href: `#${linkHref}`, target: linkTarget, onClick: (e) => {
89
+ 'anchor__link.is-active': linkHref === active,
90
+ }), { "data-l-href": linkHref, children: _jsx("a", { style: { paddingLeft: 16 + level * 16 }, href: `#${linkHref}`, target: linkTarget, onClick: (e) => {
98
91
  e.preventDefault();
99
92
  handleLinkClick(linkHref);
100
93
  onClick === null || onClick === void 0 ? void 0 : onClick(linkHref, link);
@@ -12,7 +12,7 @@ import { CascaderPanel } from './internal/CascaderPanel';
12
12
  import { CascaderSearchPanel } from './internal/CascaderSearchPanel';
13
13
  import { CLASSES } from './vars';
14
14
  import { Dropdown } from '../dropdown';
15
- import { useComponentProps, useControlled, useDesign, useFocusVisible, useLayout, useListenGlobalScrolling, useMaxIndex, useNamespace, useScopedProps, useStyled, useTranslation, } from '../hooks';
15
+ import { useComponentProps, useControlled, useDesign, useFocusVisible, useJSS, useLayout, useListenGlobalScrolling, useMaxIndex, useNamespace, useScopedProps, useStyled, useTranslation, } from '../hooks';
16
16
  import { Icon } from '../icon';
17
17
  import { CircularProgress } from '../internal/circular-progress';
18
18
  import { Portal } from '../internal/portal';
@@ -29,6 +29,7 @@ function CascaderFC(props, ref) {
29
29
  const _a = useComponentProps('Cascader', props), { styleOverrides, styleProvider, formControl, list, model, defaultModel, visible: visibleProp, defaultVisible, placeholder, multiple = false, searchable = false, searchValue: searchValueProp, defaultSearchValue, onlyLeafSelectable = true, clearable: clearableProp = false, loading = false, size: sizeProp, disabled: disabledProp = false, virtual = false, escClosable = true, customItem, customSelected, customSearch, inputRef: inputRefProp, inputRender, onModelChange, onVisibleChange, onSearch, onClear, onFirstFocus, afterVisibleChange } = _a, restProps = __rest(_a, ["styleOverrides", "styleProvider", "formControl", "list", "model", "defaultModel", "visible", "defaultVisible", "placeholder", "multiple", "searchable", "searchValue", "defaultSearchValue", "onlyLeafSelectable", "clearable", "loading", "size", "disabled", "virtual", "escClosable", "customItem", "customSelected", "customSearch", "inputRef", "inputRender", "onModelChange", "onVisibleChange", "onSearch", "onClear", "onFirstFocus", "afterVisibleChange"]);
30
30
  const namespace = useNamespace();
31
31
  const styled = useStyled(CLASSES, { cascader: styleProvider === null || styleProvider === void 0 ? void 0 : styleProvider.cascader, 'cascader-popup': styleProvider === null || styleProvider === void 0 ? void 0 : styleProvider['cascader-popup'] }, styleOverrides);
32
+ const sheet = useJSS();
32
33
  const { t } = useTranslation();
33
34
  const uniqueId = useId();
34
35
  const listId = `${namespace}-cascader-list-${uniqueId}`;
@@ -178,11 +179,7 @@ function CascaderFC(props, ref) {
178
179
  })();
179
180
  const maxZIndex = useMaxIndex(visible);
180
181
  const zIndex = `calc(var(--${namespace}-zindex-fixed) + ${maxZIndex})`;
181
- const [transformOrigin, setTransformOrigin] = useState();
182
- const [popupPositionStyle, setPopupPositionStyle] = useState({
183
- top: '-200vh',
184
- left: '-200vw',
185
- });
182
+ const transformOrigin = useRef();
186
183
  const updatePosition = useEventCallback(() => {
187
184
  if (visible && boxRef.current && popupRef.current) {
188
185
  const height = popupRef.current.offsetHeight;
@@ -192,12 +189,16 @@ function CascaderFC(props, ref) {
192
189
  placement: 'bottom-left',
193
190
  inWindow: WINDOW_SPACE,
194
191
  });
195
- setTransformOrigin(position.transformOrigin);
196
- setPopupPositionStyle({
192
+ transformOrigin.current = position.transformOrigin;
193
+ if (sheet.classes.position) {
194
+ popupRef.current.classList.toggle(sheet.classes.position, false);
195
+ }
196
+ sheet.replaceRule('position', {
197
197
  top: position.top,
198
198
  left: position.left,
199
199
  maxWidth,
200
200
  });
201
+ popupRef.current.classList.toggle(sheet.classes.position, true);
201
202
  }
202
203
  });
203
204
  const listenGlobalScrolling = useListenGlobalScrolling(updatePosition, !visible);
@@ -453,7 +454,7 @@ function CascaderFC(props, ref) {
453
454
  case 'entering':
454
455
  transitionStyle = {
455
456
  transition: ['transform', 'opacity'].map((attr) => `${attr} ${TTANSITION_DURING_POPUP}ms ease-out`).join(', '),
456
- transformOrigin,
457
+ transformOrigin: transformOrigin.current,
457
458
  };
458
459
  break;
459
460
  case 'leaving':
@@ -461,7 +462,7 @@ function CascaderFC(props, ref) {
461
462
  transform: 'scaleY(0.7)',
462
463
  opacity: 0,
463
464
  transition: ['transform', 'opacity'].map((attr) => `${attr} ${TTANSITION_DURING_POPUP}ms ease-in`).join(', '),
464
- transformOrigin,
465
+ transformOrigin: transformOrigin.current,
465
466
  };
466
467
  break;
467
468
  case 'leaved':
@@ -471,7 +472,7 @@ function CascaderFC(props, ref) {
471
472
  break;
472
473
  }
473
474
  return (_jsxs("div", Object.assign({}, mergeCS(styled('cascader-popup'), {
474
- style: Object.assign(Object.assign({ zIndex }, popupPositionStyle), transitionStyle),
475
+ style: Object.assign({ zIndex }, transitionStyle),
475
476
  }), { ref: popupRef, onMouseDown: (e) => {
476
477
  preventBlur(e);
477
478
  }, onMouseUp: (e) => {
@@ -6,12 +6,12 @@ import { ReactComponent as CancelFilled } from '@material-design-icons/svg/fille
6
6
  import { ReactComponent as CalendarTodayOutlined } from '@material-design-icons/svg/outlined/calendar_today.svg';
7
7
  import { ReactComponent as SwapHorizOutlined } from '@material-design-icons/svg/outlined/swap_horiz.svg';
8
8
  import { isArray, isBoolean, isNull, isUndefined } from 'lodash';
9
- import { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react';
9
+ import { forwardRef, useEffect, useImperativeHandle, useRef } from 'react';
10
10
  import { DatePickerPanel } from './internal/DatePickerPanel';
11
11
  import { CLASSES } from './vars';
12
12
  import { Button } from '../button';
13
13
  import dayjs from '../dayjs';
14
- import { useComponentProps, useControlled, useDesign, useLayout, useListenGlobalScrolling, useMaxIndex, useNamespace, useScopedProps, useStyled, useTranslation, } from '../hooks';
14
+ import { useComponentProps, useControlled, useDesign, useJSS, useLayout, useListenGlobalScrolling, useMaxIndex, useNamespace, useScopedProps, useStyled, useTranslation, } from '../hooks';
15
15
  import { Icon } from '../icon';
16
16
  import { Portal } from '../internal/portal';
17
17
  import { Transition } from '../internal/transition';
@@ -29,6 +29,7 @@ export const DatePicker = forwardRef((props, ref) => {
29
29
  'time-picker': styleProvider === null || styleProvider === void 0 ? void 0 : styleProvider['time-picker'],
30
30
  'date-picker-popup': styleProvider === null || styleProvider === void 0 ? void 0 : styleProvider['date-picker-popup'],
31
31
  }, styleOverrides);
32
+ const sheet = useJSS();
32
33
  const { t } = useTranslation();
33
34
  const forceUpdate = useForceUpdate();
34
35
  const async = useAsync();
@@ -117,11 +118,7 @@ export const DatePicker = forwardRef((props, ref) => {
117
118
  const { size, disabled } = useScopedProps({ size: sizeProp, disabled: disabledProp || (formControl === null || formControl === void 0 ? void 0 : formControl.control.disabled) });
118
119
  const maxZIndex = useMaxIndex(visible);
119
120
  const zIndex = `calc(var(--${namespace}-zindex-fixed) + ${maxZIndex})`;
120
- const [transformOrigin, setTransformOrigin] = useState();
121
- const [popupPositionStyle, setPopupPositionStyle] = useState({
122
- top: '-200vh',
123
- left: '-200vw',
124
- });
121
+ const transformOrigin = useRef();
125
122
  const updatePosition = useEventCallback(() => {
126
123
  if (visible && boxRef.current && popupRef.current) {
127
124
  const height = popupRef.current.offsetHeight;
@@ -131,12 +128,16 @@ export const DatePicker = forwardRef((props, ref) => {
131
128
  placement: 'bottom-left',
132
129
  inWindow: WINDOW_SPACE,
133
130
  });
134
- setTransformOrigin(position.transformOrigin);
135
- setPopupPositionStyle({
131
+ transformOrigin.current = position.transformOrigin;
132
+ if (sheet.classes.position) {
133
+ popupRef.current.classList.toggle(sheet.classes.position, false);
134
+ }
135
+ sheet.replaceRule('position', {
136
136
  top: position.top,
137
137
  left: position.left,
138
138
  maxWidth,
139
139
  });
140
+ popupRef.current.classList.toggle(sheet.classes.position, true);
140
141
  }
141
142
  });
142
143
  const listenGlobalScrolling = useListenGlobalScrolling(updatePosition, !visible);
@@ -314,7 +315,7 @@ export const DatePicker = forwardRef((props, ref) => {
314
315
  case 'entering':
315
316
  transitionStyle = {
316
317
  transition: ['transform', 'opacity'].map((attr) => `${attr} ${TTANSITION_DURING_POPUP}ms ease-out`).join(', '),
317
- transformOrigin,
318
+ transformOrigin: transformOrigin.current,
318
319
  };
319
320
  break;
320
321
  case 'leaving':
@@ -322,7 +323,7 @@ export const DatePicker = forwardRef((props, ref) => {
322
323
  transform: 'scaleY(0.7)',
323
324
  opacity: 0,
324
325
  transition: ['transform', 'opacity'].map((attr) => `${attr} ${TTANSITION_DURING_POPUP}ms ease-in`).join(', '),
325
- transformOrigin,
326
+ transformOrigin: transformOrigin.current,
326
327
  };
327
328
  break;
328
329
  case 'leaved':
@@ -332,7 +333,7 @@ export const DatePicker = forwardRef((props, ref) => {
332
333
  break;
333
334
  }
334
335
  return (_jsxs("div", Object.assign({}, mergeCS(styled('date-picker-popup'), {
335
- style: Object.assign(Object.assign({ zIndex }, popupPositionStyle), transitionStyle),
336
+ style: Object.assign({ zIndex }, transitionStyle),
336
337
  }), { ref: popupRef, onMouseDown: (e) => {
337
338
  preventBlur(e);
338
339
  }, onMouseUp: (e) => {
@@ -9,7 +9,7 @@ import { DropdownItem as DropdownItemFC } from './internal/DropdownItem';
9
9
  import { DropdownSub } from './internal/DropdownSub';
10
10
  import { checkEnableItem, getSameLevelEnableItems } from './utils';
11
11
  import { CLASSES } from './vars';
12
- import { useComponentProps, useControlled, useFocusVisible, useMaxIndex, useNamespace, useNestedPopup, useStyled, useTranslation, } from '../hooks';
12
+ import { useComponentProps, useControlled, useFocusVisible, useJSS, useMaxIndex, useNamespace, useNestedPopup, useStyled, useTranslation, } from '../hooks';
13
13
  import { Popup } from '../internal/popup';
14
14
  import { Portal } from '../internal/portal';
15
15
  import { Transition } from '../internal/transition';
@@ -22,6 +22,7 @@ function DropdownFC(props, ref) {
22
22
  const namespace = useNamespace();
23
23
  const { t } = useTranslation();
24
24
  const styled = useStyled(CLASSES, { dropdown: styleProvider === null || styleProvider === void 0 ? void 0 : styleProvider.dropdown, 'dropdown-popup': styleProvider === null || styleProvider === void 0 ? void 0 : styleProvider['dropdown-popup'] }, styleOverrides);
25
+ const sheet = useJSS();
25
26
  const uniqueId = useId();
26
27
  const id = (_a = restProps.id) !== null && _a !== void 0 ? _a : `${namespace}-dropdown-${uniqueId}`;
27
28
  let triggerId;
@@ -91,26 +92,28 @@ function DropdownFC(props, ref) {
91
92
  };
92
93
  const maxZIndex = useMaxIndex(visible);
93
94
  const zIndex = !isUndefined(zIndexProp) ? zIndexProp : `calc(var(--${namespace}-zindex-fixed) + ${maxZIndex})`;
94
- const [transformOrigin, setTransformOrigin] = useState();
95
- const [popupPositionStyle, setPopupPositionStyle] = useState({
96
- top: '-200vh',
97
- left: '-200vw',
98
- });
99
- const [placement, setPlacement] = useState(placementProp);
95
+ const transformOrigin = useRef();
96
+ const placement = useRef(placementProp);
100
97
  const updatePosition = useEventCallback(() => {
101
- if (visible && triggerRef.current && popupRef.current) {
98
+ if (visible && triggerRef.current && dropdownRef.current && popupRef.current) {
102
99
  const [width, height] = [popupRef.current.offsetWidth, popupRef.current.offsetHeight];
103
100
  const position = getVerticalSidePosition(triggerRef.current, { width, height }, {
104
101
  placement: placementProp,
105
102
  placementFixed,
106
103
  inWindow: WINDOW_SPACE,
107
104
  });
108
- setTransformOrigin(position.transformOrigin);
109
- setPopupPositionStyle({
105
+ transformOrigin.current = position.transformOrigin;
106
+ dropdownRef.current.classList.toggle(`${namespace}-dropdown--${placement.current}`, false);
107
+ placement.current = position.placement;
108
+ dropdownRef.current.classList.toggle(`${namespace}-dropdown--${placement.current}`, true);
109
+ if (sheet.classes.position) {
110
+ popupRef.current.classList.toggle(sheet.classes.position, false);
111
+ }
112
+ sheet.replaceRule('position', {
110
113
  top: position.top,
111
114
  left: position.left,
112
115
  });
113
- setPlacement(position.placement);
116
+ popupRef.current.classList.toggle(sheet.classes.position, true);
114
117
  }
115
118
  });
116
119
  const preventBlur = (e) => {
@@ -231,7 +234,7 @@ function DropdownFC(props, ref) {
231
234
  else {
232
235
  dataRef.current.updatePosition.set(itemId, fn);
233
236
  }
234
- }, namespace: namespace, styled: styled, dropdownRef: dropdownRef, id: id, level: level, icon: itemIcon, list: children && getNodes(children, 0, newSubParents), popupState: popupState === null || popupState === void 0 ? void 0 : popupState.visible, trigger: trigger, empty: isEmpty, focus: focusVisible && isFocus, disabled: itemDisabled, zIndex: isUndefined(zIndex)
237
+ }, namespace: namespace, styled: styled, id: id, level: level, icon: itemIcon, list: children && getNodes(children, 0, newSubParents), popupState: popupState === null || popupState === void 0 ? void 0 : popupState.visible, trigger: trigger, empty: isEmpty, focus: focusVisible && isFocus, disabled: itemDisabled, zIndex: isUndefined(zIndex)
235
238
  ? zIndex
236
239
  : isNumber(zIndex)
237
240
  ? zIndex + 1 + subParents.length
@@ -339,7 +342,7 @@ function DropdownFC(props, ref) {
339
342
  case 'entering':
340
343
  transitionStyle = {
341
344
  transition: ['transform', 'opacity'].map((attr) => `${attr} ${TTANSITION_DURING_POPUP}ms ease-out`).join(', '),
342
- transformOrigin,
345
+ transformOrigin: transformOrigin.current,
343
346
  };
344
347
  break;
345
348
  case 'leaving':
@@ -347,7 +350,7 @@ function DropdownFC(props, ref) {
347
350
  transform: 'scaleY(0.7)',
348
351
  opacity: 0,
349
352
  transition: ['transform', 'opacity'].map((attr) => `${attr} ${TTANSITION_DURING_POPUP}ms ease-in`).join(', '),
350
- transformOrigin,
353
+ transformOrigin: transformOrigin.current,
351
354
  };
352
355
  break;
353
356
  case 'leaved':
@@ -356,7 +359,7 @@ function DropdownFC(props, ref) {
356
359
  default:
357
360
  break;
358
361
  }
359
- return (_jsx("div", Object.assign({}, restProps, mergeCS(styled('dropdown', `dropdown--${placement}`), {
362
+ return (_jsx("div", Object.assign({}, restProps, mergeCS(styled('dropdown'), {
360
363
  className: restProps.className,
361
364
  style: restProps.style,
362
365
  }), { ref: dropdownRef, onMouseDown: (e) => {
@@ -368,7 +371,7 @@ function DropdownFC(props, ref) {
368
371
  (_a = restProps.onMouseUp) === null || _a === void 0 ? void 0 : _a.call(restProps, e);
369
372
  preventBlur(e);
370
373
  }, children: renderPopup(_jsxs("div", Object.assign({}, mergeCS(styled('dropdown-popup'), {
371
- style: Object.assign(Object.assign({ zIndex }, popupPositionStyle), transitionStyle),
374
+ style: Object.assign({ zIndex }, transitionStyle),
372
375
  }), { ref: popupRef, children: [_jsx("ul", Object.assign({}, styled('dropdown__list'), { ref: ulRef, id: id, tabIndex: -1, role: "menu", "aria-labelledby": triggerId, "aria-activedescendant": isUndefined(focusId) ? undefined : getItemId(focusId), children: list.length === 0 ? _jsx("div", Object.assign({}, styled('dropdown__empty'), { children: t('No Data') })) : nodes })), arrow && _jsx("div", Object.assign({}, styled('dropdown__arrow')))] }))) })));
373
376
  } }) })] }));
374
377
  } }));
@@ -3,7 +3,6 @@ import type { Styled } from '../../hooks/useStyled';
3
3
  import type { CLASSES } from '../vars';
4
4
  interface DropdownSubProps {
5
5
  children: React.ReactNode;
6
- dropdownRef: React.RefObject<HTMLDivElement>;
7
6
  namespace: string;
8
7
  styled: Styled<typeof CLASSES>;
9
8
  id: string;