Skip to content

Commit

Permalink
feat: typescript
Browse files Browse the repository at this point in the history
+ Migrate core logic to typescript
+ Update rollup config to support TS
+ Add initial tsconfig
+ Remove manual typings
  • Loading branch information
breadadams committed Nov 11, 2022
1 parent 2602489 commit 620950e
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 54 deletions.
12 changes: 8 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,13 @@
"@babel/preset-react": "latest",
"@rollup/plugin-babel": "latest",
"@rollup/plugin-terser": "latest",
"@rollup/plugin-typescript": "latest",
"@storybook/builder-webpack5": "latest",
"@storybook/manager-webpack5": "latest",
"@storybook/react": "latest",
"@types/react": "^18",
"babel-loader": "latest",
"html-webpack-plugin": "latest",
"finepack": "latest",
"nano-staged": "latest",
"prettier-standard": "latest",
"prop-types": "latest",
Expand All @@ -46,7 +48,9 @@
"rollup-plugin-visualizer": "latest",
"simple-git-hooks": "latest",
"standard": "latest",
"standard-markdown": "latest"
"standard-markdown": "latest",
"ts-standard": "latest",
"typescript": "latest"
},
"engines": {
"node": ">= 8"
Expand All @@ -59,7 +63,7 @@
"build": "NODE_ENV=production rollup -c rollup.config.js --bundleConfigAsCjs",
"build-storybook": "NODE_ENV=production build-storybook",
"dev": "start-storybook -p 6006",
"lint": "standard-markdown && standard src stories",
"lint": "standard-markdown && ts-standard src && standard stories",
"prepare": "npx simple-git-hooks",
"prepublishOnly": "npm run build",
"pretest": "npm run lint",
Expand Down Expand Up @@ -89,5 +93,5 @@
],
"parser": "@babel/eslint-parser"
},
"typings": "typings/index.d.ts"
"types": "dist/index.d.ts"
}
4 changes: 3 additions & 1 deletion rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ import { visualizer } from 'rollup-plugin-visualizer'
import terser from '@rollup/plugin-terser'
import filesize from 'rollup-plugin-filesize'
import babel from '@rollup/plugin-babel'
import typescript from '@rollup/plugin-typescript'
import fs from 'fs'

import pkg from './package.json'

const babelRc = JSON.parse(fs.readFileSync('./.babelrc'))

export default {
input: 'src/index.js',
input: 'src/index.ts',
output: [
{
file: pkg.main,
Expand All @@ -32,6 +33,7 @@ export default {
babelHelpers: 'inline',
...babelRc
}),
typescript(),
terser(),
filesize(),
visualizer({ template: 'treemap' })
Expand Down
74 changes: 40 additions & 34 deletions src/index.js → src/index.ts
Original file line number Diff line number Diff line change
@@ -1,45 +1,68 @@
import { createElement, useRef, useEffect, useCallback } from 'react'
import PropTypes from 'prop-types'
import { createElement, useRef, useEffect, useCallback, useMemo } from 'react'

interface Props {
accessibility?: boolean
debounce?: number
ellipsis?: string
is?: string
lines?: number
text: string
}

const DEFAULT_ELLIPSIS = '…'
const DEFAULT_TEXT = '.'

const debounceFn = (func, timeoutMs) => {
let timeout
const later = () => {
timeout = null
const debounceFn = (func: () => void, timeoutMs: number): () => void => {
let timeout: NodeJS.Timeout | undefined

const later = (): void => {
timeout = undefined
func()
}

return () => {
const callNow = !timeout
const callNow = timeout == null
clearTimeout(timeout)
timeout = setTimeout(later, timeoutMs)
if (callNow) func()
}
}

const NanoClamp = ({ accessibility, debounce, ellipsis, is, lines, text, ...props }) => {
const elementRef = useRef()
const textRef = useRef(DEFAULT_TEXT)

const NanoClamp = ({
accessibility = true,
debounce = 300,
ellipsis = DEFAULT_ELLIPSIS,
is = 'div',
lines = 3,
text,
...props
}: Props): JSX.Element | null => {
const elementRef = useRef<HTMLElement>(null)
const textRef = useRef<string>(DEFAULT_TEXT)

const clampProps = {
ref: elementRef,
...(accessibility ? { title: text } : {}),
...props
}

const hasText = useMemo(() => typeof text === 'string' && text.length > 0, [text])

const clampLines = useCallback(() => {
if (!text) return
if (!hasText) return

const updateTextRefs = newText => {
const updateTextRefs = (newText: string): void => {
textRef.current = newText
elementRef.current.innerText = newText

if (elementRef.current != null) {
elementRef.current.innerText = newText
}
}

updateTextRefs(DEFAULT_TEXT)

const lineHeight = elementRef.current.clientHeight + 1
const lineHeight = (elementRef.current?.clientHeight ?? 0) + 1
const maxHeight = lineHeight * lines + 1

const ellipsisLength = ellipsis === DEFAULT_ELLIPSIS ? 5 : ellipsis.length * 1.2
Expand All @@ -58,7 +81,7 @@ const NanoClamp = ({ accessibility, debounce, ellipsis, is, lines, text, ...prop
return
}

if (elementRef.current.clientHeight <= maxHeight) {
if ((elementRef.current?.clientHeight ?? 0) <= maxHeight) {
start = middle + 1
} else {
end = middle - 1
Expand All @@ -68,7 +91,7 @@ const NanoClamp = ({ accessibility, debounce, ellipsis, is, lines, text, ...prop
const textPlusEllipsis = text.slice(0, Math.max(middle - ellipsisLength, 0)).trim() + ellipsis

updateTextRefs(textPlusEllipsis)
}, [ellipsis, lines, text])
}, [ellipsis, hasText, lines, text])

useEffect(() => {
clampLines()
Expand All @@ -79,24 +102,7 @@ const NanoClamp = ({ accessibility, debounce, ellipsis, is, lines, text, ...prop
return () => window.removeEventListener('resize', clampLinesDebounced)
}, [clampLines, debounce])

return text ? createElement(is, clampProps, textRef.current) : null
}

NanoClamp.defaultProps = {
accessibility: true,
is: 'div',
lines: 3,
ellipsis: DEFAULT_ELLIPSIS,
debounce: 300
}

NanoClamp.propTypes = {
accessibility: PropTypes.bool,
is: PropTypes.string,
lines: PropTypes.number,
debounce: PropTypes.number,
text: PropTypes.string.isRequired,
ellipsis: PropTypes.string
return hasText ? createElement(is, clampProps, textRef.current) : null
}

export default NanoClamp
16 changes: 16 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"compilerOptions": {
"moduleResolution": "node",
"removeComments": false,
"sourceMap": true,
"target": "es2018",
"outDir": "dist",
"declaration": true,
"strict": true,
"module": "esnext",
"noEmitOnError": true,
"lib": ["dom", "es2017"],
"esModuleInterop": false
},
"include": ["src"]
}
15 changes: 0 additions & 15 deletions typings/index.d.ts

This file was deleted.

0 comments on commit 620950e

Please sign in to comment.