Skip to content

Commit

Permalink
Merge pull request #11851 from element-plus/dev
Browse files Browse the repository at this point in the history
D2M
  • Loading branch information
jw-foss committed Mar 6, 2023
2 parents cada1a0 + 0d8884b commit c75ba99
Show file tree
Hide file tree
Showing 26 changed files with 379 additions and 168 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.en-US.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
## Changelog

### 2.2.34

_2023-03-06_

#### Bug fixes

- Components [table-v2] class of column is not valid (#11815 by @tolking)
- Components [tree-select] cache data update incorrect (#11225 by @yujinpan)
- Components [global-config] (#11847 by @jw-foss)

### 2.2.33

Expand Down
15 changes: 5 additions & 10 deletions docs/.vitepress/plugins/markdown-transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,24 +48,19 @@ export function MarkdownTransform(): Plugin {
}

const combineScriptSetup = (codes: string[]) =>
`<script setup>
`\n<script setup>
${codes.join('\n')}
</script>\n
</script>
`

const combineMarkdown = (
code: string,
headers: string[],
footers: string[]
) => {
const frontmatterEnds = code.indexOf('---\n\n')
const firstSubheader = code.search(/## \w/)
const sliceIndex =
firstSubheader < 0
? frontmatterEnds < 0
? 0
: frontmatterEnds + 5
: firstSubheader
const frontmatterEnds = code.indexOf('---\n\n') + 4
const firstSubheader = code.search(/\n## \w/)
const sliceIndex = firstSubheader < 0 ? frontmatterEnds : firstSubheader

if (headers.length > 0)
code =
Expand Down
4 changes: 2 additions & 2 deletions docs/.vitepress/vitepress/components/globals/icons.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { computed, ref } from 'vue'
import { computed, ref, shallowRef } from 'vue'
import clipboardCopy from 'clipboard-copy'
import { ElMessage } from 'element-plus'
import * as Icons from '@element-plus/icons-vue'
Expand Down Expand Up @@ -44,7 +44,7 @@ const copySvgIcon = async (name, refs) => {
}
}
const categories = ref<CategoriesItem[]>([])
const categories = shallowRef<CategoriesItem[]>([])
const iconMap = new Map(Object.entries(Icons))
IconCategories.categories.forEach((o) => {
Expand Down
2 changes: 1 addition & 1 deletion docs/.vitepress/vitepress/styles/css-vars.scss
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
--content-min-width: 16rem;
--content-max-width: 48rem;

--nav-z-index: 11;
--nav-z-index: 12;
--sub-nav-z-index: 11;
--sidebar-z-index: 40;
--overlay-z-index: 30;
Expand Down
136 changes: 73 additions & 63 deletions packages/components/autocomplete/__tests__/autocomplete.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { nextTick, reactive } from 'vue'
import { defineComponent, nextTick, reactive } from 'vue'
import { mount } from '@vue/test-utils'
import { NOOP } from '@vue/shared'
import { beforeEach, describe, expect, it, test, vi } from 'vitest'
Expand All @@ -14,61 +14,73 @@ const _mount = (
payload = {},
type: 'fn-cb' | 'fn-promise' | 'fn-arr' | 'fn-async' | 'arr' = 'fn-cb'
) =>
mount({
setup() {
const state = reactive({
value: '',
list: [
{ value: 'Java', tag: 'java' },
{ value: 'Go', tag: 'go' },
{ value: 'JavaScript', tag: 'javascript' },
{ value: 'Python', tag: 'python' },
],
payload,
})

function filterList(queryString: string) {
return queryString
? state.list.filter(
(i) => i.value.indexOf(queryString.toLowerCase()) === 0
)
: state.list
}

const querySearch = (() => {
switch (type) {
case 'fn-cb':
return (
queryString: string,
cb: (arg: typeof state.list) => void
) => {
cb(filterList(queryString))
}
case 'fn-promise':
return (queryString: string) =>
Promise.resolve(filterList(queryString))
case 'fn-async':
return async (queryString: string) => {
await Promise.resolve()
return filterList(queryString)
}
case 'fn-arr':
return (queryString: string) => filterList(queryString)
case 'arr':
return state.list
mount(
defineComponent({
setup(_, { expose }) {
const state = reactive({
value: '',
list: [
{ value: 'Java', tag: 'java' },
{ value: 'Go', tag: 'go' },
{ value: 'JavaScript', tag: 'javascript' },
{ value: 'Python', tag: 'python' },
],
payload,
})

function filterList(queryString: string) {
return queryString
? state.list.filter(
(i) => i.value.indexOf(queryString.toLowerCase()) === 0
)
: state.list
}
})()

return () => (
<Autocomplete
ref="autocomplete"
v-model={state.value}
fetch-suggestions={querySearch}
{...state.payload}
/>
)
},
})

const querySearch = (() => {
switch (type) {
case 'fn-cb':
return (
queryString: string,
cb: (arg: typeof state.list) => void
) => {
cb(filterList(queryString))
}
case 'fn-promise':
return (queryString: string) =>
Promise.resolve(filterList(queryString))
case 'fn-async':
return async (queryString: string) => {
await Promise.resolve()
return filterList(queryString)
}
case 'fn-arr':
return (queryString: string) => filterList(queryString)
case 'arr':
return state.list
}
})()
const containerExposes = usePopperContainerId()

expose(containerExposes)

return () => (
<Autocomplete
ref="autocomplete"
v-model={state.value}
fetch-suggestions={querySearch}
{...state.payload}
/>
)
},
}),
{
global: {
provide: {
namespace: 'el',
},
},
}
)

describe('Autocomplete.vue', () => {
beforeEach(() => {
Expand Down Expand Up @@ -318,24 +330,22 @@ describe('Autocomplete.vue', () => {
describe('teleported API', () => {
it('should mount on popper container', async () => {
expect(document.body.innerHTML).toBe('')
_mount()
const { vm } = _mount()

await nextTick()
const { selector } = usePopperContainerId()
expect(document.body.querySelector(selector.value)?.innerHTML).not.toBe(
''
)
const { selector } = vm
expect(document.body.querySelector(selector)?.innerHTML).not.toBe('')
})

it('should not mount on the popper container', async () => {
expect(document.body.innerHTML).toBe('')
_mount({
const { vm } = _mount({
teleported: false,
})

await nextTick()
const { selector } = usePopperContainerId()
expect(document.body.querySelector(selector.value)?.innerHTML).toBe('')
const { selector } = vm
expect(document.body.querySelector(selector)?.innerHTML).toBe('')
})
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import Chinese from '@element-plus/locale/lang/zh-cn'
import English from '@element-plus/locale/lang/en'
import { ElButton, ElMessage } from '@element-plus/components'
import { rAF } from '@element-plus/test-utils/tick'
import { useGlobalConfig } from '../src/hooks/use-global-config'
import {
useGlobalComponentSettings,
useGlobalConfig,
} from '../src/hooks/use-global-config'
import ConfigProvider from '../src/config-provider'

import type { PropType } from 'vue'
Expand Down Expand Up @@ -239,4 +242,30 @@ describe('config-provider', () => {
}
)
})

describe('global component configs', () => {
it('should use global configured settings', () => {
const namespace = 'test'
const locale = Chinese
const zIndex = 1000
const block = 'button'
const receiverRef = ref()
const ReceiverComponent = defineComponent({
setup() {
receiverRef.value = useGlobalComponentSettings(block)
},
template: '<div></div>',
})
mount(() => (
<ConfigProvider zIndex={zIndex} locale={locale} namespace={namespace}>
<ReceiverComponent />
</ConfigProvider>
))

const vm = receiverRef.value
expect(vm.ns.namespace).toBe(namespace)
expect(vm.locale.locale).toBe(locale)
expect(vm.zIndex.currentZIndex).toBeGreaterThanOrEqual(zIndex)
})
})
})
26 changes: 26 additions & 0 deletions packages/components/config-provider/src/hooks/use-global-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@ import { computed, getCurrentInstance, inject, provide, ref, unref } from 'vue'
import { debugWarn, keysOf } from '@element-plus/utils'
import {
SIZE_INJECTION_KEY,
defaultInitialZIndex,
defaultNamespace,
localeContextKey,
namespaceContextKey,
useLocale,
useNamespace,
useZIndex,
zIndexContextKey,
} from '@element-plus/hooks'
import { configProviderContextKey } from '../constants'
Expand Down Expand Up @@ -39,6 +44,27 @@ export function useGlobalConfig(
}
}

// for components like `ElMessage` `ElNotification` `ElMessageBox`.
export function useGlobalComponentSettings(block: string) {
const config = useGlobalConfig()

const ns = useNamespace(
block,
computed(() => config.value?.namespace || defaultNamespace)
)

const locale = useLocale(computed(() => config.value?.locale))
const zIndex = useZIndex(
computed(() => config.value?.zIndex || defaultInitialZIndex)
)

return {
ns,
locale,
zIndex,
}
}

export const provideGlobalConfig = (
config: MaybeRef<ConfigProviderContext>,
app?: App,
Expand Down
23 changes: 17 additions & 6 deletions packages/components/loading/src/loading.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
Transition,
createApp,
createVNode,
defineComponent,
h,
reactive,
ref,
Expand All @@ -10,15 +11,16 @@ import {
withCtx,
withDirectives,
} from 'vue'
import { useNamespace } from '@element-plus/hooks'
import { useNamespace, useZIndex } from '@element-plus/hooks'
import { removeClass } from '@element-plus/utils'

import type { UseNamespaceReturn } from '@element-plus/hooks'
import type { LoadingOptionsResolved } from './types'

export function createLoadingComponent(options: LoadingOptionsResolved) {
let afterLeaveTimer: number

const ns = useNamespace('loading')
// IMPORTANT NOTE: this is only a hacking way to expose the injections on an
// instance, DO NOT FOLLOW this pattern in your own code.
const afterLeaveFlag = ref(false)
const data = reactive({
...options,
Expand All @@ -33,6 +35,7 @@ export function createLoadingComponent(options: LoadingOptionsResolved) {

function destroySelf() {
const target = data.parent
const ns = (vm as any).ns as UseNamespaceReturn
if (!target.vLoadingAddClassList) {
let loadingNumber: number | string | null =
target.getAttribute('loading-number')
Expand Down Expand Up @@ -71,9 +74,17 @@ export function createLoadingComponent(options: LoadingOptionsResolved) {
destroySelf()
}

const elLoadingComponent = {
const elLoadingComponent = defineComponent({
name: 'ElLoading',
setup() {
setup(_, { expose }) {
const ns = useNamespace('loading')
const zIndex = useZIndex()

expose({
ns,
zIndex,
})

return () => {
const svg = data.spinner || data.svg
const spinner = h(
Expand Down Expand Up @@ -136,7 +147,7 @@ export function createLoadingComponent(options: LoadingOptionsResolved) {
)
}
},
}
})

const loadingInstance = createApp(elLoadingComponent)
const vm = loadingInstance.mount(document.createElement('div'))
Expand Down

0 comments on commit c75ba99

Please sign in to comment.