diff --git a/packages/components/button/README.md b/packages/components/button/README.md index 9066b9e57..2dd324a17 100644 --- a/packages/components/button/README.md +++ b/packages/components/button/README.md @@ -5,7 +5,7 @@ spline: base isComponent: true --- - + ## 引入 全局引入,在 miniprogram 根目录下的`app.json`中配置,局部引入,在需要引入的页面或组件的`index.json`中配置。 diff --git a/packages/components/dropdown-menu/README.md b/packages/components/dropdown-menu/README.md index 7b7db3d69..0d15aaab7 100644 --- a/packages/components/dropdown-menu/README.md +++ b/packages/components/dropdown-menu/README.md @@ -13,7 +13,7 @@ isComponent: true 该组件于 0.8.0 版本上线,请留意版本。 - + ## 引入 ### 引入组件 diff --git a/packages/components/icon/README.md b/packages/components/icon/README.md index abcf3e33f..0d08390de 100644 --- a/packages/components/icon/README.md +++ b/packages/components/icon/README.md @@ -12,9 +12,9 @@ isComponent: true 打开 TDesign 图标独立站点 查看全部支持的图标。 - + ## 引入 全局引入,在 miniprogram 根目录下的`app.json`中配置,局部引入,在需要引入的页面或组件的`index.json`中配置。 diff --git a/packages/components/paragraph/README.en-US.md b/packages/components/paragraph/README.en-US.md new file mode 100644 index 000000000..623d3da44 --- /dev/null +++ b/packages/components/paragraph/README.en-US.md @@ -0,0 +1,62 @@ +:: BASE_DOC :: + +## API + + +### Paragraph Props + +name | type | default | description | required +-- | -- | -- | -- | -- +style | Object | - | CSS(Cascading Style Sheets) | N +custom-style | Object | - | CSS(Cascading Style Sheets),used to set style on virtual component | N +content | String | - | content of paragraph | N +ellipsis | Boolean / Object | false | add ellipsis style。Typescript: `boolean \| TypographyEllipsis `,[Text API Documents](./text?tab=api)。[see more ts definition](https://github.com/Tencent/tdesign-miniprogram/blob/develop/packages/components/paragraph/type.ts) | N + +### Paragraph Slots + +name | Description +-- | -- +content | content of paragraph + + +### Text Props + +name | type | default | description | required +-- | -- | -- | -- | -- +style | Object | - | CSS(Cascading Style Sheets) | N +custom-style | Object | - | CSS(Cascading Style Sheets),used to set style on virtual component | N +code | Boolean | false | add code style | N +content | String | - | content of text | N +copyable | Boolean / Object | false | Whether copyable. When value is null, the copyable slot is enabled for custom copy icon. Typescript: `boolean \| TypographyCopyable \| null` `interface TypographyCopyable { text?: string }`。[see more ts definition](https://github.com/Tencent/tdesign-miniprogram/blob/develop/packages/components/text/type.ts) | N +delete | Boolean | false | add delete line style | N +disabled | Boolean | false | add disabled style | N +ellipsis | Boolean / Object | false | add ellipsis style。Typescript: `boolean \| TypographyEllipsis ` `interface TypographyEllipsis { collapsible?: boolean; expandable?: boolean; row?: number;}`。[see more ts definition](https://github.com/Tencent/tdesign-miniprogram/blob/develop/packages/components/text/type.ts) | N +italic | Boolean | false | add italic style | N +keyboard | Boolean | false | add keyboard style | N +mark | String / Boolean | false | add mark style | N +strong | Boolean | false | add bold style | N +theme | String | - | theme of text。options: primary/secondary/success/warning/error | N +underline | Boolean | false | add underline style | N + +### Text Slots + +name | Description +-- | -- +content | content of text + + +### Title Props + +name | type | default | description | required +-- | -- | -- | -- | -- +style | Object | - | CSS(Cascading Style Sheets) | N +custom-style | Object | - | CSS(Cascading Style Sheets),used to set style on virtual component | N +content | String | - | content of title | N +ellipsis | Boolean / Object | false | add ellipsis style。Typescript: `boolean \| TypographyEllipsis `,[Text API Documents](./text?tab=api)。[see more ts definition](https://github.com/Tencent/tdesign-miniprogram/blob/develop/packages/components/title/type.ts) | N +level | String | h1 | level of title。options: h1/h2/h3/h4/h5/h6 | N + +### Title Slots + +name | Description +-- | -- +content | content of title diff --git a/packages/components/paragraph/README.md b/packages/components/paragraph/README.md new file mode 100644 index 000000000..f7b3b10c6 --- /dev/null +++ b/packages/components/paragraph/README.md @@ -0,0 +1,117 @@ +--- +title: Typography 排版 +description: 排版用于文本基础编排和样式,使用排版组件,可以快速完成页面中的文本内容制作,同时配合其他组件完成深色与浅色模式切换等风格统一的需求。 +isComponent: true +spline: base +--- + + +
+ + + + 该组件于 1.15.0 版本上线,请留意版本。 +
+ + +## 引入 + +全局引入,在 miniprogram 根目录下的`app.json`中配置,局部引入,在需要引入的页面或组件的`index.json`中配置。 + +```json +"usingComponents": { + "t-paragraph": "tdesign-miniprogram/paragraph/paragraph", + "t-text": "tdesign-miniprogram/text/text", + "t-title": "tdesign-miniprogram/title/title" +} +``` + +## 代码演示 + + 在开发者工具中预览效果 + +
+

Tips: 请确保开发者工具为打开状态。导入开发者工具后,依次执行:npm i > 构建npm包 > 勾选 "将JS编译成ES5"

+
+ +### 基础文本 + +{{ base }} + +### 组合用法 + +{{ combination }} + +### 主题样式 + +{{ theme }} + +### 可复制 + +{{ copyable }} + +### 文本省略 + +{{ ellipsis }} + + +## API + + +### Paragraph Props + +名称 | 类型 | 默认值 | 描述 | 必传 +-- | -- | -- | -- | -- +style | Object | - | 样式 | N +custom-style | Object | - | 样式,一般用于开启虚拟化组件节点场景 | N +content | String | - | 段落内容 | N +ellipsis | Boolean / Object | false | 是否省略展示,可通过配置参数自定义省略操作的具体功能和样式。TS 类型:`boolean \| TypographyEllipsis `,[Text API Documents](./text?tab=api)。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/blob/develop/packages/components/paragraph/type.ts) | N + +### Paragraph Slots + +名称 | 描述 +-- | -- +content | 自定义 `content` 显示内容 + + +### Text Props + +名称 | 类型 | 默认值 | 描述 | 必传 +-- | -- | -- | -- | -- +style | Object | - | 样式 | N +custom-style | Object | - | 样式,一般用于开启虚拟化组件节点场景 | N +code | Boolean | false | 是否添加代码样式 | N +content | String | - | 文本内容 | N +copyable | Boolean / Object | false | 是否可复制,值为 null 时表示使用 copyable 插槽自定义复制图标。TS 类型:`boolean \| TypographyCopyable \| null` `interface TypographyCopyable { text?: string }`。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/blob/develop/packages/components/text/type.ts) | N +delete | Boolean | false | 是否添加删除线样式 | N +disabled | Boolean | false | 是否添加不可用样式 | N +ellipsis | Boolean / Object | false | 是否省略展示,可通过配置参数自定义省略操作的具体功能和样式。TS 类型:`boolean \| TypographyEllipsis ` `interface TypographyEllipsis { collapsible?: boolean; expandable?: boolean; row?: number;}`。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/blob/develop/packages/components/text/type.ts) | N +italic | Boolean | false | 文本是否为斜体 | N +keyboard | Boolean | false | 是否添加键盘样式 | N +mark | String / Boolean | false | 是否添加标记样式,默认为黄色,可通过配置颜色修改标记样式,如#0052D9 | N +strong | Boolean | false | 文本是否加粗 | N +theme | String | - | 主题。可选项:primary/secondary/success/warning/error | N +underline | Boolean | false | 是否添加下划线样式 | N + +### Text Slots + +名称 | 描述 +-- | -- +content | 自定义 `content` 显示内容 + + +### Title Props + +名称 | 类型 | 默认值 | 描述 | 必传 +-- | -- | -- | -- | -- +style | Object | - | 样式 | N +custom-style | Object | - | 样式,一般用于开启虚拟化组件节点场景 | N +content | String | - | 段落内容 | N +ellipsis | Boolean / Object | false | 是否省略展示,可通过配置参数自定义省略操作的具体功能和样式。TS 类型:`boolean \| TypographyEllipsis `,[Text API Documents](./text?tab=api)。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/blob/develop/packages/components/title/type.ts) | N +level | String | h1 | 标题等级。可选项:h1/h2/h3/h4/h5/h6 | N + +### Title Slots + +名称 | 描述 +-- | -- +content | 自定义 `content` 显示内容 diff --git a/packages/components/paragraph/__test__/__snapshots__/demo.test.js.snap b/packages/components/paragraph/__test__/__snapshots__/demo.test.js.snap new file mode 100644 index 000000000..7196a3d88 --- /dev/null +++ b/packages/components/paragraph/__test__/__snapshots__/demo.test.js.snap @@ -0,0 +1,237 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Paragraph Paragraph base demo works fine 1`] = ` + + + + + +`; + +exports[`Paragraph Paragraph combination demo works fine 1`] = ` + + + + + + + + TDesign features a unified design values, consistent design language, and visual style, helping users form + continuous and coherent perceptions of the experience. + + + + Based on this, TDesign offers out-typography-of-the-box UI component libraries, design guidelines, and design + assets, elegantly and efficiently freeing design and development from repetitive tasks. Simultaneously, it + facilitates easy extension on top of TDesign, enabling a better alignment with business requirements. + + + + Comprehensive + + + + TDesign Support + + + Vue 2 + + , + + Vue 3 + + , + + + React + + + components for Desktop Application and + + + Vue 3 + + , + + + Wechat MiniProgram + + + components for Mobile Application. + + + + + • Features + + + • Comprehensive + + + • Consistency + + + • Usability + + + • Join TDesign + + + + + 1. Features + + + 2. Comprehensive + + + 1. Consistency + + + 2. Usability + + + 3. Join TDesign + + + + +`; + +exports[`Paragraph Paragraph copyable demo works fine 1`] = ` + + + + + + + + + + +`; + +exports[`Paragraph Paragraph ellipsis demo works fine 1`] = ` + + + + + + + + + + + + + +`; + +exports[`Paragraph Paragraph theme demo works fine 1`] = ` + + + + + + + + + +`; diff --git a/packages/components/paragraph/__test__/demo.test.js b/packages/components/paragraph/__test__/demo.test.js new file mode 100644 index 000000000..5634d74f3 --- /dev/null +++ b/packages/components/paragraph/__test__/demo.test.js @@ -0,0 +1,19 @@ +/** + * 该文件为由脚本 `npm run test:demo` 自动生成,如需修改,执行脚本命令即可。请勿手写直接修改,否则会被覆盖 + */ + +import path from 'path'; +import simulate from 'miniprogram-simulate'; + +const mapper = ['base', 'combination', 'copyable', 'ellipsis', 'theme']; + +describe('Paragraph', () => { + mapper.forEach((demoName) => { + it(`Paragraph ${demoName} demo works fine`, () => { + const id = load(path.resolve(__dirname, `../../paragraph/_example/${demoName}/index`), demoName); + const container = simulate.render(id); + container.attach(document.createElement('parent-wrapper')); + expect(container.toJSON()).toMatchSnapshot(); + }); + }); +}); diff --git a/packages/components/paragraph/__test__/index.test.js b/packages/components/paragraph/__test__/index.test.js new file mode 100644 index 000000000..7576be5ec --- /dev/null +++ b/packages/components/paragraph/__test__/index.test.js @@ -0,0 +1,283 @@ +import path from 'path'; +import simulate from 'miniprogram-simulate'; +import * as paragraphProps from '../props'; +import * as paragraphType from '../type'; + +describe('paragraph exports', () => { + it(': props module can be loaded', () => { + expect(paragraphProps).toBeDefined(); + }); + + it(': type module can be loaded', () => { + expect(paragraphType).toBeDefined(); + }); +}); + +describe('paragraph', () => { + const Paragraph = load(path.resolve(__dirname, '../paragraph')); + + describe('props', () => { + it(': style && customStyle', async () => { + const id = simulate.load({ + template: ``, + data: { + style: 'color: red', + customStyle: 'font-size: 9px', + }, + usingComponents: { + 't-paragraph': Paragraph, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $paragraph = comp.querySelector('.paragraph >>> .t-typography'); + if (VIRTUAL_HOST) { + expect( + $paragraph.dom.getAttribute('style').includes(`${comp.data.style}; ${comp.data.customStyle}`), + ).toBeTruthy(); + } else { + expect($paragraph.dom.getAttribute('style').includes(`${comp.data.customStyle}`)).toBeTruthy(); + } + }); + + it(': content', () => { + const id = simulate.load({ + template: ``, + data: { + content: 'TDesign 是腾讯各业务团队在服务业务过程中沉淀的一套企业级设计体系。', + }, + usingComponents: { + 't-paragraph': Paragraph, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + expect(comp.querySelector('.paragraph').dom.textContent).toContain(comp.data.content); + }); + + it(': slot content', () => { + const id = simulate.load({ + template: `Slot Content`, + usingComponents: { + 't-paragraph': Paragraph, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + expect(comp.querySelector('.paragraph').dom.textContent).toContain('Slot Content'); + }); + + it(': ellipsis[Boolean]', () => { + const id = simulate.load({ + template: ``, + data: { + content: 'TDesign 秉承开放的设计理念从创立之初就采用开源协作的方式进行设计和开发。', + }, + usingComponents: { + 't-paragraph': Paragraph, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $wrapper = comp.querySelector('.paragraph >>> .t-typography__ellipsis-wrapper'); + expect($wrapper).toBeDefined(); + const $content = comp.querySelector('.paragraph >>> .t-typography__ellipsis-content'); + expect($content).toBeDefined(); + }); + + it(': ellipsis[Object] with row', () => { + const id = simulate.load({ + template: ``, + data: { + content: 'TDesign 秉承开放的设计理念从创立之初就采用开源协作的方式进行设计和开发。', + ellipsis: { row: 3 }, + }, + usingComponents: { + 't-paragraph': Paragraph, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $content = comp.querySelector('.paragraph >>> .t-typography__ellipsis-content'); + expect($content).toBeDefined(); + expect($content.dom.getAttribute('style')).toContain('-webkit-line-clamp:3'); + }); + + it(': ellipsis[Object] with expandable', async () => { + const handleExpand = jest.fn(); + const id = simulate.load({ + template: ``, + data: { + content: 'TDesign 秉承开放的设计理念从创立之初就采用开源协作的方式进行设计和开发。', + ellipsis: { row: 1, expandable: true }, + }, + methods: { + handleExpand, + }, + usingComponents: { + 't-paragraph': Paragraph, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $expandBtn = comp.querySelector('.paragraph >>> .t-typography-ellipsis-symbol'); + expect($expandBtn).toBeDefined(); + expect($expandBtn.dom.textContent).toContain('展开'); + + $expandBtn.dispatchEvent('tap'); + await simulate.sleep(10); + expect(handleExpand).toHaveBeenCalledTimes(1); + }); + + it(': ellipsis[Object] with expandable and collapsible', async () => { + const handleExpand = jest.fn(); + const id = simulate.load({ + template: ``, + data: { + content: 'TDesign 秉承开放的设计理念从创立之初就采用开源协作的方式进行设计和开发。', + ellipsis: { row: 2, expandable: true, collapsible: true }, + }, + methods: { + handleExpand, + }, + usingComponents: { + 't-paragraph': Paragraph, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + // 展开 + const $expandBtn = comp.querySelector('.paragraph >>> .t-typography-ellipsis-symbol'); + $expandBtn.dispatchEvent('tap'); + await simulate.sleep(10); + + // 收起按钮 + const $collapseBtn = comp.querySelector('.paragraph >>> .t-typography-ellipsis-symbol'); + expect($collapseBtn).toBeDefined(); + expect($collapseBtn.dom.textContent).toContain('收起'); + + // 收起 + $collapseBtn.dispatchEvent('tap'); + await simulate.sleep(10); + expect(handleExpand).toHaveBeenCalledTimes(2); + }); + + it(': ellipsis[Object] without expandable does not show button', () => { + const id = simulate.load({ + template: ``, + data: { + content: 'TDesign 秉承开放的设计理念从创立之初就采用开源协作的方式进行设计和开发。', + ellipsis: { row: 2, expandable: false }, + }, + usingComponents: { + 't-paragraph': Paragraph, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $expandBtn = comp.querySelector('.paragraph >>> .t-typography-ellipsis-symbol'); + expect($expandBtn).not.toBeTruthy(); + }); + + it(': ellipsis[Object] with expandable but not collapsible', async () => { + const id = simulate.load({ + template: ``, + data: { + content: 'TDesign 秉承开放的设计理念从创立之初就采用开源协作的方式进行设计和开发。', + ellipsis: { row: 1, expandable: true, collapsible: false }, + }, + usingComponents: { + 't-paragraph': Paragraph, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $expandBtn = comp.querySelector('.paragraph >>> .t-typography-ellipsis-symbol'); + expect($expandBtn).toBeDefined(); + + $expandBtn.dispatchEvent('tap'); + await simulate.sleep(10); + + // 展开后 collapsible=false,不应有收起按钮 + const $paragraph = comp.querySelector('.paragraph'); + expect($paragraph.data.isExpanded).toBe(true); + }); + + it(': ellipsis[Object] with suffix slot', async () => { + const handleExpand = jest.fn(); + const id = simulate.load({ + template: `更多`, + data: { + content: 'TDesign 秉承开放的设计理念从创立之初就采用开源协作的方式进行设计和开发。', + ellipsis: { row: 1, expandable: true, collapsible: false, suffix: true }, + }, + methods: { + handleExpand, + }, + usingComponents: { + 't-paragraph': Paragraph, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $suffixBtn = comp.querySelector('.paragraph >>> .t-typography-ellipsis-symbol'); + expect($suffixBtn).toBeDefined(); + + $suffixBtn.dispatchEvent('tap'); + await simulate.sleep(10); + expect(handleExpand).toHaveBeenCalledTimes(1); + }); + + it(': without ellipsis does not show ellipsis wrapper', () => { + const id = simulate.load({ + template: ``, + usingComponents: { + 't-paragraph': Paragraph, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $wrapper = comp.querySelector('.paragraph >>> .t-typography__ellipsis-wrapper'); + expect($wrapper).not.toBeTruthy(); + }); + + it(': ellipsis expanded removes line clamp style', async () => { + const id = simulate.load({ + template: ``, + data: { + content: 'TDesign 秉承开放的设计理念从创立之初就采用开源协作的方式进行设计和开发。', + ellipsis: { row: 2, expandable: true, collapsible: true }, + }, + usingComponents: { + 't-paragraph': Paragraph, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + // 展开前有 line-clamp 样式 + let $content = comp.querySelector('.paragraph >>> .t-typography__ellipsis-content'); + expect($content.dom.getAttribute('style')).toContain('-webkit-line-clamp:2'); + + // 点击展开 + const $expandBtn = comp.querySelector('.paragraph >>> .t-typography-ellipsis-symbol'); + $expandBtn.dispatchEvent('tap'); + await simulate.sleep(10); + + // 展开后样式应为空(isExpanded = true) + $content = comp.querySelector('.paragraph >>> .t-typography__ellipsis-content'); + expect($content.dom.getAttribute('style')).toBe(''); + }); + }); +}); diff --git a/packages/components/paragraph/__test__/text.test.js b/packages/components/paragraph/__test__/text.test.js new file mode 100644 index 000000000..35c1000bd --- /dev/null +++ b/packages/components/paragraph/__test__/text.test.js @@ -0,0 +1,642 @@ +import path from 'path'; +import simulate from 'miniprogram-simulate'; +import * as textExports from '../../text/index'; + +describe('text exports', () => { + it(': index.ts should export props and type', () => { + expect(textExports).toBeDefined(); + }); +}); + +describe('text', () => { + const Text = load(path.resolve(__dirname, '../../text/text')); + + describe('props', () => { + it(': style && customStyle', async () => { + const id = simulate.load({ + template: ``, + data: { + style: 'color: red', + customStyle: 'font-size: 9px', + }, + usingComponents: { + 't-text': Text, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $text = comp.querySelector('.text >>> .t-typography'); + if (VIRTUAL_HOST) { + expect($text.dom.getAttribute('style').includes(`${comp.data.style}; ${comp.data.customStyle}`)).toBeTruthy(); + } else { + expect($text.dom.getAttribute('style').includes(`${comp.data.customStyle}`)).toBeTruthy(); + } + }); + + it(': content', () => { + const id = simulate.load({ + template: ``, + data: { + content: 'TDesign 是腾讯各业务团队在服务业务过程中沉淀的一套企业级设计体系。', + }, + usingComponents: { + 't-text': Text, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + expect(comp.querySelector('.text').dom.textContent).toContain(comp.data.content); + }); + + it(': code', () => { + const id = simulate.load({ + template: ``, + usingComponents: { + 't-text': Text, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $inner = comp.querySelector('.text >>> .t-typography--code'); + expect($inner).toBeDefined(); + }); + + it(': strong', () => { + const id = simulate.load({ + template: ``, + usingComponents: { + 't-text': Text, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $inner = comp.querySelector('.text >>> .t-typography--strong'); + expect($inner).toBeDefined(); + }); + + it(': italic', () => { + const id = simulate.load({ + template: ``, + usingComponents: { + 't-text': Text, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $inner = comp.querySelector('.text >>> .t-typography--italic'); + expect($inner).toBeDefined(); + }); + + it(': underline', () => { + const id = simulate.load({ + template: ``, + usingComponents: { + 't-text': Text, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $inner = comp.querySelector('.text >>> .t-typography--underline'); + expect($inner).toBeDefined(); + }); + + it(': delete', () => { + const id = simulate.load({ + template: ``, + usingComponents: { + 't-text': Text, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $inner = comp.querySelector('.text >>> .t-typography--delete'); + expect($inner).toBeDefined(); + }); + + it(': keyboard', () => { + const id = simulate.load({ + template: ``, + usingComponents: { + 't-text': Text, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $inner = comp.querySelector('.text >>> .t-typography--keyboard'); + expect($inner).toBeDefined(); + }); + + it(': mark[Boolean]', () => { + const id = simulate.load({ + template: ``, + usingComponents: { + 't-text': Text, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $inner = comp.querySelector('.text >>> .t-typography--mark'); + expect($inner).toBeDefined(); + }); + + it(': mark[String] with custom color', () => { + const id = simulate.load({ + template: ``, + data: { + mark: '#07c160', + }, + usingComponents: { + 't-text': Text, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $inner = comp.querySelector('.text >>> .t-typography--mark'); + expect($inner).toBeDefined(); + // markStyle 在上层容器或 decor 元素的 style 中 + const $text = comp.querySelector('.text >>> .t-typography'); + const style = $text.dom.getAttribute('style') || ''; + const decorStyle = $inner.dom.getAttribute('style') || ''; + expect(style + decorStyle).toContain('background-color:#07c160'); + }); + + it(': disabled', () => { + const id = simulate.load({ + template: ``, + usingComponents: { + 't-text': Text, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $text = comp.querySelector('.text >>> .t-typography'); + expect($text.dom.getAttribute('class').includes('t-typography--disabled')).toBeTruthy(); + }); + + it(': theme - primary', () => { + const id = simulate.load({ + template: ``, + usingComponents: { + 't-text': Text, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $text = comp.querySelector('.text >>> .t-typography'); + expect($text.dom.getAttribute('class').includes('t-typography--primary')).toBeTruthy(); + }); + + it(': theme - secondary', () => { + const id = simulate.load({ + template: ``, + usingComponents: { + 't-text': Text, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $text = comp.querySelector('.text >>> .t-typography'); + expect($text.dom.getAttribute('class').includes('t-typography--secondary')).toBeTruthy(); + }); + + it(': theme - success', () => { + const id = simulate.load({ + template: ``, + usingComponents: { + 't-text': Text, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $text = comp.querySelector('.text >>> .t-typography'); + expect($text.dom.getAttribute('class').includes('t-typography--success')).toBeTruthy(); + }); + + it(': theme - warning', () => { + const id = simulate.load({ + template: ``, + usingComponents: { + 't-text': Text, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $text = comp.querySelector('.text >>> .t-typography'); + expect($text.dom.getAttribute('class').includes('t-typography--warning')).toBeTruthy(); + }); + + it(': theme - error', () => { + const id = simulate.load({ + template: ``, + usingComponents: { + 't-text': Text, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $text = comp.querySelector('.text >>> .t-typography'); + expect($text.dom.getAttribute('class').includes('t-typography--error')).toBeTruthy(); + }); + + it(': theme should not add class when disabled', () => { + const id = simulate.load({ + template: ``, + usingComponents: { + 't-text': Text, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $text = comp.querySelector('.text >>> .t-typography'); + expect($text.dom.getAttribute('class').includes('t-typography--disabled')).toBeTruthy(); + expect($text.dom.getAttribute('class').includes('t-typography--primary')).not.toBeTruthy(); + }); + + it(': multiple decorations combined', () => { + const id = simulate.load({ + template: ``, + usingComponents: { + 't-text': Text, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $strong = comp.querySelector('.text >>> .t-typography--strong'); + const $italic = comp.querySelector('.text >>> .t-typography--italic'); + const $underline = comp.querySelector('.text >>> .t-typography--underline'); + const $code = comp.querySelector('.text >>> .t-typography--code'); + expect($strong).toBeDefined(); + expect($italic).toBeDefined(); + expect($underline).toBeDefined(); + expect($code).toBeDefined(); + }); + + it(': ellipsis[Boolean]', () => { + const id = simulate.load({ + template: ``, + data: { + content: 'TDesign 秉承开放的设计理念从创立之初就采用开源协作的方式进行设计和开发。', + }, + usingComponents: { + 't-text': Text, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $wrapper = comp.querySelector('.text >>> .t-typography__ellipsis-wrapper'); + expect($wrapper).toBeDefined(); + const $content = comp.querySelector('.text >>> .t-typography__ellipsis-content'); + expect($content).toBeDefined(); + }); + + it(': ellipsis[Object] with row', () => { + const id = simulate.load({ + template: ``, + data: { + content: 'TDesign 秉承开放的设计理念从创立之初就采用开源协作的方式进行设计和开发。', + ellipsis: { row: 2 }, + }, + usingComponents: { + 't-text': Text, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $content = comp.querySelector('.text >>> .t-typography__ellipsis-content'); + expect($content).toBeDefined(); + expect($content.dom.getAttribute('style')).toContain('-webkit-line-clamp:2'); + }); + + it(': ellipsis[Object] with expandable', async () => { + const handleExpand = jest.fn(); + const id = simulate.load({ + template: ``, + data: { + content: 'TDesign 秉承开放的设计理念从创立之初就采用开源协作的方式进行设计和开发。', + ellipsis: { row: 1, expandable: true }, + }, + methods: { + handleExpand, + }, + usingComponents: { + 't-text': Text, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $expandBtn = comp.querySelector('.text >>> .t-typography-ellipsis-symbol'); + expect($expandBtn).toBeDefined(); + expect($expandBtn.dom.textContent).toContain('展开'); + + $expandBtn.dispatchEvent('tap'); + await simulate.sleep(10); + expect(handleExpand).toHaveBeenCalledTimes(1); + }); + + it(': ellipsis[Object] with collapsible', async () => { + const handleExpand = jest.fn(); + const id = simulate.load({ + template: ``, + data: { + content: 'TDesign 秉承开放的设计理念从创立之初就采用开源协作的方式进行设计和开发。', + ellipsis: { row: 1, expandable: true, collapsible: true }, + }, + methods: { + handleExpand, + }, + usingComponents: { + 't-text': Text, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + // 先展开 + const $expandBtn = comp.querySelector('.text >>> .t-typography-ellipsis-symbol'); + $expandBtn.dispatchEvent('tap'); + await simulate.sleep(10); + + // 展开后应有收起按钮 + const $collapseBtn = comp.querySelector('.text >>> .t-typography-ellipsis-symbol'); + expect($collapseBtn).toBeDefined(); + expect($collapseBtn.dom.textContent).toContain('收起'); + + $collapseBtn.dispatchEvent('tap'); + await simulate.sleep(10); + expect(handleExpand).toHaveBeenCalledTimes(2); + }); + + it(': ellipsis[Object] with expandable but not collapsible', async () => { + const id = simulate.load({ + template: ``, + data: { + content: 'TDesign 秉承开放的设计理念从创立之初就采用开源协作的方式进行设计和开发。', + ellipsis: { row: 1, expandable: true, collapsible: false }, + }, + usingComponents: { + 't-text': Text, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $expandBtn = comp.querySelector('.text >>> .t-typography-ellipsis-symbol'); + expect($expandBtn).toBeDefined(); + + $expandBtn.dispatchEvent('tap'); + await simulate.sleep(10); + + // 展开后 collapsible=false,不应有收起按钮(querySelector 未找到返回 undefined) + const $text = comp.querySelector('.text'); + expect($text.data.isExpanded).toBe(true); + }); + + it(': ellipsis with copyable shows extra margin', () => { + const id = simulate.load({ + template: ``, + data: { + content: 'TDesign 秉承开放的设计理念从创立之初就采用开源协作的方式进行设计和开发。', + ellipsis: { expandable: true }, + }, + usingComponents: { + 't-text': Text, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $expandBtn = comp.querySelector('.text >>> .t-typography-ellipsis-symbol'); + expect($expandBtn).toBeDefined(); + // rpx 在编译后变为 px + expect($expandBtn.dom.getAttribute('style')).toContain('margin-right:16px'); + }); + + it(': copyable[Boolean]', () => { + const id = simulate.load({ + template: ``, + usingComponents: { + 't-text': Text, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $copy = comp.querySelector('.text >>> .t-typography__copy'); + expect($copy).toBeDefined(); + }); + + it(': copyable triggers copy event', async () => { + const handleCopy = jest.fn(); + const id = simulate.load({ + template: ``, + data: { + content: '复制文本', + }, + methods: { + handleCopy, + }, + usingComponents: { + 't-text': Text, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $copy = comp.querySelector('.text >>> .t-typography__copy'); + $copy.dispatchEvent('tap'); + await simulate.sleep(10); + expect(handleCopy).toHaveBeenCalledTimes(1); + }); + + it(': copyable[Object] with custom text', async () => { + const handleCopy = jest.fn(); + const id = simulate.load({ + template: ``, + data: { + copyable: { text: '自定义复制内容' }, + }, + methods: { + handleCopy, + }, + usingComponents: { + 't-text': Text, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $copy = comp.querySelector('.text >>> .t-typography__copy'); + $copy.dispatchEvent('tap'); + await simulate.sleep(10); + expect(handleCopy).toHaveBeenCalledTimes(1); + }); + + it(': copyable prevents double click', async () => { + const handleCopy = jest.fn(); + const id = simulate.load({ + template: ``, + methods: { + handleCopy, + }, + usingComponents: { + 't-text': Text, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $copy = comp.querySelector('.text >>> .t-typography__copy'); + $copy.dispatchEvent('tap'); + await simulate.sleep(10); + + // 第二次点击应被忽略(isCopied 状态) + $copy.dispatchEvent('tap'); + await simulate.sleep(10); + expect(handleCopy).toHaveBeenCalledTimes(1); + }); + + it(': copyable icon resets after timeout', async () => { + const id = simulate.load({ + template: ``, + usingComponents: { + 't-text': Text, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $copy = comp.querySelector('.text >>> .t-typography__copy'); + $copy.dispatchEvent('tap'); + await simulate.sleep(10); + + const $text = comp.querySelector('.text'); + expect($text.data.isCopied).toBe(true); + + // 等待 1500ms+ 后恢复 + await simulate.sleep(1600); + expect($text.data.isCopied).toBe(false); + }); + + it(': copyable triggers copy event with empty content', async () => { + const handleCopy = jest.fn(); + const id = simulate.load({ + template: ``, + methods: { + handleCopy, + }, + usingComponents: { + 't-text': Text, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $copy = comp.querySelector('.text >>> .t-typography__copy'); + $copy.dispatchEvent('tap'); + await simulate.sleep(10); + expect(handleCopy).toHaveBeenCalledTimes(1); + expect(handleCopy.mock.calls[0][0].detail).toEqual({ text: '' }); + }); + + it(': copyable with suffix slot', () => { + const id = simulate.load({ + template: `自定义`, + data: { + copyable: { suffix: true }, + }, + usingComponents: { + 't-text': Text, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $copy = comp.querySelector('.text >>> .t-typography__copy'); + expect($copy).toBeDefined(); + }); + + it(': without ellipsis renders inline', () => { + const id = simulate.load({ + template: ``, + usingComponents: { + 't-text': Text, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $text = comp.querySelector('.text >>> .t-typography'); + expect($text.dom.getAttribute('style')).toContain('display:inline'); + }); + }); + + describe('observers', () => { + it(': theme change updates className', async () => { + const id = simulate.load({ + template: ``, + data: { + theme: 'primary', + }, + usingComponents: { + 't-text': Text, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $textComp = comp.querySelector('.text'); + expect($textComp.data.className.includes('t-typography--primary')).toBeTruthy(); + + // 通过组件实例直接修改 properties 来触发 observer + $textComp.setData({ theme: 'success' }); + await simulate.sleep(10); + + expect($textComp.data.className.includes('t-typography--success')).toBeTruthy(); + expect($textComp.data.className.includes('t-typography--primary')).not.toBeTruthy(); + }); + + it(': disabled change updates className', async () => { + const id = simulate.load({ + template: ``, + data: { + disabled: false, + }, + usingComponents: { + 't-text': Text, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $textComp = comp.querySelector('.text'); + expect($textComp.data.className.includes('t-typography--primary')).toBeTruthy(); + + $textComp.setData({ disabled: true }); + await simulate.sleep(10); + + expect($textComp.data.className.includes('t-typography--disabled')).toBeTruthy(); + expect($textComp.data.className.includes('t-typography--primary')).not.toBeTruthy(); + }); + }); +}); diff --git a/packages/components/paragraph/__test__/title.test.js b/packages/components/paragraph/__test__/title.test.js new file mode 100644 index 000000000..478285d56 --- /dev/null +++ b/packages/components/paragraph/__test__/title.test.js @@ -0,0 +1,286 @@ +import path from 'path'; +import simulate from 'miniprogram-simulate'; +import * as titleProps from '../../title/props'; +import * as titleType from '../../title/type'; + +describe('title exports', () => { + it(': props module can be loaded', () => { + expect(titleProps).toBeDefined(); + }); + + it(': type module can be loaded', () => { + expect(titleType).toBeDefined(); + }); +}); + +describe('title', () => { + const Title = load(path.resolve(__dirname, '../../title/title')); + + describe('props', () => { + it(': style && customStyle', async () => { + const id = simulate.load({ + template: ``, + data: { + style: 'color: red', + customStyle: 'font-size: 9px', + }, + usingComponents: { + 't-title': Title, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $title = comp.querySelector('.title >>> .t-typography'); + if (VIRTUAL_HOST) { + expect($title.dom.getAttribute('style').includes(`${comp.data.style}; ${comp.data.customStyle}`)).toBeTruthy(); + } else { + expect($title.dom.getAttribute('style').includes(`${comp.data.customStyle}`)).toBeTruthy(); + } + }); + + it(': content', () => { + const id = simulate.load({ + template: ``, + data: { + content: '标题内容', + }, + usingComponents: { + 't-title': Title, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + expect(comp.querySelector('.title').dom.textContent).toContain(comp.data.content); + }); + + it(': level - h1 (default)', () => { + const id = simulate.load({ + template: ``, + usingComponents: { + 't-title': Title, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $title = comp.querySelector('.title >>> .t-typography'); + expect($title.dom.getAttribute('class').includes('t-typography--h1')).toBeTruthy(); + }); + + it(': level - h2', () => { + const id = simulate.load({ + template: ``, + usingComponents: { + 't-title': Title, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $title = comp.querySelector('.title >>> .t-typography'); + expect($title.dom.getAttribute('class').includes('t-typography--h2')).toBeTruthy(); + }); + + it(': level - h3', () => { + const id = simulate.load({ + template: ``, + usingComponents: { + 't-title': Title, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $title = comp.querySelector('.title >>> .t-typography'); + expect($title.dom.getAttribute('class').includes('t-typography--h3')).toBeTruthy(); + }); + + it(': level - h4', () => { + const id = simulate.load({ + template: ``, + usingComponents: { + 't-title': Title, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $title = comp.querySelector('.title >>> .t-typography'); + expect($title.dom.getAttribute('class').includes('t-typography--h4')).toBeTruthy(); + }); + + it(': level - h5', () => { + const id = simulate.load({ + template: ``, + usingComponents: { + 't-title': Title, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $title = comp.querySelector('.title >>> .t-typography'); + expect($title.dom.getAttribute('class').includes('t-typography--h5')).toBeTruthy(); + }); + + it(': level - h6', () => { + const id = simulate.load({ + template: ``, + usingComponents: { + 't-title': Title, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $title = comp.querySelector('.title >>> .t-typography'); + expect($title.dom.getAttribute('class').includes('t-typography--h6')).toBeTruthy(); + }); + + it(': ellipsis[Boolean]', () => { + const id = simulate.load({ + template: ``, + data: { + content: 'TDesign 秉承开放的设计理念从创立之初就采用开源协作的方式进行设计和开发。', + }, + usingComponents: { + 't-title': Title, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $wrapper = comp.querySelector('.title >>> .t-typography__ellipsis-wrapper'); + expect($wrapper).toBeDefined(); + const $content = comp.querySelector('.title >>> .t-typography__ellipsis-content'); + expect($content).toBeDefined(); + }); + + it(': ellipsis[Object] with row', () => { + const id = simulate.load({ + template: ``, + data: { + content: 'TDesign 秉承开放的设计理念从创立之初就采用开源协作的方式进行设计和开发。', + ellipsis: { row: 2 }, + }, + usingComponents: { + 't-title': Title, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $content = comp.querySelector('.title >>> .t-typography__ellipsis-content'); + expect($content).toBeDefined(); + expect($content.dom.getAttribute('style')).toContain('-webkit-line-clamp:2'); + }); + + it(': ellipsis[Object] with expandable', async () => { + const handleExpand = jest.fn(); + const id = simulate.load({ + template: ``, + data: { + content: 'TDesign 秉承开放的设计理念从创立之初就采用开源协作的方式进行设计和开发。', + ellipsis: { row: 1, expandable: true }, + }, + methods: { + handleExpand, + }, + usingComponents: { + 't-title': Title, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $expandBtn = comp.querySelector('.title >>> .t-typography-ellipsis-symbol'); + expect($expandBtn).toBeDefined(); + expect($expandBtn.dom.textContent).toContain('展开'); + + $expandBtn.dispatchEvent('tap'); + await simulate.sleep(10); + expect(handleExpand).toHaveBeenCalledTimes(1); + }); + + it(': ellipsis[Object] with expandable and collapsible', async () => { + const handleExpand = jest.fn(); + const id = simulate.load({ + template: ``, + data: { + content: 'TDesign 秉承开放的设计理念从创立之初就采用开源协作的方式进行设计和开发。', + ellipsis: { row: 1, expandable: true, collapsible: true }, + }, + methods: { + handleExpand, + }, + usingComponents: { + 't-title': Title, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + // 展开 + const $expandBtn = comp.querySelector('.title >>> .t-typography-ellipsis-symbol'); + $expandBtn.dispatchEvent('tap'); + await simulate.sleep(10); + + // 收起按钮出现 + const $collapseBtn = comp.querySelector('.title >>> .t-typography-ellipsis-symbol'); + expect($collapseBtn).toBeDefined(); + expect($collapseBtn.dom.textContent).toContain('收起'); + + // 收起 + $collapseBtn.dispatchEvent('tap'); + await simulate.sleep(10); + expect(handleExpand).toHaveBeenCalledTimes(2); + }); + + it(': ellipsis[Object] without expandable does not show button', () => { + const id = simulate.load({ + template: ``, + data: { + content: 'TDesign 秉承开放的设计理念从创立之初就采用开源协作的方式进行设计和开发。', + ellipsis: { row: 2, expandable: false }, + }, + usingComponents: { + 't-title': Title, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $expandBtn = comp.querySelector('.title >>> .t-typography-ellipsis-symbol'); + expect($expandBtn).not.toBeTruthy(); + }); + + it(': without ellipsis does not show ellipsis wrapper', () => { + const id = simulate.load({ + template: ``, + usingComponents: { + 't-title': Title, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + const $wrapper = comp.querySelector('.title >>> .t-typography__ellipsis-wrapper'); + expect($wrapper).not.toBeTruthy(); + }); + + it(': slot content', () => { + const id = simulate.load({ + template: `Slot Title`, + usingComponents: { + 't-title': Title, + }, + }); + const comp = simulate.render(id); + comp.attach(document.createElement('parent-wrapper')); + + expect(comp.querySelector('.title').dom.textContent).toContain('Slot Title'); + }); + }); +}); diff --git a/packages/components/paragraph/_example/base/index.js b/packages/components/paragraph/_example/base/index.js new file mode 100644 index 000000000..b79c5124b --- /dev/null +++ b/packages/components/paragraph/_example/base/index.js @@ -0,0 +1 @@ +Component({}); diff --git a/packages/components/paragraph/_example/base/index.json b/packages/components/paragraph/_example/base/index.json new file mode 100644 index 000000000..e0cb8aade --- /dev/null +++ b/packages/components/paragraph/_example/base/index.json @@ -0,0 +1,7 @@ +{ + "component": true, + "styleIsolation": "apply-shared", + "usingComponents": { + "t-typography-text": "tdesign-miniprogram/text/text" + } +} diff --git a/packages/components/paragraph/_example/base/index.wxml b/packages/components/paragraph/_example/base/index.wxml new file mode 100644 index 000000000..cb97291c9 --- /dev/null +++ b/packages/components/paragraph/_example/base/index.wxml @@ -0,0 +1,3 @@ + + + diff --git a/packages/components/paragraph/_example/base/index.wxss b/packages/components/paragraph/_example/base/index.wxss new file mode 100644 index 000000000..e69de29bb diff --git a/packages/components/paragraph/_example/combination/index.js b/packages/components/paragraph/_example/combination/index.js new file mode 100644 index 000000000..b79c5124b --- /dev/null +++ b/packages/components/paragraph/_example/combination/index.js @@ -0,0 +1 @@ +Component({}); diff --git a/packages/components/paragraph/_example/combination/index.json b/packages/components/paragraph/_example/combination/index.json new file mode 100644 index 000000000..cd240fabe --- /dev/null +++ b/packages/components/paragraph/_example/combination/index.json @@ -0,0 +1,9 @@ +{ + "component": true, + "styleIsolation": "apply-shared", + "usingComponents": { + "t-typography-text": "tdesign-miniprogram/text/text", + "t-typography-title": "tdesign-miniprogram/title/title", + "t-typography-paragraph": "tdesign-miniprogram/paragraph/paragraph" + } +} diff --git a/packages/components/paragraph/_example/combination/index.wxml b/packages/components/paragraph/_example/combination/index.wxml new file mode 100644 index 000000000..2c2aad69a --- /dev/null +++ b/packages/components/paragraph/_example/combination/index.wxml @@ -0,0 +1,41 @@ + + + + + + TDesign features a unified design values, consistent design language, and visual style, helping users form + continuous and coherent perceptions of the experience. + + Based on this, TDesign offers out-typography-of-the-box UI component libraries, design guidelines, and design + assets, elegantly and efficiently freeing design and development from repetitive tasks. Simultaneously, it + facilitates easy extension on top of TDesign, enabling a better alignment with business requirements. + + + Comprehensive + + TDesign Support + Vue 2, Vue 3, + React + components for Desktop Application and + Vue 3, + Wechat MiniProgram + components for Mobile Application. + + + • Features + • Comprehensive + • Consistency + • Usability + • Join TDesign + + + 1. Features + 2. Comprehensive + 1. Consistency + 2. Usability + 3. Join TDesign + + diff --git a/packages/components/paragraph/_example/combination/index.wxss b/packages/components/paragraph/_example/combination/index.wxss new file mode 100644 index 000000000..e69de29bb diff --git a/packages/components/paragraph/_example/copyable/index.js b/packages/components/paragraph/_example/copyable/index.js new file mode 100644 index 000000000..36bfc6357 --- /dev/null +++ b/packages/components/paragraph/_example/copyable/index.js @@ -0,0 +1,7 @@ +Component({ + data: { + copyableCustomSuffix: { + suffix: true, + }, + }, +}); diff --git a/packages/components/paragraph/_example/copyable/index.json b/packages/components/paragraph/_example/copyable/index.json new file mode 100644 index 000000000..e783eb00c --- /dev/null +++ b/packages/components/paragraph/_example/copyable/index.json @@ -0,0 +1,8 @@ +{ + "component": true, + "styleIsolation": "apply-shared", + "usingComponents": { + "t-typography-text": "tdesign-miniprogram/text/text", + "t-icon": "tdesign-miniprogram/icon/icon" + } +} diff --git a/packages/components/paragraph/_example/copyable/index.wxml b/packages/components/paragraph/_example/copyable/index.wxml new file mode 100644 index 000000000..218d77f5d --- /dev/null +++ b/packages/components/paragraph/_example/copyable/index.wxml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/packages/components/paragraph/_example/copyable/index.wxss b/packages/components/paragraph/_example/copyable/index.wxss new file mode 100644 index 000000000..e69de29bb diff --git a/packages/components/paragraph/_example/ellipsis/index.js b/packages/components/paragraph/_example/ellipsis/index.js new file mode 100644 index 000000000..e91d3101c --- /dev/null +++ b/packages/components/paragraph/_example/ellipsis/index.js @@ -0,0 +1,17 @@ +Component({ + data: { + content: + 'TDesign 秉承开放的设计理念从创立之初就采用开源协作的方式进行设计和开发。协作方案讨论、组件设计以及 API 设计,包括源代码在内均在公司内部完全开放,赢得了内部开发者和设计师的广泛关注。TDesign 遵循平等、开放、严格的原则,不论参与者的角色如何。', + ellipsisExpandable: { + row: 2, + expandable: true, + collapsible: true, + }, + ellipsisCustomSuffix: { + row: 1, + expandable: true, + collapsible: false, + suffix: true, + }, + }, +}); diff --git a/packages/components/paragraph/_example/ellipsis/index.json b/packages/components/paragraph/_example/ellipsis/index.json new file mode 100644 index 000000000..c24644ca7 --- /dev/null +++ b/packages/components/paragraph/_example/ellipsis/index.json @@ -0,0 +1,8 @@ +{ + "component": true, + "styleIsolation": "apply-shared", + "usingComponents": { + "t-typography-paragraph": "tdesign-miniprogram/paragraph/paragraph", + "t-icon": "tdesign-miniprogram/icon/icon" + } +} diff --git a/packages/components/paragraph/_example/ellipsis/index.wxml b/packages/components/paragraph/_example/ellipsis/index.wxml new file mode 100644 index 000000000..6ab9160d7 --- /dev/null +++ b/packages/components/paragraph/_example/ellipsis/index.wxml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/packages/components/paragraph/_example/ellipsis/index.wxss b/packages/components/paragraph/_example/ellipsis/index.wxss new file mode 100644 index 000000000..e69de29bb diff --git a/packages/components/paragraph/_example/paragraph.json b/packages/components/paragraph/_example/paragraph.json new file mode 100644 index 000000000..31f76ff2e --- /dev/null +++ b/packages/components/paragraph/_example/paragraph.json @@ -0,0 +1,11 @@ +{ + "navigationBarTitleText": "Typography", + "navigationBarBackgroundColor": "#fff", + "usingComponents": { + "base": "./base", + "theme": "./theme", + "copyable": "./copyable", + "ellipsis": "./ellipsis", + "combination": "./combination" + } +} diff --git a/packages/components/paragraph/_example/paragraph.less b/packages/components/paragraph/_example/paragraph.less new file mode 100644 index 000000000..1af7bc8bf --- /dev/null +++ b/packages/components/paragraph/_example/paragraph.less @@ -0,0 +1,27 @@ +.typography-example { + display: flex; + padding: 0 32rpx; + background-color: var(--bg-color-demo, #fff); + + &--inline { + display: inline-block; + } + + &--theme { + gap: 24px; + } + + &--border { + position: relative; + + &::after { + content: ''; + position: absolute; + bottom: 0; + left: 16px; + right: 16px; + border-bottom: 1px solid var(--td-stroke-color, #e7e7e7); + transform: scaleY(0.5); + } + } +} diff --git a/packages/components/paragraph/_example/paragraph.ts b/packages/components/paragraph/_example/paragraph.ts new file mode 100644 index 000000000..560d44d43 --- /dev/null +++ b/packages/components/paragraph/_example/paragraph.ts @@ -0,0 +1 @@ +Page({}); diff --git a/packages/components/paragraph/_example/paragraph.wxml b/packages/components/paragraph/_example/paragraph.wxml new file mode 100644 index 000000000..b5bbf42fb --- /dev/null +++ b/packages/components/paragraph/_example/paragraph.wxml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + diff --git a/packages/components/paragraph/_example/theme/index.js b/packages/components/paragraph/_example/theme/index.js new file mode 100644 index 000000000..b79c5124b --- /dev/null +++ b/packages/components/paragraph/_example/theme/index.js @@ -0,0 +1 @@ +Component({}); diff --git a/packages/components/paragraph/_example/theme/index.json b/packages/components/paragraph/_example/theme/index.json new file mode 100644 index 000000000..e0cb8aade --- /dev/null +++ b/packages/components/paragraph/_example/theme/index.json @@ -0,0 +1,7 @@ +{ + "component": true, + "styleIsolation": "apply-shared", + "usingComponents": { + "t-typography-text": "tdesign-miniprogram/text/text" + } +} diff --git a/packages/components/paragraph/_example/theme/index.wxml b/packages/components/paragraph/_example/theme/index.wxml new file mode 100644 index 000000000..b4ba5b539 --- /dev/null +++ b/packages/components/paragraph/_example/theme/index.wxml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/packages/components/paragraph/_example/theme/index.wxss b/packages/components/paragraph/_example/theme/index.wxss new file mode 100644 index 000000000..e69de29bb diff --git a/packages/components/paragraph/ellipsis.wxml b/packages/components/paragraph/ellipsis.wxml new file mode 100644 index 000000000..36ca7e1de --- /dev/null +++ b/packages/components/paragraph/ellipsis.wxml @@ -0,0 +1,18 @@ + diff --git a/packages/components/paragraph/paragraph.json b/packages/components/paragraph/paragraph.json new file mode 100644 index 000000000..79f273097 --- /dev/null +++ b/packages/components/paragraph/paragraph.json @@ -0,0 +1,4 @@ +{ + "component": true, + "styleIsolation": "apply-shared" +} diff --git a/packages/components/paragraph/paragraph.less b/packages/components/paragraph/paragraph.less new file mode 100644 index 000000000..feae8f6aa --- /dev/null +++ b/packages/components/paragraph/paragraph.less @@ -0,0 +1,189 @@ +@import '../common/style/base.less'; + +// ==================== 变量定义(对应 _var.less) ==================== +@typography-text-primary-color: @text-color-primary; +@typography-text-secondary-color: @text-color-secondary; +@typography-text-disabled-color: @text-color-disabled; +@typography-text-success-color: @success-color; +@typography-text-error-color: @error-color; +@typography-text-warning-color: @warning-color; +@typography-text-mark-color: #fcdf47; +@typography-icon-color: @brand-color; + +@typography-text-strong: 600; + +@typography-text-font: @font-body-medium; +@typography-code-font: @font-body-small; +@typography-h1-font: @font-headline-large; +@typography-h2-font: @font-headline-medium; +@typography-h3-font: @font-headline-small; +@typography-h4-font: @font-title-large; +@typography-h5-font: @font-title-medium; +@typography-h6-font: @font-title-small; + +@typography-code-family: + Source Code Pro, + -apple-system, + BlinkMacSystemFont, + Segoe UI, + Roboto, + Hiragino Sans GB, + Microsoft YaHei UI, + Microsoft YaHei; + +// ==================== 主样式(对应 _index.less) ==================== +.@{prefix}-typography { + color: @typography-text-primary-color; + font: @font-body-medium; + margin: @spacer-2 0; + + // 标题级别(小程序用 modifier 类名模拟 h1-h6 标签选择器) + &--h1 { + font: @typography-h1-font; + margin-top: @spacer-4; + margin-bottom: @spacer-3; + } + + &--h2 { + font: @typography-h2-font; + margin-top: @spacer-4; + margin-bottom: @spacer-3; + } + + &--h3 { + font: @typography-h3-font; + margin-top: @spacer-4; + margin-bottom: @spacer-2; + } + + &--h4 { + font: @typography-h4-font; + margin-top: @spacer-3; + margin-bottom: @spacer-2; + } + + &--h5 { + font: @typography-h5-font; + margin-top: @spacer-3; + margin-bottom: @spacer-2; + } + + &--h6 { + font: @typography-h6-font; + } + + strong, + &--strong { + font-weight: @typography-text-strong; + } + + mark, + &--mark { + background-color: @typography-text-mark-color; + } + + code, + &--code { + border-radius: @radius-default; + border: 1px solid @component-border; + margin: 0 @spacer; + background-color: @bg-color-secondarycontainer; + padding: 0 @spacer; + transition: background-color 0.2s; + white-space: nowrap; + font: @typography-code-font; + font-family: @typography-code-family; + display: inline-block; + } + + kbd, + &--keyboard { + border-radius: @radius-default; + border: 1px solid @component-border; + margin: 0 calc(@spacer / 2); + background-color: @bg-color-secondarycontainer; + padding: 0 @spacer; + box-shadow: 0 1px 0 0 @component-border; + font: @typography-code-font; + font-family: @typography-code-family; + display: inline-block; + } + + // 不可选样式 + &--disabled { + color: @typography-text-disabled-color; + cursor: not-allowed; + } + + // 主题样式 + &--success { + color: @typography-text-success-color; + } + + &--warning { + color: @typography-text-warning-color; + } + + &--error { + color: @typography-text-error-color; + } + + &--secondary { + color: @typography-text-secondary-color; + } + + &-ellipsis-symbol, + .t-icon-copy { + color: @typography-icon-color; + cursor: pointer; + } + + .t-icon-checked { + color: @success-color; + } + + // ==================== 小程序适配补充 ==================== + + i, + &--italic { + font-style: italic; + } + + u, + &--underline { + text-decoration: underline; + } + + del, + &--delete { + text-decoration: line-through; + } + + // 省略相关 + &__ellipsis-wrapper { + display: flex; + align-items: flex-end; + } + + &__ellipsis-content { + overflow: hidden; + text-overflow: ellipsis; + white-space: normal; + display: -webkit-box; + -webkit-box-orient: vertical; + } + + &-ellipsis-symbol { + text-decoration: none; + white-space: nowrap; + flex: 1; + } + + // 复制按钮 + &__copy { + display: inline-flex; + align-items: center; + margin-left: 16rpx; + flex-shrink: 0; + } +} diff --git a/packages/components/paragraph/paragraph.ts b/packages/components/paragraph/paragraph.ts new file mode 100644 index 000000000..d0634c22f --- /dev/null +++ b/packages/components/paragraph/paragraph.ts @@ -0,0 +1,41 @@ +import { SuperComponent, wxComponent } from '../common/src/index'; +import config from '../common/config'; +import props from './props'; + +const { prefix } = config; +const name = `${prefix}-typography`; + +@wxComponent() +export default class Paragraph extends SuperComponent { + externalClasses = [`${prefix}-class`]; + + options = { + multipleSlots: true, + }; + + properties = props; + + data = { + prefix, + classPrefix: name, + isExpanded: false, + }; + + methods = { + onExpand() { + this.setData({ isExpanded: true }); + const { ellipsis } = this.properties; + if (typeof ellipsis === 'object') { + this.triggerEvent('expand', { expanded: true }); + } + }, + + onCollapse() { + this.setData({ isExpanded: false }); + const { ellipsis } = this.properties; + if (typeof ellipsis === 'object') { + this.triggerEvent('expand', { expanded: false }); + } + }, + }; +} diff --git a/packages/components/paragraph/paragraph.wxml b/packages/components/paragraph/paragraph.wxml new file mode 100644 index 000000000..30952c275 --- /dev/null +++ b/packages/components/paragraph/paragraph.wxml @@ -0,0 +1,36 @@ + + + + + + + + {{content}} + + + + {{content}} + + + + + + + + + + +