Skip to content

Commit a7097eb

Browse files
committed
feat(text): introduce @nivo/text package
1 parent f0ea985 commit a7097eb

14 files changed

+167
-133
lines changed

packages/core/index.d.ts

+6
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as React from 'react'
22
import { Interpolation, SpringConfig } from '@react-spring/web'
33
import { CurveFactory } from 'd3-shape'
44
import { ComponentType } from 'react'
5+
import { extendDefaultTheme } from './src'
56

67
export type DatumValue = string | number | Date
78

@@ -54,6 +55,7 @@ export type TextStyle = {
5455
fill: string
5556
outlineWidth: number
5657
outlineColor: string
58+
outlineOpacity: number
5759
} & Partial<React.CSSProperties>
5860

5961
export type CompleteTheme = {
@@ -265,6 +267,10 @@ export type Theme = Partial<{
265267

266268
export function useTheme(): CompleteTheme
267269
export function usePartialTheme(theme?: Theme): CompleteTheme
270+
export function extendDefaultTheme(
271+
defaultTheme: ThemeWithoutInheritance,
272+
customTheme: Theme
273+
): CompleteTheme
268274

269275
export type MotionProps = Partial<{
270276
animate: boolean

packages/core/src/theming/defaultTheme.js

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export const defaultTheme = {
1818
fill: '#333333',
1919
outlineWidth: 0,
2020
outlineColor: 'transparent',
21+
outlineOpacity: 1,
2122
},
2223
axis: {
2324
domain: {

packages/core/src/theming/extend.js

+13-17
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import merge from 'lodash/merge'
1010
import get from 'lodash/get'
1111
import set from 'lodash/set'
1212

13-
const textProps = [
13+
const textPropsWithInheritance = [
1414
'axis.ticks.text',
1515
'axis.legend.text',
1616
'legends.title.text',
@@ -23,6 +23,16 @@ const textProps = [
2323
'annotations.text',
2424
]
2525

26+
/**
27+
* @param {Partial<TextStyle>} partialStyle
28+
* @param {TextStyle} rootStyle
29+
* @returns {TextStyle}
30+
*/
31+
export const inheritRootThemeText = (partialStyle, rootStyle) => ({
32+
...rootStyle,
33+
...partialStyle,
34+
})
35+
2636
/**
2737
* @param {ThemeWithoutInheritance} defaultTheme
2838
* @param {Theme} customTheme
@@ -31,22 +41,8 @@ const textProps = [
3141
export const extendDefaultTheme = (defaultTheme, customTheme) => {
3242
const theme = merge({}, defaultTheme, customTheme)
3343

34-
textProps.forEach(prop => {
35-
if (get(theme, `${prop}.fontFamily`) === undefined) {
36-
set(theme, `${prop}.fontFamily`, theme.text.fontFamily)
37-
}
38-
if (get(theme, `${prop}.fontSize`) === undefined) {
39-
set(theme, `${prop}.fontSize`, theme.text.fontSize)
40-
}
41-
if (get(theme, `${prop}.fill`) === undefined) {
42-
set(theme, `${prop}.fill`, theme.text.fill)
43-
}
44-
if (get(theme, `${prop}.outlineWidth`) === undefined) {
45-
set(theme, `${prop}.outlineWidth`, theme.text.outlineWidth)
46-
}
47-
if (get(theme, `${prop}.outlineColor`) === undefined) {
48-
set(theme, `${prop}.outlineColor`, theme.text.outlineColor)
49-
}
44+
textPropsWithInheritance.forEach(prop => {
45+
set(theme, prop, inheritRootThemeText(get(theme, prop), theme.text))
5046
})
5147

5248
return theme

packages/core/src/theming/index.js

-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
* For the full copyright and license information, please view the LICENSE
77
* file that was distributed with this source code.
88
*/
9-
export * from './propTypes'
109
export * from './defaultTheme'
1110
export * from './extend'
1211
export * from './context'

packages/core/src/theming/propTypes.js

-115
This file was deleted.

packages/text/LICENSE.md

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Copyright (c) Raphaël Benitte
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy of
4+
this software and associated documentation files (the "Software"), to deal in
5+
the Software without restriction, including without limitation the rights to
6+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7+
of the Software, and to permit persons to whom the Software is furnished to do
8+
so, subject to the following conditions:
9+
10+
The above copyright notice and this permission notice shall be included in all
11+
copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19+
SOFTWARE.

packages/text/README.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<a href="https://nivo.rocks"><img alt="nivo" src="https://raw.githubusercontent.com/plouc/nivo/master/nivo.png" width="216" height="68"/></a>
2+
3+
# `@nivo/text`
4+
5+
[![version](https://img.shields.io/npm/v/@nivo/text?style=for-the-badge)](https://www.npmjs.com/package/@nivo/text)
6+
[![downloads](https://img.shields.io/npm/dm/@nivo/text?style=for-the-badge)](https://www.npmjs.com/package/@nivo/text)

packages/text/package.json

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
"name": "@nivo/text",
3+
"version": "0.86.0",
4+
"license": "MIT",
5+
"author": {
6+
"name": "Raphaël Benitte",
7+
"url": "https://github.com/plouc"
8+
},
9+
"repository": {
10+
"type": "git",
11+
"url": "https://github.com/plouc/nivo.git",
12+
"directory": "packages/text"
13+
},
14+
"sideEffects": false,
15+
"main": "./dist/nivo-text.cjs.js",
16+
"module": "./dist/nivo-text.es.js",
17+
"types": "./dist/types/index.d.ts",
18+
"files": [
19+
"README.md",
20+
"LICENSE.md",
21+
"dist/",
22+
"!dist/tsconfig.tsbuildinfo"
23+
],
24+
"dependencies": {
25+
"@nivo/core": "workspace:*",
26+
"@react-spring/web": "9.4.5 || ^9.7.2"
27+
},
28+
"peerDependencies": {
29+
"react": ">= 16.14.0 < 19.0.0"
30+
},
31+
"publishConfig": {
32+
"access": "public"
33+
}
34+
}

packages/text/src/Text.tsx

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { PropsWithChildren, ComponentType } from 'react'
2+
import { animated } from '@react-spring/web'
3+
import { TextStyle as ThemeStyle } from '@nivo/core'
4+
5+
type GetComponentProps<T> = T extends ComponentType<infer P> ? P : never
6+
type AnimatedComponentProps = GetComponentProps<(typeof animated)['text']>
7+
8+
type TextProps = PropsWithChildren<
9+
Omit<AnimatedComponentProps, 'style'> & {
10+
style: AnimatedComponentProps['style'] &
11+
Pick<ThemeStyle, 'outlineWidth' | 'outlineColor' | 'outlineOpacity'>
12+
}
13+
>
14+
15+
export const Text = ({ style: fullStyle, children, ...attributes }: TextProps) => {
16+
const { outlineWidth, outlineColor, outlineOpacity, ...style } = fullStyle
17+
18+
return (
19+
<>
20+
{outlineWidth > 0 && (
21+
<animated.text
22+
{...attributes}
23+
style={{
24+
...style,
25+
strokeWidth: outlineWidth * 2,
26+
stroke: outlineColor,
27+
strokeOpacity: outlineOpacity,
28+
strokeLinejoin: 'round',
29+
}}
30+
>
31+
{children}
32+
</animated.text>
33+
)}
34+
<animated.text {...attributes} style={style}>
35+
{children}
36+
</animated.text>
37+
</>
38+
)
39+
}

packages/text/src/canvas.ts

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { TextStyle } from '@nivo/core'
2+
3+
export const setCanvasFont = (ctx: CanvasRenderingContext2D, style: TextStyle) => {
4+
ctx.font = `${style.fontWeight ? `${style.fontWeight} ` : ''}${style.fontSize}px ${
5+
style.fontFamily
6+
}`
7+
}
8+
9+
export const drawCanvasText = (
10+
ctx: CanvasRenderingContext2D,
11+
style: TextStyle,
12+
text: string,
13+
x = 0,
14+
y = 0
15+
) => {
16+
if (style.outlineWidth > 0) {
17+
ctx.strokeStyle = style.outlineColor
18+
ctx.lineWidth = style.outlineWidth * 2
19+
ctx.lineJoin = 'round'
20+
ctx.strokeText(text, x, y)
21+
}
22+
23+
ctx.fillStyle = style.fill
24+
ctx.fillText(text, x, y)
25+
}

packages/text/src/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './canvas'
2+
export * from './Text'

packages/text/tsconfig.json

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"extends": "../../tsconfig.types.json",
3+
"compilerOptions": {
4+
"baseUrl": ".",
5+
"outDir": "./dist/types",
6+
"rootDir": "./src"
7+
},
8+
"include": ["src/**/*"]
9+
}

pnpm-lock.yaml

+12
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tsconfig.monorepo.json

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// { "path": "./packages/core" },
66

77
// Shared next because charts need them
8+
{ "path": "./packages/text" },
89
{ "path": "./packages/canvas" },
910
{ "path": "./packages/annotations" },
1011
{ "path": "./packages/scales" },

0 commit comments

Comments
 (0)