Skip to content

Commit

Permalink
feat(app): add AvatarGroup
Browse files Browse the repository at this point in the history
This pull request is intended to add the AvatarGroup component.
  • Loading branch information
Selemondev authored and Selemondev committed Jul 28, 2023
1 parent 97843b2 commit c5986b0
Show file tree
Hide file tree
Showing 23 changed files with 263 additions and 205 deletions.
2 changes: 1 addition & 1 deletion example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
},
"devDependencies": {
"@tsconfig/node18": "^18.2.0",
"@types/node": "^18.17.1",
"@types/node": "^20.4.5",
"@vitejs/plugin-vue": "^4.2.3",
"@vue/tsconfig": "^0.4.0",
"@windi-ui/tailwind-config": "workspace:^",
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"lint:fix": "nr lint --fix",
"clean": "rimraf packages/*/{dist,es,lib}",
"example": "pnpm --filter @windi-ui/example",
"playground": "pnpm --filter @windi-ui/playground",
"test": "vitest",
"test:update": "vitest -u",
"test:coverage": "vitest --coverage",
Expand All @@ -24,7 +25,6 @@
"major": "taze minor -wIr"
},
"dependencies": {
"fs": "0.0.1-security",
"vue-ui-next": "^0.0.0"
},
"devDependencies": {
Expand All @@ -33,6 +33,7 @@
"@types/node": "^20.4.5",
"@vitejs/plugin-vue": "^4.2.3",
"@vitest/coverage-c8": "^0.33.0",
"@vitest/coverage-v8": "^0.33.0",
"@vitest/ui": "^0.33.0",
"@vue/test-utils": "^2.4.1",
"@vueuse/core": "^10.2.1",
Expand Down
2 changes: 1 addition & 1 deletion packages/windi/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
"ts-node": "^10.9.1",
"typescript": "^5.1.6",
"vite": "^4.4.7",
"vite-plugin-dts": "^2.3.0"
"vite-plugin-dts": "^3.3.1"
},
"publishConfig": {
"access": "public"
Expand Down
9 changes: 7 additions & 2 deletions packages/windi/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,14 @@ function handleClose() {
</script>

<template>
<div>
<WAvatarGroup :max="2" size="md">
<WAvatar src="https://github.com/selemondev.png" name="Selemon" initials="SB" />
<WAvatar src="https://github.com/selemondev.png" name="Selemon" initials="SB" />
<WAvatar src="https://github.cm/selemondev.png" name="Selemon" initials="SB" />
</WAvatarGroup>
</div>
<div class="mt-48 p-4 space-y-2">
<WAvatar src="https://github.cm/selemondev.png" name="Selemon" chip-position="top-right" initials="SB" chip-color="red" />

<WAlert :is-visible="show" icon="ph:sun" :trailing="false" variant="danger-light" transition="slideRight" title="Alert" closable @close="handleClose">
<WAlertDescription>
Hello from alert
Expand Down
7 changes: 7 additions & 0 deletions packages/windi/src/Types/componentsTypes/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,15 @@ export interface WAvatar extends WComponentRoot {
placeholderClass?: string
}

export interface WAvatarGroup extends WComponentRoot {
margin?: string
reverse?: string
}

export type WAlertVariants = WithVariantProps<WAlert>

export type WAvatarVariants = WithVariantProps<WAvatar>

export type WIconVariants = WithVariantProps<WIcon>

export type WAvatarGroupVariants = WithVariantProps<WAvatarGroup>
1 change: 1 addition & 0 deletions packages/windi/src/Types/enums/Components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ export enum Components {
WAlertDescription = 'WAlertDescription',
WIcon = 'WIcon',
WAvatar = 'WAvatar',
WAvatarGroup = 'WAvatarGroup',
}
3 changes: 2 additions & 1 deletion packages/windi/src/Types/variant.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Components } from './enums/Components'
import type { WAlertVariants, WAvatarVariants, WIconVariants } from './componentsTypes/components'
import type { WAlertVariants, WAvatarGroup, WAvatarVariants, WIconVariants } from './componentsTypes/components'

export declare interface CSSClassKeyValuePair {
[key: string]: any
Expand Down Expand Up @@ -33,5 +33,6 @@ export interface WindiUIConfiguration {
[Components.WAlert]?: WAlertVariants
[Components.WAvatar]?: WAvatarVariants
[Components.WIcon]?: WIconVariants
[Components.WAvatarGroup]?: WAvatarGroup

}
20 changes: 20 additions & 0 deletions packages/windi/src/components/Avatar/Types/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { Slot, VNode } from 'vue'

export function getSlotsFromChildren(slot: Slot | any): VNode[] {
let children = slot?.default?.()
if (children.length) {
children = children.flatMap((c: { type: { name: string }; children: any; ctx: { slots: { default: () => any } } }) => {
if (typeof c.type === 'symbol') {
if (typeof c.children === 'string')
return false

return c.children
}
else if (c.type.name === 'ContentSlot') {
return c.ctx.slots.default?.()
}
return c
}).filter(Boolean)
}
return children
}
66 changes: 66 additions & 0 deletions packages/windi/src/components/Avatar/WAvatarGroup.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<script lang="ts">
import { cloneVNode, computed, defineComponent, h } from 'vue'
import type { PropType, VNode } from 'vue'
import classNames from 'classnames'
import windiTheme from '../../theme/windiTheme'
import { getSlotsFromChildren } from './Types'
import WAvatar from './WAvatar.vue'
import { getVariantPropsWithClassesList } from '@/utils/getVariantProps'
import type { WAvatarGroup } from '@/Types/componentsTypes/components'
import { Components } from '@/Types/enums/Components'
export type AvatarSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl'
export default defineComponent({
name: Components.WAvatarGroup,
...getVariantPropsWithClassesList<WAvatarGroup>(),
props: {
size: {
type: String as PropType<AvatarSize>,
default: 'md',
},
max: {
type: Number,
default: null,
},
},
setup(props, { slots }) {
const children = computed(() => getSlotsFromChildren(slots))
// if max is passed as a string, we go ahead and convert it into an integer
const max = computed(() => typeof props.max === 'string' ? Number.parseInt(props.max) : props.max)
const clones = computed(() => children.value.map((node: VNode<unknown, unknown, { [key: string]: any }>, index: number) => {
const vProps: Record<string, string> = {}
if (!props.max || (max.value && index < max.value)) {
if (props.size)
vProps.size = props.size
vProps.class = node.props?.class || ''
vProps.class += `${classNames(
windiTheme.WAvatarGroup.base.margin,
)}`
return cloneVNode(node, vProps)
}
if (max.value !== undefined && index === max.value) {
return h(WAvatar, {
size: props.size,
text: `${children.value.length - max.value}`,
name: `${children.value.length - max.value}`,
})
}
return null
}).filter(Boolean).reverse())
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
return () => h('div', { class: windiTheme.WAvatarGroup.base.root }, clones.value)
},
})
</script>
2 changes: 2 additions & 0 deletions packages/windi/src/components/Avatar/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import Avatar from './WAvatar.vue'
import AvatarGroup from './WAvatarGroup.vue'

export default {
Avatar,
AvatarGroup,
}
3 changes: 3 additions & 0 deletions packages/windi/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ import AlertDescription from './components/Alert/WAlertDescription.vue'
import Avatar from './components/Avatar/WAvatar.vue'
import Icon from './components/Icon/WIcon.vue'
import type { WindiUIConfiguration } from './Types/variant'
import AvatarGroup from './components/Avatar/WAvatarGroup.vue'
import windiTheme from './theme/windiTheme'

const components: Record<string, ReturnType<typeof defineComponent>> = {
Alert,
AlertDescription,
Icon,
Avatar,
AvatarGroup,
}

function install(app: App, configuration: WindiUIConfiguration) {
Expand All @@ -26,3 +28,4 @@ export { default as Alert } from './components/Alert'
export { default as AlertDescription } from './components/Alert'
export { default as Icon } from './components/Icon'
export { default as Avatar } from './components/Avatar'
export { default as AvatarGroup } from './components/Avatar'
11 changes: 11 additions & 0 deletions packages/windi/src/theme/windiTheme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,17 @@ export default {
},
},
},
WAvatarGroup: {
base: {
root: 'flex flex-row-reverse',
margin: '-mx-2.5',
},

variants: {
root: 'flex flex-row-reverse',
margin: '-mx-2.5',
},
},
WIcon: {
base: {
'root': 'w-6 h-6 block',
Expand Down
10 changes: 6 additions & 4 deletions playground/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,16 @@
},
"homepage": "https://github.com/selemondev/windi-ui#readme",
"dependencies": {
"@vue/repl": "^2.5.5",
"compare-versions": "^6.0.0",
"ohmyfetch": "^0.4.21"
"@vue/repl": "^1.4.1",
"compare-versions": "^4.1.4",
"ohmyfetch": "^0.4.21",
"@windi-ui/tailwind-config": "workspace:^",
"windi-ui": "workspace:^"
},
"devDependencies": {
"@types/prettier": "^2.7.3",
"@unocss/reset": "^0.53.6",
"execa": "^7.2.0",
"execa": "^4.1.0",
"prettier": "^3.0.0"
}
}
1 change: 1 addition & 0 deletions playground/postcss.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('@windi-ui/tailwind-config/postcss.config')
6 changes: 4 additions & 2 deletions playground/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { createApp } from 'vue'
import App from './App.vue'
import '@vue/repl/dist/style.css'
import { ui } from "vue-ui-next";
import install from "windi-ui"
import config from "windi-ui/dist/theme/windiTheme"
import '@unocss/reset/tailwind.css'
// import 'onu-ui/dist/style.css'
import 'uno.css'
Expand All @@ -11,5 +12,6 @@ window.VUE_DEVTOOLS_CONFIG = {
defaultSelectedAppId: 'repl',
}

const app = createApp(App).use(ui)
const app = createApp(App)
app.use(install, config)
app.mount('#play_ground')
8 changes: 4 additions & 4 deletions playground/src/template/lib-install.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { getCurrentInstance } from 'vue'
// import UnoUI from 'onu-ui'
import { ui } from "vue-ui-next";
import install from 'windi-ui'

let installed = false

Expand All @@ -9,7 +9,7 @@ export function libInstall() {
return
const instance = getCurrentInstance()

// instance.appContext.app.use(ui)
instance.appContext.app.use(install)
installed = true
}

Expand Down Expand Up @@ -40,13 +40,13 @@ export function createInjectUnocss() {
})
}

// 发送dom信息到 父页面

export function sendHtml() {
const div = document.querySelector('#app').innerHTML
top.postMessage(div, location.ancestorOrigins[0])
}

// 收父页面传来到 css

export function getUnocssCompileRes() {
window.addEventListener('message', (event) => {
const styleElm = document.querySelector('#unocss_style')
Expand Down
4 changes: 2 additions & 2 deletions playground/src/template/welcome.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<script setup lang='ts'>
</script>

<template>
<div>

hello there
</div>
</template>
7 changes: 3 additions & 4 deletions playground/src/utils/dependency.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const genCDNLink = (
return `${cdnUrl}${pkg}${version}${path}`
}

// 生成 vue 依赖配置

export const genVueLink = (version: string) => {
const compilerSfc = genCDNLink(
'@vue/compiler-sfc',
Expand All @@ -44,13 +44,12 @@ export const genVueLink = (version: string) => {
}
}

// 生成构建依赖对象
// (包括 vue、ui组件库,将在store中与用户依赖合并传递给 vue-repl)

export const genImportMap = ({
vue,
[playConfig.compLibShort]: lib,
}: Partial<Versions> = {}): ImportMap => {
// 指定组件库依赖路径,用于去cdn加载 组件库

const deps: Record<string, Dependency> = {
...playConfig.coreDeps,
}
Expand Down
2 changes: 1 addition & 1 deletion playground/src/utils/format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { ReplStore } from '~/composables/store'

export const formatCode = async (loadedFormat: boolean, store: ReplStore) => {
let close: Fn | undefined
// 加载依赖

const [format, parserHtml, parserTypeScript, parserBabel, parserPostcss]
= await Promise.all([
import('prettier/standalone').then(r => r.format),
Expand Down
12 changes: 6 additions & 6 deletions playground/src/utils/versions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import playConfig from '../../playground.config'
import { genVueLink } from '~/utils/dependency'
import type { VersionKey, Versions } from '~/composables/store'
import { IS_DEV } from '~/constants'
// 发送请求到 npm 查询 vue、组件库版本

export const getVersions = (pkg: MaybeRef<string>) => {
const url = computed(() => `${playConfig.versionUrl}${unref(pkg)}`)
return useFetch(url, {
Expand All @@ -16,7 +16,7 @@ export const getVersions = (pkg: MaybeRef<string>) => {
}).json<string[]>().data as Ref<string[]>
}

// 过滤支持的最小 vue、组件库版本

export const getSupportVersions = (pkg: string, minVersion: string) => {
const versions = getVersions(pkg)
const IS_VUE = pkg === 'vue'
Expand All @@ -33,16 +33,16 @@ export const getSupportVersions = (pkg: string, minVersion: string) => {
})
}

// 设置 vue 版本

export async function setVueVersion(
version: string,
compiler: ShallowRef<typeof import('vue/compiler-sfc') | undefined>,
state: { vueRuntimeURL: string },
versions: Versions,
) {
// 获取 vue 依赖配置

const { compilerSfc, runtimeDom } = genVueLink(version)
// 根据配置请求相关的编译模块,并传递给 vue-repl

compiler.value = await import(/* @vite-ignore */ compilerSfc)
state.vueRuntimeURL = runtimeDom
versions.vue = version
Expand All @@ -51,7 +51,7 @@ export async function setVueVersion(
console.info(`[@vue/repl] Now using Vue version: ${version}`)
}

// 设置 vue 或 组件库版本

export async function setVersion(
key: VersionKey,
version: string,
Expand Down

0 comments on commit c5986b0

Please sign in to comment.