Skip to content

Commit

Permalink
🚩 feat: input support overflow (#177)
Browse files Browse the repository at this point in the history
* 📝 docs: add checkbox demo

* 🚩 feat: input support overflow

* ✅ test: update test case
  • Loading branch information
MadCcc committed Jan 13, 2023
1 parent 174ee9f commit 0ff7b55
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 42 deletions.
4 changes: 4 additions & 0 deletions config/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ const antdComponents: SideBarRoute = {
title: 'Modal 浮层',
link: 'e2e/components/modal',
},
{
title: 'Input',
link: 'e2e/components/Input',
},
],
};

Expand Down
8 changes: 8 additions & 0 deletions docs/e2e/components/Input.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
title: Input
order: 51
---

# Input

<code src="./demos/Input.tsx"></code>
11 changes: 11 additions & 0 deletions docs/e2e/components/demos/Input.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Input } from 'antd';
import React from 'react';

export default () => (
<>
<Input placeholder="请输入请输入请输入请输入" style={{ width: 100 }} />
<br />
<br />
<Input value="请输入请输入请输入请输入" style={{ width: 100 }} />
</>
);
11 changes: 4 additions & 7 deletions src/function/nodeToGroup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,7 @@ const consoleGroupStyle = `font-weight:bold;color:#666;`;
* @param node
* @param options
*/
const nodeToGroup = async (
node: Element,
options?: Options,
): Promise<Group> => {
const nodeToGroup = async (node: Element, options?: Options): Promise<Group> => {
if (!node) throw Error('解析对象不存在 请检查传入对象');

const bcr = node.getBoundingClientRect();
Expand Down Expand Up @@ -91,9 +88,7 @@ const nodeToGroup = async (
) {
console.groupCollapsed('%c清理无效层级', consoleGroupStyle);
const layer = group.layers[0];
console.log(
`该 group 只包含一个子级 [${layer.class}]: ${layer.name} ,丢弃...`,
);
console.log(`该 group 只包含一个子级 [${layer.class}]: ${layer.name} ,丢弃...`);
console.groupEnd();
// 将父级的图层关系还给子集
layer.x += group.x;
Expand Down Expand Up @@ -122,6 +117,8 @@ const nodeToGroup = async (
group.name = getName(node.nodeName);
}

console.log(group.name, group.frame);

group.className = node.className;
console.info('%c输出 Group 为:', 'font-weight:bold;color:#4590f7;', group);

Expand Down
34 changes: 13 additions & 21 deletions src/parser/inputText.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Group } from 'html2sketch/models';
import { createOverflowMask } from 'html2sketch/utils/overflow';
import Text from '../models/Layer/Text';
import { getTextLinesAndRange } from '../utils/text';

Expand All @@ -6,12 +8,9 @@ import { getTextLinesAndRange } from '../utils/text';
*/
export const parseInputTextToText = (
node: HTMLInputElement | HTMLTextAreaElement,
): Text | undefined => {
): Text | Group | undefined => {
// 判断一下是否有伪类
const inputTextStyle: CSSStyleDeclaration = getComputedStyle(
node,
'placeholder',
);
const inputTextStyle: CSSStyleDeclaration = getComputedStyle(node, 'placeholder');
let pseudoText: string;

/// *** 处理 input 的文本值 *** ///
Expand All @@ -26,8 +25,7 @@ export const parseInputTextToText = (

const pseudoNode = document.createElement('text');

const { paddingLeft, paddingRight, paddingTop, borderTopWidth } =
inputTextStyle;
const { paddingLeft, paddingRight, paddingTop, borderTopWidth } = inputTextStyle;

const nodeBCR = node.getBoundingClientRect();

Expand All @@ -45,13 +43,9 @@ export const parseInputTextToText = (

document.body.removeChild(pseudoNode); // 处理完成后移除

const textStyle = Text.getTextStyleFromNode(node, '::placeholder');

// ***** Placeholder 文本颜色的解法 ***** //
// 无法用 js 的方式获取 placeholder 的颜色
// 相关资料:
// https://stackoverflow.com/questions/52355140/get-the-correct-placeholder-color-with-js
// https://css-tricks.com/almanac/selectors/p/placeholder/
const textStyle = Text.getTextStyleFromNode(node, value ? undefined : '::placeholder');
// Chromium seems cannot get correct color from '::placeholder'
// Ref: https://bugs.chromium.org/p/chromium/issues/detail?id=850744
// -----
// 最终解法来源:
// https://stackoverflow.com/questions/28592895/trying-to-get-style-of-placeholder-attribute-of-element
Expand All @@ -70,8 +64,8 @@ export const parseInputTextToText = (
// 针对每条规则进行一次判断
// 如果包含 placeholder 的样式
if (
selectorText?.includes(node.className) &&
selectorText?.includes('::placeholder')
selectorText?.includes('::placeholder') &&
Array.from(node.classList).some((cls) => selectorText?.includes(cls))
) {
textColor = style.color; // 那么把相应的 style 取出来
}
Expand All @@ -93,10 +87,7 @@ export const parseInputTextToText = (
const { lineHeight } = inputTextStyle;

// TODO: 还有什么时候需要垂直居中呢?
if (
node.nodeName !== 'TEXTAREA' &&
parseFloat(lineHeight) > rangeBCR.height
) {
if (node.nodeName !== 'TEXTAREA' && parseFloat(lineHeight) > rangeBCR.height) {
// 需要垂直居中的地方
console.log(y, nodeBCR.y);
console.log(nodeBCR.height, rangeBCR.height);
Expand Down Expand Up @@ -127,5 +118,6 @@ export const parseInputTextToText = (
case 'right':
text.right = nodeBCR.right - parseFloat(paddingRight);
}
return text;

return createOverflowMask(node, text);
};
24 changes: 24 additions & 0 deletions src/utils/overflow.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Group, Rectangle } from 'html2sketch';

export const createOverflowMask = (node: HTMLElement, children: any) => {
const { width, height, left, top } = node.getBoundingClientRect();
const nodeStyles = getComputedStyle(node);
const paddingLeft = parseFloat(nodeStyles.getPropertyValue('padding-left'));
const paddingTop = parseFloat(nodeStyles.getPropertyValue('padding-top'));
const paddingRight = parseFloat(nodeStyles.getPropertyValue('padding-right'));
const paddingBottom = parseFloat(nodeStyles.getPropertyValue('padding-bottom'));
const rect = new Rectangle({
width: width - paddingLeft - paddingRight,
height: height - paddingTop - paddingBottom,
x: paddingLeft,
y: paddingTop,
name: '蒙层',
});
rect.hasClippingMask = true;

const group = new Group({ x: left, y: top, name: '子元素' });
group.layers.push(rect);
group.addLayer(children);

return group;
};
27 changes: 13 additions & 14 deletions tests/__tests__/parser/InputText.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import type { Text } from 'html2sketch';
import { parseInputTextToText } from 'html2sketch';

const getInputText = (node: HTMLInputElement | HTMLTextAreaElement) =>
parseInputTextToText(node)?.layers[1];

describe('parseInputTextToText', () => {
beforeAll(() => {
document.head.innerHTML = `
Expand Down Expand Up @@ -40,35 +43,31 @@ describe('parseInputTextToText', () => {

it('input 不返回', () => {
const node = document.getElementById('input') as HTMLInputElement;
const input = parseInputTextToText(node);
const input = getInputText(node);

expect(input).toBeUndefined();
});

it('textarea 不返回', () => {
const node = document.getElementById('pure-textarea') as HTMLTextAreaElement;
console.log(node)
const input = parseInputTextToText(node);
console.log(node);
const input = getInputText(node);

expect(input).toBeUndefined();
});

it('input-placeholder 解析成文本', () => {
const node = document.getElementById(
'input-placeholder',
) as HTMLInputElement;
const input = parseInputTextToText(node) as Text;
const node = document.getElementById('input-placeholder') as HTMLInputElement;
const input = getInputText(node) as Text;
expect(input.textStyle.color.red).toBe(255);
const json = input.toSketchJSON();
expect(json._class).toBe('text');
expect(json.attributedString.string).toBe('测试输入框');
});

it('textarea-placeholder 解析成文本', () => {
const node = document.getElementById(
'textarea-placeholder',
) as HTMLInputElement;
const input = parseInputTextToText(node) as Text;
const node = document.getElementById('textarea-placeholder') as HTMLInputElement;
const input = getInputText(node) as Text;
expect(input.textStyle.color.red).toBe(255);
const json = input.toSketchJSON();
expect(json._class).toBe('text');
Expand All @@ -77,7 +76,7 @@ describe('parseInputTextToText', () => {

it('input-value 解析成文本', () => {
const node = document.getElementById('input-value') as HTMLInputElement;
const input = parseInputTextToText(node) as Text;
const input = getInputText(node) as Text;
const json = input.toSketchJSON();
expect(json._class).toBe('text');
expect(json.attributedString.string).toBe('这是值');
Expand All @@ -86,15 +85,15 @@ describe('parseInputTextToText', () => {

it('textarea-value 解析成文本', () => {
const node = document.getElementById('textarea-value') as HTMLTextAreaElement;
const input = parseInputTextToText(node) as Text;
const input = getInputText(node) as Text;
const json = input.toSketchJSON();
expect(json._class).toBe('text');
expect(json.attributedString.string).toBe('这是值');
});

it('input-center 解析成文本', () => {
const node = document.getElementById('input-center') as HTMLInputElement;
const input = parseInputTextToText(node) as Text;
const input = getInputText(node) as Text;
const json = input.toSketchJSON();
expect(json._class).toBe('text');
expect(json.attributedString.string).toBe('123456');
Expand Down

0 comments on commit 0ff7b55

Please sign in to comment.