diff --git a/packages/components/default.less b/packages/components/default.less index 582b8405e..684aa35f1 100644 --- a/packages/components/default.less +++ b/packages/components/default.less @@ -39,6 +39,7 @@ @import './input-number/style/themes/default.less'; @import './layout/style/themes/default.less'; @import './list/style/themes/default.less'; +@import './loading-bar/style/themes/default.less'; @import './menu/style/themes/default.less'; @import './message/style/themes/default.less'; @import './modal/style/themes/default.less'; @@ -61,6 +62,7 @@ @import './table/style/themes/default.less'; @import './tabs/style/themes/default.less'; @import './tag/style/themes/default.less'; +@import './text/style/themes/default.less'; @import './textarea/style/themes/default.less'; @import './time-picker/style/themes/default.less'; @import './timeline/style/themes/default.less'; @@ -71,4 +73,3 @@ @import './typography/style/themes/default.less'; @import './upload/style/themes/default.less'; @import './watermark/style/themes/default.less'; -@import './loading-bar/style/themes/default.less'; diff --git a/packages/components/form/docs/Theme.zh.md b/packages/components/form/docs/Theme.zh.md index e00ad020a..f7c7d4094 100644 --- a/packages/components/form/docs/Theme.zh.md +++ b/packages/components/form/docs/Theme.zh.md @@ -32,8 +32,8 @@ | `@form-focus-color` | `@color-primary-d10` | - | - | | `@form-focus-box-shadow` | `0 0 0 2px fade(@form-focus-color, 20%)` | - | - | | `@form-disabled-color` | `@text-color-disabled` | - | - | -| `@form-disabled-border-color` | `@color-graphite-l20` | - | - | -| `@form-disabled-background-color` | `@background-color-disabled` | - | - | +| `@form-disabled-border-color` | `var(--ix-background-color)` | - | - | +| `@form-disabled-background-color` | `var(--ix-background-color-deep)` | - | - | | `@form-icon-color` | `@color-graphite-d20` | - | - | | `@form-icon-hover-color` | `@color-graphite-d20` | `@color-primary` | - | | `@form-item-valid-color` | `@color-success` | `@color-success-d10` | - | diff --git a/packages/components/index.ts b/packages/components/index.ts index d2e9b1dcb..8e6880954 100644 --- a/packages/components/index.ts +++ b/packages/components/index.ts @@ -66,6 +66,7 @@ import { IxSwitch } from '@idux/components/switch' import { IxTable, IxTableColumn } from '@idux/components/table' import { IxTab, IxTabs } from '@idux/components/tabs' import { IxTag, IxTagGroup } from '@idux/components/tag' +import { IxText } from '@idux/components/text' import { IxTextarea } from '@idux/components/textarea' import { IxTimePicker, IxTimeRangePicker } from '@idux/components/time-picker' import { IxTimeline, IxTimelineItem } from '@idux/components/timeline' @@ -169,6 +170,7 @@ const components = [ IxTabs, IxTag, IxTagGroup, + IxText, IxTextarea, IxTimePicker, IxTimeRangePicker, @@ -257,6 +259,7 @@ export * from '@idux/components/switch' export * from '@idux/components/table' export * from '@idux/components/tabs' export * from '@idux/components/tag' +export * from '@idux/components/text' export * from '@idux/components/textarea' export * from '@idux/components/time-picker' export * from '@idux/components/timeline' diff --git a/packages/components/seer.less b/packages/components/seer.less index a6e333033..ad950b6c2 100644 --- a/packages/components/seer.less +++ b/packages/components/seer.less @@ -39,6 +39,7 @@ @import './input-number/style/themes/seer.less'; @import './layout/style/themes/seer.less'; @import './list/style/themes/seer.less'; +@import './loading-bar/style/themes/seer.less'; @import './menu/style/themes/seer.less'; @import './message/style/themes/seer.less'; @import './modal/style/themes/seer.less'; @@ -61,6 +62,7 @@ @import './table/style/themes/seer.less'; @import './tabs/style/themes/seer.less'; @import './tag/style/themes/seer.less'; +@import './text/style/themes/seer.less'; @import './textarea/style/themes/seer.less'; @import './time-picker/style/themes/seer.less'; @import './timeline/style/themes/seer.less'; @@ -71,4 +73,3 @@ @import './typography/style/themes/seer.less'; @import './upload/style/themes/seer.less'; @import './watermark/style/themes/seer.less'; -@import './loading-bar/style/themes/seer.less'; diff --git a/packages/components/style/variable/prefix.less b/packages/components/style/variable/prefix.less index 176d0586c..bf17aefa0 100644 --- a/packages/components/style/variable/prefix.less +++ b/packages/components/style/variable/prefix.less @@ -6,6 +6,7 @@ @icon-prefix: ~'@{idux-prefix}-icon'; @tag-prefix: ~'@{idux-prefix}-tag'; @tag-group-prefix: ~'@{idux-prefix}-tag-group'; +@text-prefix: ~'@{idux-prefix}-text'; @typography-prefix: ~'@{idux-prefix}-typography'; // Layout diff --git a/packages/components/table/docs/Theme.zh.md b/packages/components/table/docs/Theme.zh.md index c7dd0a405..f171799da 100644 --- a/packages/components/table/docs/Theme.zh.md +++ b/packages/components/table/docs/Theme.zh.md @@ -24,5 +24,5 @@ | `@table-body-row-background-color-hover` | `var(--ix-background-color-light)` | - | - | | `@table-body-row-background-color-selected` | `var(--ix-color-primary-l50)` | `var(--ix-background-color)` | - | | `@table-expandable-icon-color` | `var(--ix-text-color-secondary)` | `@color-graphite-l10` | - | -| `@table-expandable-background-color` | `var(--ix-background-color-light)` | - | - | -| `@table-expandable-background-color-hover` | `var(--ix-background-color-medium)` | - | - | +| `@table-expandable-background-color` | `@table-body-row-background-color-hover` | - | - | +| `@table-expandable-background-color-hover` | `@table-body-row-background-color-hover` | - | - | diff --git a/packages/components/tabs/docs/Theme.zh.md b/packages/components/tabs/docs/Theme.zh.md index 21d90377a..c9f4d7228 100644 --- a/packages/components/tabs/docs/Theme.zh.md +++ b/packages/components/tabs/docs/Theme.zh.md @@ -21,7 +21,6 @@ | `@tabs-nav-tab-text-color` | `@color-graphite-d40` | - | - | | `@tabs-nav-bar-color` | `@color-primary` | - | - | | `@tabs-nav-bar-height` | `2px` | - | - | -| `@tabs-nav-pre-next-width` | `20px` | - | - | | `@tabs-border-radius` | `2px` | - | - | | `@tabs-pane-min-width` | `72px` | - | - | | `@tabs-pane-padding` | `16px` | - | - | diff --git a/packages/components/text/__tests__/__snapshots__/text.spec.ts.snap b/packages/components/text/__tests__/__snapshots__/text.spec.ts.snap new file mode 100644 index 000000000..9f4eba225 --- /dev/null +++ b/packages/components/text/__tests__/__snapshots__/text.spec.ts.snap @@ -0,0 +1,61 @@ +// Vitest Snapshot v1 + +exports[`Text > copyable work 1`] = ` +"
@idux 是一套企业级中后台 UI 组件库, 致力于提供高效愉悦的开发体验。 基于 Vue 3.x + TypeScript 开发, + 全部代码开源并遵循 MIT 协议,任何企业、组织及个人均可免费使用。
" +`; + +exports[`Text > copyable work 2`] = ` +"@idux 是一套企业级中后台 UI 组件库, 致力于提供高效愉悦的开发体验。 基于 Vue 3.x + TypeScript 开发, + 全部代码开源并遵循 MIT 协议,任何企业、组织及个人均可免费使用。" +`; + +exports[`Text > expandable work 1`] = ` +"@idux 是一套企业级中后台 UI 组件库, 致力于提供高效愉悦的开发体验。 基于 Vue 3.x + TypeScript 开发, + 全部代码开源并遵循 MIT 协议,任何企业、组织及个人均可免费使用。" +`; + +exports[`Text > expandable work 2`] = ` +"@idux 是一套企业级中后台 UI 组件库, 致力于提供高效愉悦的开发体验。 基于 Vue 3.x + TypeScript 开发, + 全部代码开源并遵循 MIT 协议,任何企业、组织及个人均可免费使用。" +`; + +exports[`Text > lineClamp work 1`] = ` +"@idux 是一套企业级中后台 UI 组件库, 致力于提供高效愉悦的开发体验。 基于 Vue 3.x + TypeScript 开发, + 全部代码开源并遵循 MIT 协议,任何企业、组织及个人均可免费使用。" +`; + +exports[`Text > lineClamp work 2`] = ` +"@idux 是一套企业级中后台 UI 组件库, 致力于提供高效愉悦的开发体验。 基于 Vue 3.x + TypeScript 开发, + 全部代码开源并遵循 MIT 协议,任何企业、组织及个人均可免费使用。" +`; + +exports[`Text > render work 1`] = ` +"@idux 是一套企业级中后台 UI 组件库, 致力于提供高效愉悦的开发体验。 基于 Vue 3.x + TypeScript 开发, + 全部代码开源并遵循 MIT 协议,任何企业、组织及个人均可免费使用。" +`; + +exports[`Text > tag work 1`] = ` +"
@idux 是一套企业级中后台 UI 组件库, 致力于提供高效愉悦的开发体验。 基于 Vue 3.x + TypeScript 开发, + 全部代码开源并遵循 MIT 协议,任何企业、组织及个人均可免费使用。
" +`; + +exports[`Text > tag work 2`] = ` +"@idux 是一套企业级中后台 UI 组件库, 致力于提供高效愉悦的开发体验。 基于 Vue 3.x + TypeScript 开发, + 全部代码开源并遵循 MIT 协议,任何企业、组织及个人均可免费使用。" +`; + +exports[`Text > tooltip work 1`] = ` +"@idux 是一套企业级中后台 UI 组件库, 致力于提供高效愉悦的开发体验。 基于 Vue 3.x + TypeScript 开发, + 全部代码开源并遵循 MIT 协议,任何企业、组织及个人均可免费使用。" +`; + +exports[`Text > tooltip work 2`] = ` +"@idux 是一套企业级中后台 UI 组件库, 致力于提供高效愉悦的开发体验。 基于 Vue 3.x + TypeScript 开发, + 全部代码开源并遵循 MIT 协议,任何企业、组织及个人均可免费使用。" +`; + +exports[`Text > tooltip work 3`] = ` +"@idux 是一套企业级中后台 UI 组件库, 致力于提供高效愉悦的开发体验。 基于 Vue 3.x + TypeScript 开发, + 全部代码开源并遵循 MIT 协议,任何企业、组织及个人均可免费使用。" +`; diff --git a/packages/components/text/__tests__/text.spec.ts b/packages/components/text/__tests__/text.spec.ts new file mode 100644 index 000000000..1960fd739 --- /dev/null +++ b/packages/components/text/__tests__/text.spec.ts @@ -0,0 +1,91 @@ +import { MountingOptions, mount } from '@vue/test-utils' + +import { renderWork } from '@tests' + +import Text from '../src/Text' +import { TextProps } from '../src/types' + +const defaultSlot = + () => `@idux 是一套企业级中后台 UI 组件库, 致力于提供高效愉悦的开发体验。 基于 Vue 3.x + TypeScript 开发, + 全部代码开源并遵循 MIT 协议,任何企业、组织及个人均可免费使用。` + +describe('Text', () => { + const TextMount = (options?: MountingOptions>) => { + const { slots } = options || {} + return mount(Text, { ...(options as MountingOptions), slots: { default: defaultSlot, ...slots } }) + } + + renderWork(Text, { + slots: { default: defaultSlot }, + }) + + test('copyable work', async () => { + const wrapper = TextMount({ props: { copyable: true } }) + + expect(wrapper.html()).toMatchSnapshot() + expect(wrapper.classes()).toContain('ix-text-wrapper') + + document.execCommand = vi.fn().mockReturnValue(true) + await wrapper.find('.ix-text-copy-icon').trigger('click') + + expect(document.execCommand).toHaveBeenCalledWith('copy') + + await wrapper.setProps({ copyable: false }) + + expect(wrapper.html()).toMatchSnapshot() + expect(wrapper.classes()).not.toContain('ix-text-wrapper') + expect(wrapper.classes()).toContain('ix-text') + }) + + // 需要 E2E 测试 + test('expandable work', async () => { + const wrapper = TextMount({ props: { lineClamp: 2, expandable: true } }) + + expect(wrapper.html()).toMatchSnapshot() + + await wrapper.trigger('click') + + expect(wrapper.html()).toMatchSnapshot() + }) + + test('lineClamp work', async () => { + const wrapper = TextMount({ props: { lineClamp: 2 } }) + + expect(wrapper.html()).toMatchSnapshot() + expect(wrapper.classes()).toContain('ix-text-line-clamp') + + await wrapper.setProps({ lineClamp: undefined }) + + expect(wrapper.html()).toMatchSnapshot() + expect(wrapper.classes()).not.toContain('ix-text-line-clamp') + }) + + test('tag work', async () => { + const wrapper = TextMount({ props: { tag: 'div' } }) + + expect(wrapper.html()).toMatchSnapshot() + expect(wrapper.element.tagName).toBe('DIV') + + await wrapper.setProps({ tag: undefined }) + + expect(wrapper.html()).toMatchSnapshot() + expect(wrapper.element.tagName).toBe('SPAN') + }) + + test('tooltip work', async () => { + const wrapper = TextMount({ props: { tooltip: 'native' } }) + + // 无效 + await wrapper.trigger('mouseenter') + + expect(wrapper.html()).toMatchSnapshot() + + await wrapper.setProps({ tooltip: true }) + + expect(wrapper.html()).toMatchSnapshot() + + await wrapper.setProps({ tooltip: false }) + + expect(wrapper.html()).toMatchSnapshot() + }) +}) diff --git a/packages/components/text/demo/Basic.md b/packages/components/text/demo/Basic.md new file mode 100644 index 000000000..0ddf241aa --- /dev/null +++ b/packages/components/text/demo/Basic.md @@ -0,0 +1,14 @@ +--- +order: 0 +title: + zh: 基本使用 + en: Basic usage +--- + +## zh + +最简单的用法。 + +## en + +The simplest usage. diff --git a/packages/components/text/demo/Basic.vue b/packages/components/text/demo/Basic.vue new file mode 100644 index 000000000..0b918b86f --- /dev/null +++ b/packages/components/text/demo/Basic.vue @@ -0,0 +1,5 @@ + diff --git a/packages/components/text/demo/Copyable.md b/packages/components/text/demo/Copyable.md new file mode 100644 index 000000000..544869412 --- /dev/null +++ b/packages/components/text/demo/Copyable.md @@ -0,0 +1,14 @@ +--- +order: 2 +title: + zh: 可复制 + en: Copyable +--- + +## zh + +提供了简单的文本复制能力,需要注意的是,内容只能是纯文本。 + +## en + +The simplest usage. diff --git a/packages/components/text/demo/Copyable.vue b/packages/components/text/demo/Copyable.vue new file mode 100644 index 000000000..e5246e5d1 --- /dev/null +++ b/packages/components/text/demo/Copyable.vue @@ -0,0 +1,5 @@ + diff --git a/packages/components/text/demo/Expandable.md b/packages/components/text/demo/Expandable.md new file mode 100644 index 000000000..0179ab1d3 --- /dev/null +++ b/packages/components/text/demo/Expandable.md @@ -0,0 +1,14 @@ +--- +order: 8 +title: + zh: 可展开的 + en: Expandable +--- + +## zh + +搭配 `lineClamp` 使用时,可以通过点击展开全部文本。 + +## en + +The simplest usage. diff --git a/packages/components/text/demo/Expandable.vue b/packages/components/text/demo/Expandable.vue new file mode 100644 index 000000000..05587011c --- /dev/null +++ b/packages/components/text/demo/Expandable.vue @@ -0,0 +1,8 @@ + diff --git a/packages/components/text/demo/LineClamp.md b/packages/components/text/demo/LineClamp.md new file mode 100644 index 000000000..b6fc7bc94 --- /dev/null +++ b/packages/components/text/demo/LineClamp.md @@ -0,0 +1,14 @@ +--- +order: 6 +title: + zh: 多行省略 + en: Basic usage +--- + +## zh + +提供基于 `-webkit-line-clamp` 的多行省略,兼容性参见 [caniuse](https://caniuse.com/?search=line-clamp) + +## en + +The simplest usage. diff --git a/packages/components/text/demo/LineClamp.vue b/packages/components/text/demo/LineClamp.vue new file mode 100644 index 000000000..74dc8b97f --- /dev/null +++ b/packages/components/text/demo/LineClamp.vue @@ -0,0 +1,8 @@ + diff --git a/packages/components/text/demo/Tooltip.md b/packages/components/text/demo/Tooltip.md new file mode 100644 index 000000000..3eb299e55 --- /dev/null +++ b/packages/components/text/demo/Tooltip.md @@ -0,0 +1,15 @@ +--- +order: 10 +title: + zh: 浮层配置 + en: Tooltip +--- + +## zh + +可以通过 `tooltip` 来配置悬浮提示,还可以通过 `title` 插槽来自定义提示内容。 +注意:当 `tooltip='native'` 时,`title` 插槽仅支持纯文本内容。 + +## en + +The simplest usage. diff --git a/packages/components/text/demo/Tooltip.vue b/packages/components/text/demo/Tooltip.vue new file mode 100644 index 000000000..c632e3dd6 --- /dev/null +++ b/packages/components/text/demo/Tooltip.vue @@ -0,0 +1,24 @@ + + + diff --git a/packages/components/text/docs/Api.en.md b/packages/components/text/docs/Api.en.md new file mode 100644 index 000000000..6ab9c55e5 --- /dev/null +++ b/packages/components/text/docs/Api.en.md @@ -0,0 +1,19 @@ +### IxText + +#### TextProps + +| Name | Description | Type | Default | Global Config | Remark | +| --- | --- | --- | --- | --- | --- | +| - | - | - | - | ✅ | - | + +#### TextSlots + +| Name | Description | Parameter Type | Remark | +| --- | --- | --- | --- | +| - | - | - | - | + +#### TextMethods + +| Name | Description | Parameter Type | Remark | +| --- | --- | --- | --- | +| - | - | - | - | diff --git a/packages/components/text/docs/Api.zh.md b/packages/components/text/docs/Api.zh.md new file mode 100644 index 000000000..ff420cc7d --- /dev/null +++ b/packages/components/text/docs/Api.zh.md @@ -0,0 +1,18 @@ +### IxText + +#### TextProps + +| 名称 | 说明 | 类型 | 默认值 | 全局配置 | 备注 | +| --- | --- | --- | --- | --- | --- | +| `copyable` | 点击图标可复制文本 | `boolean` | `false` | - | 仅支持普通文本 | +| `expandable` | 点击可展开文本 | `boolean` | `false` | - | 建议搭配 `lineClamp` 一起使用 | +| `lineClamp` | 多行省略 | `string \| number` | - | - | 基于 `-webkit-line-clamp` 的多行省略,兼容性参见 [caniuse](https://caniuse.com/?search=line-clamp) | +| `tag` | 渲染的标签名 | `string \| Component` | `span` | - | - | +| `tooltip` | 浮层配置 | `boolean \| 'native' \| TooltipProps` | `true` | - | 为 `native` 时展示原生提示,此时的提示内容仅支持普通文本 | + +#### TextSlots + +| 名称 | 说明 | 参数类型 | 备注 | +| --- | --- | --- | --- | +| `title` | 自定义提示的内容 | - | - | +| `copyIcon` | 自定义复制图表 | `{ copied: boolean }` | - | diff --git a/packages/components/text/docs/Index.en.md b/packages/components/text/docs/Index.en.md new file mode 100644 index 000000000..4720bc6c8 --- /dev/null +++ b/packages/components/text/docs/Index.en.md @@ -0,0 +1,8 @@ +--- +category: components +type: General +order: 0 +title: Text +subtitle: +--- + diff --git a/packages/components/text/docs/Index.zh.md b/packages/components/text/docs/Index.zh.md new file mode 100644 index 000000000..43f9f9bbf --- /dev/null +++ b/packages/components/text/docs/Index.zh.md @@ -0,0 +1,9 @@ +--- +category: components +type: 通用 +order: 0 +title: Text +subtitle: 文本 +theme: true +--- + diff --git a/packages/components/text/docs/Theme.en.md b/packages/components/text/docs/Theme.en.md new file mode 100644 index 000000000..06e4c3fce --- /dev/null +++ b/packages/components/text/docs/Theme.en.md @@ -0,0 +1,3 @@ +| name | default | seer | mark | +| --- | --- | --- | --- | +| - | - | - | - | diff --git a/packages/components/text/docs/Theme.zh.md b/packages/components/text/docs/Theme.zh.md new file mode 100644 index 000000000..957cc1a90 --- /dev/null +++ b/packages/components/text/docs/Theme.zh.md @@ -0,0 +1,4 @@ +| 名称 | default | seer | 备注 | +| --- | --- | --- | --- | +| `@text-copy-icon-font-size` | `var(--ix-font-size-lg)` | - | - | +| `@text-copy-icon-color` | `var(--ix-color-primary)` | - | - | diff --git a/packages/components/text/index.ts b/packages/components/text/index.ts new file mode 100644 index 000000000..22845806d --- /dev/null +++ b/packages/components/text/index.ts @@ -0,0 +1,16 @@ +/** + * @license + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE + */ + +import type { TextComponent } from './src/types' + +import Text from './src/Text' + +const IxText = Text as unknown as TextComponent + +export { IxText } + +export type { TextInstance, TextComponent, TextPublicProps as TextProps } from './src/types' diff --git a/packages/components/text/src/Text.tsx b/packages/components/text/src/Text.tsx new file mode 100644 index 000000000..2f232301f --- /dev/null +++ b/packages/components/text/src/Text.tsx @@ -0,0 +1,157 @@ +/** + * @license + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE + */ + +import { type Slot, computed, defineComponent, normalizeClass, shallowRef } from 'vue' + +import { isObject, isString, throttle } from 'lodash-es' + +import { useClipboard } from '@idux/cdk/clipboard' +import { getFirstValidNode, useState } from '@idux/cdk/utils' +import { useGlobalConfig } from '@idux/components/config' +import { IxIcon } from '@idux/components/icon' +import { IxTooltip } from '@idux/components/tooltip' + +import { textProps } from './types' + +export default defineComponent({ + name: 'IxText', + inheritAttrs: false, + props: textProps, + setup(props, { attrs, slots }) { + const common = useGlobalConfig('common') + const mergedPrefixCls = computed(() => `${common.prefixCls}-text`) + + const elementRef = shallowRef() + const [mergedDisabled, setDisabled] = useState(true) + const [mergedEntered, setEntered] = useState(false) + const [mergedExpanded, setExpanded] = useState(false) + const [mergedCopied, setCopied] = useState(false) + + const { copy } = useClipboard() + + const checkDisabled = () => { + const element = elementRef.value + if (mergedExpanded.value || !element) { + return true + } + + const { lineClamp } = props + if (lineClamp !== undefined) { + return element.scrollHeight <= element.offsetHeight + } else { + const currOverflow = element.style.overflow + if (!currOverflow || currOverflow === 'visible') { + element.style.overflow = 'hidden' + } + const isOverflowing = element.clientWidth < element.scrollWidth || element.clientHeight < element.scrollHeight + element.style.overflow = currOverflow + return !isOverflowing + } + } + + const onClick = () => { + const nextExpanded = !mergedExpanded.value + setExpanded(nextExpanded) + setDisabled(nextExpanded) + } + + const onMouseEnter = () => { + setEntered(true) + setDisabled(checkDisabled()) + } + + const onCopy = throttle((text: string) => { + if (!text || mergedCopied.value) { + return + } + copy(text).then(success => { + if (success) { + setCopied(true) + setTimeout(() => setCopied(false), 3000) + } + }) + }, 300) + + const classes = computed(() => { + const prefixCls = mergedPrefixCls.value + const { lineClamp } = props + return normalizeClass({ + [prefixCls]: true, + [`${prefixCls}-line-clamp`]: lineClamp !== undefined, + }) + }) + + const style = computed(() => { + const { expandable, lineClamp } = props + const expanded = mergedExpanded.value + return { + cursor: expandable ? 'pointer' : '', + 'text-overflow': !expanded && lineClamp === undefined ? 'ellipsis' : '', + '-webkit-line-clamp': !expanded && lineClamp !== undefined ? lineClamp : '', + } + }) + + return () => { + const { tag: Tag, tooltip, expandable, copyable } = props + const prefixCls = mergedPrefixCls.value + const disabled = mergedDisabled.value + const entered = mergedEntered.value + const isNative = tooltip === 'native' + const titleSlot = slots.title || slots.default + + let node = ( + + {slots.default?.()} + + ) + + if (!disabled && entered && tooltip && !isNative) { + const tooltipProps = isObject(tooltip) ? { ...tooltip, disabled } : { disabled } + node = ( + + {node} + + ) + } + + if (copyable) { + const copied = mergedCopied.value + const copyIcon = slots.copyIcon ? slots.copyIcon({ copied }) : + node = ( +
+ {node} + onCopy(getStringBySlot(slots.default))}> + {copyIcon} + +
+ ) + } + + return node + } + }, +}) + +function getStringBySlot(slot: Slot | undefined) { + const validNode = getFirstValidNode(slot?.()) + if (!validNode) { + return '' + } + const { children } = validNode + if (isString(children)) { + return children + } + return '' +} diff --git a/packages/components/text/src/types.ts b/packages/components/text/src/types.ts new file mode 100644 index 000000000..1a008aca5 --- /dev/null +++ b/packages/components/text/src/types.ts @@ -0,0 +1,23 @@ +/** + * @license + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE + */ + +import type { ExtractInnerPropTypes, ExtractPublicPropTypes } from '@idux/cdk/utils' +import type { TooltipProps } from '@idux/components/tooltip' +import type { Component, DefineComponent, HTMLAttributes, PropType } from 'vue' + +export const textProps = { + copyable: { type: Boolean, default: false }, + expandable: { type: Boolean, default: false }, + lineClamp: { type: [String, Number] as PropType, default: undefined }, + tag: { type: [String, Object] as PropType, default: 'span' }, + tooltip: { type: [Boolean, String, Object] as PropType, default: true }, +} as const + +export type TextProps = ExtractInnerPropTypes +export type TextPublicProps = ExtractPublicPropTypes +export type TextComponent = DefineComponent & TextPublicProps> +export type TextInstance = InstanceType> diff --git a/packages/components/text/style/index.less b/packages/components/text/style/index.less new file mode 100644 index 000000000..516f9c478 --- /dev/null +++ b/packages/components/text/style/index.less @@ -0,0 +1,37 @@ +@import '../../style/mixins/reset.less'; + +.@{text-prefix} { + .reset-component-new(); + .reset-font-size(); + + overflow: hidden; + + &-line-clamp { + display: inline-box; + -webkit-box-orient: vertical; + } + + &:not(&-line-clamp) { + display: inline-block; + vertical-align: bottom; + white-space: nowrap; + max-width: 100%; + } + + &-copy-icon { + margin-left: 2px; + padding: 2px; + line-height: 1; + font-size: @text-copy-icon-font-size; + color: @text-copy-icon-color; + cursor: pointer; + } + + &-wrapper { + .reset-component-new(); + + display: inline-flex; + align-items: center; + max-width: 100%; + } +} diff --git a/packages/components/text/style/themes/default.less b/packages/components/text/style/themes/default.less new file mode 100644 index 000000000..a66443560 --- /dev/null +++ b/packages/components/text/style/themes/default.less @@ -0,0 +1,4 @@ +@import '../../../style/themes/default.less'; +@import './default.variable.less'; + +@import '../index.less'; diff --git a/packages/components/text/style/themes/default.ts b/packages/components/text/style/themes/default.ts new file mode 100644 index 000000000..215f89b3f --- /dev/null +++ b/packages/components/text/style/themes/default.ts @@ -0,0 +1,5 @@ +// style dependencies +import '@idux/components/icon/style/themes/default' +import '@idux/components/tooltip/style/themes/default' + +import './default.less' diff --git a/packages/components/text/style/themes/default.variable.less b/packages/components/text/style/themes/default.variable.less new file mode 100644 index 000000000..af748b69e --- /dev/null +++ b/packages/components/text/style/themes/default.variable.less @@ -0,0 +1,2 @@ +@text-copy-icon-font-size: var(--ix-font-size-lg); +@text-copy-icon-color: var(--ix-color-primary); diff --git a/packages/components/text/style/themes/seer.less b/packages/components/text/style/themes/seer.less new file mode 100644 index 000000000..32bf707c1 --- /dev/null +++ b/packages/components/text/style/themes/seer.less @@ -0,0 +1,4 @@ +@import '../../../style/themes/seer.less'; +@import './seer.variable.less'; + +@import '../index.less'; diff --git a/packages/components/text/style/themes/seer.ts b/packages/components/text/style/themes/seer.ts new file mode 100644 index 000000000..659f933e7 --- /dev/null +++ b/packages/components/text/style/themes/seer.ts @@ -0,0 +1,5 @@ +// style dependencies +import '@idux/components/icon/style/themes/seer' +import '@idux/components/tooltip/style/themes/seer' + +import './seer.less' diff --git a/packages/components/text/style/themes/seer.variable.less b/packages/components/text/style/themes/seer.variable.less new file mode 100644 index 000000000..498793af1 --- /dev/null +++ b/packages/components/text/style/themes/seer.variable.less @@ -0,0 +1 @@ +@import './default.variable.less'; diff --git a/packages/components/types.d.ts b/packages/components/types.d.ts index f5cfaf0f2..0e770cf7f 100644 --- a/packages/components/types.d.ts +++ b/packages/components/types.d.ts @@ -78,6 +78,7 @@ import type { SwitchComponent } from '@idux/components/switch' import type { TableColumnComponent, TableComponent } from '@idux/components/table' import type { TabComponent, TabsComponent } from '@idux/components/tabs' import type { TagComponent, TagGroupComponent } from '@idux/components/tag' +import type { TextComponent } from '@idux/components/text' import type { TextareaComponent } from '@idux/components/textarea' import type { TimePickerComponent, TimeRangePickerComponent } from '@idux/components/time-picker' import type { TimelineComponent, TimelineItemComponent } from '@idux/components/timeline' @@ -177,6 +178,7 @@ declare module 'vue' { IxTabs: TabsComponent IxTag: TagComponent IxTagGroup: TagGroupComponent + IxText: TextComponent IxTextarea: TextareaComponent IxTimeline: TimelineComponent IxTimelineItem: TimelineItemComponent