Skip to content

Commit

Permalink
chore(ui): UI components typescript integration (#162)
Browse files Browse the repository at this point in the history
* chore(juno-ui): integrate typescript without tests

* chore(juno-ui): migrate PageHeader component to typescript

* chore(ui): test and vitest configuration

* chore(ui): enable test together vitest and jest

* chore(ui): fix ts lint

* chore(ui): unified build to dist

* chore(ui): fix rollup build with ts

* chore(ui): format prettier

* chore(ui): rename dist to build

* chore(ui): rollback pageHeader component

* chore(ui): vitest supports svg import

* chore(ui): migrate IntroBox to ts

* chore(ui): format prettier
  • Loading branch information
barsukov authored Aug 2, 2024
1 parent ed9b963 commit 03e8205
Show file tree
Hide file tree
Showing 17 changed files with 19,875 additions and 9,704 deletions.
29,189 changes: 19,600 additions & 9,589 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion packages/eslint-config/juno-typescript.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export default [
},
},
{
files: ["**/*.js", "*.js", "*.config.js", "*.config.ts", "*.test.js", "*.mjs"],
files: ["**/*.js","**/*.jsx", "*.js", "*.jsx", "*.config.js", "*.config.ts", "*.test.js", "*.mjs"],
...tseslint.configs.disableTypeChecked,
},
...fixupConfigRules(pluginReactConfig),
Expand Down
20 changes: 16 additions & 4 deletions packages/ui-components/.storybook/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ const config = {
],
staticDirs: ["../public"],
webpackFinal: async (config) => {
// Default rule for images /\.(svg|ico|jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani|pdf)(\?.*)?$/
// Exclude SVG files so that they can be loaded via svgr
const fileLoaderRule = config.module.rules.find((rule) => rule.test && rule.test.test(".svg"))
fileLoaderRule.exclude = /\.svg$/

Expand All @@ -33,7 +31,7 @@ const config = {
config.module.rules.push({
test: /\.svg$/i,
enforce: "pre",
issuer: /\.jsx?$/,
issuer: /\.(js|jsx|ts|tsx)$/, // Updated to include ts and tsx
resourceQuery: { not: [/url/] }, // exclude react component if import filename *.svg?url
loader: require.resolve("@svgr/webpack"),
options: {
Expand Down Expand Up @@ -61,7 +59,6 @@ const config = {
"css-loader",
{
loader: "postcss-loader",
// important! use local installed postcss (version 8)
options: {
implementation: require("postcss"),
},
Expand All @@ -77,6 +74,20 @@ const config = {
],
include: [path.resolve(__dirname, "../src")],
})
// Add TypeScript support
config.module.rules.push({
test: /\.(ts|tsx)$/,
use: [
{
loader: require.resolve("ts-loader"),
options: {
transpileOnly: true,
configFile: path.resolve(__dirname, "tsconfig.storybook.json"), // Specify the path to your tsconfig.json
},
},
],
})
config.resolve.extensions.push(".ts", ".tsx")

return config
},
Expand All @@ -89,4 +100,5 @@ const config = {
autodocs: true,
},
}

export default config
8 changes: 8 additions & 0 deletions packages/ui-components/.storybook/tsconfig.storybook.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"composite": null,
"declaration": null,
"declarationMap": null,
},
}
2 changes: 1 addition & 1 deletion packages/ui-components/eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

import junoConfigs from "@cloudoperators/juno-eslint-config/juno.mjs"
import junoConfigs from "@cloudoperators/juno-eslint-config/juno-typescript.mjs"

export default [
...junoConfigs,
Expand Down
47 changes: 33 additions & 14 deletions packages/ui-components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"@babel/preset-env": "^7.20.2",
"@babel/preset-react": "^7.18.6",
"@cloudoperators/juno-eslint-config": "*",
"@cloudoperators/juno-typescript-config": "*",
"@floating-ui/react": "^0.25.1",
"@headlessui-float/react": "^0.11.2",
"@headlessui/react": "^1.7.15",
Expand All @@ -35,38 +36,43 @@
"@rollup/plugin-babel": "^6.0.3",
"@rollup/plugin-commonjs": "^24.0.0",
"@rollup/plugin-node-resolve": "^15.1.3",
"@storybook/addon-docs": "^7.5.3",
"@storybook/addon-essentials": "^7.5.3",
"@rollup/plugin-typescript": "11.1.6",
"@storybook/addon-docs": "^7.6.20",
"@storybook/addon-essentials": "^7.6.20",
"@storybook/addon-interactions": "^7.5.3",
"@storybook/addon-links": "^7.5.3",
"@storybook/addon-mdx-gfm": "^7.5.3",
"@storybook/addon-links": "^7.6.20",
"@storybook/addon-mdx-gfm": "^7.6.20",
"@storybook/addon-postcss": "^2.0.0",
"@storybook/blocks": "^7.5.3",
"@storybook/manager-api": "^7.5.3",
"@storybook/react": "^7.5.3",
"@storybook/react-webpack5": "^7.5.3",
"@storybook/react": "^7.6.20",
"@storybook/react-webpack5": "^7.6.20",
"@storybook/testing-library": "^0.2.2",
"@svgr/rollup": "^6.2.1",
"@svgr/webpack": "^6.2.1",
"@svgr/webpack": "^6.5.1",
"@testing-library/dom": "^10.3.2",
"@testing-library/jest-dom": "^6.4.6",
"@testing-library/jest-dom": "^6.4.8",
"@testing-library/react": "^16.0.0",
"@testing-library/user-event": "^14.5.2",
"@types/react": "^18.3.3",
"@vitejs/plugin-react": "^4.3.1",
"add": "^2.0.6",
"autoprefixer": "^10.4.2",
"babel-jest": "^29.3.1",
"babel-loader": "^8.2.3",
"css-loader": "^6.6.0",
"css-loader": "^6.11.0",
"flatpickr": "4.6.13",
"focus-trap-react": "^10.2.3",
"glob": "^8.1.0",
"jest": "^29.3.1",
"jest-environment-jsdom": "^29.3.1",
"jsdom": "^24.1.1",
"node-sass-glob-importer": "^3.0.2",
"postcss": "^8.4.6",
"postcss-loader": "^6.2.1",
"prop-types": "^15.8.1",
"react": "^18.2.0",
"react-docgen-typescript-loader": "^3.7.2",
"react-dom": "^18.2.0",
"react-jss": "^10.8.1",
"react-tabs": "^4.2.1",
Expand All @@ -79,10 +85,14 @@
"rollup-plugin-node-resolve": "^5.2.0",
"rollup-plugin-postcss": "^4.0.2",
"sass": "^1.49.7",
"sass-loader": "^12.4.0",
"sass-loader": "^12.6.0",
"storybook": "^7.6.17",
"style-loader": "^3.3.1",
"tailwindcss": "^3.3.1"
"tailwindcss": "^3.3.1",
"ts-loader": "^9.5.1",
"typescript": "^5.5.4",
"vite-plugin-svgr": "^4.2.0",
"vitest": "^2.0.5"
},
"peerDependencies": {
"prop-types": "15.8.1",
Expand All @@ -94,21 +104,30 @@
"build-storybook": "storybook build",
"build": "NODE_ENV=production rollup -c",
"dev": "NODE_ENV=development rollup -c -w",
"clean": "rm -rf build && rm -rf node_modules && rm -rf .turbo",
"lint": "eslint .",
"test": "jest",
"test:watch": "jest --watchAll"
"test": "npm run test-vitest && npm run test-jest",
"test-vitest": "vitest run",
"typecheck": "tsc --noEmit",
"test-jest": "jest",
"test:watch": "jest --watchAll",
"test-vitest:watch": "vitest"
},
"jest": {
"verbose": true,
"testEnvironment": "jsdom",
"transformIgnorePatterns": [
"node_modules/(?!(react-merge-refs)/)"
],
"testMatch": [
"**/__tests__/**/*.[j]s?(x)",
"**/?(*.)+(spec|test).[j]s?(x)"
],
"setupFilesAfterEnv": [
"./setupTests.js"
],
"transform": {
"\\.[jt]sx?$": "babel-jest",
"\\.[j]sx?$": "babel-jest",
"\\.mjs$": "babel-jest",
"^.+\\.svg$": "<rootDir>/test/__mocks__/svg.js"
},
Expand Down
65 changes: 38 additions & 27 deletions packages/ui-components/rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,19 @@ const analyze = require("rollup-plugin-analyzer")
const { nodeResolve } = require("@rollup/plugin-node-resolve")
const commonjs = require("@rollup/plugin-commonjs")
const svgr = require("@svgr/rollup")
const typescript = require("@rollup/plugin-typescript")
const path = require("path")
const glob = require("glob")
const { generateTailwindThemeClassesJson } = require("./src/docs/ColorPalette/generateTailwindThemeClassesJson")

// generates tailwind classes for documentation usages.
generateTailwindThemeClassesJson()

// IMPORTANT!
// package.json is single source of truth policy

// Ensure the module value in package.json is correct
if (!/.+\/.+\.js/.test(pkg.module)) throw new Error("module value is incorrect, use DIR/FILE.js like build/index.js")
const buildDir = pkg.module.slice(0, pkg.module.lastIndexOf("/"))
// filename is extracted from module key in package.json
// because of single source of truth policy
const buildDir = "build"
const filename = pkg.module.slice(pkg.module.lastIndexOf("/") + 1, pkg.module.lastIndexOf("."))

// define plugins here to use it in different configs
const plugins = [
svgr({
svgo: false,
Expand All @@ -39,17 +36,15 @@ const plugins = [
path: "./postcss.config.js",
},
extract: false,
minimize: false, //true,
minimize: false,
inject: false,
extensions: [".scss", ".css"],
use: ["sass", "glob-imports"],
loaders: [
// custom loader!!! to load all scss files in globals.scss
{
name: "glob-imports",
test: /\.(sass|scss)$/,
process({ code }) {
// handle glob import
return new Promise((resolve, _reject) => {
const match = [...code.matchAll(/@import\s+(.*\*+.*);/g)]
match.forEach((m) => {
Expand All @@ -66,9 +61,6 @@ const plugins = [

nodeResolve(),
babel({
// babelrc: false,
// // exclude: "node_modules/**",
// presets: ["@babel/preset-react"],
babelHelpers: "bundled",
}),
commonjs(),
Expand All @@ -77,34 +69,53 @@ const plugins = [
summaryOnly: true,
limit: 0,
}),
typescript({ tsconfig: path.resolve(__dirname, "./tsconfig.build.json") }), // Reference tsconfig.build.json
]

// input is a map of all components of format { [componentName]: path }
// it is also contains the main entry point of the library (pkg.source)
const input = fs.readdirSync("./src/components").reduce(
(map, file) => {
map[file] = `src/components/${file}/index.js`
return map
},
{ [filename]: pkg.source }
)
// Function to get component paths
function getComponentPaths() {
const componentsDir = path.resolve(__dirname, "src/components")
const components = fs.readdirSync(componentsDir)

return components.reduce(
(map, file) => {
const componentPath = path.join(componentsDir, file)
const componentName = path.basename(file, path.extname(file)) // Get the component name without extension

if (/\.test\.[tj]sx?$/.test(file) || /\.stories\.[tj]sx?$/.test(file)) {
// Skip test and story files
return map
}

if (fs.lstatSync(componentPath).isDirectory()) {
const indexFile = ["index.ts", "index.js"].find((file) => fs.existsSync(path.join(componentPath, file)))
if (indexFile) {
map[componentName] = path.join(componentPath, indexFile)
}
} else {
map[componentName] = componentPath
}

return map
},
{ [filename]: pkg.source }
)
}

const input = getComponentPaths()

const config = [
// bundle all components
{
input,
output: [
// { dir: "lib", format: "cjs", preserveModules: false },
{
dir: buildDir,
dir: buildDir, // Ensure this matches the `outDir` in tsconfig.build.json
format: "esm",
preserveModules: false,
compact: true,
},
],

plugins: [del({ targets: [`${buildDir}/**/*`] }), ...plugins],

external: Object.keys(pkg.peerDependencies || {}),
},
{
Expand Down
2 changes: 1 addition & 1 deletion packages/ui-components/src/components/Form/Form.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { CheckboxGroup } from "../CheckboxGroup/index.js"
import { Checkbox } from "../Checkbox/index.js"
import { Button } from "../Button/index.js"
import { ButtonRow } from "../ButtonRow/index.js"
import { IntroBox } from "../IntroBox/index.js"
import { IntroBox } from "../IntroBox/index"

export default {
title: "Forms/Form",
Expand Down
Loading

0 comments on commit 03e8205

Please sign in to comment.