Repository: opentiny/tiny-vue
Pull request #3419: feat(design-config): design-config adds arbitrary attribute features of global configuration components
Author: login: zzcr
Labels: name: enhancement
description: New feature or request （功能增强）
Created: 2025-05-13T08:31:46Z | Merged: 2025-05-14T02:48:27Z

feat(design-config): design-config添加全局配置组件任意属性特性
![image](https://github.com/user-attachments/assets/4a8f9ab4-1134-4b74-98ca-d27e7caa0a65)

# PR

## PR Checklist

Please check if your PR fulfills the following requirements:

- [ ] The commit message follows our [Commit Message Guidelines](https://github.com/opentiny/tiny-vue/blob/dev/CONTRIBUTING.md)
- [ ] Tests for the changes have been added (for bug fixes / features)
- [ ] Docs have been added / updated (for bug fixes / features)

## PR Type

What kind of change does this PR introduce?

<!-- Please check the one that applies to this PR using "x". -->

- [ ] Bugfix
- [ ] Feature
- [ ] Code style update (formatting, local variables)
- [ ] Refactoring (no functional changes, no api changes)
- [ ] Build related changes
- [ ] CI related changes
- [ ] Documentation content changes
- [ ] Other... Please describe:

## What is the current behavior?

<!-- Please describe the current behavior that you are modifying, or link to a relevant issue. -->

Issue Number: N/A

## What is the new behavior?

## Does this PR introduce a breaking change?

- [ ] Yes
- [ ] No

<!-- If this PR contains a breaking change, please describe the impact and migration path for existing applications below. -->

## Other information


<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

## Summary by CodeRabbit

- **New Features**
  - Alert component content is now centered by default in demos and global configuration.
  - Enhanced component setup merges default design properties with user-defined properties for improved customization.
  - Design configuration is accessible within renderless APIs for greater flexibility.

- **Bug Fixes**
  - Added a test verifying Alert content is centered as expected.

- **Chores**
  - Minor formatting update in package configuration (no functional impact).
  - Updated demo description to clarify global design prop customization support starting from version 3.23.0.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->


Diff:
diff --git a/examples/sites/demos/pc/app/config-provider/base-composition-api.vue b/examples/sites/demos/pc/app/config-provider/base-composition-api.vue
index 6919fd0907..bf629317dd 100644
--- a/examples/sites/demos/pc/app/config-provider/base-composition-api.vue
+++ b/examples/sites/demos/pc/app/config-provider/base-composition-api.vue
@@ -53,6 +53,9 @@ const design = {
       icons: {
         warning: iconWarningTriangle()
       },
+      props: {
+        center: true
+      },
       /**
        *
        * @param {*} props 组件属性集合
diff --git a/examples/sites/demos/pc/app/config-provider/base.vue b/examples/sites/demos/pc/app/config-provider/base.vue
index f14e29ba86..6b9a61b282 100644
--- a/examples/sites/demos/pc/app/config-provider/base.vue
+++ b/examples/sites/demos/pc/app/config-provider/base.vue
@@ -60,6 +60,9 @@ export default {
             }
           },
           Alert: {
+            props: {
+              center: true
+            },
             icons: {
               warning: iconWarningTriangle()
             },
diff --git a/examples/sites/demos/pc/app/config-provider/basic.spec.ts b/examples/sites/demos/pc/app/config-provider/basic.spec.ts
index 8329c67a10..09a79e567d 100644
--- a/examples/sites/demos/pc/app/config-provider/basic.spec.ts
+++ b/examples/sites/demos/pc/app/config-provider/basic.spec.ts
@@ -4,8 +4,11 @@ test('测试自定义事件', async ({ page }) => {
   page.on('pageerror', (exception) => expect(exception).toBeNull())
   await page.goto('config-provider#base')
 
-  // 验证自定义方法
   const demo = page.locator('#base')
+  // 验证文字居中
+  await expect(demo.locator('.tiny-alert')).toHaveCSS('justify-content', 'center')
+
+  // 验证自定义方法
   await demo.locator('.tiny-config-provider .tiny-alert > .tiny-alert__close').click()
   await page.waitForTimeout(500)
   await expect(page.locator('.tiny-modal > .tiny-modal__box').nth(1)).toHaveText('触发自定方法')
diff --git a/examples/sites/demos/pc/app/config-provider/webdoc/config-provider.js b/examples/sites/demos/pc/app/config-provider/webdoc/config-provider.js
index f49b70845f..3301a555c1 100644
--- a/examples/sites/demos/pc/app/config-provider/webdoc/config-provider.js
+++ b/examples/sites/demos/pc/app/config-provider/webdoc/config-provider.js
@@ -12,9 +12,9 @@ export default {
       },
       desc: {
         'zh-CN':
-          '可通过<code> design </code>属性设置自定义不同设计规范的图标和逻辑，例如：全局配置 Form 表单组件的必填星号是否默认显示、Button 组件的点击后的禁用时间和是否默认圆角。',
+          '通过 <code>design</code> 属性可以自定义不同设计规范的图标和逻辑。从 3.23.0 版本开始，支持全局配置组件的任意 <code>props</code> 属性（仅支持双层组件），例如：可以全局配置 Form 组件必填项星号的默认显示状态、Button 组件的点击防抖时间以及是否默认显示圆角等。',
         'en-US':
-          'Icons and logic for different design specifications can be customized through the <code>design</code> attribute configuration.'
+          'You can use the <code> design </code> property to set custom icons and logic for different design specifications, starting from version 3.23.0, the global configuration component (only supports double-layer components) supports the function of any <code> props </code> attribute, for example: the default display of the required star of the global configuration Form form component, the disabled time after the click of the Button component, and whether the default roundness is enabled.'
       },
       codeFiles: ['base.vue']
     },
diff --git a/packages/vue-common/src/adapter/vue2.7/index.ts b/packages/vue-common/src/adapter/vue2.7/index.ts
index b1faf1fc07..ef9bf7be62 100644
--- a/packages/vue-common/src/adapter/vue2.7/index.ts
+++ b/packages/vue-common/src/adapter/vue2.7/index.ts
@@ -26,18 +26,32 @@ export const renderComponent = ({
   view = null as any,
   component = null as any,
   props,
+  customDesignProps,
   context: { attrs, listeners: on, slots },
   extend = {}
 }) => {
   return () =>
     hooks.h(
       (view && view.value) || component,
-      Object.assign({ props, attrs, [extend.isSvg ? 'nativeOn' : 'on']: on, scopedSlots: { ...slots } }, extend)
+      Object.assign(
+        {
+          props: { ...props, ...customDesignProps },
+          attrs,
+          [extend.isSvg ? 'nativeOn' : 'on']: on,
+          scopedSlots: { ...slots }
+        },
+        extend
+      )
     )
 }
 
 export const rootConfig = () => hooks.getCurrentInstance()?.proxy.$root
 
+export const getCustomProps = () => {
+  const instance = hooks.getCurrentInstance()?.proxy
+  return instance?.$options?.propsData || {}
+}
+
 export const getComponentName = () => {
   // 此处组件最多为两层组件，所以对多获取到父级组件即可
   const instance = hooks.getCurrentInstance()
diff --git a/packages/vue-common/src/adapter/vue2/index.ts b/packages/vue-common/src/adapter/vue2/index.ts
index ba801ac572..1dee08a22e 100644
--- a/packages/vue-common/src/adapter/vue2/index.ts
+++ b/packages/vue-common/src/adapter/vue2/index.ts
@@ -34,6 +34,7 @@ export const renderComponent = ({
   view = null as any,
   component = null as any,
   props,
+  customDesignProps,
   context: { attrs, listeners: on, slots },
   extend = {}
 }) => {
@@ -41,7 +42,13 @@ export const renderComponent = ({
     hooks.h(
       (view && view.value) || component,
       Object.assign(
-        { props, attrs, [extend.isSvg ? 'nativeOn' : 'on']: on, ref: 'modeTemplate', scopedSlots: { ...slots } },
+        {
+          props: { ...props, ...customDesignProps },
+          attrs,
+          [extend.isSvg ? 'nativeOn' : 'on']: on,
+          ref: 'modeTemplate',
+          scopedSlots: { ...slots }
+        },
         extend
       )
     )
@@ -49,6 +56,11 @@ export const renderComponent = ({
 
 export const rootConfig = () => hooks.getCurrentInstance()?.proxy.$root
 
+export const getCustomProps = () => {
+  const instance = hooks.getCurrentInstance()?.proxy
+  return instance?.$options?.propsData || {}
+}
+
 export const getComponentName = () => {
   // 此处组件最多为两层组件，所以对多获取到父级组件即可
   const instance = hooks.getCurrentInstance()
diff --git a/packages/vue-common/src/adapter/vue3/index.ts b/packages/vue-common/src/adapter/vue3/index.ts
index cfb1e4ea08..72b31830c6 100644
--- a/packages/vue-common/src/adapter/vue3/index.ts
+++ b/packages/vue-common/src/adapter/vue3/index.ts
@@ -26,10 +26,16 @@ export const renderComponent = ({
   view = undefined as any,
   component = undefined as any,
   props,
+  customDesignProps,
   context: { attrs, slots },
   extend = {}
 }) => {
-  return () => hooks.h((view && view.value) || component, { ref: 'modeTemplate', ...props, ...attrs, ...extend }, slots)
+  return () =>
+    hooks.h(
+      (view && view.value) || component,
+      { ref: 'modeTemplate', ...props, ...attrs, ...customDesignProps, ...extend },
+      slots
+    )
 }
 
 export const rootConfig = (context) => {
@@ -38,6 +44,11 @@ export const rootConfig = (context) => {
   return instance?.appContext.config.globalProperties
 }
 
+export const getCustomProps = () => {
+  const instance = hooks.getCurrentInstance()
+  return instance?.vnode?.props || {}
+}
+
 export const getComponentName = () => {
   // 此处组件最多为两层组件，所以对多获取到父级组件即可
   const instance = hooks.getCurrentInstance()
diff --git a/packages/vue-common/src/index.ts b/packages/vue-common/src/index.ts
index 0556b9d4e6..926047c73e 100644
--- a/packages/vue-common/src/index.ts
+++ b/packages/vue-common/src/index.ts
@@ -16,6 +16,7 @@ import {
   tools,
   useRouter,
   getComponentName,
+  getCustomProps,
   isVnode
 } from './adapter'
 import { t } from '@opentiny/vue-locale'
@@ -122,19 +123,6 @@ const resolveChartTheme = (props, context) => {
   return tinyChartTheme
 }
 
-export const $setup = ({ props, context, template, extend = {} }) => {
-  const mode = resolveMode(props, context)
-  const view = hooks.computed(() => {
-    if (typeof props.tiny_template !== 'undefined') return props.tiny_template
-
-    const component = template(mode, props)
-
-    return typeof component === 'function' ? defineAsyncComponent(component) : component
-  })
-
-  return renderComponent({ view, props, context, extend })
-}
-
 // 提供给没有renderless层的组件使用（比如TinyVuePlus组件）
 export const design = {
   configKey: Symbol('designConfigKey'),
@@ -168,17 +156,55 @@ export const customDesignConfig: CustomDesignConfig = {
   twMerge: () => ''
 }
 
-export const mergeClass = (...cssClasses) => customDesignConfig.twMerge(stringifyCssClass(cssClasses))
-
-export const setup = ({ props, context, renderless, api, extendOptions = {}, mono = false, classes = {} }) => {
-  const render = typeof props.tiny_renderless === 'function' ? props.tiny_renderless : renderless
-
+const getDesignConfig = () => {
   // 获取组件级配置和全局配置（inject需要带有默认值，否则控制台会报警告）
   let globalDesignConfig: DesignConfig = customDesignConfig.designConfig || hooks.inject(design.configKey, {})
+
   // globalDesignConfig 可能是响应式对象，比如 computed
   globalDesignConfig = globalDesignConfig?.value || globalDesignConfig || {}
   const designConfig = globalDesignConfig?.components?.[getComponentName().replace($prefix, '')]
+  return {
+    designConfig,
+    globalDesignConfig
+  }
+}
+
+export const $setup = ({ props: propData, context, template, extend = {} }) => {
+  const mode = resolveMode(propData, context)
+  const view = hooks.computed(() => {
+    if (typeof propData.tiny_template !== 'undefined') return propData.tiny_template
+
+    const component = template(mode, propData)
+
+    return typeof component === 'function' ? defineAsyncComponent(component) : component
+  })
+
+  const { designConfig } = getDesignConfig()
+  const customDesignProps = {}
+
+  const designProps = designConfig?.props
+
+  if (designProps) {
+    // 获取用户传递的props
+    const customProps = getCustomProps()
+
+    Object.keys(designProps).forEach((key) => {
+      // 用户没有配置的属性才进行覆盖
+      if (!Object.prototype.hasOwnProperty.call(customProps, key)) {
+        customDesignProps[key] = designProps[key]
+      }
+    })
+  }
+
+  return renderComponent({ view, props: propData, customDesignProps, context, extend })
+}
+
+export const mergeClass = (...cssClasses) => customDesignConfig.twMerge(stringifyCssClass(cssClasses))
+
+export const setup = ({ props, context, renderless, api, extendOptions = {}, mono = false, classes = {} }) => {
+  const render = typeof props.tiny_renderless === 'function' ? props.tiny_renderless : renderless
 
+  const { designConfig, globalDesignConfig } = getDesignConfig()
   const utils = {
     $prefix,
     t,
diff --git a/packages/vue/package.json b/packages/vue/package.json
index d0b9717ecb..23287a174b 100644
--- a/packages/vue/package.json
+++ b/packages/vue/package.json
@@ -237,4 +237,4 @@
     "build": "pnpm -w build:ui",
     "postversion": "pnpm build"
   }
-}
+}
\ No newline at end of file


Reviews:
user: login: petercat-assistant[bot]
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-13T08:32:05Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 2**

<details>
<summary>🧹 Nitpick comments (3)</summary><blockquote>

<details>
<summary>packages/vue-common/src/index.ts (3)</summary><blockquote>

`159-170`: **`getDesignConfig` – handle case-mismatch & null component names**

`getComponentName()` may return an empty string for anonymous components, leading to an undefined lookup in `globalDesignConfig.components`.  
Also, component names in user config might be written in different cases (e.g. `alert`, `Alert`, `ALERT`).  

Consider normalising both sides to the same case and early-returning when no name is found:

```diff
-  const designConfig = globalDesignConfig?.components?.[getComponentName().replace($prefix, '')]
+  const compName = getComponentName()?.replace($prefix, '') || ''
+  const designConfig =
+    compName &&
+    Object.keys(globalDesignConfig?.components ?? {}).find(
+      (key) => key.toLowerCase() === compName.toLowerCase()
+    )
+      ? globalDesignConfig.components[
+          Object.keys(globalDesignConfig.components).find(
+            (key) => key.toLowerCase() === compName.toLowerCase()
+          )
+        ]
+      : undefined
```

This prevents subtle “config not applied” bugs when users write `alert` instead of `Alert`.

---

`172-201`: **`$setup` – avoid recomputation of `customProps` inside computed**

`getCustomProps()` relies on `getCurrentInstance()`; when called during setup it is cheap, but invoking it on *every* component instantiation is unnecessary.  
Move the call outside the `designProps` loop to compute once:

```diff
-  const designProps = designConfig?.props
-  if (designProps) {
-    // 获取用户传递的props
-    const customProps = getCustomProps()
+  const designProps = designConfig?.props
+  const customProps = getCustomProps()
+  if (designProps) {
```

Negligible performance gain but improves readability.

---

`202-208`: **`mergeClass` helper leaks tailwind-merge to every consumer**

`mergeClass` calls `customDesignConfig.twMerge` directly. If a user replaces `twMerge` later (lazy injection), already-imported modules will still hold the old reference.

Export it as a function capturing the *current* `twMerge` at call time:

```diff
-export const mergeClass = (...cssClasses) => customDesignConfig.twMerge(stringifyCssClass(cssClasses))
+export const mergeClass = (...cssClasses) =>
+  (customDesignConfig.twMerge ?? ((v) => v))(stringifyCssClass(cssClasses))
```

Prevents runtime crashes when `twMerge` is swapped or not provided.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 580b065ba57373cd5b78c50f139f9acdcf9131ec and 14958c9aa2ec5d3938bea8b1a16bb3d107a4bad1.

</details>

<details>
<summary>📒 Files selected for processing (8)</summary>

* `examples/sites/demos/pc/app/config-provider/base-composition-api.vue` (1 hunks)
* `examples/sites/demos/pc/app/config-provider/base.vue` (1 hunks)
* `examples/sites/demos/pc/app/config-provider/basic.spec.ts` (1 hunks)
* `packages/vue-common/src/adapter/vue2.7/index.ts` (1 hunks)
* `packages/vue-common/src/adapter/vue2/index.ts` (1 hunks)
* `packages/vue-common/src/adapter/vue3/index.ts` (2 hunks)
* `packages/vue-common/src/index.ts` (2 hunks)
* `packages/vue/package.json` (1 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Graph Analysis (4)</summary>

<details>
<summary>packages/vue-common/src/adapter/vue2/index.ts (2)</summary><blockquote>

<details>
<summary>packages/vue-common/src/adapter/vue2.7/index.ts (1)</summary>

* `getCustomProps` (41-44)

</details>
<details>
<summary>packages/vue-common/src/adapter/vue3/index.ts (1)</summary>

* `getCustomProps` (47-50)

</details>

</blockquote></details>
<details>
<summary>packages/vue-common/src/adapter/vue2.7/index.ts (2)</summary><blockquote>

<details>
<summary>packages/vue-common/src/adapter/vue2/index.ts (1)</summary>

* `getCustomProps` (52-55)

</details>
<details>
<summary>packages/vue-common/src/adapter/vue3/index.ts (1)</summary>

* `getCustomProps` (47-50)

</details>

</blockquote></details>
<details>
<summary>packages/vue-common/src/adapter/vue3/index.ts (2)</summary><blockquote>

<details>
<summary>packages/vue-common/src/adapter/vue2/index.ts (1)</summary>

* `getCustomProps` (52-55)

</details>
<details>
<summary>packages/vue-common/src/adapter/vue2.7/index.ts (1)</summary>

* `getCustomProps` (41-44)

</details>

</blockquote></details>
<details>
<summary>packages/vue-common/src/index.ts (1)</summary><blockquote>

<details>
<summary>packages/vue-common/src/adapter/vue3/index.ts (3)</summary>

* `getComponentName` (52-61)
* `getCustomProps` (47-50)
* `renderComponent` (25-39)

</details>

</blockquote></details>

</details><details>
<summary>🪛 Biome (1.9.4)</summary>

<details>
<summary>packages/vue-common/src/adapter/vue3/index.ts</summary>

[error] 35-35: Change to an optional chain.

Unsafe fix: Change to an optional chain.


(lint/complexity/useOptionalChain)

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: PR E2E Test (pnpm test:e2e3)

</details>

<details>
<summary>🔇 Additional comments (6)</summary><blockquote>

<details>
<summary>packages/vue-common/src/adapter/vue2/index.ts (1)</summary>

`52-55`: **Well-implemented utility function to support arbitrary attributes**

This `getCustomProps` function elegantly retrieves the component instance's props data, allowing access to user-defined props. This is essential for the design-config feature to support arbitrary attributes in global configuration components.

The implementation correctly handles potential undefined values using optional chaining and provides a fallback empty object. It's also consistent with the similar implementations in Vue 2.7 and Vue 3 adapters.

</details>
<details>
<summary>packages/vue/package.json (1)</summary>

`240-240`: **LGTM - Minor whitespace change**

The only change is the removal of a trailing newline, which is a trivial formatting change with no functional impact.

</details>
<details>
<summary>examples/sites/demos/pc/app/config-provider/base-composition-api.vue (1)</summary>

`56-58`: **Well-implemented design configuration attribute**

Adding the `center: true` prop to the Alert component's design configuration demonstrates the new arbitrary attribute feature. This change makes the Alert component's text centered by default when using this design configuration.

The implementation is clean and properly structured within the existing configuration object.

</details>
<details>
<summary>examples/sites/demos/pc/app/config-provider/basic.spec.ts (1)</summary>

`13-15`: **Good test coverage for the new feature**

This test properly verifies that the Alert component's text is centered as a result of the `center: true` design configuration property. The test confirms that the CSS `text-align` property is correctly set to `center`.

The comment "验证文字居中" (verifying text centering) clearly documents the purpose of this test case.

</details>
<details>
<summary>examples/sites/demos/pc/app/config-provider/base.vue (1)</summary>

`63-66`: **Nice addition – validates the new design-config capability**

Adding `center: true` under `Alert.props` showcases the arbitrary-attribute feature nicely and should read well in demos.

Once the Vue 2 adapters forward `customDesignProps` (see previous comment) this demo will work across all targets.

</details>
<details>
<summary>packages/vue-common/src/adapter/vue3/index.ts (1)</summary>

`25-39`: **Ordering & duplication guard in the merged‐prop spread**

1. `...attrs` is placed before `...customDesignProps`.  
   Because Vue normalises incoming attrs into props when names match, a user could still override a design default via an attribute instead of a prop, so this order is correct – keep it. 👍

2. However, `props` and `customDesignProps` are independent spreads and may contain the same key; the later spread (`customDesignProps`) will win.  
   That contradicts the rule implemented in `$setup` (“only override when the user did **not** set the prop”).  
   Consider merging **before** calling `h` to ensure the carefully-filtered object is passed only once:

```diff
-      { ref: 'modeTemplate', ...props, ...attrs, ...customDesignProps, ...extend },
+      {
+        ref: 'modeTemplate',
+        ...attrs,
+        ...customDesignProps,
+        ...props,          // user props last -> guaranteed priority
+        ...extend
+      },
```
  
Double-check with a simple unit test that a runtime prop (`<tiny-alert center="false" />`) still overrides the design default.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Biome (1.9.4)</summary>

[error] 35-35: Change to an optional chain.

Unsafe fix: Change to an optional chain.


(lint/complexity/useOptionalChain)

</details>

</details>

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-13T08:35:59Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 1**

<details>
<summary>♻️ Duplicate comments (1)</summary><blockquote>

<details>
<summary>packages/vue-common/src/adapter/vue2.7/index.ts (1)</summary><blockquote>

`36-39`: _⚠️ Potential issue_

**`customDesignProps` is passed incorrectly to the component**

The current implementation adds `customDesignProps` as a separate property in the object passed to the Vue component, but it needs to be merged with the `props` object to actually apply the design configuration properties to the component.



Apply this fix to properly merge design props with user props:

```diff
 Object.assign(
-  { props, attrs, customDesignProps, [extend.isSvg ? 'nativeOn' : 'on']: on, scopedSlots: { ...slots } },
+  { props: { ...customDesignProps, ...props }, attrs, [extend.isSvg ? 'nativeOn' : 'on']: on, scopedSlots: { ...slots } },
   extend
 )
```

This ensures that:
1. Design configuration properties are applied to the component
2. User props take precedence over design defaults (as they should)
3. The implementation is consistent with the expected behavior

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 92c2625ced50239dff07930024f9abdf0152970c and 22aeaf0a258baa0ad0bc67ca186fd9567dfab363.

</details>

<details>
<summary>📒 Files selected for processing (2)</summary>

* `packages/vue-common/src/adapter/vue2.7/index.ts` (1 hunks)
* `packages/vue-common/src/adapter/vue2/index.ts` (1 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Graph Analysis (1)</summary>

<details>
<summary>packages/vue-common/src/adapter/vue2/index.ts (3)</summary><blockquote>

<details>
<summary>packages/vue-common/src/index.ts (1)</summary>

* `hooks` (412-412)

</details>
<details>
<summary>packages/vue-common/src/adapter/vue2.7/index.ts (2)</summary>

* `rootConfig` (43-43)
* `getCustomProps` (45-48)

</details>
<details>
<summary>packages/vue-common/src/adapter/vue3/index.ts (2)</summary>

* `rootConfig` (41-45)
* `getCustomProps` (47-50)

</details>

</blockquote></details>

</details><details>
<summary>🪛 Biome (1.9.4)</summary>

<details>
<summary>packages/vue-common/src/adapter/vue2.7/index.ts</summary>

[error] 35-35: Change to an optional chain.

Unsafe fix: Change to an optional chain.


(lint/complexity/useOptionalChain)

</details>
<details>
<summary>packages/vue-common/src/adapter/vue2/index.ts</summary>

[error] 44-46: Change to an optional chain.

Unsafe fix: Change to an optional chain.


(lint/complexity/useOptionalChain)

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: PR E2E Test (pnpm test:e2e3)

</details>

<details>
<summary>🔇 Additional comments (4)</summary><blockquote>

<details>
<summary>packages/vue-common/src/adapter/vue2/index.ts (2)</summary>

`37-37`: **Added new parameter `customDesignProps` for design configuration support**

The parameter has been added to support arbitrary attributes from design configuration, which aligns with the PR objectives.

---

`60-63`: **`getCustomProps` implementation looks good**

The function correctly retrieves the current component instance's props data, which will be used for merging with design configuration.

</details>
<details>
<summary>packages/vue-common/src/adapter/vue2.7/index.ts (2)</summary>

`29-29`: **Added new parameter `customDesignProps` for design configuration support**

The parameter has been added to support arbitrary attributes from design configuration, which aligns with the PR objectives.

---

`45-48`: **`getCustomProps` implementation looks good**

The function correctly retrieves the current component instance's props data, which will be used for merging with design configuration.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-13T08:51:19Z
user: login: kagol
state: APPROVED
author_association: MEMBER
submitted_at: 2025-05-14T02:48:05Z

Review comments:
diff_hunk: @@ -168,17 +156,55 @@ export const customDesignConfig: CustomDesignConfig = {
   twMerge: () => ''
 }
 
-export const mergeClass = (...cssClasses) => customDesignConfig.twMerge(stringifyCssClass(cssClasses))
-
-export const setup = ({ props, context, renderless, api, extendOptions = {}, mono = false, classes = {} }) => {
-  const render = typeof props.tiny_renderless === 'function' ? props.tiny_renderless : renderless
-
+const getDesignConfig = () => {
   // 获取组件级配置和全局配置（inject需要带有默认值，否则控制台会报警告）
   let globalDesignConfig: DesignConfig = customDesignConfig.designConfig || hooks.inject(design.configKey, {})
+
   // globalDesignConfig 可能是响应式对象，比如 computed
   globalDesignConfig = globalDesignConfig?.value || globalDesignConfig || {}
   const designConfig = globalDesignConfig?.components?.[getComponentName().replace($prefix, '')]
+  return {
+    designConfig,
+    globalDesignConfig
+  }
+}
+
+export const $setup = ({ props: propData, context, template, extend = {} }) => {
+  const mode = resolveMode(propData, context)
+  const view = hooks.computed(() => {
+    if (typeof propData.tiny_template !== 'undefined') return propData.tiny_template
+
+    const component = template(mode, propData)
+
+    return typeof component === 'function' ? defineAsyncComponent(component) : component
+  })
+
+  const { designConfig } = getDesignConfig()
+  const customDesignProps = {}
+
+  const designProps = designConfig?.props
+
+  if (designProps) {
+    // 获取用户传递的props
+    const customProps = getCustomProps()
+
+    Object.keys(designProps).forEach((key) => {
+      // 用户没有配置的属性才进行覆盖
+      if (!Object.prototype.hasOwnProperty.call(customProps, key)) {
path: packages/vue-common/src/index.ts
user: login: petercat-assistant[bot]
body: Ensure that `Object.prototype.hasOwnProperty.call` is used correctly to avoid potential issues with objects that may not inherit from `Object.prototype`. This is a critical check to prevent unexpected behavior.
created_at: 2025-05-13T08:32:05Z
author_association: NONE
diff_hunk: @@ -38,6 +38,11 @@ export const renderComponent = ({
 
 export const rootConfig = () => hooks.getCurrentInstance()?.proxy.$root
 
+export const getCustomProps = () => {
+  const instance = hooks.getCurrentInstance()?.proxy
+  return instance?.$options?.propsData || {}
+}
path: packages/vue-common/src/adapter/vue2.7/index.ts
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**`getCustomProps` added, but the surrounding adapter is still oblivious to the new `customDesignProps` flow**

`getCustomProps` itself looks fine, yet the Vue 2.7 adapter never forwards the merged `customDesignProps` object that `$setup` now passes in.  
As a result, any default props coming from the global **design-config** are silently ignored in a Vue 2.7 runtime, breaking the very feature this PR introduces (e.g. the new `Alert.center` default will not work).

Minimal patch (works for both Vue 2 and Vue 2.7 adapters):

```diff
 export const renderComponent = ({
   view = null as any,
   component = null as any,
   props,
+  customDesignProps = {},
   context: { attrs, listeners: on, slots },
   extend = {}
 }) => {
   return () =>
     hooks.h(
       (view && view.value) || component,
-      Object.assign({ props, attrs, [extend.isSvg ? 'nativeOn' : 'on']: on, scopedSlots: { ...slots } }, extend)
+      Object.assign(
+        { props: { ...customDesignProps, ...props }, attrs, [extend.isSvg ? 'nativeOn' : 'on']: on, scopedSlots: { ...slots } },
+        extend
+      )
     )
 }
```

Key points  
1. Keep the existing ordering so **user props still win** over design defaults.  
2. Provide a default `{}` to stay backwards-compatible with callers that do not yet supply the parameter.

Please mirror the same change in `packages/vue-common/src/adapter/vue2/index.ts` to keep all Vue-2 builds consistent.  
 


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
export const renderComponent = ({
  view = null as any,
  component = null as any,
  props,
  customDesignProps = {},
  context: { attrs, listeners: on, slots },
  extend = {}
}) => {
  return () =>
    hooks.h(
      (view && view.value) || component,
      Object.assign(
        { props: { ...customDesignProps, ...props }, attrs, [extend.isSvg ? 'nativeOn' : 'on']: on, scopedSlots: { ...slots } },
        extend
      )
    )
}
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-13T08:35:58Z
author_association: NONE
diff_hunk: @@ -38,6 +44,11 @@ export const rootConfig = (context) => {
   return instance?.appContext.config.globalProperties
 }
 
+export const getCustomProps = () => {
+  const instance = hooks.getCurrentInstance()
+  return instance?.vnode?.props || {}
+}
path: packages/vue-common/src/adapter/vue3/index.ts
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Prefer `instance.props` to capture camel-cased prop keys**

`instance.vnode.props` gives you the raw vnode props which may preserve kebab-cased keys and include attrs/events.  
`instance.props` exposes the *normalised* reactive props object, mapping kebab-case to camelCase – a closer match to the keys declared in `designConfig.props`.

```diff
-export const getCustomProps = () => {
-  const instance = hooks.getCurrentInstance()
-  return instance?.vnode?.props || {}
-}
+export const getCustomProps = () => {
+  const instance = hooks.getCurrentInstance()
+  return instance?.props || {}
+}
```

This avoids false negatives when a user passes `center="false"` (kebab) but the design config checks for `center` (camel).  



<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
export const getCustomProps = () => {
  const instance = hooks.getCurrentInstance()
  return instance?.props || {}
}
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-13T08:35:59Z
author_association: NONE
diff_hunk: @@ -34,21 +34,34 @@ export const renderComponent = ({
   view = null as any,
   component = null as any,
   props,
+  customDesignProps,
   context: { attrs, listeners: on, slots },
   extend = {}
 }) => {
   return () =>
     hooks.h(
       (view && view.value) || component,
       Object.assign(
-        { props, attrs, [extend.isSvg ? 'nativeOn' : 'on']: on, ref: 'modeTemplate', scopedSlots: { ...slots } },
+        {
+          props,
+          attrs,
+          customDesignProps,
+          [extend.isSvg ? 'nativeOn' : 'on']: on,
+          ref: 'modeTemplate',
+          scopedSlots: { ...slots }
+        },
path: packages/vue-common/src/adapter/vue2/index.ts
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**`customDesignProps` is passed incorrectly to the component**

The current implementation adds `customDesignProps` as a separate property in the object passed to the Vue component, but it needs to be merged with the `props` object to actually apply the design configuration properties to the component.


Apply this fix to properly merge design props with user props:

```diff
 Object.assign(
   {
-    props,
+    props: { ...customDesignProps, ...props },
     attrs,
-    customDesignProps,
     [extend.isSvg ? 'nativeOn' : 'on']: on,
     ref: 'modeTemplate',
     scopedSlots: { ...slots }
   },
   extend
 )
```

This ensures that:
1. Design configuration properties are applied to the component
2. User props take precedence over design defaults (as they should)
3. The implementation is consistent with the expected behavior


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
        {
          props: { ...customDesignProps, ...props },
          attrs,
          [extend.isSvg ? 'nativeOn' : 'on']: on,
          ref: 'modeTemplate',
          scopedSlots: { ...slots }
        },
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-13T08:51:19Z
author_association: NONE

PR comments:
user: login: coderabbitai[bot]
created_at: 2025-05-13T08:31:52Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough

The changes introduce and propagate a default `center: true` property for the `Alert` component within design configurations and ensure this behavior is reflected in both Vue 2 and Vue 3 adapters. The setup logic is enhanced to merge design-specific props with user props, and a new utility, `getCustomProps`, is added across Vue adapters. A related test and configuration demos are updated accordingly.

## Changes

| File(s)                                                                                  | Change Summary                                                                                                                        |
|-----------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------|
| examples/sites/demos/pc/app/config-provider/base.vue<br>examples/sites/demos/pc/app/config-provider/base-composition-api.vue | Added `center: true` to the `props` of the `Alert` component in the design config, centering alert content by default.                |
| examples/sites/demos/pc/app/config-provider/basic.spec.ts                               | Extended test to assert that `.tiny-alert` has `justify-content: center` style, verifying the new default.                            |
| packages/vue-common/src/adapter/vue2/index.ts<br>packages/vue-common/src/adapter/vue2.7/index.ts<br>packages/vue-common/src/adapter/vue3/index.ts | Added new exported function `getCustomProps` to retrieve the current component's props; updated `renderComponent` to accept and merge `customDesignProps`. |
| packages/vue-common/src/index.ts                                                        | Refactored `$setup` to merge design config props with user props; introduced `getDesignConfig`; updated `setup` to expose design config in renderless utils.                |
| examples/sites/demos/pc/app/config-provider/webdoc/config-provider.js                   | Updated description text for the "design" property to clarify version support and customization scope in both Chinese and English.    |
| packages/vue/package.json                                                               | Removed trailing newline; no functional changes.                                                                                      |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant User
    participant Component
    participant $setup
    participant getDesignConfig
    participant getCustomProps
    participant renderComponent

    User->>Component: Uses Alert component
    Component->>$setup: Calls setup with props/context
    $setup->>getDesignConfig: Fetch design config (global & component)
    $setup->>getCustomProps: Retrieve user-passed props
    $setup->>renderComponent: Merge design props (e.g., center: true) with user props
    renderComponent-->>Component: Rendered with merged props
```

## Poem

> In the meadow of code, an alert stands tall,  
> Now centered with grace, admired by all.  
> With helpers for props, and configs that blend,  
> The rabbit ensures defaults and customs both mend.  
> Tests check the style, adapters align—  
> Hopping forward, the UI will shine!  
> 🐇✨

<!-- walkthrough_end -->
<!-- This is an auto-generated comment: all tool run failures by coderabbit.ai -->

> [!WARNING]
> There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.
> 
> <details>
> <summary>🔧 ESLint</summary>
> 
> > If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.
> 
> <details>
> <summary>examples/sites/demos/pc/app/config-provider/webdoc/config-provider.js</summary>
> 
> 
> Oops! Something went wrong! :(
> 
> ESLint: 8.57.1
> 
> ESLint couldn't find the plugin "eslint-plugin-vue".
> 
> (The package "eslint-plugin-vue" was not found when loaded as a Node module from the directory "".)
> 
> It's likely that the plugin isn't installed correctly. Try reinstalling by running the following:
> 
>     npm install eslint-plugin-vue@latest --save-dev
> 
> The plugin "eslint-plugin-vue" was referenced from the config file in ".eslintrc.js » @antfu/eslint-config » @antfu/eslint-config-vue".
> 
> If you still can't figure out the problem, please stop by https://eslint.org/chat/help to chat with the team.
> 
> 
> </details>
> 
> <details>
> <summary>packages/vue-common/src/adapter/vue2.7/index.ts</summary>
> 
> 
> Oops! Something went wrong! :(
> 
> ESLint: 8.57.1
> 
> ESLint couldn't find the plugin "eslint-plugin-vue".
> 
> (The package "eslint-plugin-vue" was not found when loaded as a Node module from the directory "".)
> 
> It's likely that the plugin isn't installed correctly. Try reinstalling by running the following:
> 
>     npm install eslint-plugin-vue@latest --save-dev
> 
> The plugin "eslint-plugin-vue" was referenced from the config file in ".eslintrc.js » @antfu/eslint-config » @antfu/eslint-config-vue".
> 
> If you still can't figure out the problem, please stop by https://eslint.org/chat/help to chat with the team.
> 
> 
> </details>
> 
> <details>
> <summary>packages/vue-common/src/adapter/vue2/index.ts</summary>
> 
> 
> Oops! Something went wrong! :(
> 
> ESLint: 8.57.1
> 
> ESLint couldn't find the plugin "eslint-plugin-vue".
> 
> (The package "eslint-plugin-vue" was not found when loaded as a Node module from the directory "".)
> 
> It's likely that the plugin isn't installed correctly. Try reinstalling by running the following:
> 
>     npm install eslint-plugin-vue@latest --save-dev
> 
> The plugin "eslint-plugin-vue" was referenced from the config file in ".eslintrc.js » @antfu/eslint-config » @antfu/eslint-config-vue".
> 
> If you still can't figure out the problem, please stop by https://eslint.org/chat/help to chat with the team.
> 
> 
> </details>
> 
> </details>

<!-- end of auto-generated comment: all tool run failures by coderabbit.ai -->

<!-- announcements_start -->

> [!TIP]
> <details>
> <summary>⚡️ Faster reviews with caching</summary>
> 
> - CodeRabbit now supports caching for code and dependencies, helping speed up reviews. This means quicker feedback, reduced wait times, and a smoother review experience overall. Cached data is encrypted and stored securely. This feature will be automatically enabled for all accounts on May 16th. To opt out, configure `Review - Disable Cache` at either the organization or repository level. If you prefer to disable all data retention across your organization, simply turn off the `Data Retention` setting under your Organization Settings.
> 
> Enjoy the performance boost—your workflow just got faster.
> 
> </details>

<!-- announcements_end -->

---

<details>
<summary>📜 Recent review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 22aeaf0a258baa0ad0bc67ca186fd9567dfab363 and 3e400b411210c62bea7362bc6b5551eb9b3c7a9e.

</details>

<details>
<summary>📒 Files selected for processing (3)</summary>

* `examples/sites/demos/pc/app/config-provider/webdoc/config-provider.js` (1 hunks)
* `packages/vue-common/src/adapter/vue2.7/index.ts` (1 hunks)
* `packages/vue-common/src/adapter/vue2/index.ts` (1 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Graph Analysis (2)</summary>

<details>
<summary>packages/vue-common/src/adapter/vue2.7/index.ts (3)</summary><blockquote>

<details>
<summary>packages/vue-common/src/index.ts (2)</summary>

* `hooks` (412-412)
* `props` (54-62)

</details>
<details>
<summary>packages/vue-common/src/adapter/vue2/index.ts (2)</summary>

* `rootConfig` (57-57)
* `getCustomProps` (59-62)

</details>
<details>
<summary>packages/vue-common/src/adapter/vue3/index.ts (2)</summary>

* `rootConfig` (41-45)
* `getCustomProps` (47-50)

</details>

</blockquote></details>
<details>
<summary>packages/vue-common/src/adapter/vue2/index.ts (3)</summary><blockquote>

<details>
<summary>packages/vue-common/src/index.ts (2)</summary>

* `hooks` (412-412)
* `props` (54-62)

</details>
<details>
<summary>packages/vue-common/src/adapter/vue2.7/index.ts (2)</summary>

* `rootConfig` (48-48)
* `getCustomProps` (50-53)

</details>
<details>
<summary>packages/vue-common/src/adapter/vue3/index.ts (2)</summary>

* `rootConfig` (41-45)
* `getCustomProps` (47-50)

</details>

</blockquote></details>

</details><details>
<summary>🪛 Biome (1.9.4)</summary>

<details>
<summary>packages/vue-common/src/adapter/vue2.7/index.ts</summary>

[error] 35-35: Change to an optional chain.

Unsafe fix: Change to an optional chain.


(lint/complexity/useOptionalChain)

</details>
<details>
<summary>packages/vue-common/src/adapter/vue2/index.ts</summary>

[error] 44-46: Change to an optional chain.

Unsafe fix: Change to an optional chain.


(lint/complexity/useOptionalChain)

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: PR E2E Test (pnpm test:e2e3)

</details>

<details>
<summary>🔇 Additional comments (6)</summary><blockquote>

<details>
<summary>packages/vue-common/src/adapter/vue2/index.ts (2)</summary>

`37-37`: **Implementation of `customDesignProps` parameter in `renderComponent`**

The addition of the `customDesignProps` parameter to the `renderComponent` function supports the feature to allow global configuration of arbitrary component props. This parameter will be used to pass design configuration properties to components.

---

`59-62`: **Implementation of `getCustomProps` utility**

The addition of the `getCustomProps` function is a good utility that retrieves the component's props data from the current instance. This is important for accessing user-provided props to merge with design configuration props.

</details>
<details>
<summary>packages/vue-common/src/adapter/vue2.7/index.ts (2)</summary>

`29-29`: **Implementation of `customDesignProps` parameter in Vue 2.7 adapter**

The addition of the `customDesignProps` parameter to the `renderComponent` function in Vue 2.7 adapter mirrors the change in the Vue 2 adapter, maintaining consistency across adapters.

---

`50-53`: **Implementation of `getCustomProps` utility in Vue 2.7 adapter**

The `getCustomProps` function is correctly implemented to retrieve props data from the current Vue 2.7 instance, consistent with the Vue 2 implementation but adapted for Vue 2.7 specifics.

</details>
<details>
<summary>examples/sites/demos/pc/app/config-provider/webdoc/config-provider.js (2)</summary>

`15-15`: **Updated documentation for design property in Chinese**

The description now clearly explains that from version 3.23.0, the global configuration supports customizing any `props` attribute for double-layer components. Good examples are provided to help users understand the feature's capabilities.

---

`17-17`: **Updated documentation for design property in English**

The English description has been updated to match the Chinese description, providing consistent documentation across languages. The text clearly explains the feature's capabilities and limitations.

</details>

</blockquote></details>

</details>
<!-- internal state start -->


<!-- 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= -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details open="true">
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=opentiny/tiny-vue&utm_content=3419):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Explain this complex logic.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai explain this code block.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and explain its main purpose.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: NONE
user: login: petercat-assistant[bot]
created_at: 2025-05-13T08:32:03Z
body: ### Walkthrough
This PR introduces a feature to the design-config that allows global configuration components to accept arbitrary attributes. It includes updates to various Vue adapter files to support this functionality, as well as modifications to demo and test files to verify the new behavior.

### Changes
| Files | Summary |
|-------|---------|
| `base-composition-api.vue`, `base.vue` | Added `props` with `center: true` to components. |
| `basic.spec.ts` | Added test to verify text alignment is centered. |
| `index.ts` (vue2.7, vue2, vue3) | Introduced `getCustomProps` function to retrieve custom properties. |
| `index.ts` (vue-common) | Refactored `$setup` and `setup` functions to incorporate `customDesignProps`. |
| `package.json` | Minor version update. |
author_association: NONE