@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.
- package/dist/cjs/components/dateTimePicker/timer.js +1 -1
- package/dist/cjs/components/optionsBase/optionsBase.d.ts +4 -0
- package/dist/cjs/components/optionsBase/optionsBase.js +11 -10
- package/dist/cjs/components/popper/popperContext.d.ts +1 -1
- package/dist/cjs/components/popper/popperContext.js +3 -3
- package/dist/cjs/components/textarea/textarea.d.ts +8 -2
- package/dist/cjs/components/textarea/textarea.js +3 -2
- package/dist/esm/components/dateTimePicker/timer.js +2 -2
- package/dist/esm/components/optionsBase/optionsBase.d.ts +4 -0
- package/dist/esm/components/optionsBase/optionsBase.js +13 -12
- package/dist/esm/components/popper/popperContext.d.ts +1 -1
- package/dist/esm/components/popper/popperContext.js +2 -2
- package/dist/esm/components/textarea/textarea.d.ts +8 -2
- package/dist/esm/components/textarea/textarea.js +3 -2
- package/package.json +1 -1
|
@@ -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.
|
|
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.
|
|
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
|
|
87
|
+
params.opt?.onClick?.(e);
|
|
88
88
|
syncOnToggleSelected.current?.(params.value, e);
|
|
89
89
|
},
|
|
90
90
|
onPointerEnter: e => {
|
|
91
|
-
params.opt
|
|
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,
|
|
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
|
-
|
|
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
|
|
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.
|
|
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
|
|
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
|
|
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 {
|
|
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 =
|
|
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,
|
|
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 =
|
|
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
|
|
84
|
+
params.opt?.onClick?.(e);
|
|
85
85
|
syncOnToggleSelected.current?.(params.value, e);
|
|
86
86
|
},
|
|
87
87
|
onPointerEnter: e => {
|
|
88
|
-
params.opt
|
|
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,
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
});
|