@canlooks/can-ui 0.0.182 → 0.0.184

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.
@@ -107,7 +107,6 @@ exports.DataGridHead = (0, react_2.memo)(({ allowSelectAll, columnResizable, fla
107
107
  : (0, jsx_runtime_1.jsx)(bubble_1.Bubble, { ...(0, utils_1.mergeComponentProps)({
108
108
  style: { maxWidth: 360 },
109
109
  trigger: 'click',
110
- placement: 'bottomRight',
111
110
  autoClose: false,
112
111
  content: ((0, jsx_runtime_1.jsx)(filterBubbleContent_1.FilterBubbleContent, { columnKey: _key, columnFilterProps: filter })),
113
112
  onClick: e => e.stopPropagation()
@@ -40,8 +40,10 @@ variant, size, color, disabled, readOnly, autoFocus, ...props }) => {
40
40
  onChange: value => {
41
41
  setInnerValue(o => [value, o?.[1] || null]);
42
42
  if (value && !showTimer) {
43
- endPickerInputRef.current.focus();
44
- innerOpen.current === 'start' && setInnerOpen('end');
43
+ requestAnimationFrame(() => {
44
+ endPickerInputRef.current.focus();
45
+ innerOpen.current === 'start' && setInnerOpen('end');
46
+ });
45
47
  }
46
48
  }
47
49
  }
@@ -22,6 +22,20 @@ const getAttemptOrder = (placement) => {
22
22
  }
23
23
  return order;
24
24
  };
25
+ const splitPlacement = {
26
+ top: ['top'],
27
+ bottom: ['bottom'],
28
+ left: ['left'],
29
+ right: ['right'],
30
+ topLeft: ['top', 'left'],
31
+ topRight: ['top', 'right'],
32
+ bottomLeft: ['bottom', 'left'],
33
+ bottomRight: ['bottom', 'right'],
34
+ leftTop: ['left', 'top'],
35
+ leftBottom: ['left', 'bottom'],
36
+ rightTop: ['right', 'top'],
37
+ rightBottom: ['right', 'bottom']
38
+ };
25
39
  function Popper({ ref, popperRef, anchorElement, container, effectContainer, content, offset, trigger = 'hover', clickToClose, placement = 'top', variant = 'zoom', sizeAdaptable = variant === 'collapse', mouseEnterDelay = 150, mouseLeaveDelay = 150, defaultOpen = false, open, onOpenChange, onOpenChangeEnd, disabled, autoClose = false, forceRender, animation = true, children, ...props }) {
26
40
  const { spacing } = (0, theme_1.useTheme)();
27
41
  offset ??= spacing[2];
@@ -118,7 +132,7 @@ function Popper({ ref, popperRef, anchorElement, container, effectContainer, con
118
132
  const popperEl = innerPopperRef.current;
119
133
  let { offsetWidth: popperWidth, offsetHeight: popperHeight } = popperEl;
120
134
  let pA, pB;
121
- let left, top;
135
+ let top, bottom, left, right;
122
136
  let width, height;
123
137
  let originX, originY;
124
138
  let attempt;
@@ -127,69 +141,64 @@ function Popper({ ref, popperRef, anchorElement, container, effectContainer, con
127
141
  const mouseX = contextMenuEvent.current.clientX - containerRect.left;
128
142
  const mouseY = contextMenuEvent.current.clientY - containerRect.top;
129
143
  attempt = placement => {
130
- [, pA, pB] = placement.match(/^(top|bottom|left|right)(Top|Bottom|Left|Right)?/);
131
- if (pB) {
132
- switch (placement) {
133
- case 'topLeft':
134
- case 'leftTop':
135
- left = mouseX - popperWidth;
136
- top = mouseY - popperHeight;
137
- originX = '100%';
138
- originY = '100%';
139
- break;
140
- case 'topRight':
141
- case 'rightTop':
142
- left = mouseX;
143
- top = mouseY - popperHeight;
144
- originX = '0%';
145
- originY = '100%';
146
- break;
147
- case 'bottomLeft':
148
- case 'leftBottom':
149
- left = mouseX - popperWidth;
150
- top = mouseY;
151
- originX = '100%';
152
- originY = '0%';
153
- break;
154
- case 'bottomRight':
155
- case 'rightBottom':
156
- left = mouseX;
157
- top = mouseY;
158
- originX = '0%';
159
- originY = '0%';
160
- break;
161
- }
162
- }
163
- else {
164
- switch (pA) {
165
- case 'top':
166
- top = mouseY - popperHeight;
167
- originY = '100%';
168
- break;
169
- case 'bottom':
170
- top = mouseY;
171
- originY = '0%';
172
- break;
173
- case 'left':
174
- left = mouseX - popperWidth;
175
- originX = '100%';
176
- break;
177
- case 'right':
178
- left = mouseX;
179
- originX = '0%';
180
- break;
181
- }
182
- if (pA === 'top' || pA === 'bottom') {
144
+ switch (placement) {
145
+ case 'topLeft':
146
+ case 'leftTop':
147
+ bottom = -mouseY;
148
+ right = containerRect.width - mouseX;
149
+ originX = '100%';
150
+ originY = '100%';
151
+ break;
152
+ case 'topRight':
153
+ case 'rightTop':
154
+ bottom = -mouseY;
155
+ left = mouseX;
156
+ originX = '0%';
157
+ originY = '100%';
158
+ break;
159
+ case 'bottomLeft':
160
+ case 'leftBottom':
161
+ top = mouseY;
162
+ right = containerRect.width - mouseX;
163
+ originX = '100%';
164
+ originY = '0%';
165
+ break;
166
+ case 'bottomRight':
167
+ case 'rightBottom':
168
+ top = mouseY;
169
+ left = mouseX;
170
+ originX = '0%';
171
+ originY = '0%';
172
+ break;
173
+ case 'top':
174
+ top = mouseY - popperHeight;
183
175
  left = mouseX - popperWidth / 2;
184
176
  originX = '50%';
185
- }
186
- else {
177
+ originY = '100%';
178
+ break;
179
+ case 'bottom':
180
+ top = mouseY;
181
+ left = mouseX - popperWidth / 2;
182
+ originX = '50%';
183
+ originY = '0%';
184
+ break;
185
+ case 'left':
187
186
  top = mouseY - popperHeight / 2;
187
+ left = mouseX - popperWidth;
188
+ originX = '100%';
188
189
  originY = '50%';
189
- }
190
+ break;
191
+ case 'right':
192
+ top = mouseY - popperHeight / 2;
193
+ left = mouseX;
194
+ originX = '0%';
195
+ originY = '50%';
196
+ break;
190
197
  }
191
- popperEl.style.left = left + 'px';
192
- popperEl.style.top = top + 'px';
198
+ popperEl.style.top = typeof top === 'undefined' ? '' : top + 'px';
199
+ popperEl.style.bottom = typeof bottom === 'undefined' ? '' : bottom + 'px';
200
+ popperEl.style.left = typeof left === 'undefined' ? '' : left + 'px';
201
+ popperEl.style.right = typeof right === 'undefined' ? '' : right + 'px';
193
202
  return (0, utils_1.isElementOverflowed)(popperEl, containerEl.current === document.body ? void 0 : containerEl.current);
194
203
  };
195
204
  }
@@ -197,9 +206,11 @@ function Popper({ ref, popperRef, anchorElement, container, effectContainer, con
197
206
  // 非右键菜单
198
207
  const anchorRect = getAnchorElement().getBoundingClientRect();
199
208
  const topEdge = anchorRect.top - containerRect.top;
209
+ const bottomEdge = anchorRect.bottom - containerRect.top;
200
210
  const leftEdge = anchorRect.left - containerRect.left;
211
+ const rightEdge = containerRect.left + containerRect.width - anchorRect.right;
201
212
  attempt = placement => {
202
- [, pA, pB] = placement.match(/^(top|bottom|left|right)(Top|Bottom|Left|Right)?/);
213
+ [pA, pB] = splitPlacement[placement];
203
214
  if (sizeAdaptable) {
204
215
  if (pA === 'top' || pA === 'bottom') {
205
216
  width = popperWidth = anchorRect.width;
@@ -217,39 +228,48 @@ function Popper({ ref, popperRef, anchorElement, container, effectContainer, con
217
228
  }
218
229
  switch (pA) {
219
230
  case 'top':
220
- top = topEdge - popperHeight - offset;
231
+ top = void 0;
232
+ bottom = -(topEdge - offset);
221
233
  originY = '100%';
222
234
  break;
223
235
  case 'bottom':
224
- top = topEdge + anchorRect.height + offset;
236
+ bottom = void 0;
237
+ top = bottomEdge + offset;
225
238
  originY = '0%';
226
239
  break;
227
240
  case 'left':
228
- left = leftEdge - popperWidth - offset;
241
+ left = void 0;
242
+ right = leftEdge - offset;
229
243
  originX = '100%';
230
244
  break;
231
245
  case 'right':
232
- left = leftEdge + anchorRect.width + offset;
246
+ right = void 0;
247
+ left = rightEdge + offset;
233
248
  originX = '0%';
234
249
  }
235
250
  switch (pB) {
236
- case 'Left':
251
+ case 'left':
237
252
  left = leftEdge;
253
+ right = void 0;
238
254
  originX = '0%';
239
255
  break;
240
- case 'Right':
241
- left = leftEdge - popperWidth + anchorRect.width;
256
+ case 'right':
257
+ left = void 0;
258
+ right = rightEdge;
242
259
  originX = '100%';
243
260
  break;
244
- case 'Top':
261
+ case 'top':
245
262
  top = topEdge;
263
+ bottom = void 0;
246
264
  originY = '0%';
247
265
  break;
248
- case 'Bottom':
249
- top = topEdge - popperHeight + anchorRect.height;
266
+ case 'bottom':
267
+ top = void 0;
268
+ bottom = bottomEdge;
250
269
  originY = '100%';
251
270
  break;
252
271
  default:
272
+ // pB === undefined
253
273
  if (pA === 'top' || pA === 'bottom') {
254
274
  left = leftEdge + (anchorRect.width - popperWidth) / 2;
255
275
  originX = '50%';
@@ -259,8 +279,12 @@ function Popper({ ref, popperRef, anchorElement, container, effectContainer, con
259
279
  originY = '50%';
260
280
  }
261
281
  }
262
- popperEl.style.left = left + 'px';
263
- popperEl.style.top = top + 'px';
282
+ popperEl.style.top = typeof top === 'undefined' ? '' : top + 'px';
283
+ popperEl.style.bottom = typeof bottom === 'undefined' ? '' : bottom + 'px';
284
+ popperEl.style.left = typeof left === 'undefined' ? '' : left + 'px';
285
+ popperEl.style.right = typeof right === 'undefined' ? '' : right + 'px';
286
+ popperEl.style.width = typeof width === 'undefined' ? '' : width + 'px';
287
+ popperEl.style.height = typeof height === 'undefined' ? '' : height + 'px';
264
288
  return (0, utils_1.isElementOverflowed)(popperEl, containerEl.current === document.body ? void 0 : containerEl.current);
265
289
  };
266
290
  }
@@ -270,40 +294,29 @@ function Popper({ ref, popperRef, anchorElement, container, effectContainer, con
270
294
  else {
271
295
  const attemptOrder = getAttemptOrder(placement);
272
296
  for (let i = 0; i < attemptOrder.length; i++) {
273
- if (attempt(attemptOrder[i]) === false) {
297
+ const t = attempt(attemptOrder[i]);
298
+ if (t === false) {
274
299
  break;
275
300
  }
276
301
  }
277
302
  }
303
+ beforeOpen?.();
278
304
  const settle = () => {
279
305
  setPopperBounding({
280
- left, top, width, height,
306
+ top, bottom, left, right, width, height,
281
307
  transformOrigin: `${originX} ${originY}`
282
308
  });
283
309
  placeA.current = pA;
284
310
  placeB.current = pB;
285
311
  };
286
- if (beforeOpen) {
287
- if (sizeAdaptable) {
288
- // 自适应尺寸需要在打开前设置
289
- popperEl.style.width = width ? width + 'px' : '';
290
- popperEl.style.height = height ? height + 'px' : '';
291
- }
292
- beforeOpen();
293
- }
294
312
  if (options?.openAnimation) {
295
313
  popperEl.style.transform = variant === 'collapse'
296
314
  ? pA === 'top' || pA === 'bottom' ? 'scaleY(0)' : 'scaleX(0)'
297
315
  : 'scale(0)';
298
316
  animating.current = true;
299
- requestAnimationFrame(() => {
300
- settle();
301
- setOpenNextFrame(true);
302
- });
303
- }
304
- else {
305
- settle();
317
+ setOpenNextFrame(true);
306
318
  }
319
+ settle();
307
320
  };
308
321
  (0, react_1.useLayoutEffect)(() => {
309
322
  if (innerOpen.current) {
@@ -539,12 +552,12 @@ function Popper({ ref, popperRef, anchorElement, container, effectContainer, con
539
552
  })
540
553
  : children, renderedOnce.current && containerEl.current && (0, react_dom_1.createPortal)((0, jsx_runtime_1.jsx)(clickAway_1.ClickAway, { disabled: !clickable && !enterable && !contextMenuable,
541
554
  // 右键菜单点击anchor需要关闭弹框
542
- targets: () => contextMenuEvent.current ? void 0 : getAnchorElement(), onClickAway: onClickAway, children: (0, jsx_runtime_1.jsx)("div", { ...props, ref: innerPopperRef, css: popper_style_1.style, className: (0, utils_1.clsx)(popper_style_1.classes.root, props.className), style: {
543
- ...popperBounding,
544
- ...!openNextFrame.current && {
545
- transition: 'none',
546
- transform: 'scale(1)'
547
- },
548
- ...props.style
549
- }, "data-open": innerOpen.current, "data-variant": variant, "data-place-a": placeA.current, "data-place-b": placeB.current, "data-animation": animation, onTransitionEnd: onTransitionEnd, children: (0, jsx_runtime_1.jsx)(popperContext_1.PopperContext, { value: contextValue, children: content }) }) }), containerEl.current)] }));
555
+ targets: () => contextMenuEvent.current ? void 0 : getAnchorElement(), onClickAway: onClickAway, children: (0, jsx_runtime_1.jsx)("div", { css: popper_style_1.style, className: popper_style_1.classes.placeHelper, children: (0, jsx_runtime_1.jsx)("div", { ...props, ref: innerPopperRef, className: (0, utils_1.clsx)(popper_style_1.classes.root, props.className), style: {
556
+ ...popperBounding,
557
+ ...!openNextFrame.current && {
558
+ transition: 'none',
559
+ transform: 'scale(1)'
560
+ },
561
+ ...props.style
562
+ }, "data-open": innerOpen.current, "data-variant": variant, "data-place-a": placeA.current, "data-place-b": placeB.current, "data-animation": animation, onTransitionEnd: onTransitionEnd, children: (0, jsx_runtime_1.jsx)(popperContext_1.PopperContext, { value: contextValue, children: content }) }) }) }), containerEl.current)] }));
550
563
  }
@@ -1,6 +1,6 @@
1
1
  import { Theme } from '../theme';
2
2
  export declare const classes: {
3
- popper: string;
3
+ placeHelper: string;
4
4
  } & {
5
5
  root: string;
6
6
  };
@@ -6,7 +6,7 @@ const utils_1 = require("../../utils");
6
6
  const app_style_1 = require("../app/app.style");
7
7
  const theme_1 = require("../theme");
8
8
  exports.classes = (0, utils_1.defineInnerClasses)('popper', [
9
- 'popper',
9
+ 'placeHelper'
10
10
  ]);
11
11
  exports.style = (0, utils_1.defineCss)(theme => {
12
12
  const { easing } = theme;
@@ -14,37 +14,43 @@ exports.style = (0, utils_1.defineCss)(theme => {
14
14
  (0, app_style_1.appStyleCallback)(theme),
15
15
  (0, react_1.css) `
16
16
  @layer reset {
17
+ width: 100%;
18
+ height: 0;
17
19
  position: absolute;
18
20
  top: 0;
19
21
  left: 0;
20
- z-index: ${theme_1.zIndex.popper};
21
- transition-property: transform, opacity;
22
22
 
23
- &[data-animation=true] {
24
- transition-duration: .25s;
25
- }
26
-
27
- &[data-open=true] {
28
- transition-timing-function: ${easing.bounce}, ${easing.easeOut};
29
- opacity: 1;
30
- transform: scale(1);
31
- }
23
+ .${exports.classes.root} {
24
+ position: absolute;
25
+ z-index: ${theme_1.zIndex.popper};
26
+ transition-property: transform, opacity;
32
27
 
33
- &:not([data-open=true]) {
34
- transition-timing-function: ${easing.easeIn};
35
- opacity: 0;
28
+ &[data-animation=true] {
29
+ transition-duration: .25s;
30
+ }
36
31
 
37
- &[data-variant=zoom] {
38
- transform: scale(0);
32
+ &[data-open=true] {
33
+ transition-timing-function: ${easing.bounce}, ${easing.easeOut};
34
+ opacity: 1;
35
+ transform: scale(1);
39
36
  }
40
37
 
41
- &[data-variant=collapse] {
42
- &[data-place-a=top], &[data-place-a=bottom] {
43
- transform: scaleY(0);
38
+ &:not([data-open=true]) {
39
+ transition-timing-function: ${easing.easeIn};
40
+ opacity: 0;
41
+
42
+ &[data-variant=zoom] {
43
+ transform: scale(0);
44
44
  }
45
45
 
46
- &[data-place-a=left], &[data-place-a=right] {
47
- transform: scaleX(0);
46
+ &[data-variant=collapse] {
47
+ &[data-place-a=top], &[data-place-a=bottom] {
48
+ transform: scaleY(0);
49
+ }
50
+
51
+ &[data-place-a=left], &[data-place-a=right] {
52
+ transform: scaleX(0);
53
+ }
48
54
  }
49
55
  }
50
56
  }
@@ -145,6 +145,14 @@ function useContainer(container, effectContainer, defaultContainer) {
145
145
  if (container) {
146
146
  return typeof container === 'function' ? container() : container;
147
147
  }
148
+ if (!prev) {
149
+ if (typeof defaultContainer !== 'undefined') {
150
+ return typeof defaultContainer === 'function' ? defaultContainer() : defaultContainer;
151
+ }
152
+ if (typeof document !== 'undefined') {
153
+ return document.body;
154
+ }
155
+ }
148
156
  return prev;
149
157
  }, [container]);
150
158
  (0, react_1.useEffect)(() => {
@@ -50,11 +50,6 @@ export type OverflowEdge = 'top' | 'bottom' | 'left' | 'right';
50
50
  * @returns 'top' | 'bottom' | 'left' | 'right' | false
51
51
  */
52
52
  export declare function isElementOverflowed(target: Element, container?: Element): OverflowEdge | false;
53
- /**
54
- * 下一个事件循环
55
- * @param callback
56
- */
57
- export declare function nextTick(callback?: () => void): Promise<void>;
58
53
  /**
59
54
  * 克隆Ref
60
55
  * @param refs
@@ -9,7 +9,6 @@ exports.cloneDeep = cloneDeep;
9
9
  exports.mergeDeep = mergeDeep;
10
10
  exports.arrayShallowEqual = arrayShallowEqual;
11
11
  exports.isElementOverflowed = isElementOverflowed;
12
- exports.nextTick = nextTick;
13
12
  exports.cloneRef = cloneRef;
14
13
  exports.isUnset = isUnset;
15
14
  exports.isPromise = isPromise;
@@ -184,18 +183,6 @@ function isElementOverflowed(target, container) {
184
183
  const vHeight = window.innerHeight || document.documentElement.clientHeight;
185
184
  return judge({ left: 0, top: 0, right: vWidth, bottom: vHeight });
186
185
  }
187
- /**
188
- * 下一个事件循环
189
- * @param callback
190
- */
191
- function nextTick(callback) {
192
- return new Promise(resolve => {
193
- queueMicrotask(() => {
194
- callback?.();
195
- resolve();
196
- });
197
- });
198
- }
199
186
  /**
200
187
  * 克隆Ref
201
188
  * @param refs
@@ -104,7 +104,6 @@ export const DataGridHead = memo(({ allowSelectAll, columnResizable, flattedColu
104
104
  : _jsx(Bubble, { ...mergeComponentProps({
105
105
  style: { maxWidth: 360 },
106
106
  trigger: 'click',
107
- placement: 'bottomRight',
108
107
  autoClose: false,
109
108
  content: (_jsx(FilterBubbleContent, { columnKey: _key, columnFilterProps: filter })),
110
109
  onClick: e => e.stopPropagation()
@@ -37,8 +37,10 @@ variant, size, color, disabled, readOnly, autoFocus, ...props }) => {
37
37
  onChange: value => {
38
38
  setInnerValue(o => [value, o?.[1] || null]);
39
39
  if (value && !showTimer) {
40
- endPickerInputRef.current.focus();
41
- innerOpen.current === 'start' && setInnerOpen('end');
40
+ requestAnimationFrame(() => {
41
+ endPickerInputRef.current.focus();
42
+ innerOpen.current === 'start' && setInnerOpen('end');
43
+ });
42
44
  }
43
45
  }
44
46
  }
@@ -19,6 +19,20 @@ const getAttemptOrder = (placement) => {
19
19
  }
20
20
  return order;
21
21
  };
22
+ const splitPlacement = {
23
+ top: ['top'],
24
+ bottom: ['bottom'],
25
+ left: ['left'],
26
+ right: ['right'],
27
+ topLeft: ['top', 'left'],
28
+ topRight: ['top', 'right'],
29
+ bottomLeft: ['bottom', 'left'],
30
+ bottomRight: ['bottom', 'right'],
31
+ leftTop: ['left', 'top'],
32
+ leftBottom: ['left', 'bottom'],
33
+ rightTop: ['right', 'top'],
34
+ rightBottom: ['right', 'bottom']
35
+ };
22
36
  export function Popper({ ref, popperRef, anchorElement, container, effectContainer, content, offset, trigger = 'hover', clickToClose, placement = 'top', variant = 'zoom', sizeAdaptable = variant === 'collapse', mouseEnterDelay = 150, mouseLeaveDelay = 150, defaultOpen = false, open, onOpenChange, onOpenChangeEnd, disabled, autoClose = false, forceRender, animation = true, children, ...props }) {
23
37
  const { spacing } = useTheme();
24
38
  offset ??= spacing[2];
@@ -115,7 +129,7 @@ export function Popper({ ref, popperRef, anchorElement, container, effectContain
115
129
  const popperEl = innerPopperRef.current;
116
130
  let { offsetWidth: popperWidth, offsetHeight: popperHeight } = popperEl;
117
131
  let pA, pB;
118
- let left, top;
132
+ let top, bottom, left, right;
119
133
  let width, height;
120
134
  let originX, originY;
121
135
  let attempt;
@@ -124,69 +138,64 @@ export function Popper({ ref, popperRef, anchorElement, container, effectContain
124
138
  const mouseX = contextMenuEvent.current.clientX - containerRect.left;
125
139
  const mouseY = contextMenuEvent.current.clientY - containerRect.top;
126
140
  attempt = placement => {
127
- [, pA, pB] = placement.match(/^(top|bottom|left|right)(Top|Bottom|Left|Right)?/);
128
- if (pB) {
129
- switch (placement) {
130
- case 'topLeft':
131
- case 'leftTop':
132
- left = mouseX - popperWidth;
133
- top = mouseY - popperHeight;
134
- originX = '100%';
135
- originY = '100%';
136
- break;
137
- case 'topRight':
138
- case 'rightTop':
139
- left = mouseX;
140
- top = mouseY - popperHeight;
141
- originX = '0%';
142
- originY = '100%';
143
- break;
144
- case 'bottomLeft':
145
- case 'leftBottom':
146
- left = mouseX - popperWidth;
147
- top = mouseY;
148
- originX = '100%';
149
- originY = '0%';
150
- break;
151
- case 'bottomRight':
152
- case 'rightBottom':
153
- left = mouseX;
154
- top = mouseY;
155
- originX = '0%';
156
- originY = '0%';
157
- break;
158
- }
159
- }
160
- else {
161
- switch (pA) {
162
- case 'top':
163
- top = mouseY - popperHeight;
164
- originY = '100%';
165
- break;
166
- case 'bottom':
167
- top = mouseY;
168
- originY = '0%';
169
- break;
170
- case 'left':
171
- left = mouseX - popperWidth;
172
- originX = '100%';
173
- break;
174
- case 'right':
175
- left = mouseX;
176
- originX = '0%';
177
- break;
178
- }
179
- if (pA === 'top' || pA === 'bottom') {
141
+ switch (placement) {
142
+ case 'topLeft':
143
+ case 'leftTop':
144
+ bottom = -mouseY;
145
+ right = containerRect.width - mouseX;
146
+ originX = '100%';
147
+ originY = '100%';
148
+ break;
149
+ case 'topRight':
150
+ case 'rightTop':
151
+ bottom = -mouseY;
152
+ left = mouseX;
153
+ originX = '0%';
154
+ originY = '100%';
155
+ break;
156
+ case 'bottomLeft':
157
+ case 'leftBottom':
158
+ top = mouseY;
159
+ right = containerRect.width - mouseX;
160
+ originX = '100%';
161
+ originY = '0%';
162
+ break;
163
+ case 'bottomRight':
164
+ case 'rightBottom':
165
+ top = mouseY;
166
+ left = mouseX;
167
+ originX = '0%';
168
+ originY = '0%';
169
+ break;
170
+ case 'top':
171
+ top = mouseY - popperHeight;
180
172
  left = mouseX - popperWidth / 2;
181
173
  originX = '50%';
182
- }
183
- else {
174
+ originY = '100%';
175
+ break;
176
+ case 'bottom':
177
+ top = mouseY;
178
+ left = mouseX - popperWidth / 2;
179
+ originX = '50%';
180
+ originY = '0%';
181
+ break;
182
+ case 'left':
184
183
  top = mouseY - popperHeight / 2;
184
+ left = mouseX - popperWidth;
185
+ originX = '100%';
185
186
  originY = '50%';
186
- }
187
+ break;
188
+ case 'right':
189
+ top = mouseY - popperHeight / 2;
190
+ left = mouseX;
191
+ originX = '0%';
192
+ originY = '50%';
193
+ break;
187
194
  }
188
- popperEl.style.left = left + 'px';
189
- popperEl.style.top = top + 'px';
195
+ popperEl.style.top = typeof top === 'undefined' ? '' : top + 'px';
196
+ popperEl.style.bottom = typeof bottom === 'undefined' ? '' : bottom + 'px';
197
+ popperEl.style.left = typeof left === 'undefined' ? '' : left + 'px';
198
+ popperEl.style.right = typeof right === 'undefined' ? '' : right + 'px';
190
199
  return isElementOverflowed(popperEl, containerEl.current === document.body ? void 0 : containerEl.current);
191
200
  };
192
201
  }
@@ -194,9 +203,11 @@ export function Popper({ ref, popperRef, anchorElement, container, effectContain
194
203
  // 非右键菜单
195
204
  const anchorRect = getAnchorElement().getBoundingClientRect();
196
205
  const topEdge = anchorRect.top - containerRect.top;
206
+ const bottomEdge = anchorRect.bottom - containerRect.top;
197
207
  const leftEdge = anchorRect.left - containerRect.left;
208
+ const rightEdge = containerRect.left + containerRect.width - anchorRect.right;
198
209
  attempt = placement => {
199
- [, pA, pB] = placement.match(/^(top|bottom|left|right)(Top|Bottom|Left|Right)?/);
210
+ [pA, pB] = splitPlacement[placement];
200
211
  if (sizeAdaptable) {
201
212
  if (pA === 'top' || pA === 'bottom') {
202
213
  width = popperWidth = anchorRect.width;
@@ -214,39 +225,48 @@ export function Popper({ ref, popperRef, anchorElement, container, effectContain
214
225
  }
215
226
  switch (pA) {
216
227
  case 'top':
217
- top = topEdge - popperHeight - offset;
228
+ top = void 0;
229
+ bottom = -(topEdge - offset);
218
230
  originY = '100%';
219
231
  break;
220
232
  case 'bottom':
221
- top = topEdge + anchorRect.height + offset;
233
+ bottom = void 0;
234
+ top = bottomEdge + offset;
222
235
  originY = '0%';
223
236
  break;
224
237
  case 'left':
225
- left = leftEdge - popperWidth - offset;
238
+ left = void 0;
239
+ right = leftEdge - offset;
226
240
  originX = '100%';
227
241
  break;
228
242
  case 'right':
229
- left = leftEdge + anchorRect.width + offset;
243
+ right = void 0;
244
+ left = rightEdge + offset;
230
245
  originX = '0%';
231
246
  }
232
247
  switch (pB) {
233
- case 'Left':
248
+ case 'left':
234
249
  left = leftEdge;
250
+ right = void 0;
235
251
  originX = '0%';
236
252
  break;
237
- case 'Right':
238
- left = leftEdge - popperWidth + anchorRect.width;
253
+ case 'right':
254
+ left = void 0;
255
+ right = rightEdge;
239
256
  originX = '100%';
240
257
  break;
241
- case 'Top':
258
+ case 'top':
242
259
  top = topEdge;
260
+ bottom = void 0;
243
261
  originY = '0%';
244
262
  break;
245
- case 'Bottom':
246
- top = topEdge - popperHeight + anchorRect.height;
263
+ case 'bottom':
264
+ top = void 0;
265
+ bottom = bottomEdge;
247
266
  originY = '100%';
248
267
  break;
249
268
  default:
269
+ // pB === undefined
250
270
  if (pA === 'top' || pA === 'bottom') {
251
271
  left = leftEdge + (anchorRect.width - popperWidth) / 2;
252
272
  originX = '50%';
@@ -256,8 +276,12 @@ export function Popper({ ref, popperRef, anchorElement, container, effectContain
256
276
  originY = '50%';
257
277
  }
258
278
  }
259
- popperEl.style.left = left + 'px';
260
- popperEl.style.top = top + 'px';
279
+ popperEl.style.top = typeof top === 'undefined' ? '' : top + 'px';
280
+ popperEl.style.bottom = typeof bottom === 'undefined' ? '' : bottom + 'px';
281
+ popperEl.style.left = typeof left === 'undefined' ? '' : left + 'px';
282
+ popperEl.style.right = typeof right === 'undefined' ? '' : right + 'px';
283
+ popperEl.style.width = typeof width === 'undefined' ? '' : width + 'px';
284
+ popperEl.style.height = typeof height === 'undefined' ? '' : height + 'px';
261
285
  return isElementOverflowed(popperEl, containerEl.current === document.body ? void 0 : containerEl.current);
262
286
  };
263
287
  }
@@ -267,40 +291,29 @@ export function Popper({ ref, popperRef, anchorElement, container, effectContain
267
291
  else {
268
292
  const attemptOrder = getAttemptOrder(placement);
269
293
  for (let i = 0; i < attemptOrder.length; i++) {
270
- if (attempt(attemptOrder[i]) === false) {
294
+ const t = attempt(attemptOrder[i]);
295
+ if (t === false) {
271
296
  break;
272
297
  }
273
298
  }
274
299
  }
300
+ beforeOpen?.();
275
301
  const settle = () => {
276
302
  setPopperBounding({
277
- left, top, width, height,
303
+ top, bottom, left, right, width, height,
278
304
  transformOrigin: `${originX} ${originY}`
279
305
  });
280
306
  placeA.current = pA;
281
307
  placeB.current = pB;
282
308
  };
283
- if (beforeOpen) {
284
- if (sizeAdaptable) {
285
- // 自适应尺寸需要在打开前设置
286
- popperEl.style.width = width ? width + 'px' : '';
287
- popperEl.style.height = height ? height + 'px' : '';
288
- }
289
- beforeOpen();
290
- }
291
309
  if (options?.openAnimation) {
292
310
  popperEl.style.transform = variant === 'collapse'
293
311
  ? pA === 'top' || pA === 'bottom' ? 'scaleY(0)' : 'scaleX(0)'
294
312
  : 'scale(0)';
295
313
  animating.current = true;
296
- requestAnimationFrame(() => {
297
- settle();
298
- setOpenNextFrame(true);
299
- });
300
- }
301
- else {
302
- settle();
314
+ setOpenNextFrame(true);
303
315
  }
316
+ settle();
304
317
  };
305
318
  useLayoutEffect(() => {
306
319
  if (innerOpen.current) {
@@ -536,12 +549,12 @@ export function Popper({ ref, popperRef, anchorElement, container, effectContain
536
549
  })
537
550
  : children, renderedOnce.current && containerEl.current && createPortal(_jsx(ClickAway, { disabled: !clickable && !enterable && !contextMenuable,
538
551
  // 右键菜单点击anchor需要关闭弹框
539
- targets: () => contextMenuEvent.current ? void 0 : getAnchorElement(), onClickAway: onClickAway, children: _jsx("div", { ...props, ref: innerPopperRef, css: style, className: clsx(classes.root, props.className), style: {
540
- ...popperBounding,
541
- ...!openNextFrame.current && {
542
- transition: 'none',
543
- transform: 'scale(1)'
544
- },
545
- ...props.style
546
- }, "data-open": innerOpen.current, "data-variant": variant, "data-place-a": placeA.current, "data-place-b": placeB.current, "data-animation": animation, onTransitionEnd: onTransitionEnd, children: _jsx(PopperContext, { value: contextValue, children: content }) }) }), containerEl.current)] }));
552
+ targets: () => contextMenuEvent.current ? void 0 : getAnchorElement(), onClickAway: onClickAway, children: _jsx("div", { css: style, className: classes.placeHelper, children: _jsx("div", { ...props, ref: innerPopperRef, className: clsx(classes.root, props.className), style: {
553
+ ...popperBounding,
554
+ ...!openNextFrame.current && {
555
+ transition: 'none',
556
+ transform: 'scale(1)'
557
+ },
558
+ ...props.style
559
+ }, "data-open": innerOpen.current, "data-variant": variant, "data-place-a": placeA.current, "data-place-b": placeB.current, "data-animation": animation, onTransitionEnd: onTransitionEnd, children: _jsx(PopperContext, { value: contextValue, children: content }) }) }) }), containerEl.current)] }));
547
560
  }
@@ -1,6 +1,6 @@
1
1
  import { Theme } from '../theme/index.js';
2
2
  export declare const classes: {
3
- popper: string;
3
+ placeHelper: string;
4
4
  } & {
5
5
  root: string;
6
6
  };
@@ -3,7 +3,7 @@ import { defineCss, defineInnerClasses } from '../../utils/index.js';
3
3
  import { appStyleCallback } from '../app/app.style.js';
4
4
  import { zIndex } from '../theme/index.js';
5
5
  export const classes = defineInnerClasses('popper', [
6
- 'popper',
6
+ 'placeHelper'
7
7
  ]);
8
8
  export const style = defineCss(theme => {
9
9
  const { easing } = theme;
@@ -11,37 +11,43 @@ export const style = defineCss(theme => {
11
11
  appStyleCallback(theme),
12
12
  css `
13
13
  @layer reset {
14
+ width: 100%;
15
+ height: 0;
14
16
  position: absolute;
15
17
  top: 0;
16
18
  left: 0;
17
- z-index: ${zIndex.popper};
18
- transition-property: transform, opacity;
19
19
 
20
- &[data-animation=true] {
21
- transition-duration: .25s;
22
- }
23
-
24
- &[data-open=true] {
25
- transition-timing-function: ${easing.bounce}, ${easing.easeOut};
26
- opacity: 1;
27
- transform: scale(1);
28
- }
20
+ .${classes.root} {
21
+ position: absolute;
22
+ z-index: ${zIndex.popper};
23
+ transition-property: transform, opacity;
29
24
 
30
- &:not([data-open=true]) {
31
- transition-timing-function: ${easing.easeIn};
32
- opacity: 0;
25
+ &[data-animation=true] {
26
+ transition-duration: .25s;
27
+ }
33
28
 
34
- &[data-variant=zoom] {
35
- transform: scale(0);
29
+ &[data-open=true] {
30
+ transition-timing-function: ${easing.bounce}, ${easing.easeOut};
31
+ opacity: 1;
32
+ transform: scale(1);
36
33
  }
37
34
 
38
- &[data-variant=collapse] {
39
- &[data-place-a=top], &[data-place-a=bottom] {
40
- transform: scaleY(0);
35
+ &:not([data-open=true]) {
36
+ transition-timing-function: ${easing.easeIn};
37
+ opacity: 0;
38
+
39
+ &[data-variant=zoom] {
40
+ transform: scale(0);
41
41
  }
42
42
 
43
- &[data-place-a=left], &[data-place-a=right] {
44
- transform: scaleX(0);
43
+ &[data-variant=collapse] {
44
+ &[data-place-a=top], &[data-place-a=bottom] {
45
+ transform: scaleY(0);
46
+ }
47
+
48
+ &[data-place-a=left], &[data-place-a=right] {
49
+ transform: scaleX(0);
50
+ }
45
51
  }
46
52
  }
47
53
  }
@@ -130,6 +130,14 @@ export function useContainer(container, effectContainer, defaultContainer) {
130
130
  if (container) {
131
131
  return typeof container === 'function' ? container() : container;
132
132
  }
133
+ if (!prev) {
134
+ if (typeof defaultContainer !== 'undefined') {
135
+ return typeof defaultContainer === 'function' ? defaultContainer() : defaultContainer;
136
+ }
137
+ if (typeof document !== 'undefined') {
138
+ return document.body;
139
+ }
140
+ }
133
141
  return prev;
134
142
  }, [container]);
135
143
  useEffect(() => {
@@ -50,11 +50,6 @@ export type OverflowEdge = 'top' | 'bottom' | 'left' | 'right';
50
50
  * @returns 'top' | 'bottom' | 'left' | 'right' | false
51
51
  */
52
52
  export declare function isElementOverflowed(target: Element, container?: Element): OverflowEdge | false;
53
- /**
54
- * 下一个事件循环
55
- * @param callback
56
- */
57
- export declare function nextTick(callback?: () => void): Promise<void>;
58
53
  /**
59
54
  * 克隆Ref
60
55
  * @param refs
@@ -158,18 +158,6 @@ export function isElementOverflowed(target, container) {
158
158
  const vHeight = window.innerHeight || document.documentElement.clientHeight;
159
159
  return judge({ left: 0, top: 0, right: vWidth, bottom: vHeight });
160
160
  }
161
- /**
162
- * 下一个事件循环
163
- * @param callback
164
- */
165
- export function nextTick(callback) {
166
- return new Promise(resolve => {
167
- queueMicrotask(() => {
168
- callback?.();
169
- resolve();
170
- });
171
- });
172
- }
173
161
  /**
174
162
  * 克隆Ref
175
163
  * @param refs
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@canlooks/can-ui",
3
- "version": "0.0.182",
3
+ "version": "0.0.184",
4
4
  "author": "C.CanLiang <canlooks@gmail.com>",
5
5
  "description": "My ui framework",
6
6
  "license": "MIT",