Skip to content

Commit

Permalink
Merge pull request #69 from bywhitebird/64-create-the-whitebird-ui-co…
Browse files Browse the repository at this point in the history
…mponents

64 create the whitebird UI components
  • Loading branch information
arthur-fontaine authored Nov 11, 2023
2 parents 772dfd7 + 160c306 commit 68dda4f
Show file tree
Hide file tree
Showing 37 changed files with 2,604 additions and 232 deletions.
7 changes: 5 additions & 2 deletions apps/kazam/src/adapters/cli/commands/generate.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as fs from 'node:fs'
import path from 'node:path'

import { loadConfig } from 'c12'
import { Command } from 'commander'
Expand Down Expand Up @@ -32,9 +33,11 @@ export const generateCommand = new Command()
if (config === null || configFile === undefined)
throw new Error('Could not load config')

const rootDir = path.dirname(configFile)

const generatePromise = options.watch === true
? generateWatch(config, configFile, fs)
: generate(config, configFile, fs)
? generateWatch(config, rootDir, fs)
: generate(config, rootDir, fs)

render(
<GenerateView
Expand Down
8 changes: 4 additions & 4 deletions apps/kazam/src/adapters/cli/views/generate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ export const GenerateView = (
? { error: generateEvents.getLatestReceived('error')!.message }
: { pending: true },
)
const [writtenPaths, setWrittenPaths] = useState<string[]>([])
const [writtenPaths, setWrittenPaths] = useState(new Set<string>())

useLayoutEffect(() => {
generateEvents.on('pending', () => {
setStatus({ pending: true })
setWrittenPaths([])
setWrittenPaths(new Set())
})

generateEvents.on('success', () => {
Expand All @@ -41,7 +41,7 @@ export const GenerateView = (
})

generateEvents.on('file-written', filePath =>
setWrittenPaths(writtenPaths => [...writtenPaths, filePath]),
setWrittenPaths(writtenPaths => writtenPaths.add(filePath)),
)
}, [])

Expand All @@ -52,7 +52,7 @@ export const GenerateView = (
if ('success' in status) {
return <>
<Text><Text color="green"></Text> Successfully generated components</Text>
{writtenPaths.map(writtenPath =>
{Array.from(writtenPaths.values()).map(writtenPath =>
<Text key={writtenPath} color='gray'>{' '}{path.normalize(writtenPath)}</Text>,
)}
</>
Expand Down
7 changes: 2 additions & 5 deletions apps/kazam/src/application/usecases/generate-watch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,11 @@ import chokidar from 'chokidar'

import { generate } from './generate'

const getFilesToWatch = ([config, configPath]: Parameters<typeof generate>): string[] => {
const getFilesToWatch = ([config]: Parameters<typeof generate>): string[] => {
if (!Array.isArray(config))
config = [config]

return [
...config.flatMap(config => config.input),
configPath,
]
return config.flatMap(config => config.input)
}

export const generateWatch = (...argsGenerate: Parameters<typeof generate>) => {
Expand Down
20 changes: 10 additions & 10 deletions apps/kazam/src/application/usecases/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,15 @@ const getTransformedOutputFilePath = (
sourceFilePath: string,
transformer: Transformer,
config: Exclude<KazamConfig, unknown[]>,
configPath: string,
rootDir: string,
) => {
const sourceExtension = `.${sourceFilePath.split('.').slice(-1)[0]}` ?? ''
const transformedExtension = `.${filePath.split('.').slice(-1)[0]}` ?? ''

const transformerDirectory = getTransformerDirectory(transformer, config)

const outputFilePath = path.resolve(
path.dirname(configPath),
rootDir,
transformerDirectory,
filePath.replace(
new RegExp(`${sourceExtension.replace('.', '\\.')}${transformedExtension.replace('.', '\\.')}$`),
Expand All @@ -59,12 +59,12 @@ const formatResults = (
transformerResult: TransformerOutput<{ outputFileNameFormat: string }>,
transformer: Transformer,
config: Exclude<KazamConfig, unknown[]>,
configPath: string,
rootDir: string,
): Parameters<typeof writeResults>[0] => {
const formattedTransformerResult = new Map<string, string>()

transformerResult.forEach(({ filePath, content }, sourceFilePath) => {
const outputFilePath = getTransformedOutputFilePath(filePath, sourceFilePath, transformer, config, configPath)
const outputFilePath = getTransformedOutputFilePath(filePath, sourceFilePath, transformer, config, rootDir)

formattedTransformerResult.set(outputFilePath, content)
})
Expand All @@ -74,7 +74,7 @@ const formatResults = (

const generateForConfig = async (
config: Exclude<KazamConfig, unknown[]>,
configPath: string,
rootDir: string,
fileSystem?: typeof fs | undefined,
) => {
return Promise.all(
Expand All @@ -83,7 +83,7 @@ const generateForConfig = async (

const parserOutput = await parser.loadAndParse({
...config,
configPath,
rootDir,
})

return config.transformers.map((TransformerClass) => {
Expand All @@ -92,7 +92,7 @@ const generateForConfig = async (
return [key, {
...value,
getTransformedOutputFilePath: (filePath: string) =>
getTransformedOutputFilePath(filePath, value.sourceAbsoluteFilePath, TransformerClass, config, configPath),
getTransformedOutputFilePath(filePath, value.sourceAbsoluteFilePath, TransformerClass, config, rootDir),
}] as const
}),
)
Expand All @@ -103,7 +103,7 @@ const generateForConfig = async (

if (fileSystem) {
writeResults(
formatResults(transformerResult, TransformerClass, config, configPath),
formatResults(transformerResult, TransformerClass, config, rootDir),
fileSystem,
)
}
Expand All @@ -117,7 +117,7 @@ const generateForConfig = async (

export const generate = async (
config: KazamConfig,
configPath: string,
rootDir: string,
fileSystem?: typeof fs | undefined,
) => {
generateEvents.emit('pending', undefined)
Expand All @@ -126,7 +126,7 @@ export const generate = async (
config = [config]

const results = await Promise.all(
config.map(config => generateForConfig(config, configPath, fileSystem)),
config.map(config => generateForConfig(config, rootDir, fileSystem)),
)
.then(results => results.flat())
.then((results) => {
Expand Down
3 changes: 3 additions & 0 deletions apps/whitebird-ui/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Panda
styled-system
styled-system-static
26 changes: 26 additions & 0 deletions apps/whitebird-ui/.storybook/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { join, dirname } from "path";

/**
* This function is used to resolve the absolute path of a package.
* It is needed in projects that use Yarn PnP or are set up within a monorepo.
*/
function getAbsolutePath(value) {
return dirname(require.resolve(join(value, "package.json")));
}

const config = {
stories: ["../src/**/*.mdx", "../src/**/*.stories.@(ts)"],
addons: [
getAbsolutePath("@storybook/addon-links"),
getAbsolutePath("@storybook/addon-essentials"),
getAbsolutePath("@storybook/addon-onboarding"),
],
framework: {
name: getAbsolutePath("@whitebird/storybook-plugin-kaz-react-vite"),
options: {},
},
docs: {
autodocs: "tag",
},
};
export default config;
14 changes: 14 additions & 0 deletions apps/whitebird-ui/.storybook/preview-head.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<script type="module">
import '../src/index.css'
import '../src/fonts.css'
import { token } from '../styled-system/tokens'

document.head.insertAdjacentHTML(
'beforeend',
`<style>
body, .docs-story {
background-color: ${token.var('colors.appBackground')} !important;
}
</style>`
)
</script>
19 changes: 19 additions & 0 deletions apps/whitebird-ui/.storybook/preview.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const preview = {
parameters: {
actions: { argTypesRegex: "^on[A-Z].*" },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/i,
},
},
},
argTypes: {
className: {
type: 'string',
control: 'text',
},
},
};

export default preview;
6 changes: 6 additions & 0 deletions apps/whitebird-ui/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Whitebird UI

> **Important**
> To facilitate the development of the Whitebird UI, this project is currently in the repository of Kazam. Once Kazam is ready for production, the Whitebird UI will be moved to its own repository.
Whitebird UI exports a set of components built for Whitebird and a [Panda CSS](https://panda-css.com) preset.
11 changes: 11 additions & 0 deletions apps/whitebird-ui/kazam.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { ParserKaz } from '@whitebird/kazam-parser-kaz'
import { TransformerReact } from '@whitebird/kazam-transformer-react'
import { TransformerVue } from '@whitebird/kazam-transformer-vue'
import { defineConfig } from 'kazam'

export default defineConfig({
input: ['./src/components'],
output: './dist',
parsers: [ParserKaz],
transformers: [TransformerReact, TransformerVue],
})
58 changes: 58 additions & 0 deletions apps/whitebird-ui/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"name": "@whitebird/ui",
"type": "module",
"version": "0.0.0",
"license": "MIT",
"exports": {
"./panda-preset": {
"default": "./src/panda/whitebird-preset.ts"
},
"./vue/*": "./dist/vue/*.vue",
"./vue/*.vue": "./dist/vue/*.vue",
"./react/*": "./dist/react/*",
"./react/*.tsx": "./dist/react/*.tsx",
"./css": "./dist/whitebird.css",
"./css/whitebird": "./dist/whitebird.css",
"./css/whitebird.css": "./dist/whitebird.css",
"./css/fonts": "./src/fonts.css",
"./css/fonts.css": "./src/fonts.css"
},
"files": [
"dist",
"src/panda/whitebird-preset.ts",
"src/fonts.css"
],
"scripts": {
"prepare": "panda codegen",
"prebuild": "panda cssgen --outfile dist/whitebird.css",
"build": "kazam generate",
"build:watch": "kazam generate --watch",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"dev": "run-p build:watch start-storybook",
"start-storybook": "storybook dev -p 6006",
"build-storybook": "storybook build"
},
"dependencies": {
"@pandacss/dev": "^0.14.0",
"@pandacss/preset-base": "^0.18.2",
"@whitebird/kazam-parser-kaz": "workspace:*",
"@whitebird/kazam-transformer-react": "workspace:*",
"@whitebird/kazam-transformer-vue": "workspace:*",
"kazam": "workspace:*"
},
"devDependencies": {
"@storybook/addon-essentials": "^7.5.1",
"@storybook/addon-links": "^7.5.1",
"@storybook/addon-onboarding": "^1.0.8",
"@storybook/blocks": "^7.5.1",
"@storybook/builder-vite": "^7.5.1",
"@storybook/react": "^7.5.1",
"@storybook/react-vite": "^7.5.1",
"@storybook/testing-library": "^0.2.2",
"@types/node": "^18.11.9",
"@whitebird/storybook-plugin-kaz-react-vite": "workspace:*",
"npm-run-all": "^4.1.5",
"storybook": "^7.5.1"
}
}
26 changes: 26 additions & 0 deletions apps/whitebird-ui/panda.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { defineConfig } from '@pandacss/dev'

import { whitebirdPreset } from './src/panda/whitebird-preset'

export default defineConfig({
// Whether to use css reset
preflight: true,

include: [
'./src/components/**/*.{js,jsx,ts,tsx,kaz}',
'./src/stories/**/*.{js,jsx,ts,tsx,kaz}',
// NOTE: PandaCSS statically analyzes TSX files. However, it does not analyze
// Kaz files. Therefore, we need to include the compiled TSX files.
'./dist/react/**/*.{js,jsx,ts,tsx}',
],

// Files to exclude
exclude: [],

presets: [whitebirdPreset],

// The output directory for your css system
outdir: 'styled-system',

prefix: 'wb',
})
3 changes: 3 additions & 0 deletions apps/whitebird-ui/postcss.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
plugins: [require('@pandacss/dev/postcss')()],
}
53 changes: 53 additions & 0 deletions apps/whitebird-ui/src/components/Button.kaz
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
- import { css } from '../../styled-system/css'
- import { cx } from '../../styled-system/css'

- prop text: string
- prop variant: ('primary' | 'secondary' | 'tertiary') = 'primary'
- prop size: ('small' | 'normal') = 'normal'
- prop iconName: (string | undefined) = undefined
- prop onClick: () => void = () => {}
- prop className: string = ''

button(
class={cx(
css({
bg: variant === 'primary' ? 'highContrastForeground' : variant === 'secondary' ? 'uiElementBackground' : 'transparent',
color: variant === 'primary' ? 'appBackground' : 'highContrastForeground',
textStyle: 'label',
paddingX: size === 'small' ? 'xsmall' : 'medium',
paddingY: size === 'small' ? 'xxsmall' : 'medium',
cursor: 'pointer',
display: 'inline-flex',
alignItems: 'center',
outlineColor: 'transparent',
outlineStyle: 'solid',
outlineWidth: '2px',
outlineOffset: '2px',
_active: {
outlineColor: 'border',
},
_hover: {
outlineColor: 'borderHover',
},
}),
className,
)},
on:click={onClick}
) {
@if (iconName) {
div(
class={css({
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
marginRight: size === 'small' ? 'small' : 'medium',
width: '1em',
height: '1em',
fontSize: size === 'small' ? '0.75em' : '1em',
})}
) {
Icon(name={iconName}, size="1.5em", fill={false})
}
}
${text}
}
Loading

0 comments on commit 68dda4f

Please sign in to comment.