Skip to content

Commit 8882f3b

Browse files
committed
wip(#7): add TextRenderer base component
close #13
1 parent 48f7144 commit 8882f3b

File tree

8 files changed

+224
-0
lines changed

8 files changed

+224
-0
lines changed

src/components/AbstractRenderer/AbrstractRenderer.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export interface IAbstractRendererProps {
88
}
99

1010
export interface IDateValue { value: Date }
11+
export interface ITextValue { value: string }
1112

1213
export abstract class AbstractRenderer<IRendererValueType = string, IRendererProps extends IAbstractRendererProps = IAbstractRendererProps> extends React.Component<IRendererProps> {
1314

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { Primary, Canvas, Source, Meta, ArgTypes, Description, Controls } from '@storybook/blocks';
2+
import * as TextRendererStories from './TextRenderer.stories';
3+
4+
<Meta of={TextRendererStories} name="TextRenderer Documentation" />
5+
6+
# TextRenderer
7+
8+
<Description of={TextRendererStories} />
9+
10+
### Preview
11+
12+
<Primary />
13+
14+
### Properties
15+
16+
The text representation can be customized using the appropriates tag attributes i.e. component properties, as described below.
17+
18+
<Controls of={TextRendererStories.Playground} />
19+
{/* <ArgTypes of={TextRendererStories} sort="requiredFirst" /> */}
20+
21+
Notes:
22+
23+
- This component is rendering text transformed by predefined, standard functions like "lowercase", "uppercase", "camelcase", "kebabcase" etc.
24+
- The values and options used/available within the "Control" column are for demonstration purpose only.
25+
- Use the "Reset controls" button on the top right side of the table in order to restore the initial demo values and options. Alternatively, you could reload the page.
26+
27+
### Usage
28+
29+
<Source dark type={"jsx"} code={`
30+
import { TextRenderer } from 'react-text-renderer-components';
31+
32+
const Example = () => {
33+
return <TextRenderer value={"SOME TEXT"} transform="lowercase" />
34+
}`
35+
} />
36+
37+
Back to the [Github Repository](https://github.com/khatastroffik/react-text-renderer-components)
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import React from "react";
2+
import { render } from '@testing-library/react';
3+
import { TextRenderer } from "./TextRenderer";
4+
5+
describe("TextRenderer component", () => {
6+
7+
it("should render a text value to lowercase", () => {
8+
const sourceText = "SOURCE TEXT";
9+
const r = render(<TextRenderer value={sourceText} transform="lowercase" pure />);
10+
expect(r.container.innerHTML).toEqual(sourceText.toLowerCase());
11+
});
12+
13+
it("should render a spanned, lowercased text", () => {
14+
const sourceText = "SOURCE TEXT";
15+
const r = render(<TextRenderer value={sourceText} transform="lowercase" />);
16+
expect(r.container.innerHTML).toEqual(`<span>${sourceText.toLowerCase()}</span>`);
17+
});
18+
19+
it("should render a text value to uppercase", () => {
20+
const sourceText = "source text";
21+
const r = render(<TextRenderer value={sourceText} transform="uppercase" pure />);
22+
expect(r.container.innerHTML).toEqual(sourceText.toUpperCase());
23+
});
24+
25+
it("should render an empty text when value is undefined", () => {
26+
const sourceText = undefined;
27+
const r = render(<TextRenderer value={sourceText} transform="noop" pure />);
28+
expect(r.container.innerHTML).toEqual("");
29+
});
30+
31+
it("should render an empty text when value is null", () => {
32+
const sourceText = null;
33+
const r = render(<TextRenderer value={sourceText} transform="noop" pure />);
34+
expect(r.container.innerHTML).toEqual("");
35+
});
36+
37+
it("should render an umodified text value when transformation is 'noop' (no-operation)", () => {
38+
const sourceText = "SOURCE text";
39+
const r = render(<TextRenderer value={sourceText} transform="noop" pure />);
40+
expect(r.container.innerHTML).toEqual(sourceText);
41+
});
42+
43+
it("should render an umodified text value when transformation is null", () => {
44+
const sourceText = null;
45+
const r = render(<TextRenderer value={sourceText} transform={null} pure />);
46+
expect(r.container.innerHTML).toEqual("");
47+
});
48+
49+
it("should render an umodified text value when transformation is undefined", () => {
50+
const sourceText = null;
51+
const r = render(<TextRenderer value={sourceText} transform={undefined} pure />);
52+
expect(r.container.innerHTML).toEqual("");
53+
});
54+
55+
it("protected method 'getFormatedText()' should return a string", () => {
56+
const sourceText = "SOURCE text";
57+
class TextRendererWrapper extends TextRenderer {
58+
public getFormatedText() {
59+
return super.getFormatedText();
60+
}
61+
}
62+
const component = new TextRendererWrapper({ value: sourceText, transform: "noop" });
63+
expect(component.getFormatedText()).toEqual(sourceText);
64+
});
65+
66+
});
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import React from 'react';
2+
import { Meta, StoryObj } from '@storybook/react';
3+
import { TextRenderer } from './TextRenderer';
4+
import { RemoveKeyAttribute } from "../../../.storybook/utils";
5+
6+
const testtext = "some text";
7+
8+
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9+
10+
const meta = {
11+
title: 'Components/TextRenderer',
12+
component: TextRenderer,
13+
argTypes: {
14+
value: {
15+
control: "text",
16+
description: "The text **value** (string) which should be transformed and rendered.",
17+
},
18+
pure: {
19+
control: "boolean",
20+
description: "If **pure** is set/defined, then the component will render nothing but the 'pure' text representation of the value. Otherwise, the text representation is embeded within a *&lt;span&gt;&lt;/span&gt;* tag.",
21+
},
22+
transform: {
23+
control: "select",
24+
description: "The type of transformation to be applied to the input values.",
25+
options: ["noop", "lowercase", "uppercase"],
26+
}
27+
},
28+
parameters: {
29+
docs: {
30+
controls: { sort: "requiredFirst" },
31+
source: { language: 'tsx', type: 'auto', transform: RemoveKeyAttribute },
32+
description: { component: "The **TextRenderer** component renders an input *value* of type `string` to a pure/spanned representation showing the transformed text as defined by the `transform` attribute of the component." },
33+
},
34+
layout: 'centered'
35+
},
36+
render: RenderTextRenderer
37+
} satisfies Meta<typeof TextRenderer>;
38+
39+
export default meta;
40+
type Story = StoryObj<typeof meta>;
41+
42+
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
43+
44+
function RenderTextRenderer(args) {
45+
return <TextRenderer key={Math.random()} {...args} />
46+
}
47+
48+
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
49+
50+
export const Playground = {
51+
name: "Playground",
52+
args: {
53+
value: testtext,
54+
pure: true,
55+
transform: "noop"
56+
},
57+
tags: ['!dev']
58+
} satisfies Story;
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { AbstractRenderer, IAbstractRendererProps, ITextValue, ModifyValueType } from "../AbstractRenderer";
2+
3+
export type TextRendererTransformation = "noop" | "lowercase" | "uppercase";
4+
export interface ITextRendererProps extends ModifyValueType<IAbstractRendererProps, ITextValue> {
5+
transform: TextRendererTransformation
6+
}
7+
8+
export class TextRenderer extends AbstractRenderer<string, ITextRendererProps> {
9+
protected getFormatedText(): string {
10+
const sourceText = this.value ?? "";
11+
switch (this.props.transform ?? "noop") {
12+
case 'lowercase':
13+
return sourceText.toLowerCase();
14+
break;
15+
case 'uppercase':
16+
return sourceText.toUpperCase();
17+
break;
18+
case 'noop':
19+
return sourceText;
20+
break;
21+
default:
22+
return sourceText;
23+
break;
24+
}
25+
}
26+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './TextRenderer';

src/components/introduction.mdx

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { TimeRenderer } from "./TimeRenderer";
44
import { DateTimeRenderer } from "./DateTimeRenderer";
55
import { WeekRenderer } from "./WeekRenderer";
66
import { QuarterRenderer } from "./QuarterRenderer";
7+
import { TextRenderer } from "./TextRenderer";
78
import banner from '../../docs/johannes-plenio-2QUvkQTBh5s-unsplash.jpg';
89

910
<style>
@@ -86,6 +87,16 @@ import banner from '../../docs/johannes-plenio-2QUvkQTBh5s-unsplash.jpg';
8687
.accordion > input[type="checkbox"]:checked ~ .handle label:after {
8788
content: "↓";
8889
}
90+
.previewoutput table {
91+
margin-left:auto;
92+
margin-right:auto;
93+
}
94+
.previewoutput table tbody tr {
95+
background-color: transparent!important;
96+
}
97+
.previewoutput table thead {
98+
background: #f5f5f5;
99+
}
89100
`}
90101
</style>
91102

@@ -248,6 +259,29 @@ import banner from '../../docs/johannes-plenio-2QUvkQTBh5s-unsplash.jpg';
248259
<p>Note: the Date value passed as property to the WeekRenderer component should be a **UTC** date</p>
249260
</section>
250261

262+
### TextRenderer
263+
264+
<div className="previewoutput centeredtable">
265+
| Input value string | Transformation function | Rendering Output |
266+
|---|---|---|
267+
| some text | noop | <TextRenderer value="some text" transform="noop" /> |
268+
| SOME TEXT | lowercase | <TextRenderer value="SOME TEXT" transform="lowercase" /> |
269+
| some text | uppercase | <TextRenderer value="some text" transform="uppercase" /> |
270+
</div>
271+
<section className="accordion">
272+
<input type="checkbox" name="collapse6" id="preview6" tabIndex="0" />
273+
<div className="handle" >
274+
<label htmlFor="preview6">source code</label>
275+
</div>
276+
<div className="content">
277+
<Source code={`
278+
<TextRenderer value={"some text"} transform="noop" />
279+
<TextRenderer value={"SOME TEXT"} transform="lowercase" />
280+
<TextRenderer value={"some text"} transform="uppercase" />
281+
`} dark />
282+
</div>
283+
</section>
284+
251285
<hr />
252286

253287
<div className="right">Visit the [Github Repository](https://github.com/khatastroffik/react-text-renderer-components)</div>

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ export * from './components/TimeRenderer';
44
export * from './components/DateTimeRenderer';
55
export * from './components/WeekRenderer';
66
export * from './components/QuarterRenderer';
7+
export * from './components/TextRenderer';

0 commit comments

Comments
 (0)