u
This commit is contained in:
1 parent
104e0a78c6
commit
4d0d2f875e
13 files changed
+799
-223
No files matched your search
@@ -0,0 +1,176 @@
|
|||||||
|
import type { PropType, RenderFunction } from 'vue'
|
||||||
|
import { computed, defineComponent, provide, reactive, ref, watch } from 'vue'
|
||||||
|
import { getPrefixCls } from '../_utils/getPrefixCls'
|
||||||
|
import Space from '../space/index'
|
||||||
|
import Checkbox from './checkbox'
|
||||||
|
import { checkboxGroupKey } from './context'
|
||||||
|
|
||||||
|
interface CheckboxOption {
|
||||||
|
label?: string | RenderFunction
|
||||||
|
value?: string | number
|
||||||
|
extra?: string | RenderFunction
|
||||||
|
disabled?: boolean
|
||||||
|
[key: string]: any
|
||||||
|
}
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'CheckboxGroup',
|
||||||
|
props: {
|
||||||
|
modelValue: {
|
||||||
|
type: Array as PropType<Array<string | number | boolean>>,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
defaultValue: {
|
||||||
|
type: Array as PropType<Array<string | number | boolean>>,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
disabled: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
labelField: {
|
||||||
|
type: String,
|
||||||
|
default: 'label',
|
||||||
|
},
|
||||||
|
valueField: {
|
||||||
|
type: String,
|
||||||
|
default: 'value',
|
||||||
|
},
|
||||||
|
extraField: {
|
||||||
|
type: String,
|
||||||
|
default: 'extra',
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
type: Array as PropType<Array<string | number | CheckboxOption>>,
|
||||||
|
default: [],
|
||||||
|
},
|
||||||
|
spaceProps: {
|
||||||
|
type: Object as PropType<Record<string, any>>,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: String as PropType<'default' | 'card' | 'pureCard'>,
|
||||||
|
default: 'default',
|
||||||
|
},
|
||||||
|
class: {
|
||||||
|
type: [String, Array, Object],
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
emits: ['update:modelValue', 'change'],
|
||||||
|
setup(props, { slots, emit }) {
|
||||||
|
const prefixCls = getPrefixCls('checkbox-group')
|
||||||
|
|
||||||
|
const _value = ref(props.modelValue ?? props.defaultValue ?? [])
|
||||||
|
|
||||||
|
watch(() => props.modelValue, (newVal) => {
|
||||||
|
_value.value = newVal ?? []
|
||||||
|
})
|
||||||
|
|
||||||
|
const groupDisabled = computed(() => props.disabled)
|
||||||
|
const groupType = computed(() => props.type)
|
||||||
|
|
||||||
|
const handleChange = (val: string | number | boolean, e: Event) => {
|
||||||
|
const current = _value.value ? [..._value.value] : []
|
||||||
|
const index = current.indexOf(val)
|
||||||
|
|
||||||
|
if (index > -1) {
|
||||||
|
// 已存在 -> 取消选中
|
||||||
|
current.splice(index, 1)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// 不存在 -> 添加
|
||||||
|
current.push(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 非受控模式才更新内部值
|
||||||
|
if (props.modelValue === undefined) {
|
||||||
|
_value.value = current
|
||||||
|
}
|
||||||
|
|
||||||
|
// 通知外部
|
||||||
|
emit('update:modelValue', current)
|
||||||
|
emit('change', current, e)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提供 context 给 Radio 使用
|
||||||
|
provide(checkboxGroupKey, reactive({
|
||||||
|
name: 'AoCheckboxGroup' as const,
|
||||||
|
value: _value,
|
||||||
|
disabled: groupDisabled,
|
||||||
|
type: groupType,
|
||||||
|
slots,
|
||||||
|
handleChange,
|
||||||
|
}))
|
||||||
|
|
||||||
|
const renderOptions = () => {
|
||||||
|
return props.options.map((option) => {
|
||||||
|
const opt
|
||||||
|
= typeof option === 'string' || typeof option === 'number'
|
||||||
|
? { [props.labelField]: String(option), [props.valueField]: option }
|
||||||
|
: option
|
||||||
|
|
||||||
|
const labelContent = slots.label
|
||||||
|
? slots.label({ data: opt })
|
||||||
|
: typeof opt[props.labelField] === 'function'
|
||||||
|
? opt[props.labelField]()
|
||||||
|
: opt[props.labelField]
|
||||||
|
|
||||||
|
const extraContent = slots.extra
|
||||||
|
? slots.extra({ data: opt })
|
||||||
|
: typeof opt[props.extraField] === 'function'
|
||||||
|
? opt[props.extraField]()
|
||||||
|
: opt[props.extraField]
|
||||||
|
|
||||||
|
const isChecked
|
||||||
|
= _value.value.includes(opt[props.valueField])
|
||||||
|
|
||||||
|
if (slots.radio) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={opt[props.valueField]}
|
||||||
|
onClick={e => handleChange(opt[props.valueField], e)}
|
||||||
|
>
|
||||||
|
{slots.radio({ data: opt, checked: _value.value === opt[props.valueField] })}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Checkbox
|
||||||
|
key={opt[props.valueField]}
|
||||||
|
value={opt[props.valueField]}
|
||||||
|
extra={extraContent}
|
||||||
|
disabled={opt.disabled ?? props.disabled}
|
||||||
|
checked={isChecked}
|
||||||
|
type={props.type}
|
||||||
|
>
|
||||||
|
{labelContent}
|
||||||
|
</Checkbox>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const spaceSize
|
||||||
|
= ['default', 'card', 'pureCard'].includes(groupType.value)
|
||||||
|
? [6, 6]
|
||||||
|
: props.spaceProps.size ?? 0
|
||||||
|
|
||||||
|
return () => (
|
||||||
|
<Space
|
||||||
|
align="start"
|
||||||
|
size={spaceSize}
|
||||||
|
{...props.spaceProps}
|
||||||
|
class={[
|
||||||
|
`${prefixCls}-${groupType.value}`,
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{props.options.length > 0 ? renderOptions() : slots.default?.()}
|
||||||
|
</Space>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
})
|
||||||
@@ -0,0 +1,225 @@
|
|||||||
|
import type { PropType, VNode } from 'vue'
|
||||||
|
import type { CheckboxGroupContext } from './context'
|
||||||
|
import { computed, defineComponent, inject, ref, watch } from 'vue'
|
||||||
|
import { getPrefixCls } from '../_utils/getPrefixCls'
|
||||||
|
import Icon from '../icon/index'
|
||||||
|
import { checkboxGroupKey } from './context'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'Checkbox',
|
||||||
|
props: {
|
||||||
|
modelValue: {
|
||||||
|
type: Boolean,
|
||||||
|
default: undefined,
|
||||||
|
},
|
||||||
|
checked: {
|
||||||
|
type: Boolean,
|
||||||
|
default: undefined,
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: [String, Number, Boolean] as PropType<string | number | boolean>,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
indeterminate: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
|
||||||
|
defaultChecked: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
disabled: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: String as PropType<'default' | 'card' | 'pureCard'>,
|
||||||
|
default: 'default',
|
||||||
|
},
|
||||||
|
extra: {
|
||||||
|
type: [String, Object, Function] as unknown as () => string | VNode | (() => VNode),
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
class: {
|
||||||
|
type: [String, Array, Object],
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
emits: ['update:modelValue', 'update:checked', 'change'],
|
||||||
|
setup(props, { slots, emit }) {
|
||||||
|
const prefixCls = getPrefixCls('checkbox')
|
||||||
|
|
||||||
|
const checkboxGroupCtx = inject<CheckboxGroupContext | undefined>(checkboxGroupKey, undefined)
|
||||||
|
const inGroup = computed(() => !!checkboxGroupCtx)
|
||||||
|
|
||||||
|
const isDisabled = computed(() => props.disabled || checkboxGroupCtx?.disabled)
|
||||||
|
const _checked = ref(props.defaultChecked)
|
||||||
|
|
||||||
|
const mergedType = computed(() =>
|
||||||
|
props.type || checkboxGroupCtx?.type || 'default',
|
||||||
|
)
|
||||||
|
|
||||||
|
const isChecked = computed(() => {
|
||||||
|
if (inGroup.value && checkboxGroupCtx) {
|
||||||
|
const groupValue = checkboxGroupCtx.value
|
||||||
|
if (Array.isArray(groupValue)) {
|
||||||
|
return groupValue.includes(props.value)
|
||||||
|
}
|
||||||
|
return groupValue === props.value
|
||||||
|
}
|
||||||
|
return props.checked ?? props.modelValue ?? _checked.value
|
||||||
|
})
|
||||||
|
|
||||||
|
const handleClick = (event: Event) => {
|
||||||
|
if (isDisabled.value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (inGroup.value && checkboxGroupCtx) {
|
||||||
|
checkboxGroupCtx.handleChange(props.value, event)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const newChecked = !isChecked.value
|
||||||
|
if (props.checked === undefined)
|
||||||
|
_checked.value = newChecked
|
||||||
|
|
||||||
|
emit('update:modelValue', newChecked)
|
||||||
|
emit('update:checked', newChecked)
|
||||||
|
}
|
||||||
|
emit('change', { value: props.value, event })
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(() => props.checked, (val) => {
|
||||||
|
if (val !== undefined) {
|
||||||
|
_checked.value = val
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const renderDefault = () => (
|
||||||
|
<label
|
||||||
|
class={[
|
||||||
|
`${prefixCls}-default`,
|
||||||
|
{ [`${prefixCls}-checked`]: isChecked.value },
|
||||||
|
{ [`${prefixCls}-disabled`]: isDisabled.value },
|
||||||
|
props.class,
|
||||||
|
]}
|
||||||
|
style={{ ...props.style }}
|
||||||
|
onClick={handleClick}
|
||||||
|
>
|
||||||
|
<span class={`${prefixCls}-main`}>
|
||||||
|
<input
|
||||||
|
class={`${prefixCls}-input`}
|
||||||
|
type="checkbox"
|
||||||
|
onClick={e => e.stopPropagation()}
|
||||||
|
/>
|
||||||
|
<span class={`${prefixCls}-inner`}>
|
||||||
|
{
|
||||||
|
props.indeterminate
|
||||||
|
? (
|
||||||
|
<Icon icon="garden:dash-fill-12" />
|
||||||
|
)
|
||||||
|
: isChecked.value
|
||||||
|
? (
|
||||||
|
<Icon icon="garden:check-sm-fill-12" />
|
||||||
|
)
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<div class={`${prefixCls}-content`}>
|
||||||
|
<div class={`${prefixCls}-label`}>
|
||||||
|
{slots.default?.()}
|
||||||
|
</div>
|
||||||
|
{props.extra && (
|
||||||
|
<div class={`${prefixCls}-extra`}>
|
||||||
|
{typeof props.extra === 'function' ? props.extra() : props.extra}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
)
|
||||||
|
|
||||||
|
const renderCard = () => (
|
||||||
|
<label
|
||||||
|
class={[
|
||||||
|
`${prefixCls}-card`,
|
||||||
|
{ [`${prefixCls}-checked`]: isChecked.value },
|
||||||
|
{ [`${prefixCls}-disabled`]: isDisabled.value },
|
||||||
|
props.class,
|
||||||
|
]}
|
||||||
|
style={{ ...props.style }}
|
||||||
|
onClick={handleClick}
|
||||||
|
>
|
||||||
|
<span class={`${prefixCls}-main`}>
|
||||||
|
<input
|
||||||
|
class={`${prefixCls}-input`}
|
||||||
|
type="checkbox"
|
||||||
|
onClick={e => e.stopPropagation()}
|
||||||
|
/>
|
||||||
|
<span class={`${prefixCls}-inner`}>
|
||||||
|
{
|
||||||
|
props.indeterminate
|
||||||
|
? (
|
||||||
|
<Icon icon="garden:dash-fill-12" />
|
||||||
|
)
|
||||||
|
: isChecked.value
|
||||||
|
? (
|
||||||
|
<Icon icon="garden:check-sm-fill-12" />
|
||||||
|
)
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<div class={`${prefixCls}-content`}>
|
||||||
|
<div class={`${prefixCls}-label`}>
|
||||||
|
{slots.default?.()}
|
||||||
|
</div>
|
||||||
|
{props.extra && (
|
||||||
|
<div class={`${prefixCls}-extra`}>
|
||||||
|
{typeof props.extra === 'function' ? props.extra() : props.extra}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
)
|
||||||
|
|
||||||
|
const renderPureCard = () => (
|
||||||
|
<label
|
||||||
|
class={[
|
||||||
|
`${prefixCls}-pureCard`,
|
||||||
|
{ [`${prefixCls}-checked`]: isChecked.value },
|
||||||
|
{ [`${prefixCls}-disabled`]: isDisabled.value },
|
||||||
|
props.class,
|
||||||
|
]}
|
||||||
|
style={{ ...props.style }}
|
||||||
|
onClick={handleClick}
|
||||||
|
>
|
||||||
|
<div class={`${prefixCls}-content`}>
|
||||||
|
<div class={`${prefixCls}-label`}>
|
||||||
|
{slots.default?.()}
|
||||||
|
</div>
|
||||||
|
{props.extra && (
|
||||||
|
<div class={`${prefixCls}-extra`}>
|
||||||
|
{typeof props.extra === 'function' ? props.extra() : props.extra}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
switch (mergedType.value) {
|
||||||
|
case 'card':
|
||||||
|
return renderCard()
|
||||||
|
case 'pureCard':
|
||||||
|
return renderPureCard()
|
||||||
|
default:
|
||||||
|
return renderDefault()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import type { InjectionKey, Slots } from 'vue'
|
||||||
|
|
||||||
|
export interface CheckboxGroupContext {
|
||||||
|
name: 'AoCheckboxGroup'
|
||||||
|
value: (string | number | boolean)[]
|
||||||
|
disabled: boolean
|
||||||
|
slots: Slots
|
||||||
|
type?: 'default' | 'card' | 'pureCard'
|
||||||
|
handleChange: (value: string | number | boolean, e: Event) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export const checkboxGroupKey: InjectionKey<CheckboxGroupContext>
|
||||||
|
= Symbol('CheckboxGroup')
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
/* 单个受控 */
|
||||||
|
const checked1 = ref(false)
|
||||||
|
|
||||||
|
/* 单个非受控(只用 defaultChecked) */
|
||||||
|
const checked2 = ref(true) // 只是初始值演示,不跟随
|
||||||
|
|
||||||
|
/* group 多选 */
|
||||||
|
const groupValue = ref<Array<string | number>>(['B'])
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div style="padding:20px">
|
||||||
|
<h3>单个 Checkbox(受控 v-model:checked)</h3>
|
||||||
|
<ACheckbox v-model:checked="checked1" value="single1">
|
||||||
|
选项 1
|
||||||
|
</ACheckbox>
|
||||||
|
<p>当前状态: {{ checked1 }}</p>
|
||||||
|
|
||||||
|
<h3>单个 Checkbox(非受控 defaultChecked)</h3>
|
||||||
|
<ACheckbox value="single2" :default-checked="checked2">
|
||||||
|
选项 2
|
||||||
|
</ACheckbox>
|
||||||
|
<p>初始状态: {{ checked2 }}(点击后组件自己维护,不影响这个 ref)</p>
|
||||||
|
|
||||||
|
<h3>CheckboxGroup(多选)</h3>
|
||||||
|
<ACheckboxGroup v-model="groupValue" :options="['A', 'B', 'C']" />
|
||||||
|
<p>选中值: {{ groupValue }}</p>
|
||||||
|
|
||||||
|
<h3>CheckboxGroup(自定义插槽用法)</h3>
|
||||||
|
<ACheckboxGroup v-model="groupValue">
|
||||||
|
<ACheckbox value="X">
|
||||||
|
自定义 X
|
||||||
|
</ACheckbox>
|
||||||
|
<ACheckbox value="Y">
|
||||||
|
自定义 Y
|
||||||
|
</ACheckbox>
|
||||||
|
<ACheckbox value="Z">
|
||||||
|
自定义 Z
|
||||||
|
</ACheckbox>
|
||||||
|
</ACheckboxGroup>
|
||||||
|
<p>选中值: {{ groupValue }}</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,222 @@
|
|||||||
|
@use '../_styles/_variables.scss' as *;
|
||||||
|
@use 'sass:color';
|
||||||
|
|
||||||
|
$checkbox-prefix: '#{$prefix}-checkbox';
|
||||||
|
|
||||||
|
.#{$checkbox-prefix}-default {
|
||||||
|
display: inline-flex;
|
||||||
|
vertical-align: middle;
|
||||||
|
color: $text-color-base;
|
||||||
|
align-items: flex-start;
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
&.#{$checkbox-prefix}-checked {
|
||||||
|
.#{$checkbox-prefix}-main {
|
||||||
|
.#{$checkbox-prefix}-inner {
|
||||||
|
border-color: transparent;
|
||||||
|
background-color: $primary-color;
|
||||||
|
color: $text-color-anti;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.#{$checkbox-prefix}-main {
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
outline: 0;
|
||||||
|
|
||||||
|
.#{$checkbox-prefix}-input {
|
||||||
|
opacity: 0;
|
||||||
|
outline: 0;
|
||||||
|
position: absolute;
|
||||||
|
z-index: -1;
|
||||||
|
margin: 0;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.#{$checkbox-prefix}-inner {
|
||||||
|
border: 1px solid $border-color;
|
||||||
|
border-radius: $border-radius;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
background-color: $bg-color-container;
|
||||||
|
cursor: pointer;
|
||||||
|
box-sizing: border-box;
|
||||||
|
outline: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
transition:
|
||||||
|
background-color 0.1s ease,
|
||||||
|
border-color 0.1s ease;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.#{$checkbox-prefix}-content {
|
||||||
|
margin-left: 8px;
|
||||||
|
display: inline-block;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.#{$checkbox-prefix}-label {
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 16px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
color: $text-color-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
.#{$checkbox-prefix}-extra {
|
||||||
|
font-size: 12px;
|
||||||
|
color: $text-color-secondary;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.#{$checkbox-prefix}-card {
|
||||||
|
color: $text-color-base;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
padding: 8px 12px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border-radius: $border-radius;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:hover .#{$checkbox-prefix}-main {
|
||||||
|
background-color: $bg-color-component;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.#{$checkbox-prefix}-disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.#{$checkbox-prefix}-checked {
|
||||||
|
border-color: $primary-color;
|
||||||
|
background-color: $status-info-bg-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover .#{$checkbox-prefix}-main .#{$checkbox-prefix}-inner {
|
||||||
|
border-color: $primary-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.#{$checkbox-prefix}-checked {
|
||||||
|
.#{$checkbox-prefix}-main {
|
||||||
|
.#{$checkbox-prefix}-inner {
|
||||||
|
border-color: transparent;
|
||||||
|
background-color: $primary-color;
|
||||||
|
color: $text-color-anti;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.#{$checkbox-prefix}-main {
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
outline: 0;
|
||||||
|
.#{$checkbox-prefix}-input {
|
||||||
|
opacity: 0;
|
||||||
|
outline: 0;
|
||||||
|
position: absolute;
|
||||||
|
z-index: -1;
|
||||||
|
margin: 0;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.#{$checkbox-prefix}-inner {
|
||||||
|
border: 1px solid $border-color;
|
||||||
|
border-radius: $border-radius;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
background-color: $bg-color-container;
|
||||||
|
cursor: pointer;
|
||||||
|
box-sizing: border-box;
|
||||||
|
outline: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
transition:
|
||||||
|
background-color 0.1s ease,
|
||||||
|
border-color 0.1s ease;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.#{$checkbox-prefix}-content {
|
||||||
|
margin-left: 8px;
|
||||||
|
display: inline-block;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.#{$checkbox-prefix}-label {
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 16px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
color: $text-color-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
.#{$checkbox-prefix}-extra {
|
||||||
|
font-size: 12px;
|
||||||
|
color: $text-color-secondary;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.#{$checkbox-prefix}-pureCard {
|
||||||
|
color: $text-color-base;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
padding: 8px 12px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border-radius: $border-radius;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:hover .#{$checkbox-prefix}-main {
|
||||||
|
background-color: $bg-color-component;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.#{$checkbox-prefix}-disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.#{$checkbox-prefix}-checked {
|
||||||
|
border-color: $primary-color;
|
||||||
|
background-color: $status-info-bg-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.#{$checkbox-prefix}-content {
|
||||||
|
display: inline-block;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.#{$checkbox-prefix}-label {
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 16px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
color: $text-color-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
.#{$checkbox-prefix}-extra {
|
||||||
|
font-size: 12px;
|
||||||
|
color: $text-color-secondary;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
export { default as ConfigProvider } from './_config'
|
export { default as ConfigProvider } from './_config'
|
||||||
export { default as Button } from './button'
|
export { default as Button } from './button'
|
||||||
|
export { default as Checkbox } from './checkbox/checkbox'
|
||||||
|
export { default as CheckboxGroup } from './checkbox/checkbox-group'
|
||||||
export { default as Drawer } from './drawer'
|
export { default as Drawer } from './drawer'
|
||||||
export { default as Group } from './group'
|
export { default as Group } from './group'
|
||||||
export { default as Icon } from './icon'
|
export { default as Icon } from './icon'
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
@use './space/index.scss' as *;
|
@use './space/index.scss' as *;
|
||||||
@use './separator/index.scss' as *;
|
@use './separator/index.scss' as *;
|
||||||
@use './radio/index.scss' as *;
|
@use './radio/index.scss' as *;
|
||||||
|
@use './checkbox/index.scss' as *;
|
||||||
|
|
||||||
[class*='#{variables.$prefix}-'] {
|
[class*='#{variables.$prefix}-'] {
|
||||||
-webkit-box-sizing: border-box;
|
-webkit-box-sizing: border-box;
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ $radio-group-prefix: '#{$prefix}-radio-group';
|
|||||||
}
|
}
|
||||||
|
|
||||||
.#{$radio-prefix}-content {
|
.#{$radio-prefix}-content {
|
||||||
font-size: 12px;
|
font-size: 14px;
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -465,12 +465,12 @@ $radio-group-prefix: '#{$prefix}-radio-group';
|
|||||||
}
|
}
|
||||||
|
|
||||||
.#{$radio-prefix}-content {
|
.#{$radio-prefix}-content {
|
||||||
font-size: 12px;
|
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
.#{$radio-prefix}-label {
|
.#{$radio-prefix}-label {
|
||||||
|
font-size: 14px;
|
||||||
line-height: 16px;
|
line-height: 16px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -513,11 +513,11 @@ $radio-group-prefix: '#{$prefix}-radio-group';
|
|||||||
}
|
}
|
||||||
|
|
||||||
.#{$radio-prefix}-content {
|
.#{$radio-prefix}-content {
|
||||||
font-size: 12px;
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
.#{$radio-prefix}-label {
|
.#{$radio-prefix}-label {
|
||||||
|
font-size: 14px;
|
||||||
line-height: 16px;
|
line-height: 16px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
@@ -72,13 +72,15 @@ export default defineComponent({
|
|||||||
_value.value = newVal ?? undefined
|
_value.value = newVal ?? undefined
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const groupDisabled = computed(() => props.disabled)
|
||||||
|
const groupType = computed(() => props.type)
|
||||||
|
|
||||||
const handleChange = (val: string | number | boolean | undefined, e: Event) => {
|
const handleChange = (val: string | number | boolean | undefined, e: Event) => {
|
||||||
_value.value = val
|
_value.value = val
|
||||||
emit('update:modelValue', val)
|
emit('update:modelValue', val)
|
||||||
emit('change', val, e)
|
emit('change', val, e)
|
||||||
}
|
}
|
||||||
const groupDisabled = computed(() => props.disabled)
|
|
||||||
const groupType = computed(() => props.type)
|
|
||||||
// 提供 context 给 Radio 使用
|
// 提供 context 给 Radio 使用
|
||||||
provide(radioGroupKey, reactive({
|
provide(radioGroupKey, reactive({
|
||||||
name: 'AoRadioGroup' as const,
|
name: 'AoRadioGroup' as const,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { PropType, VNode } from 'vue'
|
import type { PropType, VNode } from 'vue'
|
||||||
import type { RadioGroupContext } from './context'
|
import type { RadioGroupContext } from './context'
|
||||||
import { computed, defineComponent, inject, ref } from 'vue'
|
import { computed, defineComponent, inject, ref, watch } from 'vue'
|
||||||
import { getPrefixCls } from '../_utils/getPrefixCls'
|
import { getPrefixCls } from '../_utils/getPrefixCls'
|
||||||
import { radioGroupKey } from './context'
|
import { radioGroupKey } from './context'
|
||||||
|
|
||||||
@@ -11,6 +11,14 @@ export default defineComponent({
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: undefined,
|
default: undefined,
|
||||||
},
|
},
|
||||||
|
checked: {
|
||||||
|
type: Boolean,
|
||||||
|
default: undefined,
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: [String, Number, Boolean] as PropType<string | number | boolean>,
|
||||||
|
default: undefined,
|
||||||
|
},
|
||||||
defaultChecked: {
|
defaultChecked: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
@@ -19,10 +27,6 @@ export default defineComponent({
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
value: {
|
|
||||||
type: [String, Number, Boolean] as PropType<string | number | boolean>,
|
|
||||||
default: true,
|
|
||||||
},
|
|
||||||
allowUncheck: {
|
allowUncheck: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true,
|
default: true,
|
||||||
@@ -36,7 +40,7 @@ export default defineComponent({
|
|||||||
default: 'default',
|
default: 'default',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
emits: ['update:modelValue', 'change'],
|
emits: ['update:modelValue', 'update:checked', 'change'],
|
||||||
setup(props, { slots, emit }) {
|
setup(props, { slots, emit }) {
|
||||||
const prefixCls = getPrefixCls('radio')
|
const prefixCls = getPrefixCls('radio')
|
||||||
|
|
||||||
@@ -46,10 +50,14 @@ export default defineComponent({
|
|||||||
const isDisabled = computed(() => props.disabled || radioGroupCtx?.disabled)
|
const isDisabled = computed(() => props.disabled || radioGroupCtx?.disabled)
|
||||||
const _checked = ref(props.defaultChecked)
|
const _checked = ref(props.defaultChecked)
|
||||||
|
|
||||||
|
const mergedType = computed(() =>
|
||||||
|
props.type || radioGroupCtx?.type || 'default',
|
||||||
|
)
|
||||||
|
|
||||||
const isChecked = computed(() => {
|
const isChecked = computed(() => {
|
||||||
if (inGroup.value)
|
if (inGroup.value)
|
||||||
return props.value === radioGroupCtx!.value
|
return props.value === radioGroupCtx!.value
|
||||||
return props.modelValue ?? _checked.value
|
return props.checked ?? props.modelValue ?? _checked.value
|
||||||
})
|
})
|
||||||
|
|
||||||
const isAllowUncheck = computed(() => props.allowUncheck || radioGroupCtx?.allowUncheck)
|
const isAllowUncheck = computed(() => props.allowUncheck || radioGroupCtx?.allowUncheck)
|
||||||
@@ -66,12 +74,21 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const newValue = isAllowUncheck.value ? !isChecked.value : true
|
const newValue = isAllowUncheck.value ? !isChecked.value : true
|
||||||
|
if (props.checked === undefined) {
|
||||||
_checked.value = newValue
|
_checked.value = newValue
|
||||||
|
}
|
||||||
|
|
||||||
emit('update:modelValue', newValue)
|
emit('update:modelValue', newValue)
|
||||||
emit('change', props.value, e)
|
emit('change', props.value, e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
watch(() => props.checked, (val) => {
|
||||||
|
if (val !== undefined) {
|
||||||
|
_checked.value = val
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const renderDefault = () => (
|
const renderDefault = () => (
|
||||||
<label
|
<label
|
||||||
class={[
|
class={[
|
||||||
@@ -211,7 +228,7 @@ export default defineComponent({
|
|||||||
)
|
)
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
switch (props.type) {
|
switch (mergedType.value) {
|
||||||
case 'filled':
|
case 'filled':
|
||||||
return renderFilled()
|
return renderFilled()
|
||||||
case 'primaryFilled':
|
case 'primaryFilled':
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { PropType } from 'vue'
|
import type { PropType } from 'vue'
|
||||||
import type { TagGroupContext } from './context'
|
import type { TagGroupContext } from './context'
|
||||||
import { computed, defineComponent, inject, ref } from 'vue'
|
import { computed, defineComponent, inject, ref, watch } from 'vue'
|
||||||
import { getPrefixCls } from '../_utils/getPrefixCls'
|
import { getPrefixCls } from '../_utils/getPrefixCls'
|
||||||
import Icon from '../icon/index'
|
import Icon from '../icon/index'
|
||||||
import { tagGroupKey } from './context'
|
import { tagGroupKey } from './context'
|
||||||
@@ -8,23 +8,72 @@ import { tagGroupKey } from './context'
|
|||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'Tag',
|
name: 'Tag',
|
||||||
props: {
|
props: {
|
||||||
shape: { type: String as PropType<'square' | 'round' | 'mark'>, default: 'square' },
|
shape: {
|
||||||
size: { type: String as PropType<'small' | 'medium' | 'large'>, default: 'medium' },
|
type: String as PropType<'square' | 'round' | 'mark'>,
|
||||||
type: { type: String as () => 'solid' | 'light' | 'outline' | 'outline-light', default: 'solid' },
|
default: 'square',
|
||||||
status: { type: String as () => 'primary' | 'danger' | 'warning' | 'success' | 'default', default: 'default' },
|
|
||||||
checkable: { type: Boolean, default: false },
|
|
||||||
value: { type: [String, Number, Boolean] as PropType<string | number | boolean>, required: true },
|
|
||||||
checked: { type: Boolean, default: undefined },
|
|
||||||
defaultChecked: { type: Boolean, default: false },
|
|
||||||
checkedProps: { type: Object as PropType<any>, default: () => ({ type: 'solid', status: 'primary' }) },
|
|
||||||
uncheckedProps: { type: Object as PropType<any>, default: () => ({ type: 'solid', status: 'default' }) },
|
|
||||||
showClose: { type: Boolean, default: false },
|
|
||||||
icon: { type: String, default: '' },
|
|
||||||
disabled: { type: Boolean, default: false },
|
|
||||||
class: { type: [String, Array, Object], default: '' },
|
|
||||||
style: { type: Object, default: () => ({}) },
|
|
||||||
},
|
},
|
||||||
emits: ['click', 'close', 'update:checked'],
|
size: {
|
||||||
|
type: String as PropType<'small' | 'medium' | 'large'>,
|
||||||
|
default: 'medium',
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: String as () => 'solid' | 'light' | 'outline' | 'outline-light',
|
||||||
|
default: 'solid',
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
type: String as () => 'primary' | 'danger' | 'warning' | 'success' | 'default',
|
||||||
|
default: 'default',
|
||||||
|
},
|
||||||
|
checkable: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: [String, Number, Boolean] as PropType<string | number | boolean>,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
modelValue: {
|
||||||
|
type: Boolean,
|
||||||
|
default: undefined,
|
||||||
|
},
|
||||||
|
checked: {
|
||||||
|
type: Boolean,
|
||||||
|
default: undefined,
|
||||||
|
},
|
||||||
|
defaultChecked: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
checkedProps: {
|
||||||
|
type: Object as PropType<any>,
|
||||||
|
default: () => ({ type: 'solid', status: 'primary' }),
|
||||||
|
},
|
||||||
|
uncheckedProps: {
|
||||||
|
type: Object as PropType<any>,
|
||||||
|
default: () => ({ type: 'solid', status: 'default' }),
|
||||||
|
},
|
||||||
|
showClose: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
disabled: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
class: {
|
||||||
|
type: [String, Array, Object],
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
emits: ['change', 'close', 'update:modelValue', 'update:checked'],
|
||||||
setup(props, { slots, emit }) {
|
setup(props, { slots, emit }) {
|
||||||
const prefixCls = getPrefixCls('tag')
|
const prefixCls = getPrefixCls('tag')
|
||||||
const tagGroupCtx = inject<TagGroupContext | undefined>(tagGroupKey, undefined)
|
const tagGroupCtx = inject<TagGroupContext | undefined>(tagGroupKey, undefined)
|
||||||
@@ -43,7 +92,7 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
return groupValue === props.value
|
return groupValue === props.value
|
||||||
}
|
}
|
||||||
return props.checked ?? _checked.value
|
return props.checked ?? props.modelValue ?? _checked.value
|
||||||
})
|
})
|
||||||
|
|
||||||
const handleClick = (event: MouseEvent) => {
|
const handleClick = (event: MouseEvent) => {
|
||||||
@@ -54,12 +103,14 @@ export default defineComponent({
|
|||||||
tagGroupCtx.handleChange(props.value, event)
|
tagGroupCtx.handleChange(props.value, event)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// 独立 Tag 自己控制
|
|
||||||
const newChecked = !isChecked.value
|
const newChecked = !isChecked.value
|
||||||
|
if (props.checked === undefined)
|
||||||
_checked.value = newChecked
|
_checked.value = newChecked
|
||||||
|
|
||||||
|
emit('update:modelValue', newChecked)
|
||||||
emit('update:checked', newChecked)
|
emit('update:checked', newChecked)
|
||||||
}
|
}
|
||||||
emit('click', { value: props.value, event })
|
emit('change', { value: props.value, event })
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleClose = (event: MouseEvent) => {
|
const handleClose = (event: MouseEvent) => {
|
||||||
@@ -68,6 +119,12 @@ export default defineComponent({
|
|||||||
emit('close', { value: props.value, event })
|
emit('close', { value: props.value, event })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
watch(() => props.checked, (val) => {
|
||||||
|
if (val !== undefined) {
|
||||||
|
_checked.value = val
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
return () =>
|
return () =>
|
||||||
visible.value && (
|
visible.value && (
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -1,200 +1,13 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue'
|
|
||||||
|
|
||||||
const selectedValue = ref()
|
|
||||||
|
|
||||||
// 自定义字段名
|
|
||||||
const options = [
|
|
||||||
{ name: '选项一', id: 1, note: '这是额外信息 1' },
|
|
||||||
{ name: '选项二', id: 2, note: '这是额外信息 2' },
|
|
||||||
{ name: '选项三', id: 3 },
|
|
||||||
]
|
|
||||||
|
|
||||||
function handleChange(val: string | number | boolean) {
|
|
||||||
console.log('当前选中值:', val)
|
|
||||||
}
|
|
||||||
|
|
||||||
function toggleThemeLight() {
|
|
||||||
document.documentElement.setAttribute('theme-mode', 'light')
|
|
||||||
}
|
|
||||||
function toggleThemeDark() {
|
|
||||||
document.documentElement.setAttribute('theme-mode', 'dark')
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<AButton status="primary" @click="toggleThemeLight">
|
<div>
|
||||||
白天
|
content
|
||||||
</AButton>
|
|
||||||
<AButton status="primary" @click="toggleThemeDark">
|
|
||||||
黑天
|
|
||||||
</AButton>
|
|
||||||
|
|
||||||
<div class="demo-wrapper">
|
|
||||||
<div class="demo-container">
|
|
||||||
<h3>Default</h3>
|
|
||||||
<ARadioGroup
|
|
||||||
v-model="selectedValue"
|
|
||||||
:options="options"
|
|
||||||
label-field="name"
|
|
||||||
value-field="id"
|
|
||||||
extra-field="note"
|
|
||||||
type="default"
|
|
||||||
@change="handleChange"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="demo-container">
|
|
||||||
<h3>filled</h3>
|
|
||||||
<ARadioGroup
|
|
||||||
v-model="selectedValue"
|
|
||||||
:options="options"
|
|
||||||
label-field="name"
|
|
||||||
value-field="id"
|
|
||||||
extra-field="note"
|
|
||||||
type="filled"
|
|
||||||
size="small"
|
|
||||||
:allow-uncheck="false"
|
|
||||||
@change="handleChange"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="demo-container">
|
|
||||||
<h3>filled</h3>
|
|
||||||
<ARadioGroup
|
|
||||||
v-model="selectedValue"
|
|
||||||
:options="options"
|
|
||||||
label-field="name"
|
|
||||||
value-field="id"
|
|
||||||
extra-field="note"
|
|
||||||
type="filled"
|
|
||||||
@change="handleChange"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="demo-container">
|
|
||||||
<h3>filled</h3>
|
|
||||||
<ARadioGroup
|
|
||||||
v-model="selectedValue"
|
|
||||||
:options="options"
|
|
||||||
label-field="name"
|
|
||||||
value-field="id"
|
|
||||||
extra-field="note"
|
|
||||||
type="filled"
|
|
||||||
size="large"
|
|
||||||
@change="handleChange"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="demo-container">
|
|
||||||
<h3>primaryFilled</h3>
|
|
||||||
<ARadioGroup
|
|
||||||
v-model="selectedValue"
|
|
||||||
:options="options"
|
|
||||||
label-field="name"
|
|
||||||
value-field="id"
|
|
||||||
extra-field="note"
|
|
||||||
type="primaryFilled"
|
|
||||||
@change="handleChange"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="demo-container">
|
|
||||||
<h3>outline</h3>
|
|
||||||
<ARadioGroup
|
|
||||||
v-model="selectedValue"
|
|
||||||
:options="options"
|
|
||||||
label-field="name"
|
|
||||||
value-field="id"
|
|
||||||
extra-field="note"
|
|
||||||
type="outline"
|
|
||||||
@change="handleChange"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="demo-container">
|
|
||||||
<h3>card</h3>
|
|
||||||
<ARadioGroup
|
|
||||||
v-model="selectedValue"
|
|
||||||
:options="options"
|
|
||||||
label-field="name"
|
|
||||||
value-field="id"
|
|
||||||
extra-field="note"
|
|
||||||
type="card"
|
|
||||||
@change="handleChange"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="demo-container">
|
|
||||||
<h3>pureCard</h3>
|
|
||||||
<ARadioGroup
|
|
||||||
v-model="selectedValue"
|
|
||||||
:options="options"
|
|
||||||
label-field="name"
|
|
||||||
value-field="id"
|
|
||||||
extra-field="note"
|
|
||||||
type="pureCard"
|
|
||||||
@change="handleChange"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="demo-container">
|
|
||||||
<h3>自定义插槽radio</h3>
|
|
||||||
<ARadioGroup
|
|
||||||
v-model="selectedValue" :options="options"
|
|
||||||
value-field="id"
|
|
||||||
>
|
|
||||||
<template #radio="{ data, checked }">
|
|
||||||
<div
|
|
||||||
:style="{
|
|
||||||
padding: '4px 8px',
|
|
||||||
border: checked ? '2px solid #409eff' : '1px solid #dcdfe6',
|
|
||||||
borderRadius: '4px',
|
|
||||||
cursor: 'pointer',
|
|
||||||
marginRight: '4px',
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
{{ checked ? '选中' : '未选中' }} - {{ data.name }}
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</ARadioGroup>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style lang="scss" scoped>
|
||||||
.demo-wrapper {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
gap: 16px;
|
|
||||||
padding: 24px 16px;
|
|
||||||
min-height: 100vh;
|
|
||||||
transition: background-color 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.demo-container {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 8px;
|
|
||||||
padding: 12px 16px;
|
|
||||||
border-radius: 6px;
|
|
||||||
box-shadow: 0 1px 6px rgba(0, 0, 0, 0.08);
|
|
||||||
width: 100%;
|
|
||||||
max-width: 400px;
|
|
||||||
text-align: center;
|
|
||||||
transition: background-color 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
margin: 0;
|
|
||||||
font-weight: 500;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 主题背景色 */
|
|
||||||
:root[theme-mode='light'] .demo-wrapper {
|
|
||||||
}
|
|
||||||
:root[theme-mode='dark'] .demo-wrapper {
|
|
||||||
background-color: #1e1e1e;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
@@ -9,6 +9,8 @@ export {}
|
|||||||
declare module 'vue' {
|
declare module 'vue' {
|
||||||
export interface GlobalComponents {
|
export interface GlobalComponents {
|
||||||
AButton: typeof import('@ao/ao-design')['Button']
|
AButton: typeof import('@ao/ao-design')['Button']
|
||||||
|
ACheckbox: typeof import('@ao/ao-design')['Checkbox']
|
||||||
|
ACheckboxGroup: typeof import('@ao/ao-design')['CheckboxGroup']
|
||||||
AConfigProvider: typeof import('@ao/ao-design')['ConfigProvider']
|
AConfigProvider: typeof import('@ao/ao-design')['ConfigProvider']
|
||||||
ADrawer: typeof import('@ao/ao-design')['Drawer']
|
ADrawer: typeof import('@ao/ao-design')['Drawer']
|
||||||
AGroup: typeof import('@ao/ao-design')['Group']
|
AGroup: typeof import('@ao/ao-design')['Group']
|
||||||
|
|||||||
Reference in new issue
Block a user