diff --git a/packages/mini-demo/order.json b/packages/mini-demo/order.json
index 8f23290e8..db246f103 100644
--- a/packages/mini-demo/order.json
+++ b/packages/mini-demo/order.json
@@ -1 +1 @@
-{"input":{"AutoHeight":"6","Basic":"1","Clearable":"2","Disabled":"5","Native":"3","ReadOnly":"4","ShowLength":"7","Vertical":"8","Readonly":"4","Disable":0},"swipe-action":{"Basic":0}}
+{"input":{"AutoHeight":"6","Basic":"1","Clearable":"2","Disabled":"5","Native":"3","ReadOnly":"4","ShowLength":"7","Vertical":"8","Readonly":"4","Disable":0},"swipe-action":{"Basic":0},"checkbox":{"Controlled":"3","Custom":"6","Basic":"1","Buttton":"2","List":"4","CustomIcon":"6"}}
diff --git a/packages/mini-demo/src/app.config.ts b/packages/mini-demo/src/app.config.ts
index df9ea8bc8..908bdfdd6 100644
--- a/packages/mini-demo/src/app.config.ts
+++ b/packages/mini-demo/src/app.config.ts
@@ -8,6 +8,7 @@ export default defineAppConfig({
'pages/tabs/index',
'pages/input/index',
'pages/swipe-action/index',
+ 'pages/checkbox/index',
],
window: {
backgroundTextStyle: 'light',
diff --git a/packages/mini-demo/src/pages/checkbox/component/basic.tsx b/packages/mini-demo/src/pages/checkbox/component/basic.tsx
new file mode 100644
index 000000000..db518eea6
--- /dev/null
+++ b/packages/mini-demo/src/pages/checkbox/component/basic.tsx
@@ -0,0 +1,26 @@
+import React from 'react';
+import { Checkbox, List, Panel } from 'zarm/mini';
+
+/* order: 1 */
+
+function Demo() {
+ return (
+
+
+
+ console.log(e)}>普通
+
+
+
+ 默认选中
+
+
+
+ 禁用
+
+
+
+ );
+}
+
+export default Demo;
diff --git a/packages/mini-demo/src/pages/checkbox/component/buttton.tsx b/packages/mini-demo/src/pages/checkbox/component/buttton.tsx
new file mode 100644
index 000000000..4f697c882
--- /dev/null
+++ b/packages/mini-demo/src/pages/checkbox/component/buttton.tsx
@@ -0,0 +1,22 @@
+import React from 'react';
+import { Checkbox, List, Panel } from 'zarm/mini';
+
+/* order: 2 */
+
+function Demo() {
+ return (
+
+
+
+ console.log(e)} block>
+ 选项一
+ 选项二
+ 选项三
+
+
+
+
+ );
+}
+
+export default Demo;
diff --git a/packages/mini-demo/src/pages/checkbox/component/controlled.tsx b/packages/mini-demo/src/pages/checkbox/component/controlled.tsx
new file mode 100644
index 000000000..4108135bd
--- /dev/null
+++ b/packages/mini-demo/src/pages/checkbox/component/controlled.tsx
@@ -0,0 +1,39 @@
+import React, { useState } from 'react';
+import { showModal } from '@tarojs/taro';
+import { Checkbox, List, Panel } from 'zarm/mini';
+
+/* order: 3 */
+
+const Demo = () => {
+ const [checked, setChecked] = useState(false);
+
+ const onChange = (e) => {
+ if (!e.target.checked) {
+ showModal({
+ content: '是否要取消选择',
+ cancelText: '不取消',
+ success: ({ confirm }) => {
+ if (confirm) {
+ setChecked(false);
+ }
+ },
+ });
+ return false;
+ }
+ setChecked(true);
+ };
+
+ return (
+
+
+
+
+ 取消勾选前确认
+
+
+
+
+ );
+};
+
+export default Demo;
diff --git a/packages/mini-demo/src/pages/checkbox/component/custom-icon.tsx b/packages/mini-demo/src/pages/checkbox/component/custom-icon.tsx
new file mode 100644
index 000000000..b08b20e44
--- /dev/null
+++ b/packages/mini-demo/src/pages/checkbox/component/custom-icon.tsx
@@ -0,0 +1,37 @@
+import React from 'react';
+import { List, Checkbox, Panel } from 'zarm/mini';
+import { Star, StarFill, Success, Close } from '@zarm-design/icons';
+
+/* order: 6 */
+
+function Demo() {
+ return (
+
+
+
+
+
+ checked ? :
+ }
+ >
+ 选项一
+
+
+ checked ? :
+ }
+ >
+ 选项二
+
+ 选项三
+
+
+
+
+ )
+}
+
+export default Demo;
diff --git a/packages/mini-demo/src/pages/checkbox/component/custom.tsx b/packages/mini-demo/src/pages/checkbox/component/custom.tsx
new file mode 100644
index 000000000..081d6538a
--- /dev/null
+++ b/packages/mini-demo/src/pages/checkbox/component/custom.tsx
@@ -0,0 +1,73 @@
+import React, { useState } from 'react';
+import { List, Checkbox, Panel } from 'zarm/mini';
+import { Success } from '@zarm-design/icons';
+import { View } from '@tarojs/components';
+
+/* order: 6 */
+
+const items = ['选项一', '选项二', '选项三'];
+
+const Demo = () => {
+ const [value, setValue] = useState(['0']);
+
+ const onChange = (v) => {
+ console.log('onChange', v);
+ setValue(v);
+ };
+
+ const CustomCheckbox = (props) => {
+ return (
+
+ {({ checked }) => (
+
+
+
+
+ {props.label}
+
+ )}
+
+ );
+ };
+ return (
+
+
+
+
+ {items.map((item, index) => (
+
+ ))}
+
+
+
+
+ );
+};
+
+export default Demo;
diff --git a/packages/mini-demo/src/pages/checkbox/component/list.tsx b/packages/mini-demo/src/pages/checkbox/component/list.tsx
new file mode 100644
index 000000000..ff9444bf0
--- /dev/null
+++ b/packages/mini-demo/src/pages/checkbox/component/list.tsx
@@ -0,0 +1,18 @@
+import React from 'react';
+import { Checkbox, Panel } from 'zarm/mini';
+
+/* order: 4 */
+
+function Demo() {
+ return (
+
+ console.log(e)}>
+ 选项一
+ 选项二
+ 选项三
+
+
+ );
+}
+
+export default Demo;
diff --git a/packages/mini-demo/src/pages/checkbox/index.config.ts b/packages/mini-demo/src/pages/checkbox/index.config.ts
new file mode 100644
index 000000000..267fb2a4b
--- /dev/null
+++ b/packages/mini-demo/src/pages/checkbox/index.config.ts
@@ -0,0 +1,3 @@
+export default definePageConfig({
+ navigationBarTitleText: 'Checkbox',
+});
diff --git a/packages/mini-demo/src/pages/checkbox/index.scss b/packages/mini-demo/src/pages/checkbox/index.scss
new file mode 100644
index 000000000..649525820
--- /dev/null
+++ b/packages/mini-demo/src/pages/checkbox/index.scss
@@ -0,0 +1,3 @@
+view {
+ box-sizing: border-box;
+}
diff --git a/packages/mini-demo/src/pages/checkbox/index.tsx b/packages/mini-demo/src/pages/checkbox/index.tsx
new file mode 100644
index 000000000..91f056537
--- /dev/null
+++ b/packages/mini-demo/src/pages/checkbox/index.tsx
@@ -0,0 +1,23 @@
+
+import * as React from 'react';
+import Basic from './component/basic';
+import Buttton from './component/buttton';
+import Controlled from './component/controlled';
+import CustomIcon from './component/custom-icon';
+import Custom from './component/custom';
+import List from './component/list';
+
+import './index.scss';
+
+export default () => {
+ return (
+ <>
+
+
+
+
+
+
+ >
+ )
+}
\ No newline at end of file
diff --git a/packages/mini-demo/src/site.ts b/packages/mini-demo/src/site.ts
index 4a1f85f37..aa4ada427 100644
--- a/packages/mini-demo/src/site.ts
+++ b/packages/mini-demo/src/site.ts
@@ -28,6 +28,17 @@ const siteMap = {
page: '/pages/input/index',
},
// {
+ {
+ key: 'Checkbox',
+ name: '复选框',
+ page: '/pages/checkbox/index',
+ },
+ // {
+ // key: 'Input',
+ // name: '输入框',
+ // page: '/pages/input/index',
+ // },
+ // {
// key: 'Keyboard',
// name: '键盘',
// page: '/pages/keyboard/index',
diff --git a/packages/zarm/src/button/Button.mini.tsx b/packages/zarm/src/button/Button.mini.tsx
index 9990a439c..5f98c7d22 100644
--- a/packages/zarm/src/button/Button.mini.tsx
+++ b/packages/zarm/src/button/Button.mini.tsx
@@ -7,7 +7,7 @@ import { BaseButtonProps } from './interface';
export interface ButtonProps extends BaseButtonProps, Omit {}
-const Button: React.FC = (props: ButtonProps) => {
+const Button = (props: ButtonProps) => {
const {
className,
theme,
diff --git a/packages/zarm/src/checkbox/Checkbox.mini.tsx b/packages/zarm/src/checkbox/Checkbox.mini.tsx
new file mode 100644
index 000000000..d3a7974e5
--- /dev/null
+++ b/packages/zarm/src/checkbox/Checkbox.mini.tsx
@@ -0,0 +1,185 @@
+import { BaseEventOrig, Label, Switch, SwitchProps, View } from '@tarojs/components';
+import { createBEM } from '@zarm-design/bem';
+import { Minus as MinusIcon, Success as SuccessIcon } from '@zarm-design/icons';
+import includes from 'lodash/includes';
+import React, { ReactNode, useContext, useMemo, } from 'react';
+import { useControllableEventValue } from '../utils/hooks';
+import Button from '../button/index.mini';
+import { ConfigContext } from '../config-provider';
+import List from '../list';
+import { nanoid } from '../utils';
+import { canUseDOM } from '../utils/dom';
+import { HTMLProps } from '../utils/utilityTypes';
+import { CheckboxGroupContext } from './context';
+import type { BaseCheckboxProps, CheckboxCssVars } from './interface';
+
+export type CheckboxProps = BaseCheckboxProps &
+ HTMLProps & {
+ renderIcon?: (props: CheckboxProps) => ReactNode;
+ children?: React.ReactNode | ((props: CheckboxProps) => React.ReactNode);
+ onChange?: (value: BaseEventOrig) => void;
+ };
+
+// const getChecked = (props: CheckboxProps, defaultChecked?: boolean) => {
+// return props.checked ?? props.defaultChecked ?? defaultChecked;
+// };
+
+const Checkbox = (props: CheckboxProps) => {
+ // const defaultVal: Partial<{value: boolean, defaultValue: boolean}> = {};
+ // if ('checked' in props) {
+ // defaultVal.value = props.checked;
+ // }
+ // if ('defaultChecked' in props) {
+ // defaultVal.defaultValue = props.defaultChecked;
+ // }
+ // let [checked, setChecked] = useControllableEventValue({
+ // ...props,
+ // ...defaultVal,
+ // });
+
+ // console.log(checked);
+ let [checked, setChecked] = useControllableEventValue(props, {
+ valuePropName: 'checked',
+ defaultValuePropName: 'defaultChecked'
+ });
+ checked = checked ?? false;
+
+ let { disabled } = props;
+
+ const groupContext = useContext(CheckboxGroupContext);
+ if (groupContext && props.value !== undefined) {
+ checked = includes(groupContext.value, props.value);
+ setChecked = (e: any) => {
+ if (e.target.checked === true) {
+ groupContext.check(props.value);
+ } else {
+ groupContext.uncheck(props.value);
+ }
+ };
+ disabled = disabled || groupContext.disabled;
+ }
+
+ const { prefixCls } = useContext(ConfigContext);
+ const bem = createBEM('checkbox', { prefixCls });
+ const cls = bem([
+ {
+ disabled,
+ checked: checked && !props.indeterminate,
+ untext: !props.children,
+ indeterminate: props.indeterminate,
+ },
+ props.className,
+ ]);
+
+ const currentProps = { ...props, checked };
+
+ const children =
+ typeof props.children === 'function' ? props.children(currentProps) : props.children;
+ const textRender = props.children && {children};
+
+ const iconRender = (
+
+ {props.renderIcon ? (
+ props.renderIcon(currentProps)
+ ) : (
+ {props.indeterminate ? : }
+ )}
+
+ );
+
+ const id = useMemo(() => nanoid(), []);
+
+ const passProps = canUseDOM
+ ? {
+ nativeProps: {
+ id,
+ },
+ }
+ : { id };
+
+ const inputRender = (
+ {
+ if (disabled) return;
+ setChecked({
+ target: {
+ checked: !checked,
+ }
+ } as any);
+ // props.onChange?.(e);
+ }}
+ />
+ );
+
+ if (groupContext?.type === 'button') {
+ return (
+
+ {inputRender}
+
+
+
+ );
+ }
+
+ if (groupContext?.type === 'list') {
+ const tickRender = (
+ <>
+ {inputRender}
+ {iconRender}
+ >
+ );
+
+ return (
+
+ );
+ }
+
+ const contentRender =
+ typeof props.children === 'function' ? (
+ props.children(currentProps)
+ ) : (
+ <>
+ {iconRender}
+ {textRender}
+ >
+ );
+
+ return (
+
+
+ {inputRender}
+
+ );
+};
+
+Checkbox.displayName = 'Checkbox';
+
+Checkbox.defaultProps = {
+ indeterminate: false,
+};
+
+export default Checkbox;
diff --git a/packages/zarm/src/checkbox/Checkbox.tsx b/packages/zarm/src/checkbox/Checkbox.tsx
index ca9b95dbe..73f172b66 100644
--- a/packages/zarm/src/checkbox/Checkbox.tsx
+++ b/packages/zarm/src/checkbox/Checkbox.tsx
@@ -6,68 +6,46 @@ import React, {
forwardRef,
ReactNode,
useContext,
- useEffect,
useImperativeHandle,
useRef,
- useState,
} from 'react';
import Button from '../button';
import { ConfigContext } from '../config-provider';
import List from '../list';
import type { HTMLProps } from '../utils/utilityTypes';
import { CheckboxGroupContext } from './context';
-import type { BaseCheckboxProps } from './interface';
-
-export interface CheckboxCssVars {
- '--icon-size'?: React.CSSProperties['height'];
- '--icon-background'?: React.CSSProperties['background'];
- '--icon-border-radius'?: React.CSSProperties['borderRadius'];
- '--icon-border-width'?: React.CSSProperties['borderWidth'];
- '--icon-border-color'?: React.CSSProperties['borderColor'];
- '--tick-font-size'?: React.CSSProperties['fontSize'];
- '--tick-color'?: React.CSSProperties['color'];
- '--tick-transition'?: React.CSSProperties['transition'];
- '--text-margin-horizontal'?: React.CSSProperties['marginLeft'];
- '--active-opacity'?: React.CSSProperties['opacity'];
- '--checked-icon-background'?: React.CSSProperties['background'];
- '--checked-icon-border-color'?: React.CSSProperties['borderColor'];
- '--checked-tick-color'?: React.CSSProperties['color'];
- '--disabled-icon-background'?: React.CSSProperties['background'];
- '--disabled-icon-border-color'?: React.CSSProperties['borderColor'];
- '--disabled-text-color'?: React.CSSProperties['color'];
- '--disabled-tick-color'?: React.CSSProperties['color'];
- '--group-spacing-vertical'?: React.CSSProperties['marginBottom'];
- '--group-spacing-horizontal'?: React.CSSProperties['marginRight'];
-}
+import type { BaseCheckboxProps, CheckboxCssVars } from './interface';
+import { useControllableEventValue } from '../utils/hooks';
+
export type CheckboxProps = BaseCheckboxProps &
HTMLProps & {
renderIcon?: (props: CheckboxProps) => ReactNode;
- render?: (props: CheckboxProps) => ReactNode;
+ children?: React.ReactNode | ((props: CheckboxProps) => React.ReactNode);
onChange?: (e: ChangeEvent) => void;
};
-const getChecked = (props: CheckboxProps, defaultChecked?: boolean) => {
- return props.checked ?? props.defaultChecked ?? defaultChecked;
-};
-
export interface CheckboxRef {
check: () => void;
uncheck: () => void;
toggle: () => void;
-};
+}
const Checkbox = forwardRef((props, ref) => {
const inputRef = useRef(null);
- let [checked, setChecked] = useState(getChecked(props, false));
+ let [checked, setChecked] = useControllableEventValue(props, {
+ valuePropName: 'checked',
+ defaultValuePropName: 'defaultChecked'
+ });
+ checked = checked ?? false;
let { disabled } = props;
const groupContext = useContext(CheckboxGroupContext);
- if (groupContext && props.value !== undefined) {
+ if (groupContext && props.value !== undefined ) {
checked = includes(groupContext.value, props.value);
- setChecked = (changedChecked: boolean) => {
- if (changedChecked) {
+ setChecked = (e: ChangeEvent) => {
+ if (e.target.checked === true) {
groupContext.check(props.value);
} else {
groupContext.uncheck(props.value);
@@ -89,8 +67,10 @@ const Checkbox = forwardRef((props, ref) => {
]);
const currentProps = { ...props, checked };
+ const children =
+ typeof props.children === 'function' ? props.children(currentProps) : props.children;
- const textRender = props.children && {props.children};
+ const textRender = props.children && {children};
const iconRender = (
@@ -114,11 +94,8 @@ const Checkbox = forwardRef((props, ref) => {
checked={checked}
onChange={(e: ChangeEvent) => {
if (disabled) return;
-
- if (!('checked' in props)) {
- setChecked(e.target.checked);
- }
- props.onChange?.(e);
+ setChecked(e);
+ // props.onChange?.(e);
}}
/>
);
@@ -139,13 +116,6 @@ const Checkbox = forwardRef((props, ref) => {
};
});
- useEffect(() => {
- if (props.checked === undefined) return;
- if (props.checked === checked) return;
-
- setChecked(getChecked({ checked: props.checked, defaultChecked: props.defaultChecked }, false));
- }, [props.checked, props.defaultChecked]);
-
if (groupContext?.type === 'button') {
return (
);
@@ -193,14 +163,15 @@ const Checkbox = forwardRef((props, ref) => {
);
}
- const contentRender = props.render ? (
- props.render(currentProps)
- ) : (
- <>
- {iconRender}
- {textRender}
- >
- );
+ const contentRender =
+ typeof props.children === 'function' ? (
+ props.children(currentProps)
+ ) : (
+ <>
+ {iconRender}
+ {textRender}
+ >
+ );
return (