diff --git a/packages/arco-vue-docs/locale/en-us.js b/packages/arco-vue-docs/locale/en-us.js index 3489462e1..b9f0c9dc0 100644 --- a/packages/arco-vue-docs/locale/en-us.js +++ b/packages/arco-vue-docs/locale/en-us.js @@ -94,6 +94,7 @@ export default { scrollbar: 'Scrollbar', watermark: 'Watermark', verificationCode: 'VerificationCode', + colorPicker: 'ColorPicker', }, footer: { design: 'Design', diff --git a/packages/arco-vue-docs/locale/zh-cn.js b/packages/arco-vue-docs/locale/zh-cn.js index 9ff713667..f12fde02f 100644 --- a/packages/arco-vue-docs/locale/zh-cn.js +++ b/packages/arco-vue-docs/locale/zh-cn.js @@ -94,6 +94,7 @@ export default { scrollbar: '滚动条 Scrollbar', watermark: '水印 Watermark', verificationCode: '验证码输入框 VerificationCode', + colorPicker: '颜色选择器 ColorPicker', }, footer: { design: '设计', diff --git a/packages/arco-vue-docs/router.ts b/packages/arco-vue-docs/router.ts index 71ae186e4..d3c72f762 100644 --- a/packages/arco-vue-docs/router.ts +++ b/packages/arco-vue-docs/router.ts @@ -191,6 +191,10 @@ const VerificationCode = () => import('@web-vue/components/verification-code/README.zh-CN.md'); const VerificationCodeEn = () => import('@web-vue/components/verification-code/README.en-US.md'); +const ColorPicker = () => + import('@web-vue/components/color-picker/README.zh-CN.md'); +const ColorPickerEn = () => + import('@web-vue/components/color-picker/README.en-US.md'); const docs = [ { @@ -459,6 +463,11 @@ const components = [ component: Checkbox, componentEn: CheckboxEn, }, + { + name: 'colorPicker', + component: ColorPicker, + componentEn: ColorPickerEn, + }, { name: 'datePicker', component: DatePicker, diff --git a/packages/arco-vue-scripts/src/scripts/changelog/utils.ts b/packages/arco-vue-scripts/src/scripts/changelog/utils.ts index 2aa2cbbea..3c6aafac5 100644 --- a/packages/arco-vue-scripts/src/scripts/changelog/utils.ts +++ b/packages/arco-vue-scripts/src/scripts/changelog/utils.ts @@ -71,6 +71,8 @@ const componentList = [ 'overflow-list', 'scrollbar', 'watermark', + 'color-picker', + 'verification-code', ]; export const isValidComponent = (component: string) => { diff --git a/packages/web-vue/CHANGELOG.md b/packages/web-vue/CHANGELOG.md index 7744dd3a3..2d5be5742 100644 --- a/packages/web-vue/CHANGELOG.md +++ b/packages/web-vue/CHANGELOG.md @@ -2,6 +2,131 @@ changelog: true ``` +## 2.56.0 + +`2024-07-26` + +### 🆕 Feature + +- **input-number:** Added 'keydown' event to disable default behavior ([#3248](https://github.com/arco-design/arco-design-vue/pull/3248)) + +### 🐛 BugFix + +- **tree:** fix tree node folding animation ([#3234](https://github.com/arco-design/arco-design-vue/pull/3234)) +- **color-picker:** fix shaking issue when selecting color with v-model ([#3180](https://github.com/arco-design/arco-design-vue/pull/3180)) +- **time-picker:** TriggerProps property not correctly passed through ([#3178](https://github.com/arco-design/arco-design-vue/pull/3178)) + +### 💎 Enhancement + +- **menu:** fix color transition effect in selected menu item ([#3192](https://github.com/arco-design/arco-design-vue/pull/3192)) + + +## 2.55.3 + +`2024-06-07` + +### 🆕 Feature + +- **table:** colum added the minWidth attribute ([#3157](https://github.com/arco-design/arco-design-vue/pull/3157)) + +### 🐛 BugFix + +- **time-picker:** Fix issue with read-only mode still being editable ([#3173](https://github.com/arco-design/arco-design-vue/pull/3173)) +- **time-picker:** Added `placeholder` type definition ([#3173](https://github.com/arco-design/arco-design-vue/pull/3173)) +- **input:** fix display of allow-clear input button in read-only state ([#3172](https://github.com/arco-design/arco-design-vue/pull/3172)) +- **table:** fix table sticky-header failure with scrollbar ([#3170](https://github.com/arco-design/arco-design-vue/pull/3170)) +- **table:** Restore default style when table dynamically switches row-selection ([#3155](https://github.com/arco-design/arco-design-vue/pull/3155)) + + +## 2.55.2 + +`2024-05-10` + +### 🐛 BugFix + +- **verification-code:** fix formatter not being applied during paste ([#3110](https://github.com/arco-design/arco-design-vue/pull/3110)) +- **upload:** import missing image styles for upload component ([#3101](https://github.com/arco-design/arco-design-vue/pull/3101)) +- **transfer:** fix disabled behavior in transfer simple mode ([#3067](https://github.com/arco-design/arco-design-vue/pull/3067)) +- **color-picker:** fix color-picker style import ([#3052](https://github.com/arco-design/arco-design-vue/pull/3052)) + +### 💅 Style + +- **color-picker:** Optimize color control bar background fillet style ([#3116](https://github.com/arco-design/arco-design-vue/pull/3116)) + +### 🆎 TypeScript + +- undefined ([#2998](https://github.com/arco-design/arco-design-vue/pull/2998)) + + +## 2.55.1 + +`2024-03-29` + +### 🐛 BugFix + +- **empty:** fix automatically inherited warn ([#3048](https://github.com/arco-design/arco-design-vue/pull/3048)) +- **trigger:** fix animation direction for position popup ([#3045](https://github.com/arco-design/arco-design-vue/pull/3045)) +- **color-picker:** fix v-model not working ([#3030](https://github.com/arco-design/arco-design-vue/pull/3030)) +- **color-picker:** Fix copywriting errors ([#3028](https://github.com/arco-design/arco-design-vue/pull/3028)) + +### 💅 Style + +- **tree:** fix scrollHeight calculation exception problem ([#3044](https://github.com/arco-design/arco-design-vue/pull/3044)) + + +## 2.55.0 + +`2024-03-15` + +### 🆕 Feature + +- **tree-select:** Added `input-value` related properties ([#3024](https://github.com/arco-design/arco-design-vue/pull/3024)) +- **tree:** The `title` slot has a new `title` parameter ([#3024](https://github.com/arco-design/arco-design-vue/pull/3024)) +- **color-picker:** add color-picker component ([#2958](https://github.com/arco-design/arco-design-vue/pull/2958)) + +### 💅 Style + +- **tabs:** fix transition animation for tab title ([#3008](https://github.com/arco-design/arco-design-vue/pull/3008)) + + +## 2.54.6 + +`2024-03-01` + +### 🐛 BugFix + +- **input-number:** fix overlap between step button and suffix/append ([#3005](https://github.com/arco-design/arco-design-vue/pull/3005)) +- **collapse:** resolve reserved property warning ([#2997](https://github.com/arco-design/arco-design-vue/pull/2997)) +- **transfer:** fix disabled props not working ([#2996](https://github.com/arco-design/arco-design-vue/pull/2996)) +- **tree:** resolve invalid property name console warning issue ([#2995](https://github.com/arco-design/arco-design-vue/pull/2995)) + +### 💅 Style + +- **modal:** fix fade-modal transition effect works on enter state ([#3007](https://github.com/arco-design/arco-design-vue/pull/3007)) + + +## 2.54.5 + +`2024-02-21` + +### 🐛 BugFix + +- **menu:** Fix warning “Invalid prop name: key is a reserved property.” ([#2978](https://github.com/arco-design/arco-design-vue/pull/2978)) +- **date-picker:** refactor date utility functions and week picker to correctly show selected week ([#2970](https://github.com/arco-design/arco-design-vue/pull/2970)) +- **input-number:** fix v-model not working ([#2961](https://github.com/arco-design/arco-design-vue/pull/2961)) + + +## 2.54.4 + +`2024-02-02` + +### 🐛 BugFix + +- **table:** fix virtual table list not displaying empty state ([#2949](https://github.com/arco-design/arco-design-vue/pull/2949)) +- **watermark:** Fix font color does not take effect ([#2942](https://github.com/arco-design/arco-design-vue/pull/2942)) +- **input-number:** Fix change event triggering mechanism ([#2915](https://github.com/arco-design/arco-design-vue/pull/2915)) + + ## 2.54.3 `2024-01-19` diff --git a/packages/web-vue/CHANGELOG.zh-CN.md b/packages/web-vue/CHANGELOG.zh-CN.md index b07458d88..7c311656b 100644 --- a/packages/web-vue/CHANGELOG.zh-CN.md +++ b/packages/web-vue/CHANGELOG.zh-CN.md @@ -2,6 +2,131 @@ changelog: true ``` +## 2.56.0 + +`2024-07-26` + +### 🆕 新增功能 + +- **input-number:** 增加 'keydown' 事件,可以禁止默认行为 ([#3248](https://github.com/arco-design/arco-design-vue/pull/3248)) + +### 🐛 问题修复 + +- **tree:** 修复树折叠动画不生效问题 ([#3234](https://github.com/arco-design/arco-design-vue/pull/3234)) +- **color-picker:** 修复在 v-model 下选择颜色时出现的抖动问题 ([#3180](https://github.com/arco-design/arco-design-vue/pull/3180)) +- **time-picker:** triggerProps 属性未正确透传问题 ([#3178](https://github.com/arco-design/arco-design-vue/pull/3178)) + +### 💎 功能优化 + +- **menu:** 修复已选中菜单项中的颜色动画过渡效果 ([#3192](https://github.com/arco-design/arco-design-vue/pull/3192)) + + +## 2.55.3 + +`2024-06-07` + +### 🆕 新增功能 + +- **table:** column 增加 minWidth 属性 ([#3157](https://github.com/arco-design/arco-design-vue/pull/3157)) + +### 🐛 问题修复 + +- **time-picker:** 修复只读模式仍可编辑问题 ([#3173](https://github.com/arco-design/arco-design-vue/pull/3173)) +- **time-picker:** 补充 `placeholder` 类型定义 ([#3173](https://github.com/arco-design/arco-design-vue/pull/3173)) +- **input:** 修复只读状态下显示清空输入框按钮 ([#3172](https://github.com/arco-design/arco-design-vue/pull/3172)) +- **table:** 修复虚拟滚动条开启时 sticky-header 吸顶失效 ([#3170](https://github.com/arco-design/arco-design-vue/pull/3170)) +- **table:** table动态切换row-selection时恢复默认样式 ([#3155](https://github.com/arco-design/arco-design-vue/pull/3155)) + + +## 2.55.2 + +`2024-05-10` + +### 🐛 问题修复 + +- **verification-code:** 修复粘贴时`formatter`未生效 ([#3110](https://github.com/arco-design/arco-design-vue/pull/3110)) +- **upload:** 修复上传组件预览样式引入缺失 ([#3101](https://github.com/arco-design/arco-design-vue/pull/3101)) +- **transfer:** 修复 simple 模式下禁用失效 ([#3067](https://github.com/arco-design/arco-design-vue/pull/3067)) +- **color-picker:** 修复样式按需导入错误 ([#3052](https://github.com/arco-design/arco-design-vue/pull/3052)) + +### 💅 样式更新 + +- **color-picker:** 优化颜色控制条背景圆角样式 ([#3116](https://github.com/arco-design/arco-design-vue/pull/3116)) + +### 🆎 类型修正 + +- correct the type definition for popupContainer ([#2998](https://github.com/arco-design/arco-design-vue/pull/2998)) + + +## 2.55.1 + +`2024-03-29` + +### 🐛 问题修复 + +- **empty:** 修复属性自动继承的错误 ([#3048](https://github.com/arco-design/arco-design-vue/pull/3048)) +- **trigger:** 修正位置的弹出动画方向 ([#3045](https://github.com/arco-design/arco-design-vue/pull/3045)) +- **color-picker:** 修复双向绑定不生效问题 ([#3030](https://github.com/arco-design/arco-design-vue/pull/3030)) +- **color-picker:** 修复文案错误 ([#3028](https://github.com/arco-design/arco-design-vue/pull/3028)) + +### 💅 样式更新 + +- **tree:** 修复scrollHeight计算异常问题 ([#3044](https://github.com/arco-design/arco-design-vue/pull/3044)) + + +## 2.55.0 + +`2024-03-15` + +### 🆕 新增功能 + +- **tree-select:** 新增 `input-value` 相关属性 ([#3024](https://github.com/arco-design/arco-design-vue/pull/3024)) +- **tree:** `title` 插槽新增 `title` 参数 ([#3024](https://github.com/arco-design/arco-design-vue/pull/3024)) +- **color-picker:** 新增颜色选择器 ([#2958](https://github.com/arco-design/arco-design-vue/pull/2958)) + +### 💅 样式更新 + +- **tabs:** 修复 title 过渡动画效果 ([#3008](https://github.com/arco-design/arco-design-vue/pull/3008)) + + +## 2.54.6 + +`2024-03-01` + +### 🐛 问题修复 + +- **input-number:** 修复步进按钮与 suffix/append 的样式重叠 ([#3005](https://github.com/arco-design/arco-design-vue/pull/3005)) +- **collapse:** 解决 `vue` 保留属性警告 ([#2997](https://github.com/arco-design/arco-design-vue/pull/2997)) +- **transfer:** 修复 disabled 属性不生效问题 ([#2996](https://github.com/arco-design/arco-design-vue/pull/2996)) +- **tree:** 解决无效的属性名称控制台警告问题 ([#2995](https://github.com/arco-design/arco-design-vue/pull/2995)) + +### 💅 样式更新 + +- **modal:** 修复遮罩层 fade-modal 过渡动画在进入时不生效问题 ([#3007](https://github.com/arco-design/arco-design-vue/pull/3007)) + + +## 2.54.5 + +`2024-02-21` + +### 🐛 问题修复 + +- **menu:** 修复警告 “Invalid prop name: key is a reserved property.” ([#2978](https://github.com/arco-design/arco-design-vue/pull/2978)) +- **date-picker:** 重构日期 utility 函数和 WeekPicker,以正确显示所选星期 ([#2970](https://github.com/arco-design/arco-design-vue/pull/2970)) +- **input-number:** 修复双向绑定失效 ([#2961](https://github.com/arco-design/arco-design-vue/pull/2961)) + + +## 2.54.4 + +`2024-02-02` + +### 🐛 问题修复 + +- **table:** 修复表格虚拟列表下不显示 empty 问题 ([#2949](https://github.com/arco-design/arco-design-vue/pull/2949)) +- **watermark:** 修复字体颜色不生效问题 ([#2942](https://github.com/arco-design/arco-design-vue/pull/2942)) +- **input-number:** 修复 change 事件触发逻辑 ([#2915](https://github.com/arco-design/arco-design-vue/pull/2915)) + + ## 2.54.3 `2024-01-19` diff --git a/packages/web-vue/components/_utils/color.ts b/packages/web-vue/components/_utils/color.ts new file mode 100644 index 000000000..feff96517 --- /dev/null +++ b/packages/web-vue/components/_utils/color.ts @@ -0,0 +1,215 @@ +// https://github.com/scttcper/tinycolor +export const hsvToRgb = (h: number, s: number, v: number) => { + const i = Math.floor(h * 6); + const f = h * 6 - i; + const p = v * (1 - s); + const q = v * (1 - f * s); + const t = v * (1 - (1 - f) * s); + const mod = i % 6; + const r = [v, q, p, p, t, v][mod]; + const g = [t, v, v, q, p, p][mod]; + const b = [p, p, t, v, v, q][mod]; + + return { + r: Math.round(r * 255), + g: Math.round(g * 255), + b: Math.round(b * 255), + }; +}; + +export const rgbToHsv = (r: number, g: number, b: number) => { + r /= 255; + g /= 255; + b /= 255; + + const max = Math.max(r, g, b); + const min = Math.min(r, g, b); + let h = 0; + const v = max; + const d = max - min; + const s = max === 0 ? 0 : d / max; + + if (max === min) { + h = 0; + } else { + switch (max) { + case r: + h = (g - b) / d + (g < b ? 6 : 0); + break; + case g: + h = (b - r) / d + 2; + break; + case b: + h = (r - g) / d + 4; + break; + default: + break; + } + + h /= 6; + } + + return { h, s, v }; +}; + +// +const CSS_INTEGER = '[-\\+]?\\d+%?'; + +// +const CSS_NUMBER = '[-\\+]?\\d*\\.\\d+%?'; + +// Allow positive/negative integer/number. Don't capture the either/or, just the entire outcome. +const CSS_UNIT = `(?:${CSS_NUMBER})|(?:${CSS_INTEGER})`; + +// Actual matching. +// Parentheses and commas are optional, but not required. +// Whitespace can take the place of commas or opening paren +const PERMISSIVE_MATCH3 = `[\\s|\\(]+(${CSS_UNIT})[,|\\s]+(${CSS_UNIT})[,|\\s]+(${CSS_UNIT})\\s*\\)?`; +const PERMISSIVE_MATCH4 = `[\\s|\\(]+(${CSS_UNIT})[,|\\s]+(${CSS_UNIT})[,|\\s]+(${CSS_UNIT})[,|\\s]+(${CSS_UNIT})\\s*\\)?`; + +const matchers = { + rgb: new RegExp(`rgb${PERMISSIVE_MATCH3}`), + rgba: new RegExp(`rgba${PERMISSIVE_MATCH4}`), + hex3: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/, + hex6: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/, + hex4: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/, + hex8: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/, +}; + +export const parseIntFromHex = (val: string): number => { + return parseInt(val, 16); +}; + +export const convertHexToDecimal = (h: string): number => { + return parseIntFromHex(h) / 255; +}; + +export const formatInputToRgb = ( + color: string +): { r: number; g: number; b: number; a?: number } | false => { + let match = matchers.rgb.exec(color); + if (match) { + return { + r: parseInt(match[1], 10), + g: parseInt(match[2], 10), + b: parseInt(match[3], 10), + }; + } + + match = matchers.rgba.exec(color); + if (match) { + return { + r: parseInt(match[1], 10), + g: parseInt(match[2], 10), + b: parseInt(match[3], 10), + a: parseFloat(match[4]), + }; + } + + match = matchers.hex8.exec(color); + if (match) { + return { + r: parseIntFromHex(match[1]), + g: parseIntFromHex(match[2]), + b: parseIntFromHex(match[3]), + a: convertHexToDecimal(match[4]), + }; + } + + match = matchers.hex6.exec(color); + if (match) { + return { + r: parseIntFromHex(match[1]), + g: parseIntFromHex(match[2]), + b: parseIntFromHex(match[3]), + }; + } + + match = matchers.hex4.exec(color); + if (match) { + return { + r: parseIntFromHex(match[1] + match[1]), + g: parseIntFromHex(match[2] + match[2]), + b: parseIntFromHex(match[3] + match[3]), + a: convertHexToDecimal(match[4] + match[4]), + }; + } + + match = matchers.hex3.exec(color); + if (match) { + return { + r: parseIntFromHex(match[1] + match[1]), + g: parseIntFromHex(match[2] + match[2]), + b: parseIntFromHex(match[3] + match[3]), + }; + } + + return false; +}; + +export const formatInputToHSVA = (color: string) => { + const rgba = formatInputToRgb(color); + if (rgba) { + const hsv = rgbToHsv(rgba.r, rgba.g, rgba.b); + return { + ...hsv, + a: rgba.a ?? 1, + }; + } + return { + h: 0, + s: 1, + v: 1, + a: 1, + }; +}; + +export const hexToRgb = (color: string): any => { + color = color.trim().toLowerCase(); + if (color.length === 0) { + return false; + } + + let match = matchers.hex6.exec(color); + if (match) { + return { + r: parseIntFromHex(match[1]), + g: parseIntFromHex(match[2]), + b: parseIntFromHex(match[3]), + }; + } + + match = matchers.hex3.exec(color); + if (match) { + return { + r: parseIntFromHex(match[1] + match[1]), + g: parseIntFromHex(match[2] + match[2]), + b: parseIntFromHex(match[3] + match[3]), + }; + } + + return false; +}; + +export const rgbToHex = (r: number, g: number, b: number) => { + const hex = [ + Math.round(r).toString(16).padStart(2, '0'), + Math.round(g).toString(16).padStart(2, '0'), + Math.round(b).toString(16).padStart(2, '0'), + ]; + + return hex.join('').toUpperCase(); +}; + +export const rgbaToHex = (r: number, g: number, b: number, a: number) => { + const hex = [ + Math.round(r).toString(16).padStart(2, '0'), + Math.round(g).toString(16).padStart(2, '0'), + Math.round(b).toString(16).padStart(2, '0'), + Math.round(a * 255) + .toString(16) + .padStart(2, '0'), + ]; + + return hex.join('').toUpperCase(); +}; diff --git a/packages/web-vue/components/_utils/date.ts b/packages/web-vue/components/_utils/date.ts index aedbd2842..fbf718135 100644 --- a/packages/web-vue/components/_utils/date.ts +++ b/packages/web-vue/components/_utils/date.ts @@ -51,21 +51,34 @@ export const methods = { startOf(time: Dayjs, unit: OpUnitType) { return time.startOf(unit); }, + /** + * Similar to `startOf`, returns start date of a week; used in week pickers + * @param time Selected date + * @param weekStart Start day of a week + * @returns Start date of the week containing the selected date + */ + startOfWeek(time: Dayjs, weekStart: number) { + const currentDay = time.day(); + let startOfWeek = time.subtract(currentDay - weekStart, 'day'); + if (startOfWeek.isAfter(time)) { + startOfWeek = startOfWeek.subtract(7, 'day'); + } + return startOfWeek; + }, endOf(time: Dayjs, unit: OpUnitType) { return time.endOf(unit); }, set(time: Dayjs, unit: UnitType, value: number) { return time.set(unit, value); }, - isSameWeek( - date1: Dayjs, - date2: Dayjs, - weekStart: number, - localeName: string - ) { - return date1 - .locale({ ...dayjs.Ls[localeName.toLocaleLowerCase()], weekStart }) - .isSame(date2, 'week'); + isSameWeek(date1: Dayjs, date2: Dayjs, weekStart: number) { + // calculate week number of the given date considering the given start of week + const getWeek = (date: Dayjs) => { + const day = date.day(); + const diff = day - weekStart + (day < weekStart ? 7 : 0); + return date.subtract(diff, 'day').week(); + }; + return getWeek(date1) === getWeek(date2); }, }; diff --git a/packages/web-vue/components/arco-vue.ts b/packages/web-vue/components/arco-vue.ts index 78935a4ff..a45020b85 100644 --- a/packages/web-vue/components/arco-vue.ts +++ b/packages/web-vue/components/arco-vue.ts @@ -16,6 +16,7 @@ import Carousel, { CarouselItem } from './carousel'; import Cascader, { CascaderPanel } from './cascader'; import Checkbox, { CheckboxGroup } from './checkbox'; import Collapse, { CollapseItem } from './collapse'; +import ColorPicker from './color-picker'; import Comment from './comment'; import ConfigProvider from './config-provider'; import DatePicker, { @@ -116,6 +117,7 @@ const components: Record = { Carousel, Collapse, Comment, + ColorPicker, Descriptions, Empty, Image, diff --git a/packages/web-vue/components/cascader/README.en-US.md b/packages/web-vue/components/cascader/README.en-US.md index 40ad42e82..7a4120283 100644 --- a/packages/web-vue/components/cascader/README.en-US.md +++ b/packages/web-vue/components/cascader/README.en-US.md @@ -62,7 +62,7 @@ description: Refers to the use of multi-level classification to separate the opt |default-popup-visible|Whether to display the dropdown by default (uncontrolled state)|`boolean`|`false`|| |placeholder|Placeholder|`string`|`-`|| |filter-option|Custom options filter method|`(inputValue: string, option: CascaderOption) => boolean`|`-`|| -|popup-container|Mount container for popup|`string \| HTMLElement \| null \| undefined`|`-`|| +|popup-container|Mount container for popup|`string \| HTMLElement`|`-`|| |max-tag-count|In multi-select mode, the maximum number of labels displayed. 0 means unlimited|`number`|`0`|| |format-label|Format display content|`(options: CascaderOption[]) => string`|`-`|| |trigger-props|Trigger props of the drop-down menu|`TriggerProps`|`-`|| diff --git a/packages/web-vue/components/cascader/README.zh-CN.md b/packages/web-vue/components/cascader/README.zh-CN.md index a65f20427..886f0ac1a 100644 --- a/packages/web-vue/components/cascader/README.zh-CN.md +++ b/packages/web-vue/components/cascader/README.zh-CN.md @@ -60,7 +60,7 @@ description: 指在选择器选项数量较多时,采用多级分类的方式 |default-popup-visible|是否默认显示下拉框(非受控状态)|`boolean`|`false`|| |placeholder|占位符|`string`|`-`|| |filter-option|自定义选项过滤方法|`(inputValue: string, option: CascaderOption) => boolean`|`-`|| -|popup-container|弹出框的挂载容器|`string \| HTMLElement \| null \| undefined`|`-`|| +|popup-container|弹出框的挂载容器|`string \| HTMLElement`|`-`|| |max-tag-count|多选模式下,最多显示的标签数量。0 表示不限制|`number`|`0`|| |format-label|格式化展示内容|`(options: CascaderOption[]) => string`|`-`|| |trigger-props|下拉菜单的触发器属性|`TriggerProps`|`-`|| diff --git a/packages/web-vue/components/cascader/cascader.vue b/packages/web-vue/components/cascader/cascader.vue index 4f72b110c..6766fbc81 100644 --- a/packages/web-vue/components/cascader/cascader.vue +++ b/packages/web-vue/components/cascader/cascader.vue @@ -300,9 +300,7 @@ export default defineComponent({ * @en Mount container for popup */ popupContainer: { - type: [String, Object] as PropType< - string | HTMLElement | null | undefined - >, + type: [String, Object] as PropType, }, /** * @zh 多选模式下,最多显示的标签数量。0 表示不限制 diff --git a/packages/web-vue/components/collapse/CHANGELOG.md b/packages/web-vue/components/collapse/CHANGELOG.md index 631da5b46..1b7b88e35 100644 --- a/packages/web-vue/components/collapse/CHANGELOG.md +++ b/packages/web-vue/components/collapse/CHANGELOG.md @@ -2,6 +2,15 @@ changelog: true ``` +## 2.54.6 + +`2024-03-01` + +### 🐛 BugFix + +- resolve reserved property warning ([#2997](https://github.com/arco-design/arco-design-vue/pull/2997)) + + ## 2.38.0-beta.1 `2022-10-14` diff --git a/packages/web-vue/components/collapse/CHANGELOG.zh-CN.md b/packages/web-vue/components/collapse/CHANGELOG.zh-CN.md index bf75bd2cb..2be3fe3ec 100644 --- a/packages/web-vue/components/collapse/CHANGELOG.zh-CN.md +++ b/packages/web-vue/components/collapse/CHANGELOG.zh-CN.md @@ -2,6 +2,15 @@ changelog: true ``` +## 2.54.6 + +`2024-03-01` + +### 🐛 问题修复 + +- 解决 `vue` 保留属性警告 ([#2997](https://github.com/arco-design/arco-design-vue/pull/2997)) + + ## 2.38.0-beta.1 `2022-10-14` diff --git a/packages/web-vue/components/collapse/README.en-US.md b/packages/web-vue/components/collapse/README.en-US.md index 0d122cfa6..624f812c9 100644 --- a/packages/web-vue/components/collapse/README.en-US.md +++ b/packages/web-vue/components/collapse/README.en-US.md @@ -53,7 +53,6 @@ description: The content area that can be collapsed/expanded. |Attribute|Description|Type|Default|version| |---|---|---|:---:|:---| -|key|The id of the panel, corresponding to the value in `activeKey`|`string\|number`|`-`|| |header|The title of the panel|`string`|`-`|| |disabled|Whether to disable|`boolean`|`false`|| |show-expand-icon|Whether to show the expand icon|`boolean`|`true`|| @@ -67,3 +66,9 @@ description: The content area that can be collapsed/expanded. |header|The title of the panel|-|| + +## FAQ + + +### The `key` attribute of `` components is required +In the `` component, each `` needs to specify a unique `key` attribute, and the `key` corresponding to the value in `activeKey`. diff --git a/packages/web-vue/components/collapse/README.zh-CN.md b/packages/web-vue/components/collapse/README.zh-CN.md index 3acaaf0ac..8754de71a 100644 --- a/packages/web-vue/components/collapse/README.zh-CN.md +++ b/packages/web-vue/components/collapse/README.zh-CN.md @@ -51,7 +51,6 @@ description: 可以折叠 / 展开的内容区域。 |参数名|描述|类型|默认值|版本| |---|---|---|:---:|:---| -|key|面板的 id,对应 `activeKey` 中的值|`string\|number`|`-`|| |header|面板的标题|`string`|`-`|| |disabled|是否禁用|`boolean`|`false`|| |show-expand-icon|是否显示展开图标|`boolean`|`true`|| @@ -65,3 +64,9 @@ description: 可以折叠 / 展开的内容区域。 |header|面板的标题|-|| + +## FAQ + +### `` 组件的 `key` 属性为必填 +在 `` 组件中每个 `` 都需要指定唯一的 `key` 属性,`key` 对应 `activeKey` 中的值。 + diff --git a/packages/web-vue/components/collapse/TEMPLATE.md b/packages/web-vue/components/collapse/TEMPLATE.md index 51032d129..2164fa328 100644 --- a/packages/web-vue/components/collapse/TEMPLATE.md +++ b/packages/web-vue/components/collapse/TEMPLATE.md @@ -40,3 +40,17 @@ description: The content area that can be collapsed/expanded. %%API(collapse.vue)%% %%API(collapse-item.tsx)%% + +## FAQ + +## zh-CN +### `` 组件的 `key` 属性为必填 +在 `` 组件中每个 `` 都需要指定唯一的 `key` 属性,`key` 对应 `activeKey` 中的值。 + +--- + +## en-US +### The `key` attribute of `` components is required +In the `` component, each `` needs to specify a unique `key` attribute, and the `key` corresponding to the value in `activeKey`. + +--- diff --git a/packages/web-vue/components/collapse/collapse-item.tsx b/packages/web-vue/components/collapse/collapse-item.tsx index f80751535..0877bc7fa 100644 --- a/packages/web-vue/components/collapse/collapse-item.tsx +++ b/packages/web-vue/components/collapse/collapse-item.tsx @@ -19,11 +19,6 @@ export default defineComponent({ name: 'CollapseItem', components: { IconHover, IconCaretRight, IconCaretLeft }, props: { - /** - * @zh 面板的 id,对应 `activeKey` 中的值 - * @en The id of the panel, corresponding to the value in `activeKey` - */ - key: [String, Number], /** * @zh 面板的标题 * @en The title of the panel diff --git a/packages/web-vue/components/color-picker/CHANGELOG.md b/packages/web-vue/components/color-picker/CHANGELOG.md new file mode 100644 index 000000000..eff6f9ba8 --- /dev/null +++ b/packages/web-vue/components/color-picker/CHANGELOG.md @@ -0,0 +1,44 @@ +```yaml +changelog: true +``` + +## 2.56.0 + +`2024-07-26` + +### 🐛 BugFix + +- fix shaking issue when selecting color with v-model ([#3180](https://github.com/arco-design/arco-design-vue/pull/3180)) + + +## 2.55.2 + +`2024-05-10` + +### 🐛 BugFix + +- fix color-picker style import ([#3052](https://github.com/arco-design/arco-design-vue/pull/3052)) + +### 💅 Style + +- Optimize color control bar background fillet style ([#3116](https://github.com/arco-design/arco-design-vue/pull/3116)) + + +## 2.55.1 + +`2024-03-29` + +### 🐛 BugFix + +- fix v-model not working ([#3030](https://github.com/arco-design/arco-design-vue/pull/3030)) +- Fix copywriting errors ([#3028](https://github.com/arco-design/arco-design-vue/pull/3028)) + + +## 2.55.0 + +`2024-03-15` + +### 🆕 Feature + +- add color-picker component ([#2958](https://github.com/arco-design/arco-design-vue/pull/2958)) + diff --git a/packages/web-vue/components/color-picker/CHANGELOG.zh-CN.md b/packages/web-vue/components/color-picker/CHANGELOG.zh-CN.md new file mode 100644 index 000000000..30d799a60 --- /dev/null +++ b/packages/web-vue/components/color-picker/CHANGELOG.zh-CN.md @@ -0,0 +1,44 @@ +```yaml +changelog: true +``` + +## 2.56.0 + +`2024-07-26` + +### 🐛 问题修复 + +- 修复在 v-model 下选择颜色时出现的抖动问题 ([#3180](https://github.com/arco-design/arco-design-vue/pull/3180)) + + +## 2.55.2 + +`2024-05-10` + +### 🐛 问题修复 + +- 修复样式按需导入错误 ([#3052](https://github.com/arco-design/arco-design-vue/pull/3052)) + +### 💅 样式更新 + +- 优化颜色控制条背景圆角样式 ([#3116](https://github.com/arco-design/arco-design-vue/pull/3116)) + + +## 2.55.1 + +`2024-03-29` + +### 🐛 问题修复 + +- 修复双向绑定不生效问题 ([#3030](https://github.com/arco-design/arco-design-vue/pull/3030)) +- 修复文案错误 ([#3028](https://github.com/arco-design/arco-design-vue/pull/3028)) + + +## 2.55.0 + +`2024-03-15` + +### 🆕 新增功能 + +- 新增颜色选择器 ([#2958](https://github.com/arco-design/arco-design-vue/pull/2958)) + diff --git a/packages/web-vue/components/color-picker/README.en-US.md b/packages/web-vue/components/color-picker/README.en-US.md new file mode 100644 index 000000000..cba15faf7 --- /dev/null +++ b/packages/web-vue/components/color-picker/README.en-US.md @@ -0,0 +1,47 @@ +```yaml +meta: + type: Component + category: Data Entry +title: ColorPicker +description: Used for select and display colors. +``` + +*Auto translate by google.* + +@import ./__demo__/basic.md +@import ./__demo__/size.md +@import ./__demo__/disabled.md +@import ./__demo__/format.md +@import ./__demo__/colors.md +@import ./__demo__/trigger.md +@import ./__demo__/trigger-element.md +@import ./__demo__/only-panel.md + +## API + + +### `` Props + +|Attribute|Description|Type|Default| +|---|---|---|:---:| +|model-value **(v-model)**|Value|`string`|`-`| +|default-value|Default value (uncontrolled state)|`string`|`-`| +|format|Color value format|`'hex' \| 'rgb'`|`-`| +|size|Size|`'mini' \| 'small' \| 'medium' \| 'large'`|`'medium'`| +|show-text|Show color value|`boolean`|`false`| +|show-history|Show history colors|`boolean`|`false`| +|show-preset|Show preset colors|`boolean`|`false`| +|disabled|disabled|`boolean`|`false`| +|disabled-alpha|Disable transparency channel|`boolean`|`false`| +|hide-trigger|There is no trigger element, only the color panel is displayed|`boolean`|`false`| +|trigger-props|Can accept Props of all [Trigger](/vue/component/trigger) components|`Partial`|`-`| +|history-colors|Color array of historical colors|`string[]`|`-`| +|preset-colors|Color array of preset colors|`string[]`|`() => colors`| +### `` Events + +|Event Name|Description|Parameters| +|---|---|---| +|change|Triggered when the color value changes|value: `string`| +|popup-visible-change|Triggered when the color panel is expanded and collapsed|visible: `boolean`
value: `string`| + + diff --git a/packages/web-vue/components/color-picker/README.zh-CN.md b/packages/web-vue/components/color-picker/README.zh-CN.md new file mode 100644 index 000000000..b460395b7 --- /dev/null +++ b/packages/web-vue/components/color-picker/README.zh-CN.md @@ -0,0 +1,45 @@ +```yaml +meta: + type: 组件 + category: 数据输入 +title: 颜色选择器 ColorPicker +description: 用于选择和展示颜色 +``` + +@import ./__demo__/basic.md +@import ./__demo__/size.md +@import ./__demo__/disabled.md +@import ./__demo__/format.md +@import ./__demo__/colors.md +@import ./__demo__/trigger.md +@import ./__demo__/trigger-element.md +@import ./__demo__/only-panel.md + +## API + + +### `` Props + +|参数名|描述|类型|默认值| +|---|---|---|:---:| +|model-value **(v-model)**|绑定值|`string`|`-`| +|default-value|默认值(非受控状态)|`string`|`-`| +|format|颜色值的格式|`'hex' \| 'rgb'`|`-`| +|size|尺寸|`'mini' \| 'small' \| 'medium' \| 'large'`|`'medium'`| +|show-text|显示颜色值|`boolean`|`false`| +|show-history|显示历史颜色|`boolean`|`false`| +|show-preset|显示预设颜色|`boolean`|`false`| +|disabled|禁用|`boolean`|`false`| +|disabled-alpha|禁用透明通道|`boolean`|`false`| +|hide-trigger|没有触发元素,只显示颜色面板|`boolean`|`false`| +|trigger-props|接受所有 [Trigger](/vue/component/trigger) 组件的Props|`Partial`|`-`| +|history-colors|历史颜色的颜色数组|`string[]`|`-`| +|preset-colors|预设颜色的颜色数组|`string[]`|`() => colors`| +### `` Events + +|事件名|描述|参数| +|---|---|---| +|change|颜色值改变时触发|value: `string`| +|popup-visible-change|颜色面板展开和收起时触发|visible: `boolean`
value: `string`| + + diff --git a/packages/web-vue/components/color-picker/TEMPLATE.md b/packages/web-vue/components/color-picker/TEMPLATE.md new file mode 100644 index 000000000..79f7151b0 --- /dev/null +++ b/packages/web-vue/components/color-picker/TEMPLATE.md @@ -0,0 +1,31 @@ +## zh-CN +```yaml +meta: + type: 组件 + category: 数据输入 +title: 颜色选择器 ColorPicker +description: 用于选择和展示颜色 +``` +--- +## en-US +```yaml +meta: + type: Component + category: Data Entry +title: ColorPicker +description: Used for select and display colors. +``` +--- + +@import ./__demo__/basic.md +@import ./__demo__/size.md +@import ./__demo__/disabled.md +@import ./__demo__/format.md +@import ./__demo__/colors.md +@import ./__demo__/trigger.md +@import ./__demo__/trigger-element.md +@import ./__demo__/only-panel.md + +## API + +%%API(color-picker.tsx)%% diff --git a/packages/web-vue/components/color-picker/__demo__/basic.md b/packages/web-vue/components/color-picker/__demo__/basic.md new file mode 100644 index 000000000..45e1473c5 --- /dev/null +++ b/packages/web-vue/components/color-picker/__demo__/basic.md @@ -0,0 +1,31 @@ +```yaml +title: + zh-CN: 基本使用 + en-US: Basic Usage +``` + +## zh-CN + +基本用法 + +--- + +## en-US + +Basic usage + +--- + +```vue + + + +``` diff --git a/packages/web-vue/components/color-picker/__demo__/colors.md b/packages/web-vue/components/color-picker/__demo__/colors.md new file mode 100644 index 000000000..9fcafcdcb --- /dev/null +++ b/packages/web-vue/components/color-picker/__demo__/colors.md @@ -0,0 +1,44 @@ +```yaml +title: + zh-CN: 预设颜色和历史颜色 + en-US: Preset & History +``` + +## zh-CN + +通过 `showPreset` 和 `showHistory` 开启预设颜色和历史颜色区域。历史颜色需要用户自行控制展示内容。 + +--- + +## en-US + +The preset color and history color areas can be opened through `showPreset` and `showHistory`. Historical colors require users to control the display content themselves. + +--- + +```vue + + + +``` diff --git a/packages/web-vue/components/color-picker/__demo__/disabled.md b/packages/web-vue/components/color-picker/__demo__/disabled.md new file mode 100644 index 000000000..6bde44b19 --- /dev/null +++ b/packages/web-vue/components/color-picker/__demo__/disabled.md @@ -0,0 +1,26 @@ +```yaml +title: + zh-CN: 禁用 + en-US: Disabled +``` + +## zh-CN + +设置 `disabled` 禁用选择器。 + +--- + +## en-US + +Set `disabled` to disable the selector. + +--- + +```vue + +``` diff --git a/packages/web-vue/components/color-picker/__demo__/format.md b/packages/web-vue/components/color-picker/__demo__/format.md new file mode 100644 index 000000000..570c54602 --- /dev/null +++ b/packages/web-vue/components/color-picker/__demo__/format.md @@ -0,0 +1,35 @@ +```yaml +title: + zh-CN: 颜色格式 + en-US: Color format +``` + +## zh-CN + +通过 `format` 设置颜色值的格式,支持 `hex` 和 `rgb`。 + +--- + +## en-US + +Set the format of the color value through `format`, supporting `hex` and `rgb`. + +--- + +```vue + + + +``` diff --git a/packages/web-vue/components/color-picker/__demo__/only-panel.md b/packages/web-vue/components/color-picker/__demo__/only-panel.md new file mode 100644 index 000000000..06b14488c --- /dev/null +++ b/packages/web-vue/components/color-picker/__demo__/only-panel.md @@ -0,0 +1,26 @@ +```yaml +title: + zh-CN: 只使用面板 + en-US: Only Panel +``` + +## zh-CN + +只用颜色选择面板。 + +--- + +## en-US + +Only use the color selection panel. + +--- + +```vue + +``` diff --git a/packages/web-vue/components/color-picker/__demo__/size.md b/packages/web-vue/components/color-picker/__demo__/size.md new file mode 100644 index 000000000..16a908de2 --- /dev/null +++ b/packages/web-vue/components/color-picker/__demo__/size.md @@ -0,0 +1,28 @@ +```yaml +title: + zh-CN: 尺寸 + en-US: Size +``` + +## zh-CN + +颜色选择器定义了四种尺寸(`mini`,`small`, `medium`, `large`),分别为 24px,28px,32px,36px。 + +--- + +## en-US + +ColorPicker defines four sizes (`mini`, `small`, `medium`, `large`), which are 24px, 28px, 32px, and 36px. + +--- + +```vue + +``` diff --git a/packages/web-vue/components/color-picker/__demo__/trigger-element.md b/packages/web-vue/components/color-picker/__demo__/trigger-element.md new file mode 100644 index 000000000..a37495002 --- /dev/null +++ b/packages/web-vue/components/color-picker/__demo__/trigger-element.md @@ -0,0 +1,38 @@ +```yaml +title: + zh-CN: 自定义触发元素 + en-US: Customize trigger element +``` + +## zh-CN + +自定义触发元素。 + +--- + +## en-US + +Customize trigger element. + +--- + +```vue + + + +``` diff --git a/packages/web-vue/components/color-picker/__demo__/trigger.md b/packages/web-vue/components/color-picker/__demo__/trigger.md new file mode 100644 index 000000000..5b910372e --- /dev/null +++ b/packages/web-vue/components/color-picker/__demo__/trigger.md @@ -0,0 +1,40 @@ +```yaml +title: + zh-CN: 触发器 + en-US: Trigger +``` + +## zh-CN + +可以通过 `trigger-props` 设置触发器的所有属性。 + +--- + +## en-US + +You can set the properties of the trigger through `trigger-props`. + +--- + +```vue + + + +``` diff --git a/packages/web-vue/components/color-picker/__test__/__snapshots__/demo.test.ts.snap b/packages/web-vue/components/color-picker/__test__/__snapshots__/demo.test.ts.snap new file mode 100644 index 000000000..0e8f34b14 --- /dev/null +++ b/packages/web-vue/components/color-picker/__test__/__snapshots__/demo.test.ts.snap @@ -0,0 +1,355 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` demo: render [basic] correctly 1`] = ` +"
+ +
+
+
+ +
+ +
+ +
+
+
+
#165DFF
+
+ +
+
" +`; + +exports[` demo: render [colors] correctly 1`] = ` +"
+
+ +
+" +`; + +exports[` demo: render [disabled] correctly 1`] = ` +"
+ +
+
+
+ +
+ +
+ +
+
+
+
#165DFF
+
+ +
+
" +`; + +exports[` demo: render [format] correctly 1`] = ` +"
+ +
+ +
+
+
+
#165DFF
+
+ +
+
" +`; + +exports[` demo: render [only-panel] correctly 1`] = ` +"
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Hex + + +
+
# + +
%
+
+
+
+
+
+
+
最近使用颜色
+
暂无
+
+
+
系统预设颜色
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Hex + + +
+
# + +
%
+
+
+
+
+
+ +
+
系统预设颜色
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
" +`; + +exports[` demo: render [size] correctly 1`] = ` +"
+ +
+
+
+ +
+ +
+ +
+
+
+ +
+ +
+ +
+
+
+ +
+ +
+ +
+
+
+ +
+ +
+
" +`; + +exports[` demo: render [trigger] correctly 1`] = ` +"
+ +
+ +
+
+
+ +
+ +
+
" +`; + +exports[` demo: render [trigger-element] correctly 1`] = ` +"
+ +
#165DFF + + + +
+
" +`; diff --git a/packages/web-vue/components/color-picker/__test__/demo.test.ts b/packages/web-vue/components/color-picker/__test__/demo.test.ts new file mode 100644 index 000000000..8aad704a0 --- /dev/null +++ b/packages/web-vue/components/color-picker/__test__/demo.test.ts @@ -0,0 +1,3 @@ +import demoTest from '../../../scripts/demo-test'; + +demoTest('color-picker'); diff --git a/packages/web-vue/components/color-picker/__test__/index.test.ts b/packages/web-vue/components/color-picker/__test__/index.test.ts new file mode 100644 index 000000000..3f19e2368 --- /dev/null +++ b/packages/web-vue/components/color-picker/__test__/index.test.ts @@ -0,0 +1,28 @@ +import { mount } from '@vue/test-utils'; +import ColorPicker from '../index'; + +describe('ColorPicker', () => { + test('Whether the size is rendered correctly', () => { + const wrapper = mount(ColorPicker, { + props: { + size: 'mini', + }, + }); + const colorPickerElement = wrapper.find('.arco-color-picker'); + expect(colorPickerElement.classes()).toContain( + `arco-color-picker-size-mini` + ); + }); + + test('Whether the disabled is rendered correctly', () => { + const wrapper = mount(ColorPicker, { + props: { + disabled: true, + }, + }); + const colorPickerElement = wrapper.find('.arco-color-picker'); + expect(colorPickerElement.classes()).toContain( + `arco-color-picker-disabled` + ); + }); +}); diff --git a/packages/web-vue/components/color-picker/color-picker.tsx b/packages/web-vue/components/color-picker/color-picker.tsx new file mode 100644 index 000000000..21a81c6c9 --- /dev/null +++ b/packages/web-vue/components/color-picker/color-picker.tsx @@ -0,0 +1,271 @@ +import { defineComponent, PropType, computed, watch } from 'vue'; +import { Size } from '../_utils/constant'; +import { getPrefixCls } from '../_utils/global-config'; +import { colors } from './colors'; +import { HSV } from './interface'; +import Panel from './panel'; +import Trigger, { TriggerProps } from '../trigger'; +import useState from '../_hooks/use-state'; +import { + formatInputToHSVA, + hsvToRgb, + rgbaToHex, + rgbToHex, +} from '../_utils/color'; + +export default defineComponent({ + name: 'ColorPicker', + props: { + /** + * @zh 绑定值 + * @en Value + */ + modelValue: String, + /** + * @zh 默认值(非受控状态) + * @en Default value (uncontrolled state) + */ + defaultValue: { + type: String, + }, + /** + * @zh 颜色值的格式 + * @en Color value format + */ + format: { + type: String as PropType<'hex' | 'rgb'>, + }, + /** + * @zh 尺寸 + * @en Size + * @values 'mini','small','medium','large' + */ + size: { + type: String as PropType, + default: 'medium', + }, + /** + * @zh 显示颜色值 + * @en Show color value + */ + showText: { + type: Boolean, + default: false, + }, + /** + * @zh 显示历史颜色 + * @en Show history colors + */ + showHistory: { + type: Boolean, + default: false, + }, + /** + * @zh 显示预设颜色 + * @en Show preset colors + */ + showPreset: { + type: Boolean, + default: false, + }, + /** + * @zh 禁用 + * @en disabled + */ + disabled: { + type: Boolean, + default: false, + }, + /** + * @zh 禁用透明通道 + * @en Disable transparency channel + */ + disabledAlpha: { + type: Boolean, + default: false, + }, + /** + * @zh 没有触发元素,只显示颜色面板 + * @en There is no trigger element, only the color panel is displayed + * */ + hideTrigger: { + type: Boolean, + }, + /** + * @zh 接受所有 [Trigger](/vue/component/trigger) 组件的Props + * @en Can accept Props of all [Trigger](/vue/component/trigger) components + * */ + triggerProps: { + type: Object as PropType>, + }, + /** + * @zh 历史颜色的颜色数组 + * @en Color array of historical colors + */ + historyColors: { + type: Array as PropType, + }, + /** + * @zh 预设颜色的颜色数组 + * @en Color array of preset colors + */ + presetColors: { + type: Array as PropType, + default: () => colors, + }, + }, + emits: { + 'update:modelValue': (value: string) => true, + /** + * @zh 颜色值改变时触发 + * @en Triggered when the color value changes + * @param {string} value + */ + 'change': (value: string) => true, + /** + * @zh 颜色面板展开和收起时触发 + * @en Triggered when the color panel is expanded and collapsed + * @param {boolean} visible + * @param {string} value + */ + 'popup-visible-change': (visible: boolean, value: string) => true, + }, + setup(props, { emit, slots }) { + const prefixCls = getPrefixCls('color-picker'); + const mergeValue = computed(() => { + return props.modelValue ?? props.defaultValue; + }); + + const formatInput = computed(() => { + return formatInputToHSVA(mergeValue.value || ''); + }); + + const [alpha, setAlpha] = useState(formatInput.value.a); + const [hsv, setHsv] = useState({ + h: formatInput.value.h, + s: formatInput.value.s, + v: formatInput.value.v, + }); + + watch( + () => formatInput.value, + (value) => { + if (mergeValue.value !== formatValue.value) { + setAlpha(value.a); + setHsv({ + h: value.h, + s: value.s, + v: value.v, + }); + } + } + ); + + const color = computed(() => { + const rgb = hsvToRgb(hsv.value.h, hsv.value.s, hsv.value.v); + const hex = rgbToHex(rgb.r, rgb.g, rgb.b); + return { + hsv: hsv.value, + rgb, + hex, + }; + }); + + const colorString = computed(() => { + const { r, g, b } = color.value.rgb; + return `rgba(${r}, ${g}, ${b}, ${alpha.value.toFixed(2)})`; + }); + + const formatValue = computed(() => { + const { r, g, b } = color.value.rgb; + if (props.format === 'rgb') { + return alpha.value < 1 && !props.disabledAlpha + ? `rgba(${r}, ${g}, ${b}, ${alpha.value.toFixed(2)})` + : `rgb(${r}, ${g}, ${b})`; + } + return alpha.value < 1 && !props.disabledAlpha + ? `#${rgbaToHex(r, g, b, alpha.value)}` + : `#${rgbToHex(r, g, b)}`; + }); + + watch(formatValue, (value) => { + emit('update:modelValue', value); + emit('change', value); + }); + + const onHsvChange = (_value: HSV) => { + !props.disabled && setHsv(_value); + }; + + const onAlphaChange = (_value: number) => { + !props.disabled && setAlpha(_value); + }; + + const onPopupVisibleChange = (visible: boolean) => { + emit('popup-visible-change', visible, formatValue.value); + }; + + const renderInput = () => { + return ( +
+
+ {props.showText && ( +
{formatValue.value}
+ )} + +
+ ); + }; + + const renderPanel = () => { + return ( + + ); + }; + + return () => { + return props.hideTrigger ? ( + renderPanel() + ) : ( + + {slots.default ? slots.default() : renderInput()} + + ); + }; + }, +}); diff --git a/packages/web-vue/components/color-picker/colors.ts b/packages/web-vue/components/color-picker/colors.ts new file mode 100644 index 000000000..a8fa5bb01 --- /dev/null +++ b/packages/web-vue/components/color-picker/colors.ts @@ -0,0 +1,24 @@ +export const colors = [ + '#00B42A', + '#3C7EFF', + '#FF7D00', + '#F76965', + '#F7BA1E', + '#F5319D', + '#D91AD9', + '#9FDB1D', + '#FADC19', + '#722ED1', + '#3491FA', + '#7BE188', + '#93BEFF', + '#FFCF8B', + '#FBB0A7', + '#FCE996', + '#FB9DC7', + '#F08EE6', + '#DCF190', + '#FDFA94', + '#C396ED', + '#9FD4FD', +]; diff --git a/packages/web-vue/components/color-picker/control-bar.tsx b/packages/web-vue/components/color-picker/control-bar.tsx new file mode 100644 index 000000000..864063295 --- /dev/null +++ b/packages/web-vue/components/color-picker/control-bar.tsx @@ -0,0 +1,74 @@ +import { defineComponent, PropType, toRefs, computed } from 'vue'; +import { getPrefixCls } from '../_utils/global-config'; +import { Color } from './interface'; +import { useControlBlock } from './hooks/use-control-block'; + +export default defineComponent({ + name: 'ControlBar', + props: { + x: { + type: Number, + required: true, + }, + color: { + type: Object as PropType, + required: true, + }, + colorString: String, + type: String as PropType<'hue' | 'alpha'>, + onChange: Function as PropType<(x: number) => void>, + }, + setup(props) { + const prefixCls = getPrefixCls('color-picker'); + const rgb = computed(() => props.color.rgb); + + const { blockRef, handlerRef, onMouseDown } = useControlBlock({ + value: [props.x, 0], + onChange: (pos) => props.onChange?.(pos[0]), + }); + + const renderHandler = () => { + return ( +
+ ); + }; + + return () => { + if (props.type === 'alpha') { + return ( +
+
+ {renderHandler()} +
+
+ ); + } + return ( +
+ {renderHandler()} +
+ ); + }; + }, +}); diff --git a/packages/web-vue/components/color-picker/hooks/use-control-block.ts b/packages/web-vue/components/color-picker/hooks/use-control-block.ts new file mode 100644 index 000000000..442d10d98 --- /dev/null +++ b/packages/web-vue/components/color-picker/hooks/use-control-block.ts @@ -0,0 +1,62 @@ +import { ref } from 'vue'; + +interface ControlBlockParams { + value: [number, number]; + onChange: (value: [number, number]) => void; +} + +export const useControlBlock = ({ value, onChange }: ControlBlockParams) => { + const active = ref(false); + const blockRef = ref(); + const handlerRef = ref(); + + const getPercentNumber = (value: number, max: number) => { + if (value < 0) return 0; + if (value > max) return 1; + return value / max; + }; + + const setCurrentPosition = (ev: MouseEvent) => { + if (!blockRef.value) return; + const { clientX, clientY } = ev; + const rect = blockRef.value.getBoundingClientRect(); + const newValue: [number, number] = [ + getPercentNumber(clientX - rect.x, rect.width), + getPercentNumber(clientY - rect.y, rect.height), + ]; + if (newValue[0] !== value[0] || newValue[1] !== value[1]) { + onChange?.(newValue); + } + }; + + const removeListener = () => { + active.value = false; + window.removeEventListener('mousemove', onMouseMove); + window.removeEventListener('mouseup', removeListener); + window.removeEventListener('contextmenu', removeListener); + }; + + const onMouseDown = (ev: MouseEvent) => { + active.value = true; + setCurrentPosition(ev); + window.addEventListener('mousemove', onMouseMove); + window.addEventListener('mouseup', removeListener); + window.addEventListener('contextmenu', removeListener); + }; + + function onMouseMove(ev: MouseEvent) { + ev.preventDefault(); + if (ev.buttons > 0) { + setCurrentPosition(ev); + } else { + removeListener(); + } + } + + return { + active, + blockRef, + handlerRef, + onMouseDown, + }; +}; diff --git a/packages/web-vue/components/color-picker/index.ts b/packages/web-vue/components/color-picker/index.ts new file mode 100644 index 000000000..038dae9da --- /dev/null +++ b/packages/web-vue/components/color-picker/index.ts @@ -0,0 +1,18 @@ +import type { App } from 'vue'; +import type { ArcoOptions } from '../_utils/types'; +import { setGlobalConfig, getComponentPrefix } from '../_utils/global-config'; +import _ColorPicker from './color-picker'; + +const ColorPicker = Object.assign(_ColorPicker, { + install: (app: App, options?: ArcoOptions) => { + setGlobalConfig(app, options); + const componentPrefix = getComponentPrefix(options); + + app.component(componentPrefix + _ColorPicker.name, _ColorPicker); + }, +}); + +export type { RGB, HSV, Color } from './interface'; +export type ColorPickerInstance = InstanceType; + +export default ColorPicker; diff --git a/packages/web-vue/components/color-picker/input-alpha.tsx b/packages/web-vue/components/color-picker/input-alpha.tsx new file mode 100644 index 000000000..15b6ae8d5 --- /dev/null +++ b/packages/web-vue/components/color-picker/input-alpha.tsx @@ -0,0 +1,31 @@ +import { defineComponent, PropType } from 'vue'; +import { getPrefixCls } from '../_utils/global-config'; +import InputNumber from '../input-number'; + +export default defineComponent({ + name: 'InputAlpha', + props: { + value: { + type: Number, + required: true, + }, + disabled: Boolean, + onChange: Function as PropType<(value: number) => void>, + }, + setup(props) { + const prefixCls = getPrefixCls('color-picker'); + + return () => ( + '%' }} + min={0} + max={100} + disabled={props.disabled} + modelValue={Math.round(props.value * 100)} + onChange={(a = 100) => props.onChange?.(a / 100)} + /> + ); + }, +}); diff --git a/packages/web-vue/components/color-picker/input-hex.tsx b/packages/web-vue/components/color-picker/input-hex.tsx new file mode 100644 index 000000000..0ae3eb771 --- /dev/null +++ b/packages/web-vue/components/color-picker/input-hex.tsx @@ -0,0 +1,85 @@ +import { defineComponent, PropType, toRefs, watch } from 'vue'; +import { getPrefixCls } from '../_utils/global-config'; +import { Color, HSV } from './interface'; +import { hexToRgb, rgbToHsv } from '../_utils/color'; +import useState from '../_hooks/use-state'; +import Input, { InputGroup } from '../input'; +import InputAlpha from './input-alpha'; + +export default defineComponent({ + name: 'InputHex', + props: { + color: { + type: Object as PropType, + required: true, + }, + alpha: { + type: Number, + required: true, + }, + disabled: Boolean, + disabledAlpha: Boolean, + onHsvChange: Function as PropType<(value: HSV) => void>, + onAlphaChange: Function as PropType<(value: number) => void>, + }, + setup(props) { + const prefixCls = getPrefixCls('color-picker'); + const { color } = toRefs(props); + const [hex, setHex] = useState(color.value.hex); + + const handlerChange = (value: string) => { + const _rgb = hexToRgb(value) || { r: 255, g: 0, b: 0 }; + const hsv = rgbToHsv(_rgb.r, _rgb.g, _rgb.b); + props.onHsvChange?.(hsv); + }; + + const onInputChange = (value: string) => { + const matchValue = value.match(/[a-fA-F0-9]*/g)?.join('') ?? ''; + if (matchValue !== color.value.hex) { + handlerChange(matchValue.toUpperCase()); + } + }; + + const onPaste = (ev: ClipboardEvent) => { + if (!ev.clipboardData) return; + let text = ev.clipboardData.getData('Text'); + if (text.startsWith('#')) { + text = text.slice(1); + } + onInputChange(text); + ev.preventDefault(); + }; + + watch(color, () => { + if (color.value.hex !== hex.value) { + setHex(color.value.hex); + } + }); + + return () => ( + + '#' }} + size="mini" + maxLength={6} + disabled={props.disabled} + modelValue={hex.value} + onInput={setHex} + onChange={onInputChange} + onBlur={() => handlerChange} + onPressEnter={() => handlerChange} + // @ts-ignore + onPaste={onPaste} + /> + {!props.disabledAlpha && ( + + )} + + ); + }, +}); diff --git a/packages/web-vue/components/color-picker/input-rgb.tsx b/packages/web-vue/components/color-picker/input-rgb.tsx new file mode 100644 index 000000000..9eae2afa9 --- /dev/null +++ b/packages/web-vue/components/color-picker/input-rgb.tsx @@ -0,0 +1,59 @@ +import { defineComponent, PropType, toRefs } from 'vue'; +import { getPrefixCls } from '../_utils/global-config'; +import { Color, HSV, RGB } from './interface'; +import { rgbToHsv } from '../_utils/color'; +import { InputGroup } from '../input'; +import InputNumber from '../input-number'; +import InputAlpha from './input-alpha'; + +export default defineComponent({ + name: 'InputRgb', + props: { + color: { + type: Object as PropType, + required: true, + }, + alpha: { + type: Number, + required: true, + }, + disabled: Boolean, + disabledAlpha: Boolean, + onHsvChange: Function as PropType<(value: HSV) => void>, + onAlphaChange: Function as PropType<(value: number) => void>, + }, + setup(props) { + const prefixCls = getPrefixCls('color-picker'); + const { color } = toRefs(props); + + const handleChange = (value: Partial) => { + const newRGB = { ...color.value.rgb, ...value }; + const hsv = rgbToHsv(newRGB.r, newRGB.g, newRGB.b); + props.onHsvChange?.(hsv); + }; + + return () => ( + + {(['r', 'g', 'b'] as Array).map((channel) => ( + handleChange({ [channel]: val })} + /> + ))} + {!props.disabledAlpha && ( + + )} + + ); + }, +}); diff --git a/packages/web-vue/components/color-picker/interface.ts b/packages/web-vue/components/color-picker/interface.ts new file mode 100644 index 000000000..5b2f0480e --- /dev/null +++ b/packages/web-vue/components/color-picker/interface.ts @@ -0,0 +1,17 @@ +export interface RGB { + r: number; + g: number; + b: number; +} + +export interface HSV { + h: number; + s: number; + v: number; +} + +export interface Color { + hsv: HSV; + rgb: RGB; + hex: string; +} diff --git a/packages/web-vue/components/color-picker/palette.tsx b/packages/web-vue/components/color-picker/palette.tsx new file mode 100644 index 000000000..d7218dbe5 --- /dev/null +++ b/packages/web-vue/components/color-picker/palette.tsx @@ -0,0 +1,48 @@ +import { defineComponent, computed, PropType, toRefs, watch } from 'vue'; +import { getPrefixCls } from '../_utils/global-config'; +import { hsvToRgb } from '../_utils/color'; +import { Color } from './interface'; +import { useControlBlock } from './hooks/use-control-block'; + +export default defineComponent({ + name: 'Palette', + props: { + color: { + type: Object as PropType, + required: true, + }, + onChange: Function as PropType<(s: number, v: number) => void>, + }, + setup(props) { + const prefixCls = getPrefixCls('color-picker'); + const hsv = computed(() => props.color.hsv); + + const { blockRef, handlerRef, onMouseDown } = useControlBlock({ + value: [hsv.value.s, 1 - hsv.value.v], + onChange: (value) => props.onChange?.(value[0], 1 - value[1]), + }); + + const hueColor = computed(() => { + const rgb = hsvToRgb(hsv.value.h, 1, 1); + return `rgb(${rgb.r}, ${rgb.g}, ${rgb.b})`; + }); + + return () => ( +
+
+
+ ); + }, +}); diff --git a/packages/web-vue/components/color-picker/panel.tsx b/packages/web-vue/components/color-picker/panel.tsx new file mode 100644 index 000000000..0ec53c519 --- /dev/null +++ b/packages/web-vue/components/color-picker/panel.tsx @@ -0,0 +1,178 @@ +import { PropType, computed, defineComponent, ref } from 'vue'; +import { getPrefixCls } from '../_utils/global-config'; +import { hexToRgb, rgbToHsv } from '../_utils/color'; +import { Color, HSV } from './interface'; +import { useI18n } from '../locale'; +import useState from '../_hooks/use-state'; +import ControlBar from './control-bar'; +import Palette from './palette'; +import Select from '../select'; +import InputRgb from './input-rgb'; +import InputHex from './input-hex'; + +export default defineComponent({ + name: 'Panel', + props: { + color: { + type: Object as PropType, + required: true, + }, + alpha: { + type: Number, + required: true, + }, + colorString: String, + disabled: Boolean, + disabledAlpha: Boolean, + showHistory: Boolean, + showPreset: Boolean, + format: String as PropType<'hex' | 'rgb'>, + historyColors: Array as PropType, + presetColors: Array as PropType, + onAlphaChange: Function as PropType<(alpha: number) => void>, + onHsvChange: Function as PropType<(hsv: HSV) => void>, + }, + setup(props) { + const { t } = useI18n(); + const prefixCls = getPrefixCls('color-picker'); + const hsv = computed(() => props.color.hsv); + const [format, setFormat] = useState<'hex' | 'rgb'>(props.format || 'hex'); + + const onChange = (value: any) => { + setFormat(value); + }; + + const showCopy = ref(false); + + const onHexInputChange = (value: string) => { + const _rgb = hexToRgb(value) || { r: 255, g: 0, b: 0 }; + const _hsv = rgbToHsv(_rgb.r, _rgb.g, _rgb.b); + props.onHsvChange?.(_hsv); + }; + + const renderInput = () => { + const commonProps = { + color: props.color, + alpha: props.alpha, + disabled: props.disabled, + disabledAlpha: props.disabledAlpha, + onHsvChange: props.onHsvChange, + onAlphaChange: props.onAlphaChange, + }; + if (format.value === 'rgb') { + return ; + } + return ; + }; + + const renderColorBlock = (color: string) => { + return ( +
onHexInputChange(color)} + > +
+
+ ); + }; + + const renderColorSection = (text: string, colors: string[] | undefined) => ( +
+
{text}
+
+ {colors?.length ? ( +
+ {colors.map(renderColorBlock)} +
+ ) : ( + + {t('colorPicker.empty')} + + )} +
+
+ ); + + const renderColorSec = () => { + if (props.showHistory || props.showPreset) { + return ( +
+ {props.showHistory && + renderColorSection(t('colorPicker.history'), props.historyColors)} + {props.showPreset && + renderColorSection(t('colorPicker.preset'), props.presetColors)} +
+ ); + } + return null; + }; + + return () => ( +
+ props.onHsvChange?.({ h: hsv.value.h, s, v })} + /> +
+
+
+ + props.onHsvChange?.({ h, s: hsv.value.s, v: hsv.value.v }) + } + /> + {!props.disabledAlpha && ( + + )} +
+
+
+
+
+
+ + +
+
+ +
diff --git a/packages/web-vue/components/date-picker/panels/week/index.vue b/packages/web-vue/components/date-picker/panels/week/index.vue index 3ae040acf..dda47f089 100644 --- a/packages/web-vue/components/date-picker/panels/week/index.vue +++ b/packages/web-vue/components/date-picker/panels/week/index.vue @@ -33,21 +33,22 @@ export default defineComponent({ setup(props, { emit }) { const { locale } = useI18n(); const isSameTime: IsSameTime = (current, target) => { - return methods.isSameWeek( - current, - target, - props.dayStartOfWeek, - locale.value - ); + return methods.isSameWeek(current, target, props.dayStartOfWeek); }; return { isSameTime, onSelect: (value: Dayjs) => { - const startDateOfWeek = methods.startOf(value, 'week'); + const startDateOfWeek = methods.startOfWeek( + value, + props.dayStartOfWeek + ); emit('select', startDateOfWeek); }, onCellMouseEnter: (value: Dayjs) => { - const startDateOfWeek = methods.startOf(value, 'week'); + const startDateOfWeek = methods.startOfWeek( + value, + props.dayStartOfWeek + ); emit('cell-mouse-enter', startDateOfWeek); }, }; diff --git a/packages/web-vue/components/date-picker/picker.vue b/packages/web-vue/components/date-picker/picker.vue index 1b9c98514..4555139db 100644 --- a/packages/web-vue/components/date-picker/picker.vue +++ b/packages/web-vue/components/date-picker/picker.vue @@ -264,9 +264,7 @@ export default defineComponent({ * @en Mount container for pop-up box */ popupContainer: { - type: [String, Object] as PropType< - string | HTMLElement | null | undefined - >, + type: [String, Object] as PropType, }, mode: { type: String as PropType<'date' | 'year' | 'quarter' | 'month' | 'week'>, diff --git a/packages/web-vue/components/date-picker/range-picker.vue b/packages/web-vue/components/date-picker/range-picker.vue index de9d922c5..e73e5c743 100644 --- a/packages/web-vue/components/date-picker/range-picker.vue +++ b/packages/web-vue/components/date-picker/range-picker.vue @@ -250,9 +250,7 @@ export default defineComponent({ default: true, }, popupContainer: { - type: [String, Object] as PropType< - string | HTMLElement | null | undefined - >, + type: [String, Object] as PropType, }, locale: { type: Object as PropType>, diff --git a/packages/web-vue/components/dropdown/README.en-US.md b/packages/web-vue/components/dropdown/README.en-US.md index f35c6afa8..90cf6e483 100644 --- a/packages/web-vue/components/dropdown/README.en-US.md +++ b/packages/web-vue/components/dropdown/README.en-US.md @@ -124,7 +124,7 @@ description: When there are too many commands on the page, the alternative comma |default-popup-visible|Whether the popup is visible by default (uncontrolled mode)|`boolean`|`false`| |trigger|Trigger method|`'hover' \| 'click' \| 'focus' \| 'contextMenu'`|`'click'`| |position|Popup position|`'top' \| 'tl' \| 'tr' \| 'bottom' \| 'bl' \| 'br'`|`'br'`| -|popup-container|Mount container for popup|`string \| HTMLElement \| null \| undefined`|`-`| +|popup-container|Mount container for popup|`string \| HTMLElement`|`-`| |disabled|Whether to disable|`boolean`|`false`| |type|Button type|`string`|`-`| |size|Button size|`string`|`-`| diff --git a/packages/web-vue/components/dropdown/README.zh-CN.md b/packages/web-vue/components/dropdown/README.zh-CN.md index 81784a482..b1c47f890 100644 --- a/packages/web-vue/components/dropdown/README.zh-CN.md +++ b/packages/web-vue/components/dropdown/README.zh-CN.md @@ -122,7 +122,7 @@ description: 页面上的命令过多时,可将备选命令收纳到向下展 |default-popup-visible|弹出框默认是否可见(非受控模式)|`boolean`|`false`| |trigger|触发方式|`'hover' \| 'click' \| 'focus' \| 'contextMenu'`|`'click'`| |position|弹出位置|`'top' \| 'tl' \| 'tr' \| 'bottom' \| 'bl' \| 'br'`|`'br'`| -|popup-container|弹出框的挂载容器|`string \| HTMLElement \| null \| undefined`|`-`| +|popup-container|弹出框的挂载容器|`string \| HTMLElement`|`-`| |disabled|是否禁用|`boolean`|`false`| |type|按钮类型|`string`|`-`| |size|按钮大小|`string`|`-`| diff --git a/packages/web-vue/components/dropdown/dropdown-button.vue b/packages/web-vue/components/dropdown/dropdown-button.vue index 31caf48a7..7a983eecd 100644 --- a/packages/web-vue/components/dropdown/dropdown-button.vue +++ b/packages/web-vue/components/dropdown/dropdown-button.vue @@ -92,9 +92,7 @@ export default defineComponent({ * @en Mount container for popup */ popupContainer: { - type: [String, Object] as PropType< - string | HTMLElement | null | undefined - >, + type: [String, Object] as PropType, }, /** * @zh 是否禁用 diff --git a/packages/web-vue/components/empty/CHANGELOG.md b/packages/web-vue/components/empty/CHANGELOG.md index cd85df4c9..915d857ea 100644 --- a/packages/web-vue/components/empty/CHANGELOG.md +++ b/packages/web-vue/components/empty/CHANGELOG.md @@ -2,6 +2,15 @@ changelog: true ``` +## 2.55.1 + +`2024-03-29` + +### 🐛 BugFix + +- fix automatically inherited warn ([#3048](https://github.com/arco-design/arco-design-vue/pull/3048)) + + ## 2.47.0 `2023-06-02` diff --git a/packages/web-vue/components/empty/CHANGELOG.zh-CN.md b/packages/web-vue/components/empty/CHANGELOG.zh-CN.md index 3b018f27e..6922fe567 100644 --- a/packages/web-vue/components/empty/CHANGELOG.zh-CN.md +++ b/packages/web-vue/components/empty/CHANGELOG.zh-CN.md @@ -2,6 +2,15 @@ changelog: true ``` +## 2.55.1 + +`2024-03-29` + +### 🐛 问题修复 + +- 修复属性自动继承的错误 ([#3048](https://github.com/arco-design/arco-design-vue/pull/3048)) + + ## 2.47.0 `2023-06-02` diff --git a/packages/web-vue/components/empty/empty.tsx b/packages/web-vue/components/empty/empty.tsx index 11ee816c0..ab2aca75e 100644 --- a/packages/web-vue/components/empty/empty.tsx +++ b/packages/web-vue/components/empty/empty.tsx @@ -6,6 +6,7 @@ import { configProviderInjectionKey } from '../config-provider/context'; export default defineComponent({ name: 'Empty', + inheritAttrs: false, props: { /** * @zh 描述内容 @@ -32,7 +33,7 @@ export default defineComponent({ * @en Image/Icon * @slot image */ - setup(props, { slots }) { + setup(props, { slots, attrs }) { const prefixCls = getPrefixCls('empty'); const { t } = useI18n(); const configCtx = inject(configProviderInjectionKey, undefined); @@ -47,7 +48,7 @@ export default defineComponent({ } return ( -
+
{slots.image?.() ?? (props.imgSrc ? ( diff --git a/packages/web-vue/components/image/README.en-US.md b/packages/web-vue/components/image/README.en-US.md index 7794d42a4..a833ed401 100644 --- a/packages/web-vue/components/image/README.en-US.md +++ b/packages/web-vue/components/image/README.en-US.md @@ -112,7 +112,7 @@ description: Used to show and preview pictures. |mask-closable|Whether to close the modal when mask is clicked|`boolean`|`true`| |closable|Whether to show close button|`boolean`|`true`| |actions-layout|Layout of action list|`string[]`|`[ 'fullScreen', 'rotateRight', 'rotateLeft', 'zoomIn', 'zoomOut', 'originalSize',]`| -|popup-container|Set the mount point of the pop-up box, the same as the `to` of `teleport`, the default value is document.body|`HTMLElement \| string`|`-`| +|popup-container|Set the mount point of the pop-up box, the same as the `to` of `teleport`, the default value is document.body|`string \| HTMLElement`|`-`| ### `` Events |Event Name|Description|Parameters| diff --git a/packages/web-vue/components/image/README.zh-CN.md b/packages/web-vue/components/image/README.zh-CN.md index 02c178bcc..3344ceaa2 100644 --- a/packages/web-vue/components/image/README.zh-CN.md +++ b/packages/web-vue/components/image/README.zh-CN.md @@ -110,7 +110,7 @@ description: 展示和预览图片。 |mask-closable|点击 mask 是否触发关闭|`boolean`|`true`| |closable|是否显示关闭按钮|`boolean`|`true`| |actions-layout|控制条的布局|`string[]`|`[ 'fullScreen', 'rotateRight', 'rotateLeft', 'zoomIn', 'zoomOut', 'originalSize',]`| -|popup-container|设置弹出框的挂载点,同 `teleport` 的 `to`,缺省值是 document.body|`HTMLElement \| string`|`-`| +|popup-container|设置弹出框的挂载点,同 `teleport` 的 `to`,缺省值是 document.body|`string \| HTMLElement`|`-`| ### `` Events |事件名|描述|参数| diff --git a/packages/web-vue/components/image/preview-group.vue b/packages/web-vue/components/image/preview-group.vue index a0b8639cc..8213e8857 100644 --- a/packages/web-vue/components/image/preview-group.vue +++ b/packages/web-vue/components/image/preview-group.vue @@ -129,7 +129,7 @@ export default defineComponent({ * @en Set the mount point of the pop-up box, the same as the `to` of `teleport`, the default value is document.body */ popupContainer: { - type: [Object, String] as PropType, + type: [String, Object] as PropType, }, }, emits: [ diff --git a/packages/web-vue/components/index.less b/packages/web-vue/components/index.less index e3c8f9ca7..bb8d01c5e 100644 --- a/packages/web-vue/components/index.less +++ b/packages/web-vue/components/index.less @@ -19,6 +19,7 @@ @import './cascader/style/index.less'; @import './checkbox/style/index.less'; @import './collapse/style/index.less'; +@import './color-picker/style/index.less'; @import './comment/style/index.less'; @import './date-picker/style/index.less'; @import './descriptions/style/index.less'; diff --git a/packages/web-vue/components/index.ts b/packages/web-vue/components/index.ts index 5acb1d379..2abe9acdd 100644 --- a/packages/web-vue/components/index.ts +++ b/packages/web-vue/components/index.ts @@ -49,6 +49,8 @@ export { default as Collapse, CollapseItem } from './collapse'; export type { CollapseInstance, CollapseItemInstance } from './collapse'; export { default as Comment } from './comment'; export type { CommentInstance } from './comment'; +export { default as ColorPicker } from './color-picker'; +export type { ColorPickerInstance } from './color-picker'; export { default as ConfigProvider } from './config-provider'; export type { ConfigProviderInstance } from './config-provider'; export { diff --git a/packages/web-vue/components/input-number/CHANGELOG.md b/packages/web-vue/components/input-number/CHANGELOG.md index 62d0414a9..307d9ffff 100644 --- a/packages/web-vue/components/input-number/CHANGELOG.md +++ b/packages/web-vue/components/input-number/CHANGELOG.md @@ -2,6 +2,42 @@ changelog: true ``` +## 2.56.0 + +`2024-07-26` + +### 🆕 Feature + +- Added 'keydown' event to disable default behavior ([#3248](https://github.com/arco-design/arco-design-vue/pull/3248)) + + +## 2.54.6 + +`2024-03-01` + +### 🐛 BugFix + +- fix overlap between step button and suffix/append ([#3005](https://github.com/arco-design/arco-design-vue/pull/3005)) + + +## 2.54.5 + +`2024-02-21` + +### 🐛 BugFix + +- fix v-model not working ([#2961](https://github.com/arco-design/arco-design-vue/pull/2961)) + + +## 2.54.4 + +`2024-02-02` + +### 🐛 BugFix + +- Fix change event triggering mechanism ([#2915](https://github.com/arco-design/arco-design-vue/pull/2915)) + + ## 2.52.0 `2023-09-22` diff --git a/packages/web-vue/components/input-number/CHANGELOG.zh-CN.md b/packages/web-vue/components/input-number/CHANGELOG.zh-CN.md index e93bacdb7..9a2140a77 100644 --- a/packages/web-vue/components/input-number/CHANGELOG.zh-CN.md +++ b/packages/web-vue/components/input-number/CHANGELOG.zh-CN.md @@ -2,6 +2,42 @@ changelog: true ``` +## 2.56.0 + +`2024-07-26` + +### 🆕 新增功能 + +- 增加 'keydown' 事件,可以禁止默认行为 ([#3248](https://github.com/arco-design/arco-design-vue/pull/3248)) + + +## 2.54.6 + +`2024-03-01` + +### 🐛 问题修复 + +- 修复步进按钮与 suffix/append 的样式重叠 ([#3005](https://github.com/arco-design/arco-design-vue/pull/3005)) + + +## 2.54.5 + +`2024-02-21` + +### 🐛 问题修复 + +- 修复双向绑定失效 ([#2961](https://github.com/arco-design/arco-design-vue/pull/2961)) + + +## 2.54.4 + +`2024-02-02` + +### 🐛 问题修复 + +- 修复 change 事件触发逻辑 ([#2915](https://github.com/arco-design/arco-design-vue/pull/2915)) + + ## 2.52.0 `2023-09-22` diff --git a/packages/web-vue/components/input-number/README.en-US.md b/packages/web-vue/components/input-number/README.en-US.md index a63863e68..ee0124105 100644 --- a/packages/web-vue/components/input-number/README.en-US.md +++ b/packages/web-vue/components/input-number/README.en-US.md @@ -58,6 +58,7 @@ description: Only input boxes in numeric format are allowed. |blur|Triggered when the input box loses focus|ev: `FocusEvent`|| |clear|Triggered when the user clicks the clear button|ev: `Event`|2.23.0| |input|Triggered on input|value: ` number \| undefined `
inputValue: `string`
ev: `Event`|2.27.0| +|keydown|Triggered on keydown|ev: `MouseEvent`|2.56.0| ### `` Methods |Method|Description|Parameters|Return| diff --git a/packages/web-vue/components/input-number/README.zh-CN.md b/packages/web-vue/components/input-number/README.zh-CN.md index ce05ac808..a307d4b95 100644 --- a/packages/web-vue/components/input-number/README.zh-CN.md +++ b/packages/web-vue/components/input-number/README.zh-CN.md @@ -56,6 +56,7 @@ description: 仅允许输入数字格式的输入框。 |blur|输入框失去焦点时触发|ev: `FocusEvent`|| |clear|用户点击清除按钮时触发|ev: `Event`|2.23.0| |input|输入时触发|value: ` number \| undefined `
inputValue: `string`
ev: `Event`|2.27.0| +|keydown|按下键盘时触发|ev: `MouseEvent`|2.56.0| ### `` Methods |方法名|描述|参数|返回值| diff --git a/packages/web-vue/components/input-number/input-number.tsx b/packages/web-vue/components/input-number/input-number.tsx index a7d662c36..73dc09a06 100644 --- a/packages/web-vue/components/input-number/input-number.tsx +++ b/packages/web-vue/components/input-number/input-number.tsx @@ -1,12 +1,4 @@ -import { - computed, - defineComponent, - nextTick, - PropType, - ref, - toRefs, - watch, -} from 'vue'; +import { computed, defineComponent, PropType, ref, toRefs, watch } from 'vue'; import NP from 'number-precision'; import { getPrefixCls } from '../_utils/global-config'; import { isNumber, isUndefined } from '../_utils/is'; @@ -202,6 +194,13 @@ export default defineComponent({ * @version 2.27.0 */ 'input': (value: number | undefined, inputValue: string, ev: Event) => true, + /** + * @zh 按下键盘时触发 + * @en Triggered on keydown + * @param {MouseEvent} ev + * @version 2.56.0 + */ + 'keydown': (ev: KeyboardEvent) => true, }, /** * @zh 前缀 @@ -337,39 +336,14 @@ export default defineComponent({ if (finalValue !== valueNumber.value || _value.value !== stringValue) { _value.value = stringValue; } - emit('update:modelValue', finalValue); }; - watch( - () => props.min, - (newVal) => { - const _isMin = - isNumber(valueNumber.value) && valueNumber.value <= newVal; - if (isMin.value !== _isMin) { - isMin.value = _isMin; - } - const isExceedMinValue = - isNumber(valueNumber.value) && valueNumber.value < newVal; - if (isExceedMinValue) { - handleExceedRange(); - } - } - ); watch( - () => props.max, - (newVal) => { - const _isMax = - isNumber(valueNumber.value) && valueNumber.value >= newVal; - if (isMax.value !== _isMax) { - isMax.value = _isMax; - } - - const isExceedMaxValue = - isNumber(valueNumber.value) && valueNumber.value > newVal; - if (isExceedMaxValue) { - handleExceedRange(); - } + () => [props.max, props.min], + () => { + handleExceedRange(); + updateNumberStatus(valueNumber.value); } ); @@ -421,10 +395,12 @@ export default defineComponent({ if (isNumber(Number(value)) || /^(\.|-)$/.test(value)) { _value.value = props.formatter?.(value) ?? value; updateNumberStatus(valueNumber.value); + + emit('input', valueNumber.value, _value.value, ev); if (props.modelEvent === 'input') { emit('update:modelValue', valueNumber.value); + emit('change', valueNumber.value, ev); } - emit('input', valueNumber.value, _value.value, ev); } }; @@ -433,23 +409,12 @@ export default defineComponent({ }; const handleChange = (value: string, ev: Event) => { - const finalValue = getLegalValue(valueNumber.value); - const stringValue = getStringValue(finalValue); - if (finalValue !== valueNumber.value || _value.value !== stringValue) { - _value.value = stringValue; - updateNumberStatus(finalValue); + if (ev instanceof MouseEvent && !value) { + return; } - nextTick(() => { - if (isNumber(props.modelValue) && props.modelValue !== finalValue) { - // TODO: verify number - _value.value = getStringValue(props.modelValue); - updateNumberStatus(props.modelValue); - } - }); - - emit('update:modelValue', finalValue); - emit('change', finalValue, ev); + handleExceedRange(); + emit('change', valueNumber.value, ev); }; const handleBlur = (ev: FocusEvent) => { @@ -464,7 +429,7 @@ export default defineComponent({ emit('clear', ev); }; - const onKeyDown = getKeyDownHandler( + const keyDownHandler = getKeyDownHandler( new Map([ [ KEYBOARD_KEY.ARROW_UP, @@ -483,6 +448,13 @@ export default defineComponent({ ]) ); + const onKeyDown = (event: KeyboardEvent) => { + emit('keydown', event); + if (!event.defaultPrevented) { + keyDownHandler(event); + } + }; + watch( () => props.modelValue, (value: number | undefined) => { @@ -500,7 +472,9 @@ export default defineComponent({ } return ( <> - {slots.suffix?.()} + {slots.suffix && ( +
{slots.suffix?.()}
+ )}