@canlooks/can-ui 0.0.77 → 0.0.78

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.
@@ -40,7 +40,7 @@ function TimerItem({ type, value, onChange }) {
40
40
  return false;
41
41
  };
42
42
  const scrollerRef = (0, react_1.useRef)(null);
43
- const selectedItemRef = (0, popper_1.useScrollToSelected)(scrollerRef);
43
+ const selectedItemRef = (0, popper_1.useScrollToTarget)(scrollerRef);
44
44
  const renderItems = (count) => {
45
45
  const ret = [];
46
46
  for (let i = 0; i < count; i++) {
@@ -4,6 +4,10 @@ import { LoadingProps } from '../loading';
4
4
  import { OptionType } from '../selectionContext';
5
5
  import { Id } from '../../types';
6
6
  export interface MenuOptionType<V extends Id = Id> extends Omit<MenuItemProps, 'children'>, Omit<OptionType<V>, 'children'> {
7
+ /**
8
+ * 若指定为`true`,则弹框打开时会自动滚动到该选项,默认为`false`
9
+ */
10
+ scrollHere?: boolean;
7
11
  }
8
12
  export type OptionsBaseSharedProps<O extends MenuOptionType<V>, V extends Id = Id> = {
9
13
  showCheckbox?: boolean;
@@ -68,14 +68,14 @@ searchValue, selectedValue, onToggleSelected, ...props }) => {
68
68
  * 渲染部分
69
69
  */
70
70
  const scrollerRef = (0, react_1.useRef)(null);
71
- const selectedItemRef = (0, popper_1.useScrollToSelected)(scrollerRef);
71
+ const selectedItemRef = (0, popper_1.useScrollToTarget)(scrollerRef);
72
72
  const syncOnToggleSelected = (0, utils_1.useSync)(onToggleSelected);
73
73
  const renderedOptions = (0, react_1.useMemo)(() => {
74
74
  if (!filteredOptions?.length) {
75
75
  return (0, jsx_runtime_1.jsx)(placeholder_1.Placeholder, {});
76
76
  }
77
77
  const makeProps = (params) => ({
78
- ref: params.selected ? selectedItemRef : void 0,
78
+ ref: params.scrollHere || params.selected ? selectedItemRef : void 0,
79
79
  showCheckbox,
80
80
  selected: params.selected,
81
81
  focused: verticalIndex.current === params.index,
@@ -84,11 +84,11 @@ searchValue, selectedValue, onToggleSelected, ...props }) => {
84
84
  : params.label,
85
85
  onClick: e => {
86
86
  e.stopPropagation();
87
- params.opt.onClick?.(e);
87
+ params.opt?.onClick?.(e);
88
88
  syncOnToggleSelected.current?.(params.value, e);
89
89
  },
90
90
  onPointerEnter: e => {
91
- params.opt.onPointerEnter?.(e);
91
+ params.opt?.onPointerEnter?.(e);
92
92
  setVerticalIndex(-1);
93
93
  },
94
94
  children: null
@@ -97,13 +97,13 @@ searchValue, selectedValue, onToggleSelected, ...props }) => {
97
97
  return filteredOptions.map((opt, index) => {
98
98
  const value = opt[primaryKey];
99
99
  const label = opt[labelKey] ?? value;
100
- return ((0, jsx_runtime_1.jsx)(menuItem_1.MenuItem, { value: value, ...opt, ...makeProps({
101
- opt,
100
+ return ((0, jsx_runtime_1.jsx)(menuItem_1.MenuItem, { value: value, ...(0, utils_1.mergeComponentProps)(opt, makeProps({
102
101
  label,
103
102
  value,
104
103
  index,
105
- selected: (0, utils_1.isSelected)(value, selectedValue)
106
- }) }, opt.key ?? value ?? index));
104
+ selected: (0, utils_1.isSelected)(value, selectedValue),
105
+ scrollHere: opt.scrollHere
106
+ })) }, opt.key ?? value ?? index));
107
107
  });
108
108
  }
109
109
  // children
@@ -111,13 +111,14 @@ searchValue, selectedValue, onToggleSelected, ...props }) => {
111
111
  if (!(0, react_1.isValidElement)(c)) {
112
112
  return c;
113
113
  }
114
- const { value, label } = c.props;
114
+ const { value, label, scrollHere } = c.props;
115
115
  return (0, react_1.cloneElement)(c, makeProps({
116
116
  opt: c.props,
117
117
  label,
118
118
  value: value,
119
119
  index,
120
- selected: (0, utils_1.isSelected)(value, selectedValue)
120
+ selected: (0, utils_1.isSelected)(value, selectedValue),
121
+ scrollHere
121
122
  }));
122
123
  });
123
124
  }, [filteredOptions, selectedValue, verticalIndex.current, showCheckbox]);
@@ -17,4 +17,4 @@ export declare function usePopperContext(): {
17
17
  * 当弹框打开时,滚动至已选项
18
18
  * @returns {RefObject} ref
19
19
  */
20
- export declare function useScrollToSelected<T extends HTMLElement>(scrollerRef: RefObject<Element | null>): RefObject<T | null>;
20
+ export declare function useScrollToTarget<T extends HTMLElement>(scrollerRef: RefObject<Element | null>): RefObject<T | null>;
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PopperContext = void 0;
4
4
  exports.usePopperContext = usePopperContext;
5
- exports.useScrollToSelected = useScrollToSelected;
5
+ exports.useScrollToTarget = useScrollToTarget;
6
6
  const react_1 = require("react");
7
7
  exports.PopperContext = (0, react_1.createContext)({
8
8
  autoClose: false,
@@ -20,13 +20,13 @@ function usePopperContext() {
20
20
  * 当弹框打开时,滚动至已选项
21
21
  * @returns {RefObject} ref
22
22
  */
23
- function useScrollToSelected(scrollerRef) {
23
+ function useScrollToTarget(scrollerRef) {
24
24
  const ref = (0, react_1.useRef)(null);
25
25
  const { beforeOpenCallbacks } = usePopperContext();
26
26
  (0, react_1.useEffect)(() => {
27
27
  const beforeOpen = () => {
28
28
  if (ref.current && scrollerRef.current && scrollerRef.current.scrollHeight > scrollerRef.current.clientHeight) {
29
- scrollerRef.current.scrollTop = ref.current.offsetTop - scrollerRef.current.clientHeight / 2 + ref.current.clientHeight / 2;
29
+ scrollerRef.current.scrollTop = ref.current.offsetTop + ref.current.clientHeight / 2 - scrollerRef.current.clientHeight / 2;
30
30
  }
31
31
  };
32
32
  beforeOpenCallbacks.add(beforeOpen);
@@ -1,9 +1,15 @@
1
- import { Ref, ComponentProps } from 'react';
1
+ import { Ref, ComponentProps, CSSProperties } from 'react';
2
2
  import { InputBaseProps } from '../inputBase';
3
3
  export interface TextareaProps extends Omit<InputBaseProps<'textarea'>, 'children' | 'prefix' | 'suffix'> {
4
4
  textareaProps?: ComponentProps<'textarea'>;
5
5
  textareaRef?: Ref<HTMLTextAreaElement>;
6
6
  rows?: number;
7
7
  fullWidth?: boolean;
8
+ /**
9
+ * @enum {@link fullWidth} 为`true`时,默认为`vertical`
10
+ * @enum {@link fullWidth} 为`false`时,默认为`both`
11
+ * @enum 若设为`none`,则不可调整尺寸
12
+ */
13
+ resize?: CSSProperties['resize'];
8
14
  }
9
- export declare const Textarea: import("react").MemoExoticComponent<({ textareaProps, textareaRef, rows, fullWidth, ...props }: TextareaProps) => import("@emotion/react/jsx-runtime").JSX.Element>;
15
+ export declare const Textarea: import("react").MemoExoticComponent<({ textareaProps, textareaRef, rows, fullWidth, resize, ...props }: TextareaProps) => import("@emotion/react/jsx-runtime").JSX.Element>;
@@ -6,10 +6,11 @@ const react_1 = require("react");
6
6
  const inputBase_1 = require("../inputBase");
7
7
  const textarea_style_1 = require("./textarea.style");
8
8
  const utils_1 = require("../../utils");
9
- exports.Textarea = (0, react_1.memo)(({ textareaProps, textareaRef, rows, fullWidth = false, ...props }) => {
9
+ exports.Textarea = (0, react_1.memo)(({ textareaProps, textareaRef, rows, fullWidth = false, resize = fullWidth ? 'vertical' : 'both', ...props }) => {
10
10
  return ((0, jsx_runtime_1.jsx)(inputBase_1.InputBase, { ...props, css: textarea_style_1.style, className: (0, utils_1.clsx)(textarea_style_1.classes.root, props.className), "data-full-width": fullWidth, children: inputBaseProps => (0, jsx_runtime_1.jsx)("textarea", { ...(0, utils_1.mergeComponentProps)(inputBaseProps, {
11
11
  rows,
12
12
  ref: textareaRef,
13
- className: textarea_style_1.classes.textarea
13
+ className: textarea_style_1.classes.textarea,
14
+ style: { resize }
14
15
  }) }) }));
15
16
  });
@@ -3,7 +3,7 @@ import { memo, useRef } from 'react';
3
3
  import { classes, style } from './timer.style';
4
4
  import { MenuItem } from '../menuItem';
5
5
  import { useDateTimePickerContext } from './dateTimePicker';
6
- import { useScrollToSelected } from '../popper';
6
+ import { useScrollToTarget } from '../popper';
7
7
  export const Timer = memo(({ showHours, showMinutes, showSeconds, value, onChange }) => {
8
8
  return (_jsxs("div", { css: style, className: classes.root, children: [showHours && _jsx(TimerItem, { type: "hour", value: value, onChange: onChange }), showMinutes && _jsx(TimerItem, { type: "minute", value: value, onChange: onChange }), showSeconds && _jsx(TimerItem, { type: "second", value: value, onChange: onChange })] }));
9
9
  });
@@ -37,7 +37,7 @@ function TimerItem({ type, value, onChange }) {
37
37
  return false;
38
38
  };
39
39
  const scrollerRef = useRef(null);
40
- const selectedItemRef = useScrollToSelected(scrollerRef);
40
+ const selectedItemRef = useScrollToTarget(scrollerRef);
41
41
  const renderItems = (count) => {
42
42
  const ret = [];
43
43
  for (let i = 0; i < count; i++) {
@@ -4,6 +4,10 @@ import { LoadingProps } from '../loading';
4
4
  import { OptionType } from '../selectionContext';
5
5
  import { Id } from '../../types';
6
6
  export interface MenuOptionType<V extends Id = Id> extends Omit<MenuItemProps, 'children'>, Omit<OptionType<V>, 'children'> {
7
+ /**
8
+ * 若指定为`true`,则弹框打开时会自动滚动到该选项,默认为`false`
9
+ */
10
+ scrollHere?: boolean;
7
11
  }
8
12
  export type OptionsBaseSharedProps<O extends MenuOptionType<V>, V extends Id = Id> = {
9
13
  showCheckbox?: boolean;
@@ -3,10 +3,10 @@ import { useMemo, memo, Children, isValidElement, cloneElement, useRef } from 'r
3
3
  import { Highlight } from '../highlight';
4
4
  import { MenuItem } from '../menuItem';
5
5
  import { Placeholder } from '../placeholder';
6
- import { clsx, isSelected, useKeyboard, useSync } from '../../utils';
6
+ import { clsx, isSelected, mergeComponentProps, useKeyboard, useSync } from '../../utils';
7
7
  import { classes, style } from './optionsBase.style';
8
8
  import { Loading } from '../loading';
9
- import { usePopperContext, useScrollToSelected } from '../popper';
9
+ import { usePopperContext, useScrollToTarget } from '../popper';
10
10
  export const OptionsBase = memo(({
11
11
  // 共享属性
12
12
  showCheckbox, loading, options, children, labelKey = 'label', primaryKey = 'value', searchTokenKey = 'searchToken', filterPredicate,
@@ -65,14 +65,14 @@ searchValue, selectedValue, onToggleSelected, ...props }) => {
65
65
  * 渲染部分
66
66
  */
67
67
  const scrollerRef = useRef(null);
68
- const selectedItemRef = useScrollToSelected(scrollerRef);
68
+ const selectedItemRef = useScrollToTarget(scrollerRef);
69
69
  const syncOnToggleSelected = useSync(onToggleSelected);
70
70
  const renderedOptions = useMemo(() => {
71
71
  if (!filteredOptions?.length) {
72
72
  return _jsx(Placeholder, {});
73
73
  }
74
74
  const makeProps = (params) => ({
75
- ref: params.selected ? selectedItemRef : void 0,
75
+ ref: params.scrollHere || params.selected ? selectedItemRef : void 0,
76
76
  showCheckbox,
77
77
  selected: params.selected,
78
78
  focused: verticalIndex.current === params.index,
@@ -81,11 +81,11 @@ searchValue, selectedValue, onToggleSelected, ...props }) => {
81
81
  : params.label,
82
82
  onClick: e => {
83
83
  e.stopPropagation();
84
- params.opt.onClick?.(e);
84
+ params.opt?.onClick?.(e);
85
85
  syncOnToggleSelected.current?.(params.value, e);
86
86
  },
87
87
  onPointerEnter: e => {
88
- params.opt.onPointerEnter?.(e);
88
+ params.opt?.onPointerEnter?.(e);
89
89
  setVerticalIndex(-1);
90
90
  },
91
91
  children: null
@@ -94,13 +94,13 @@ searchValue, selectedValue, onToggleSelected, ...props }) => {
94
94
  return filteredOptions.map((opt, index) => {
95
95
  const value = opt[primaryKey];
96
96
  const label = opt[labelKey] ?? value;
97
- return (_jsx(MenuItem, { value: value, ...opt, ...makeProps({
98
- opt,
97
+ return (_jsx(MenuItem, { value: value, ...mergeComponentProps(opt, makeProps({
99
98
  label,
100
99
  value,
101
100
  index,
102
- selected: isSelected(value, selectedValue)
103
- }) }, opt.key ?? value ?? index));
101
+ selected: isSelected(value, selectedValue),
102
+ scrollHere: opt.scrollHere
103
+ })) }, opt.key ?? value ?? index));
104
104
  });
105
105
  }
106
106
  // children
@@ -108,13 +108,14 @@ searchValue, selectedValue, onToggleSelected, ...props }) => {
108
108
  if (!isValidElement(c)) {
109
109
  return c;
110
110
  }
111
- const { value, label } = c.props;
111
+ const { value, label, scrollHere } = c.props;
112
112
  return cloneElement(c, makeProps({
113
113
  opt: c.props,
114
114
  label,
115
115
  value: value,
116
116
  index,
117
- selected: isSelected(value, selectedValue)
117
+ selected: isSelected(value, selectedValue),
118
+ scrollHere
118
119
  }));
119
120
  });
120
121
  }, [filteredOptions, selectedValue, verticalIndex.current, showCheckbox]);
@@ -17,4 +17,4 @@ export declare function usePopperContext(): {
17
17
  * 当弹框打开时,滚动至已选项
18
18
  * @returns {RefObject} ref
19
19
  */
20
- export declare function useScrollToSelected<T extends HTMLElement>(scrollerRef: RefObject<Element | null>): RefObject<T | null>;
20
+ export declare function useScrollToTarget<T extends HTMLElement>(scrollerRef: RefObject<Element | null>): RefObject<T | null>;
@@ -15,13 +15,13 @@ export function usePopperContext() {
15
15
  * 当弹框打开时,滚动至已选项
16
16
  * @returns {RefObject} ref
17
17
  */
18
- export function useScrollToSelected(scrollerRef) {
18
+ export function useScrollToTarget(scrollerRef) {
19
19
  const ref = useRef(null);
20
20
  const { beforeOpenCallbacks } = usePopperContext();
21
21
  useEffect(() => {
22
22
  const beforeOpen = () => {
23
23
  if (ref.current && scrollerRef.current && scrollerRef.current.scrollHeight > scrollerRef.current.clientHeight) {
24
- scrollerRef.current.scrollTop = ref.current.offsetTop - scrollerRef.current.clientHeight / 2 + ref.current.clientHeight / 2;
24
+ scrollerRef.current.scrollTop = ref.current.offsetTop + ref.current.clientHeight / 2 - scrollerRef.current.clientHeight / 2;
25
25
  }
26
26
  };
27
27
  beforeOpenCallbacks.add(beforeOpen);
@@ -1,9 +1,15 @@
1
- import { Ref, ComponentProps } from 'react';
1
+ import { Ref, ComponentProps, CSSProperties } from 'react';
2
2
  import { InputBaseProps } from '../inputBase';
3
3
  export interface TextareaProps extends Omit<InputBaseProps<'textarea'>, 'children' | 'prefix' | 'suffix'> {
4
4
  textareaProps?: ComponentProps<'textarea'>;
5
5
  textareaRef?: Ref<HTMLTextAreaElement>;
6
6
  rows?: number;
7
7
  fullWidth?: boolean;
8
+ /**
9
+ * @enum {@link fullWidth} 为`true`时,默认为`vertical`
10
+ * @enum {@link fullWidth} 为`false`时,默认为`both`
11
+ * @enum 若设为`none`,则不可调整尺寸
12
+ */
13
+ resize?: CSSProperties['resize'];
8
14
  }
9
- export declare const Textarea: import("react").MemoExoticComponent<({ textareaProps, textareaRef, rows, fullWidth, ...props }: TextareaProps) => import("@emotion/react/jsx-runtime").JSX.Element>;
15
+ export declare const Textarea: import("react").MemoExoticComponent<({ textareaProps, textareaRef, rows, fullWidth, resize, ...props }: TextareaProps) => import("@emotion/react/jsx-runtime").JSX.Element>;
@@ -3,10 +3,11 @@ import { memo } from 'react';
3
3
  import { InputBase } from '../inputBase';
4
4
  import { classes, style } from './textarea.style';
5
5
  import { clsx, mergeComponentProps } from '../../utils';
6
- export const Textarea = memo(({ textareaProps, textareaRef, rows, fullWidth = false, ...props }) => {
6
+ export const Textarea = memo(({ textareaProps, textareaRef, rows, fullWidth = false, resize = fullWidth ? 'vertical' : 'both', ...props }) => {
7
7
  return (_jsx(InputBase, { ...props, css: style, className: clsx(classes.root, props.className), "data-full-width": fullWidth, children: inputBaseProps => _jsx("textarea", { ...mergeComponentProps(inputBaseProps, {
8
8
  rows,
9
9
  ref: textareaRef,
10
- className: classes.textarea
10
+ className: classes.textarea,
11
+ style: { resize }
11
12
  }) }) }));
12
13
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@canlooks/can-ui",
3
- "version": "0.0.77",
3
+ "version": "0.0.78",
4
4
  "author": "C.CanLiang <canlooks@gmail.com>",
5
5
  "description": "My ui framework",
6
6
  "license": "MIT",