Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(ui): UI components typescript integration #162

Merged
merged 15 commits into from
Aug 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29,963 changes: 19,987 additions & 9,976 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
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
Loading