Skip to content

Commit

Permalink
docs(comp:*): api review (#741)
Browse files Browse the repository at this point in the history
  • Loading branch information
danranVm authored Jan 25, 2022
1 parent b5a9545 commit 70a8f76
Show file tree
Hide file tree
Showing 14 changed files with 129 additions and 105 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ exports[`Header render work 1`] = `
<div class=\\"ix-header-content\\">
<!---->
<!----><span class=\\"ix-header-title\\">Header title</span>
<!---->
<div class=\\"ix-header-suffix\\"><i class=\\"ix-icon ix-icon-close\\" role=\\"img\\" aria-label=\\"close\\"></i></div>
<!----><span class=\\"ix-header-suffix\\"><i class=\\"ix-icon ix-icon-close\\" role=\\"img\\" aria-label=\\"close\\"></i></span>
</div>
<!---->
</div>"
Expand Down
12 changes: 6 additions & 6 deletions packages/components/button/docs/Index.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ subtitle: 按钮
| 名称 | 说明 | 类型 | 默认值 | 全局配置 | 备注 |
| --- | --- | --- | --- | --- | --- |
| `mode` | 设置按钮种类 | `'primary' \| 'default' \| 'dashed' \| 'text' \| 'link'` | `'default'` | - |- |
| `block` | 将按钮宽度调整为自适应其父元素的宽度 | `boolean` | - | - |- |
| `danger` | 设置危险状态 | `boolean` | - | - |- |
| `ghost` | 设置幽灵状态 | `boolean` | - | - |- |
| `disabled` | 设置禁用状态 | `boolean` | - | - |- |
| `ghost` | 设置幽灵状态 | `boolean` | - | - |- |
| `icon` | 设置图标类型 | `string \| #icon` | - | - | `loading``true` 时无效 |
| `loading` | 设置加载中状态 | `boolean` | - | - |- |
| `size` | 设置按钮大小 | `'lg' \| 'md' \| 'sm'` | `'md'` | - |- |
| `mode` | 设置按钮种类 | `'primary' \| 'default' \| 'dashed' \| 'text' \| 'link'` | `'default'` | - |- |
| `shape` | 设置按钮形状 | `'circle' \| 'round'` | - | - |- |
| `block` | 将按钮宽度调整为自适应其父元素的宽度 | `boolean` | - | - |- |
| `icon` | 设置图标类型 | `string \| #icon` | - | - | `loading``true` 时无效 |
| `size` | 设置按钮大小 | `'lg' \| 'md' \| 'sm'` | `'md'` | - |- |
| `type` | 原生 `button``type` 属性 | `'button' \| 'submit' \| 'reset'` | `'button'` | - | 参考 [HTML 标准](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#attr-type) |

### IxButtonGroup
Expand All @@ -34,7 +34,7 @@ subtitle: 按钮
| 名称 | 说明 | 类型 | 默认值 | 全局配置 | 备注 |
| --- | --- | --- | --- | --- | --- |
| `mode` | 设置组内按钮种类 | `'primary' \| 'default' \| 'dashed' \| 'text' \| 'link'` | - | - |- |
| `size` | 设置组内按钮大小 | `'lg' \| 'md' \| 'sm'` | - | - |- |
| `shape` | 设置组内按钮形状 | `'circle' \| 'round'` | - | - |- |
| `size` | 设置组内按钮大小 | `'lg' \| 'md' \| 'sm'` | - | - |- |

### 主题变量
6 changes: 2 additions & 4 deletions packages/components/button/src/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import type { VNodeTypes } from 'vue'

import { computed, defineComponent, inject, normalizeClass } from 'vue'

import { hasSlot } from '@idux/cdk/utils'
import { useGlobalConfig } from '@idux/components/config'
import { FORM_TOKEN } from '@idux/components/form'
import { IxIcon } from '@idux/components/icon'
Expand All @@ -28,9 +27,8 @@ export default defineComponent({
const formContext = inject(FORM_TOKEN, null)

const mode = computed(() => props.mode ?? groupProps.mode ?? 'default')
const hasDefaultSlot = computed(() => hasSlot(slots))

const size = computed(() => props.size ?? groupProps.size ?? formContext?.size.value ?? 'md')

const classes = computed(() => {
const { block, danger, disabled, ghost, loading, icon, shape = groupProps.shape } = props
const prefixCls = mergedPrefixCls.value
Expand All @@ -41,7 +39,7 @@ export default defineComponent({
[`${prefixCls}-disabled`]: disabled || loading,
[`${prefixCls}-ghost`]: ghost,
[`${prefixCls}-loading`]: loading,
[`${prefixCls}-icon-only`]: !hasDefaultSlot.value && (icon || loading),
[`${prefixCls}-icon-only`]: !slots.default && (icon || loading),
[`${prefixCls}-${mode.value}`]: mode.value !== 'default',
[`${prefixCls}-${shape}`]: !!shape,
[`${prefixCls}-${size.value}`]: true,
Expand Down
2 changes: 1 addition & 1 deletion packages/components/button/src/ButtonGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ export default defineComponent({

provide(buttonToken, props)

return () => <div class={mergedPrefixCls.value}>{slots.default?.()}</div>
return () => <div class={mergedPrefixCls.value}>{slots.default && slots.default()}</div>
},
})
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ exports[`Collapse panel work header work 1`] = `
"<div class=\\"ix-collapse\\">
<div class=\\"ix-collapse-panel\\">
<div class=\\"ix-header ix-header-md\\">
<div class=\\"ix-header-content\\">
<div class=\\"ix-header-prefix\\"><i class=\\"ix-icon ix-icon-right\\" style=\\"transform: rotate(0deg);\\" role=\\"img\\" aria-label=\\"right\\"></i></div>
<div class=\\"ix-header-content\\"><span class=\\"ix-header-prefix\\"><i class=\\"ix-icon ix-icon-right\\" style=\\"transform: rotate(0deg);\\" role=\\"img\\" aria-label=\\"right\\"></i></span>
<!----><span class=\\"ix-header-title\\">header 0</span>
<!---->
<!---->
Expand All @@ -27,15 +26,9 @@ exports[`Collapse panel work header work 2`] = `
"<div class=\\"ix-collapse\\">
<div class=\\"ix-collapse-panel\\">
<div class=\\"ix-header ix-header-md\\">
<div class=\\"ix-header-content\\">
<div class=\\"ix-header-prefix\\"><i class=\\"ix-icon ix-icon-right\\" style=\\"transform: rotate(0deg);\\" role=\\"img\\" aria-label=\\"right\\"><svg viewBox=\\"64 64 896 896\\" focusable=\\"false\\" aria-hidden=\\"true\\" data-icon=\\"right\\">
<path d=\\"m728.896 521.024-388.48 388.544a12.8 12.8 0 0 1-18.176 0l-27.136-27.136a12.8 12.8 0 0 1 0-18.112L638.4 521.024a12.8 12.8 0 0 0 0-18.048L295.04 159.68a12.8 12.8 0 0 1 0-18.112l27.136-27.136a12.8 12.8 0 0 1 18.112 0l388.48 388.48a12.8 12.8 0 0 1 0 18.112z\\"></path>
</svg></i></div>
<div class=\\"ix-header-content\\"><span class=\\"ix-header-prefix\\"><i class=\\"ix-icon ix-icon-right\\" style=\\"transform: rotate(0deg);\\" role=\\"img\\" aria-label=\\"right\\"><svg viewBox=\\"64 64 896 896\\" focusable=\\"false\\" aria-hidden=\\"true\\" data-icon=\\"right\\"><path d=\\"m728.896 521.024-388.48 388.544a12.8 12.8 0 0 1-18.176 0l-27.136-27.136a12.8 12.8 0 0 1 0-18.112L638.4 521.024a12.8 12.8 0 0 0 0-18.048L295.04 159.68a12.8 12.8 0 0 1 0-18.112l27.136-27.136a12.8 12.8 0 0 1 18.112 0l388.48 388.48a12.8 12.8 0 0 1 0 18.112z\\"></path></svg></i></span>
<!----><span class=\\"ix-header-title\\">hello header</span>
<!---->
<div class=\\"ix-header-suffix\\"><i class=\\"ix-icon ix-icon-left\\" role=\\"img\\" aria-label=\\"left\\"><svg viewBox=\\"64 64 896 896\\" focusable=\\"false\\" aria-hidden=\\"true\\" data-icon=\\"left\\">
<path d=\\"m295.104 502.976 388.48-388.544a12.8 12.8 0 0 1 18.176 0l27.136 27.136a12.8 12.8 0 0 1 0 18.112L385.6 502.976a12.8 12.8 0 0 0 0 18.048L728.896 864.32a12.8 12.8 0 0 1 0 18.112l-27.136 27.136a12.8 12.8 0 0 1-18.112 0l-388.48-388.48a12.8 12.8 0 0 1 0-18.112z\\"></path>
</svg></i></div>
<!----><span class=\\"ix-header-suffix\\"><i class=\\"ix-icon ix-icon-left\\" role=\\"img\\" aria-label=\\"left\\"><svg viewBox=\\"64 64 896 896\\" focusable=\\"false\\" aria-hidden=\\"true\\" data-icon=\\"left\\"><path d=\\"m295.104 502.976 388.48-388.544a12.8 12.8 0 0 1 18.176 0l27.136 27.136a12.8 12.8 0 0 1 0 18.112L385.6 502.976a12.8 12.8 0 0 0 0 18.048L728.896 864.32a12.8 12.8 0 0 1 0 18.112l-27.136 27.136a12.8 12.8 0 0 1-18.112 0l-388.48-388.48a12.8 12.8 0 0 1 0-18.112z\\"></path></svg></i></span>
</div>
<!---->
</div>
Expand All @@ -54,8 +47,7 @@ exports[`Collapse render work 1`] = `
"<div class=\\"ix-collapse\\">
<div class=\\"ix-collapse-panel\\">
<div class=\\"ix-header ix-header-md\\">
<div class=\\"ix-header-content\\">
<div class=\\"ix-header-prefix\\"><i class=\\"ix-icon ix-icon-right\\" style=\\"transform: rotate(0deg);\\" role=\\"img\\" aria-label=\\"right\\"></i></div>
<div class=\\"ix-header-content\\"><span class=\\"ix-header-prefix\\"><i class=\\"ix-icon ix-icon-right\\" style=\\"transform: rotate(0deg);\\" role=\\"img\\" aria-label=\\"right\\"></i></span>
<!----><span class=\\"ix-header-title\\">header 0</span>
<!---->
<!---->
Expand All @@ -72,8 +64,7 @@ exports[`Collapse render work 1`] = `
</div>
<div class=\\"ix-collapse-panel ix-collapse-panel-expanded\\">
<div class=\\"ix-header ix-header-md\\">
<div class=\\"ix-header-content\\">
<div class=\\"ix-header-prefix\\"><i class=\\"ix-icon ix-icon-right\\" style=\\"transform: rotate(90deg);\\" role=\\"img\\" aria-label=\\"right\\"></i></div>
<div class=\\"ix-header-content\\"><span class=\\"ix-header-prefix\\"><i class=\\"ix-icon ix-icon-right\\" style=\\"transform: rotate(90deg);\\" role=\\"img\\" aria-label=\\"right\\"></i></span>
<!----><span class=\\"ix-header-title\\">header 1</span>
<!---->
<!---->
Expand All @@ -90,8 +81,7 @@ exports[`Collapse render work 1`] = `
</div>
<div class=\\"ix-collapse-panel\\">
<div class=\\"ix-header ix-header-md\\">
<div class=\\"ix-header-content\\">
<div class=\\"ix-header-prefix\\"><i class=\\"ix-icon ix-icon-right\\" style=\\"transform: rotate(0deg);\\" role=\\"img\\" aria-label=\\"right\\"></i></div>
<div class=\\"ix-header-content\\"><span class=\\"ix-header-prefix\\"><i class=\\"ix-icon ix-icon-right\\" style=\\"transform: rotate(0deg);\\" role=\\"img\\" aria-label=\\"right\\"></i></span>
<!----><span class=\\"ix-header-title\\">header 2</span>
<!---->
<!---->
Expand Down
4 changes: 2 additions & 2 deletions packages/components/header/__tests__/header.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,11 @@ describe('Header', () => {
test('showBar work', async () => {
const wrapper = HeaderMount({ props: { showBar: true } })

expect(wrapper.find('.ix-header-bar').exists()).toBe(true)
expect(wrapper.classes()).toContain('ix-header-with-bar')

await wrapper.setProps({ showBar: false })

expect(wrapper.find('.ix-header-bar').exists()).toBe(false)
expect(wrapper.classes()).not.toContain('ix-header-with-bar')
})

test('subTitle work', async () => {
Expand Down
9 changes: 2 additions & 7 deletions packages/components/header/docs/Index.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,13 @@ order: 0
| 名称 | 说明 | 类型 | 默认值 | 全局配置 | 备注 |
| --- | --- | --- | --- | --- | --- |
| `avatar` | 自定义头像 | `string \| AvatarProps \| #avatar` | - | - | 传入 `string` 时,为头像的图标 |
| `description` | 标题下方的说明文字 | `string \| #description` | - | - | - |
| `disabled` | 是否禁用 | `boolean` | `false` | - | - |
| `prefix` | 标题前缀图标 | `string \| VNode \| #prefix` | - | - | - |
| `size` | 标题大小 | `xl \| lg \| md \| sm` | `md` | - | 分别对应 `h1 \| h2 \| h3 \| h4` |
| `size` | 标题大小 | `xl \| lg \| md \| sm` | `md` | - | - |
| `showBar` | 是否显示标题前的竖条 | `boolean` | `false` | - | - |
| `subTitle` | 二级标题文字 | `string \| #subTitle` | - | - | - |
| `suffix` | 标题后缀图标 | `string \| VNode \| #suffix` | - | - | 通常用于额外操作 |
| `title` | 标题文字 | `string \| #default` | - | - | - |
| `onPrefixClick` | 前缀图标被点击 | `(evt: MouseEvent) => void` | - | - | - |
| `onSuffixClick` | 后缀图标被点击 | `(evt: MouseEvent) => void` | - | - | - |

#### HeaderSlots

| 名称 | 说明 | 参数类型 | 备注 |
| --- | --- | --- | --- |
| `description` | 标题下方的说明文字 | - | - |
80 changes: 32 additions & 48 deletions packages/components/header/src/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,16 @@
* found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE
*/

import type { HeaderProps } from './types'
import type { AvatarProps } from '@idux/components/avatar'
import type { ComputedRef, Slot, VNode } from 'vue'

import { computed, defineComponent, isVNode } from 'vue'
import { type ComputedRef, type Slot, computed, defineComponent, normalizeClass } from 'vue'

import { isString } from 'lodash-es'

import { callEmit } from '@idux/cdk/utils'
import { IxAvatar } from '@idux/components/avatar'
import { useGlobalConfig } from '@idux/components/config'
import { IxIcon } from '@idux/components/icon'
import { covertIconVNode, covertLabelVNode } from '@idux/components/utils'

import { headerProps } from './types'

Expand All @@ -34,68 +32,54 @@ export default defineComponent({
const common = useGlobalConfig('common')
const mergedPrefixCls = computed(() => `${common.prefixCls}-header`)

const classes = useClasses(props, mergedPrefixCls)
const classes = computed(() => {
const prefixCls = mergedPrefixCls.value
return normalizeClass({
[prefixCls]: true,
[`${prefixCls}-disabled`]: props.disabled,
[`${prefixCls}-with-bar`]: props.showBar,
[`${prefixCls}-${props.size}`]: true,
})
})

const avatarSize = computed(() => avatarSizeTransformMap[props.size])

const onPrefixClick = (evt: MouseEvent) => !props.disabled && callEmit(props.onPrefixClick, evt)
const onSuffixClick = (evt: MouseEvent) => !props.disabled && callEmit(props.onSuffixClick, evt)

return () => {
const { prefix, suffix, avatar, title, subTitle } = props
const prefixCls = mergedPrefixCls.value

const prefixIconNode = covertIconVNode(slots, props, 'prefix')
const suffixIconNode = covertIconVNode(slots, props, 'suffix')
const titleNode = covertLabelVNode(slots.default, props.title)
const subTitleNode = covertLabelVNode(slots, props, 'subTitle')
const descriptionNode = covertLabelVNode(slots, props, 'description')

return (
<div class={classes.value}>
<div class={`${prefixCls}-content`}>
{renderIcon(slots.prefix, prefix, onPrefixClick, `${prefixCls}-prefix`)}
{renderAvatar(slots.avatar, avatar, avatarSize)}
{renderTitle(slots.default, title, `${prefixCls}-title`)}
{renderTitle(slots.subTitle, subTitle, `${prefixCls}-sub-title`)}
{renderIcon(slots.suffix, suffix, onSuffixClick, `${prefixCls}-suffix`)}
{prefixIconNode && (
<span class={`${prefixCls}-prefix`} onClick={onPrefixClick}>
{prefixIconNode}
</span>
)}
{renderAvatar(slots.avatar, props.avatar, avatarSize)}
{titleNode && <span class={`${prefixCls}-title`}>{titleNode}</span>}
{subTitleNode && <span class={`${prefixCls}-sub-title`}>{subTitleNode}</span>}
{suffixIconNode && (
<span class={`${prefixCls}-suffix`} onClick={onSuffixClick}>
{suffixIconNode}
</span>
)}
</div>
{slots.description ? <div class={`${prefixCls}-description`}>{slots.description()}</div> : null}
{descriptionNode && <div class={`${prefixCls}-description`}>{descriptionNode}</div>}
</div>
)
}
},
})

const useClasses = (props: HeaderProps, mergedPrefixCls: ComputedRef<string>) => {
return computed(() => {
const prefixCls = mergedPrefixCls.value
return {
[prefixCls]: true,
[`${prefixCls}-bar`]: props.showBar,
[`${prefixCls}-disabled`]: props.disabled,
[`${prefixCls}-${props.size}`]: true,
}
})
}

const renderIcon = (
slot: Slot | undefined,
icon: string | VNode | undefined,
onClick: (evt: MouseEvent) => void,
wrapperClassName: string,
) => {
if (!slot && !icon) {
return null
}
const iconNode = slot ? slot() : isVNode(icon) ? icon : <IxIcon name={icon} />
return (
<div class={wrapperClassName} onClick={onClick}>
{iconNode}
</div>
)
}

const renderTitle = (slot: Slot | undefined, title: string | undefined, wrapperClassName: string) => {
if (!slot && !title) {
return null
}
return <span class={wrapperClassName}>{slot?.() ?? title}</span>
}

const renderAvatar = (
slot: Slot | undefined,
avatar: string | AvatarProps | undefined,
Expand Down
1 change: 1 addition & 0 deletions packages/components/header/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export type HeaderSize = 'xl' | 'lg' | 'md' | 'sm'

export const headerProps = {
avatar: IxPropTypes.oneOfType([String, IxPropTypes.object<AvatarProps>()]),
description: IxPropTypes.string,
disabled: IxPropTypes.bool.def(false),
prefix: IxPropTypes.oneOfType([String, IxPropTypes.vNode]),
size: IxPropTypes.oneOf<HeaderSize>(['xl', 'lg', 'md', 'sm']).def('md'),
Expand Down
32 changes: 16 additions & 16 deletions packages/components/header/style/index.less
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,6 @@
background-color: @header-background-color;
transition: @header-transition;

&-bar &-content {
padding-left: @header-bar-width * 2;

&::before {
position: absolute;
left: 0;
top: 0;
bottom: 0;
margin: @header-bar-margin;
width: @header-bar-width;
background-color: @header-bar-background-color;
border-radius: calc(@header-bar-width / 2);
content: '';
}
}

&-content {
position: relative;
width: 100%;
Expand Down Expand Up @@ -98,6 +82,22 @@
}
}

&-with-bar &-content {
padding-left: @header-bar-width * 2;

&::before {
position: absolute;
left: 0;
top: 0;
bottom: 0;
margin: @header-bar-margin;
width: @header-bar-width;
background-color: @header-bar-background-color;
border-radius: calc(@header-bar-width / 2);
content: '';
}
}

&-xl {
.header-size(@header-height-xl, @header-title-font-size-xl);
}
Expand Down
6 changes: 4 additions & 2 deletions packages/components/icon/docs/Index.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ order: 0

### IxIcon

#### Props
#### IconProps

| 名称 | 说明 | 类型 | 默认值 | 全局配置 | 备注 |
| --- | --- | --- | --- | --- | --- |
| `name`| 图标名称 | `string` | - | - | - |
| `color` | 图标颜色 | `string` | - | - | - |
| `iconfont` | 图标是否来自 `iconfont` | `boolean` | - | - | - |
| `rotate` | 图标旋转角度 | `boolean \| number` | `false` | - |`true` 时会循环旋转 |
| `size` | 图标大小 | `number \| string` | - | - | - |

### 辅助函数

Expand Down Expand Up @@ -72,7 +74,7 @@ const loadIconDynamically = (iconName: string) => {
useGlobalConfig('icon', { loadIconDynamically })
```

你可以执行 `node ./node_modules/@idux/components/bin icon` 命令将默认图标拷贝到 `public/idux-icons` 目录下。
你可以执行 `node ./node_modules/@idux/components/bin icon` 命令将默认图标拷贝到 `public/idux-icons` 目录下。
当然,你也可以手动拷贝,默认图标的存放地址为 `./node_modules/@idux/components/icon/svg`

#### 静态加载
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Popover header props work 1`] = `"<transition-stub><div class=\\"ix-overlay ix-popover\\" style=\\"position: absolute; left: 0px; top: 0px; margin: 0px;\\"><div class=\\"ix-popover-wrapper\\"><div class=\\"ix-header ix-header-sm\\"><div class=\\"ix-header-content\\"><div class=\\"ix-header-prefix\\"><i class=\\"ix-icon ix-icon-up\\" role=\\"img\\" aria-label=\\"up\\"></i></div><!----><span class=\\"ix-header-title\\">Title</span><span class=\\"ix-header-sub-title\\">subTitle</span><div class=\\"ix-header-suffix\\"><i class=\\"ix-icon ix-icon-down\\" role=\\"img\\" aria-label=\\"down\\"></i></div></div><!----></div></div><div class=\\"ix-overlay-arrow\\" style=\\"position: absolute;\\"></div></div></transition-stub>"`;
exports[`Popover header props work 1`] = `"<transition-stub><div class=\\"ix-overlay ix-popover\\" style=\\"position: absolute; left: 0px; top: 0px; margin: 0px;\\"><div class=\\"ix-popover-wrapper\\"><div class=\\"ix-header ix-header-sm\\"><div class=\\"ix-header-content\\"><span class=\\"ix-header-prefix\\"><i class=\\"ix-icon ix-icon-up\\" role=\\"img\\" aria-label=\\"up\\"></i></span><!----><span class=\\"ix-header-title\\">Title</span><span class=\\"ix-header-sub-title\\">subTitle</span><span class=\\"ix-header-suffix\\"><i class=\\"ix-icon ix-icon-down\\" role=\\"img\\" aria-label=\\"down\\"></i></span></div><!----></div></div><div class=\\"ix-overlay-arrow\\" style=\\"position: absolute;\\"></div></div></transition-stub>"`;
exports[`Popover render work 1`] = `
"<div id=\\"trigger\\">trigger</div>
Expand Down
1 change: 1 addition & 0 deletions packages/components/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

export * from './src/colors'
export * from './src/covertTarget'
export * from './src/covertVNode'
export * from './src/useFormAccessor'
export * from './src/useFormElement'
export * from './src/useKey'
Loading

0 comments on commit 70a8f76

Please sign in to comment.