Skip to content

Commit

Permalink
chore: fix build errors
Browse files Browse the repository at this point in the history
ChrisUser committed Dec 2, 2023
1 parent 6133780 commit 6cd36b4
Showing 6 changed files with 212 additions and 246 deletions.
3 changes: 1 addition & 2 deletions index.html
Original file line number Diff line number Diff line change
@@ -2,9 +2,8 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>React Usage Bar</title>
<title>React Usage Bar - Development</title>
</head>
<body>
<div id="root"></div>
374 changes: 158 additions & 216 deletions lib/UsageBar.tsx
Original file line number Diff line number Diff line change
@@ -1,252 +1,194 @@
import * as React from "react"
import "./index.css"
import * as React from 'react'
import './index.css'

interface Item {
color?: string
className?: string
dotClassName?: string
value: number
name: string
color?: string
className?: string
dotClassName?: string
value: number
name: string
}

interface Props {
items: Item[]
total: number
darkMode?: boolean
showLabels?: boolean
showPercentage?: boolean
compactLayout?: boolean
showFallbackColors?: boolean
errorMessage?: string

usageBarContainerClassName?: string
usageBarClassName?: string
tooltipClassName?: string
errorMessageClassName?: string
items: Item[]
total: number
darkMode?: boolean
showLabels?: boolean
showPercentage?: boolean
compactLayout?: boolean
showFallbackColors?: boolean
errorMessage?: string

usageBarContainerClassName?: string
usageBarClassName?: string
tooltipClassName?: string
errorMessageClassName?: string
}

const lightColors: string[] = [
"#F72585", // Flickr Pink
"#B5179E", // Byzantine (Purple)
"#7C0FC4", // French Violet
"#4900BD", // Medium Blue
"#3053F1", // Blue RYB
"#009688", // Pine Green
"#DF9541", // Carrot Orange
"#008049", // Sea Green
"#80452E", // Bole (Light brown)
"#D32A00", // Rosso Corsa (Red)
'#F72585', // Flickr Pink
'#B5179E', // Byzantine (Purple)
'#7C0FC4', // French Violet
'#4900BD', // Medium Blue
'#3053F1', // Blue RYB
'#009688', // Pine Green
'#DF9541', // Carrot Orange
'#008049', // Sea Green
'#80452E', // Bole (Light brown)
'#D32A00' // Rosso Corsa (Red)
]
const darkColors: string[] = [
"#4BBCDF", // Cyan Process
"#E8BB4A", // Maximum Yellow Red
"#9A32DF", // Purple X 11
"#E76AA2", // China Pink
"#4361EE", // Ultramarine Blue
"#439990", // Viridian Green
"#B583F1", // Lavender Floral
"#EC8C1D", // Carrot Orange
"#47CE69", // Emerald
"#989BAC", // Manatee (Blue/Gray)
'#4BBCDF', // Cyan Process
'#E8BB4A', // Maximum Yellow Red
'#9A32DF', // Purple X 11
'#E76AA2', // China Pink
'#4361EE', // Ultramarine Blue
'#439990', // Viridian Green
'#B583F1', // Lavender Floral
'#EC8C1D', // Carrot Orange
'#47CE69', // Emerald
'#989BAC' // Manatee (Blue/Gray)
]

const getPercentageValue = (value: number, total: number): string =>
`${((value / total) * 100).toFixed(0)}%`
const getPercentageValue = (value: number, total: number): string => `${((value / total) * 100).toFixed(0)}%`

const shuffleArray = (a: string[]) => {
let j, x, i
for (i = a.length - 1; i > 0; i--) {
j = Math.floor(Math.random() * (i + 1))
x = a[i]
a[i] = a[j]
a[j] = x
}
return a
let j, x, i
for (i = a.length - 1; i > 0; i--) {
j = Math.floor(Math.random() * (i + 1))
x = a[i]
a[i] = a[j]
a[j] = x
}
return a
}

const appendCustomClass = (customClass?: string) => {
if (customClass) {
return customClass[0] === " " ? customClass : ` ${customClass}`
}
return ""
if (customClass) {
return customClass[0] === ' ' ? customClass : ` ${customClass}`
}
return ''
}

const UsageBar: React.FC<Props> = ({
darkMode = false,
showLabels = true,
showPercentage = false,
compactLayout = false,
showFallbackColors = false,
total,
items,
errorMessage = "Error: Total elements values exceed 100%.",
usageBarContainerClassName,
usageBarClassName,
tooltipClassName,
errorMessageClassName,
darkMode = false,
showLabels = true,
showPercentage = false,
compactLayout = false,
showFallbackColors = false,
total,
items,
errorMessage = 'Error: Total elements values exceed 100%.',
usageBarContainerClassName,
usageBarClassName,
tooltipClassName,
errorMessageClassName
}) => {
/**
* Checks if the total value is equal or greater than the sum of all the elements values.
*/
const itemsValuesAreCorrect = React.useMemo(
(): boolean =>
total >=
items.reduce((tot: number, element: Item) => tot + element.value, 0),
[items, total]
)

/**
* Returns an array of colors based on the value of `darkMode`.
* The colors are either from the `darkColors` array or the `lightColors` array.
* The chosen array is shuffled before being returned.
*/
const fallbackColors = React.useMemo(() => {
const colorsToPickFrom = darkMode ? [...darkColors] : [...lightColors]
shuffleArray(colorsToPickFrom)
return colorsToPickFrom
}, [])

/**
* Returns the color of an element based on certain conditions.
*
* @param element - The item for which the color needs to be determined.
* @param index - The index of the item in the list.
* @returns The color of the element, either from the `color` property or a fallback
* color from the `fallbackColors` array. If the `element` does not have a `color`
* property and `showFallbackColors` is false, null is returned.
*/
const getElementColor = React.useCallback(
(element: Item, index: number) => {
if (element.color) return element.color
return showFallbackColors
? fallbackColors[index % fallbackColors.length]
: null
},
[showFallbackColors, fallbackColors]
)

if (!itemsValuesAreCorrect)
return (
<span
className={`u-UsageBar__error${appendCustomClass(
errorMessageClassName
)}`}
>
{errorMessage}
</span>
/**
* Checks if the total value is equal or greater than the sum of all the elements values.
*/
const itemsValuesAreCorrect = React.useMemo((): boolean => total >= items.reduce((tot: number, element: Item) => tot + element.value, 0), [items, total])

/**
* Returns an array of colors based on the value of `darkMode`.
* The colors are either from the `darkColors` array or the `lightColors` array.
* The chosen array is shuffled before being returned.
*/
const fallbackColors = React.useMemo(() => {
const colorsToPickFrom = darkMode ? [...darkColors] : [...lightColors]
shuffleArray(colorsToPickFrom)
return colorsToPickFrom
}, [])

/**
* Returns the color of an element based on certain conditions.
*
* @param element - The item for which the color needs to be determined.
* @param index - The index of the item in the list.
* @returns The color of the element, either from the `color` property or a fallback
* color from the `fallbackColors` array. If the `element` does not have a `color`
* property and `showFallbackColors` is false, null is returned.
*/
const getElementColor = React.useCallback(
(element: Item, index: number) => {
if (element.color) return element.color
return showFallbackColors ? fallbackColors[index % fallbackColors.length] : null
},
[showFallbackColors, fallbackColors]
)

if (items.length === 0) return null
if (!itemsValuesAreCorrect) return <span className={`u-UsageBar__error${appendCustomClass(errorMessageClassName)}`}>{errorMessage}</span>

if (items.length === 0) return null

if (compactLayout) {
return (
<div className={`c-UsageBar ${darkMode ? 'u-UsageBar-dark' : 'u-UsageBar-light'}${appendCustomClass(usageBarContainerClassName)}`}>
<div className={`o-UsageBar__bar o-UsageBar__compact__bar${appendCustomClass(usageBarClassName)}`}>
{items.map((element: Item, index: number) => (
<UsageBarElement element={element} color={getElementColor(element, index)} total={total} key={index} />
))}
</div>
{showLabels && (
<div className="o-UsageBar__bar__elements__labels__container">
{items.map((element: Item, index: number) => {
const color = getElementColor(element, index)
return (
<div key={index} className="o-UsageBar__bar__elements__label">
<div
className={`o-UsageBar__bar__elements__label--dot${appendCustomClass(element.dotClassName)}`}
style={color ? { backgroundColor: color } : {}}
/>
<span>{element.name}</span>
{showPercentage && <UsageBarPercentageLabel element={element} total={total} />}
</div>
)
})}
</div>
)}
</div>
)
}

if (compactLayout) {
return (
<div
className={`c-UsageBar ${
darkMode ? "u-UsageBar-dark" : "u-UsageBar-light"
}${appendCustomClass(usageBarContainerClassName)}`}
>
<div
className={`o-UsageBar__bar o-UsageBar__compact__bar${appendCustomClass(
usageBarClassName
)}`}
>
{items.map((element: Item, index: number) => (
<UsageBarElement
element={element}
color={getElementColor(element, index)}
total={total}
key={index}
/>
))}
<div className={`c-UsageBar ${darkMode ? 'u-UsageBar-dark' : 'u-UsageBar-light'}${appendCustomClass(usageBarContainerClassName)}`}>
<div className={`o-UsageBar__bar${appendCustomClass(usageBarClassName)}`}>
{items.map((element: Item, index: number) => (
<UsageBarElement element={element} color={getElementColor(element, index)} total={total} key={index}>
{showLabels && (
<div className={`o-UsageBar__bar__tooltip${appendCustomClass(tooltipClassName)}`}>
<span>{element.name}</span>
{showPercentage && <UsageBarPercentageLabel element={element} total={total} />}
</div>
)}
</UsageBarElement>
))}
</div>
</div>
{showLabels && (
<div className="o-UsageBar__bar__elements__labels__container">
{items.map((element: Item, index: number) => {
const color = getElementColor(element, index)
return (
<div key={index} className="o-UsageBar__bar__elements__label">
<div
className={`o-UsageBar__bar__elements__label--dot${appendCustomClass(
element.dotClassName
)}`}
style={color ? { backgroundColor: color } : {}}
/>
<span>{element.name}</span>
{showPercentage && (
<UsageBarPercentageLabel element={element} total={total} />
)}
</div>
)
})}
</div>
)}
</div>
)
}

return (
<div
className={`c-UsageBar ${
darkMode ? "u-UsageBar-dark" : "u-UsageBar-light"
}${appendCustomClass(usageBarContainerClassName)}`}
>
<div className={`o-UsageBar__bar${appendCustomClass(usageBarClassName)}`}>
{items.map((element: Item, index: number) => (
<UsageBarElement
element={element}
color={getElementColor(element, index)}
total={total}
key={index}
>
{showLabels && (
<div
className={`o-UsageBar__bar__tooltip${appendCustomClass(
tooltipClassName
)}`}
>
<span>{element.name}</span>
{showPercentage && (
<UsageBarPercentageLabel element={element} total={total} />
)}
</div>
)}
</UsageBarElement>
))}
</div>
</div>
)
}

const UsageBarElement: React.FC<{
element: Item
color: string | null
total: number
children?: React.ReactNode
element: Item
color: string | null
total: number
children?: React.ReactNode
}> = ({ element, color, total, children }) => {
return (
<div
className={`o-UsageBar__bar__element${appendCustomClass(
element.className
)}`}
style={{
width: getPercentageValue(element.value, total),
...(color ? { backgroundColor: color } : null),
}}
>
{children}
</div>
)
return (
<div
className={`o-UsageBar__bar__element${appendCustomClass(element.className)}`}
style={{
width: getPercentageValue(element.value, total),
...(color ? { backgroundColor: color } : null)
}}
>
{children}
</div>
)
}

const UsageBarPercentageLabel: React.FC<{ element: Item; total: number }> = ({
element,
total,
}) => {
return (
<span className="o-UsageBar__bar__tooltip__percentage">
{getPercentageValue(element.value, total)}
</span>
)
const UsageBarPercentageLabel: React.FC<{ element: Item; total: number }> = ({ element, total }) => {
return <span className="o-UsageBar__bar__tooltip__percentage">{getPercentageValue(element.value, total)}</span>
}

export default UsageBar
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
@@ -20,5 +20,6 @@
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src", "lib"]
"include": ["src", "lib"],
"references": [{ "path": "./tsconfig.node.json" }]
}
11 changes: 11 additions & 0 deletions tsconfig.node.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"compilerOptions": {
"composite": true,
"skipLibCheck": true,
"module": "ESNext",
"moduleResolution": "bundler",
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts"],
"exclude": []
}
27 changes: 0 additions & 27 deletions vite.config.mjs

This file was deleted.

40 changes: 40 additions & 0 deletions vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { defineConfig } from 'vite'
import { extname, relative, resolve } from 'path'
import { fileURLToPath } from 'node:url'
import { glob } from 'glob'
import react from '@vitejs/plugin-react'
import dts from 'vite-plugin-dts'

// https://vitejs.dev/config/
export default defineConfig({
plugins: [react(), dts({ include: ['lib'] })],
build: {
copyPublicDir: false,
lib: {
entry: resolve(__dirname, 'lib/main.ts'),
formats: ['es']
},
rollupOptions: {
external: ['react', 'react/jsx-runtime'],
input: Object.fromEntries(
// https://rollupjs.org/configuration-options/#input
glob.sync('lib/**/*.{ts,tsx}').map((file) => [
// 1. The name of the entry point
// lib/nested/foo.js becomes nested/foo
relative('lib', file.slice(0, file.length - extname(file).length)),
// 2. The absolute path to the entry file
// lib/nested/foo.ts becomes /project/lib/nested/foo.ts
fileURLToPath(new URL(file, import.meta.url))
])
),
output: {
// assetFileNames: '[name][extname]',
assetFileNames: (assetInfo) => {
let assetName = assetInfo.name.split('.').at(0)
return `${assetName === 'style' ? 'index' : '[name]'}[extname]`
},
entryFileNames: '[name].js'
}
}
}
})

0 comments on commit 6cd36b4

Please sign in to comment.