diff --git a/docs/.vitepress/config.js b/docs/.vitepress/config.js index c0d5bf0c..dbd07578 100644 --- a/docs/.vitepress/config.js +++ b/docs/.vitepress/config.js @@ -149,13 +149,13 @@ export default { })(), (() => { const items = [ - {text: 'Card', link: 'layout/card', icon: '/components/layout/card.svg', version: '2024.1.1'}, + {text: '卡片 (Card)', link: 'layout/card', icon: '/components/layout/card.svg', version: '2024.1.1'}, {text: 'Row / Col', link: 'layout/row-col', icon: '/components/layout/row-col.svg', version: '2024.1.2'}, {text: 'Divider', link: 'layout/divider', icon: '/components/layout/divider.svg', version: '2024.1.2'}, {text: 'Ellipsis', link: 'layout/ellipsis', icon: '/components/layout/ellipsis.svg', version: '2024.1.2'}, {text: 'Avatar', link: 'layout/avatar', icon: '/components/layout/avatar.svg', version: '2024.1.2'}, {text: 'Space', link: 'layout/space', icon: '/components/layout/space.svg', version: '2024.1.2'}, - {text: 'Skeleton', link: 'layout/skeleton', icon: '/components/layout/skeleton.svg', version: '2024.1.2'}, + {text: '骨架屏 (Skeleton)', link: 'layout/skeleton', icon: '/components/layout/skeleton.svg', version: '2024.1.2'}, {text: 'Layout', link: 'layout/layout', icon: '/components/layout/layout.svg', version: '2024.1.2'}, {text: 'Collapse', link: 'layout/collapse', icon: '/components/layout/collapse.svg', version: '2024.2.0'}, {text: 'Global Footer', link: 'layout/global-footer', icon: '/components/layout/global-footer.svg', version: '2024.2.0'}, @@ -163,7 +163,7 @@ export default { ] return { - text: `Layout [ ${items.length} ]`, + text: `布局组件 [ ${items.length} ]`, base: '/components/', collapsed: false, items: items.map(item => createSidebarItem(item)) @@ -184,7 +184,7 @@ export default { {text: 'Trend', link: 'view/trend', icon: '/components/view/trend.svg', version: '2024.2.0'}, {text: 'Exception', link: 'view/exception', icon: '/components/view/exception.svg', version: '2024.2.0'}, {text: 'Tag', link: 'view/tag', icon: '/components/view/tag.svg', version: '2024.2.0'}, - {text: 'Tree', link: 'view/tree', icon: '/components/view/tree.svg', version: '2024.3.0'}, + {text: '树 (Tree)', link: 'view/tree', icon: '/components/view/tree.svg', version: '2024.3.0'}, {text: 'Hover Card', link: 'view/hover-card', icon: '/components/view/hover-card.svg', version: '2024.4.0'}, {text: 'Logger', link: 'view/logger', icon: '/components/view/logger.svg', version: '2024.5.1'}, {text: 'Scrollbar', link: 'view/scrollbar', icon: '/components/view/scrollbar.svg', version: '2024.5.1'}, @@ -212,7 +212,7 @@ export default { {text: 'Switch', link: 'form/switch', icon: '/components/form/switch.svg', version: '2024.1.2'}, {text: 'Radio', link: 'form/radio', icon: '/components/form/radio.svg', version: '2024.1.2'}, {text: 'Checkbox', link: 'form/checkbox', icon: '/components/form/checkbox.svg', version: '2024.1.2'}, - {text: 'Select', link: 'form/select', icon: '/components/form/select.svg', version: '2024.1.2'}, + {text: '选择器 (Select)', link: 'form/select', icon: '/components/form/select.svg', version: '2024.1.2'}, {text: 'Rate', link: 'form/rate', icon: '/components/form/rate.svg', version: '2024.1.2'}, {text: 'Form', link: 'form/form', icon: '/components/form/form.svg', version: '2024.2.0'}, {text: 'Slider', link: 'form/slider', icon: '/components/form/slider.svg', version: '2024.2.0'}, diff --git a/docs/components/form/checkbox.md b/docs/components/form/checkbox.md index b41b43b1..a4f969b5 100644 --- a/docs/components/form/checkbox.md +++ b/docs/components/form/checkbox.md @@ -109,9 +109,9 @@ const checked = ref('Primary') ::: -## Group +## 组 (group) - + Checkbox Group Value: {{ checkedGroup }} Vue diff --git a/docs/components/form/radio.md b/docs/components/form/radio.md index 43b92a9d..87e49a05 100644 --- a/docs/components/form/radio.md +++ b/docs/components/form/radio.md @@ -108,9 +108,9 @@ const checked = ref('Primary') ::: -## Group +## 组 (group) - + Checkbox Group Value: {{ checkedGroup }} ON diff --git a/docs/components/form/select.md b/docs/components/form/select.md index 151ab2ef..3564c480 100644 --- a/docs/components/form/select.md +++ b/docs/components/form/select.md @@ -1,15 +1,16 @@ --- -title: Shadcn Select +title: 选择器 (Select) --- # 介绍 -This document is mainly used to describe some features and usage of the ShadcnSelect and ShadcnSelectOption component. +
+ +本文档主要用于描述 `ShadcnSelect` 组件的一些特性和用法。 ## 用法 -

Select Value: {{ defaultSelect }}

@@ -37,7 +38,6 @@ const defaultSelectOptions = [ ## 禁用 (disabled) -

Select Value: {{ defaultSelect }}

@@ -62,52 +62,10 @@ const defaultSelectOptions = [ ::: -## Slot - - -

Select Value: {{ slotSelect }}

- - - -
- -::: details 查看代码 - -```vue - - - -``` - -::: - ## 尺寸 (size)
-

Select Value: {{ defaultSelect }}

@@ -142,7 +100,6 @@ const defaultSelectOptions = [
-

Select Value: {{ defaultSelect }}

@@ -175,13 +132,12 @@ const defaultSelectOptions = [ ::: -## Border +## 边框 (border) ::: raw - +
-

Select Value: {{ defaultSelect }}

@@ -212,11 +168,11 @@ const defaultSelectOptions = [ ::: -## Group +## 组 (group) ::: raw - + - - ``` ::: -## Multiple +## 多选 (multiple) ::: raw - - Value: {{ multipleValue }} + + 值: {{ multipleValue }} @@ -83,44 +49,16 @@ console.log('Click Node:', node) - - ``` ::: -## Checkable +## 选择框 (checkable) ::: raw - - Value: {{ checkableValue }} + + 值: {{ checkableValue }} @@ -132,44 +70,16 @@ const data = [ - - ``` ::: -## Cascade +## 级联选择 (cascade) ::: raw - - Value: {{ cascadeValue }} + + 值: {{ cascadeValue }} @@ -181,44 +91,16 @@ const data = [ - - ``` ::: -## Lazy Data +## 懒加载 (lazy) ::: raw - - Value: {{ lazyValue }} + + 值: {{ lazyValue }} @@ -283,7 +165,7 @@ const loadNodeData = (item: any, callback: (children: any[]) => void) => { ::: raw - Value: {{ disabledValue }} + 值: {{ disabledValue }} @@ -328,12 +210,12 @@ const data = reactive([ ::: -## Show Line +## 显示线 (show-line) ::: raw - - Value: {{ showLineValue }} + + 值: {{ basicValue }} @@ -349,12 +231,12 @@ const data = reactive([ ::: -## Label Slot +## 自定义 Label 插槽 ::: raw - - Value: {{ customValue }} + + 值: {{ customValue }} + @@ -472,52 +354,53 @@ const data = [ ::: -## Props +## 树 (Tree) 属性 - -
+## 树节点 (Tree Node) 属性 - -## Slots +## 树 (Tree) 插槽 - -## Events +## 树 (Tree) 事件 - @@ -643,4 +526,4 @@ export default { } } } - + \ No newline at end of file diff --git a/packages/index.ts b/packages/index.ts index be2d3bfb..51e170a1 100644 --- a/packages/index.ts +++ b/packages/index.ts @@ -35,8 +35,7 @@ import ShadcnSelectGroup from '@/ui/select/group' import ShadcnRate from '@/ui/rate' import ShadcnTab from '@/ui/tab' import ShadcnTabItem from '@/ui/tab/item' -import ShadcnSkeleton from '@/ui/skeleton' -import ShadcnSkeletonItem from '@/ui/skeleton/item' +import { ShadcnSkeleton, ShadcnSkeletonItem } from '@/ui/skeleton' import ShadcnLayout from '@/ui/layout' import ShadcnLayoutHeader from '@/ui/layout/header' import ShadcnLayoutContent from '@/ui/layout/content' @@ -133,8 +132,7 @@ let components = [ ShadcnRate, ShadcnTab, ShadcnTabItem, - ShadcnSkeleton, - ShadcnSkeletonItem, + ShadcnSkeleton, ShadcnSkeletonItem, ShadcnLayout, ShadcnLayoutHeader, ShadcnLayoutContent, @@ -266,8 +264,7 @@ export { default as ShadcnSelectGroup } from '@/ui/select/group' export { default as ShadcnRate } from '@/ui/rate' export { default as ShadcnTab } from '@/ui/tab' export { default as ShadcnTabItem } from '@/ui/tab/item' -export { default as ShadcnSkeleton } from '@/ui/skeleton' -export { default as ShadcnSkeletonItem } from '@/ui/skeleton/item' +export { ShadcnSkeleton, ShadcnSkeletonItem } from '@/ui/skeleton' export { default as ShadcnLayout } from '@/ui/layout' export { default as ShadcnLayoutHeader } from '@/ui/layout/header' export { default as ShadcnLayoutContent } from '@/ui/layout/content' diff --git a/src/App.vue b/src/App.vue index 7a4ee925..9e889bc8 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,28 +1,13 @@ \ No newline at end of file diff --git a/src/ui/button/ShadcnButton.vue b/src/ui/button/ShadcnButton.vue index 2a269b1b..c7b33201 100644 --- a/src/ui/button/ShadcnButton.vue +++ b/src/ui/button/ShadcnButton.vue @@ -166,11 +166,9 @@ const circleClass = computed(() => { const buttonProps = computed(() => ({ ...(props.to ? { link: props.to } : { type: props.submit ? 'submit' : props.reset ? 'reset' : 'button' }), class: [ - // Style 'inline-flex items-center justify-center whitespace-nowrap transition-colors', - // Size + 'w-fit', !props.circle && ButtonSize[finalSize.value], - // Type style with conditional hover props.ghost ? [ 'bg-transparent', @@ -180,12 +178,9 @@ const buttonProps = computed(() => ({ !props.disabled && !props.loading && getHoverClass.value ] : getTypeStyles.value, - // Rounded corners { 'rounded-full': props.round || props.circle }, { 'rounded-md': !props.round && !props.circle }, - // Rounded circleClass.value, - // State { 'opacity-50 cursor-not-allowed': props.loading || props.disabled } ], disabled: props.loading || props.disabled, diff --git a/src/ui/common/size.ts b/src/ui/common/size.ts index 8effbb16..b0d76e53 100644 --- a/src/ui/common/size.ts +++ b/src/ui/common/size.ts @@ -1,3 +1,10 @@ +export enum BaseSize +{ + default = 'h-8', + small = 'h-6', + large = 'h-10' +} + export enum Size { default = 'h-8', @@ -34,9 +41,10 @@ export enum TabSize export enum SkeletonSize { - default = 'h-10 w-10', - small = 'h-8 w-8', - large = 'h-16 w-16' + mini = 'h-4', + default = BaseSize.default, + small = BaseSize.small, + large = BaseSize.large } export enum ButtonSize diff --git a/src/ui/select/ShadcnSelect.vue b/src/ui/select/ShadcnSelect.vue index 4712f978..d7cc83b3 100644 --- a/src/ui/select/ShadcnSelect.vue +++ b/src/ui/select/ShadcnSelect.vue @@ -1,6 +1,12 @@ @@ -56,7 +62,7 @@ leave-to-class="transform -translate-y-2 scale-95 opacity-0">
() @@ -93,7 +100,8 @@ const props = withDefaults(defineProps(), { type: 'primary', multiple: false, border: true, - lazy: false + lazy: false, + loading: false }) const isExpanded = ref(false) @@ -259,13 +267,9 @@ provide('selectContext', { onMounted(() => { document.addEventListener('click', onClickOutside) - // isExpanded.value = true - // nextTick(() => { - // isExpanded.value = false - // }) }) onUnmounted(() => { document.removeEventListener('click', onClickOutside) }) - + \ No newline at end of file diff --git a/src/ui/select/types.ts b/src/ui/select/types.ts index ee693576..fe457432 100644 --- a/src/ui/select/types.ts +++ b/src/ui/select/types.ts @@ -12,6 +12,7 @@ export interface SelectProps multiple?: boolean border?: boolean lazy?: boolean + loading?: boolean loadData?: (callback: (children: SelectOptionProps[]) => void) => void } diff --git a/src/ui/skeleton/ShadcnSkeleton.vue b/src/ui/skeleton/ShadcnSkeleton.vue index 6255d30c..358e538e 100644 --- a/src/ui/skeleton/ShadcnSkeleton.vue +++ b/src/ui/skeleton/ShadcnSkeleton.vue @@ -4,6 +4,7 @@
@@ -11,17 +12,14 @@ + \ No newline at end of file diff --git a/src/ui/skeleton/item/ShadcnSkeletonItem.vue b/src/ui/skeleton/ShadcnSkeletonItem.vue similarity index 74% rename from src/ui/skeleton/item/ShadcnSkeletonItem.vue rename to src/ui/skeleton/ShadcnSkeletonItem.vue index 7eb68528..ccbb2a14 100644 --- a/src/ui/skeleton/item/ShadcnSkeletonItem.vue +++ b/src/ui/skeleton/ShadcnSkeletonItem.vue @@ -19,15 +19,10 @@ + \ No newline at end of file diff --git a/src/ui/skeleton/index.ts b/src/ui/skeleton/index.ts index 0f817274..c1208c87 100644 --- a/src/ui/skeleton/index.ts +++ b/src/ui/skeleton/index.ts @@ -1,3 +1,2 @@ -import ShadcnSkeleton from './ShadcnSkeleton.vue' - -export default ShadcnSkeleton +export { default as ShadcnSkeleton } from './ShadcnSkeleton.vue' +export { default as ShadcnSkeletonItem } from './ShadcnSkeletonItem.vue' \ No newline at end of file diff --git a/src/ui/skeleton/item/index.ts b/src/ui/skeleton/item/index.ts deleted file mode 100644 index a7ef7554..00000000 --- a/src/ui/skeleton/item/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import ShadcnSkeletonItem from './ShadcnSkeletonItem.vue' - -export default ShadcnSkeletonItem diff --git a/src/ui/skeleton/types.ts b/src/ui/skeleton/types.ts new file mode 100644 index 00000000..94cbd3da --- /dev/null +++ b/src/ui/skeleton/types.ts @@ -0,0 +1,19 @@ +import { SkeletonType } from '@/ui/common/type.ts' +import { SkeletonSize } from '@/ui/common/size.ts' + +export interface SkeletonProps +{ + cols?: number | string + rows?: number | string + animation?: boolean + size?: keyof typeof SkeletonSize + paragraph?: { rows: number, width: (number | string)[] } +} + +export interface SkeletonItemProps +{ + animation?: boolean + width?: string + type?: keyof typeof SkeletonType + size?: keyof typeof SkeletonSize +} \ No newline at end of file diff --git a/src/ui/tree/ShadcnTree.vue b/src/ui/tree/ShadcnTree.vue index 2b2267d5..d05a1927 100644 --- a/src/ui/tree/ShadcnTree.vue +++ b/src/ui/tree/ShadcnTree.vue @@ -4,7 +4,7 @@ :key="item.value" :node="item" :level="0" - :selected-values="modelValue" + :selected-values="selectedValues" :checkable="checkable" :cascade="cascade" :show-line="showLine" @@ -27,7 +27,7 @@ + \ No newline at end of file diff --git a/src/ui/tree/ShadcnTreeNode.vue b/src/ui/tree/ShadcnTreeNode.vue index c19e1dce..8c0a5b34 100644 --- a/src/ui/tree/ShadcnTreeNode.vue +++ b/src/ui/tree/ShadcnTreeNode.vue @@ -143,8 +143,26 @@ const nodeChecked = computed({ } }) +// 判断当前节点是否是目标值的父节点 +const isParentOfSelected = (node: TreeNode, selectedValue: any): boolean => { + if (!node.children) { + return false + } + return node.children.some(child => { + if (child.value === selectedValue) { + return true + } + return isParentOfSelected(child, selectedValue) + }) +} + watch(() => props.selectedValues, (newValues) => { - if (newValues.includes(props.node.value) && hasChildren.value) { + // 如果当前节点被选中,或者是选中节点的父节点,则展开 + const shouldExpand = newValues.some(value => { + return isParentOfSelected(props.node, value) + }) + + if (shouldExpand || props.selectedValues.includes(props.node.value)) { isExpanded.value = true } }, { immediate: true }) @@ -185,4 +203,4 @@ const onNodeClick = () => { } const onChildNodeClick = (node: TreeNode) => emit('on-node-click', node) - + \ No newline at end of file diff --git a/src/ui/tree/types.ts b/src/ui/tree/types.ts index 2e130fc7..59d264c5 100644 --- a/src/ui/tree/types.ts +++ b/src/ui/tree/types.ts @@ -5,6 +5,7 @@ export interface TreeNode children: TreeNode[] isLeaf?: boolean disabled?: boolean + selected?: boolean } export interface TreeProps