diff --git a/package.json b/package.json index 546876e0..89ebafcb 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,8 @@ ], "scripts": { "serve": "vue-cli-service serve", - "build": "vue-cli-service build", + "build": "yarn build:dist && vue-cli-service build", + "build:dist": "cd ./packages/kiwi-core && yarn build && cd ../../", "lint": "vue-cli-service lint", "test:unit": "vue-cli-service test:unit", "lerna:build": "lerna run build", @@ -26,7 +27,7 @@ "deploy-storybook": "storybook-to-ghpages -- --out=.out", "now-build-storybook": "build-storybook -o dist/storybook" }, - "devDependencies": { + "dependencies": { "@babel/core": "^7.7.4", "@babel/plugin-proposal-object-rest-spread": "^7.7.4", "@babel/plugin-transform-modules-commonjs": "^7.7.4", @@ -106,6 +107,5 @@ "vue-lorem-ipsum": "^0.0.1", "vue-template-compiler": "^2.6.10", "vuepress": "^1.2.0" - }, - "dependencies": {} + } } diff --git a/packages/kiwi-core/package.json b/packages/kiwi-core/package.json index efe6a652..b2787eec 100644 --- a/packages/kiwi-core/package.json +++ b/packages/kiwi-core/package.json @@ -11,7 +11,7 @@ "private": false, "scripts": { "build": "yarn clean && rollup -c && rollup -c --environment MINIFY", - "build:watch": "rollup -c --watch", + "build:watch": "rollup -c rollup.dev.config.js --watch", "test": "echo testing ...", "clean": "rm -rf ./dist" }, diff --git a/packages/kiwi-core/rollup.config.js b/packages/kiwi-core/rollup.config.js index cff4d9c6..1f5f003c 100644 --- a/packages/kiwi-core/rollup.config.js +++ b/packages/kiwi-core/rollup.config.js @@ -1,7 +1,9 @@ import babel from 'rollup-plugin-babel' import resolve from 'rollup-plugin-node-resolve' import cjs from 'rollup-plugin-commonjs' -import { terser } from 'rollup-plugin-terser' +import { + terser +} from 'rollup-plugin-terser' import buble from 'rollup-plugin-buble' import vue from 'rollup-plugin-vue' import pkg from './package.json' @@ -66,14 +68,14 @@ const commons = { ] } -// const bannerTxt = `/*! Chakra-Vui v${pkg.version} | MIT License | github.com/codebender828/kiwi-ui */` +const bannerTxt = `/*! Chakra-ui/vue v${pkg.version} | MIT License | github.com/codebender828/kiwi-ui */` const baseFolder = './src/' -// const capitalize = (s) => { -// if (typeof s !== 'string') return '' -// return s.charAt(0).toUpperCase() + s.slice(1) -// } +const capitalize = (s) => { + if (typeof s !== 'string') return '' + return s.charAt(0).toUpperCase() + s.slice(1) +} const components = fs.readdirSync(baseFolder) .filter((f) => fs.statSync(path.join(baseFolder, f)).isDirectory()) @@ -86,30 +88,10 @@ const entries = { }, {}) } -// console.log(entries) - /** * Configurations */ export default () => { - // const mapComponent = (name) => { - // return [{ - // input: baseFolder + `${name}/index.js`, - // external: externals, - // output: { - // format: 'umd', - // name: capitalize(name), - // file: `dist/components/${name}/index.js`, - // banner: bannerTxt, - // exports: 'named', - // globals: { - // vue: 'Vue' - // } - // }, - // ...commons - // }] - // } - let config = [{ input: entries, output: { @@ -117,51 +99,30 @@ export default () => { format: 'esm' }, ...commons + }, + { + input: entries, + output: { + dir: `dist/cjs/`, + format: 'cjs', + exports: 'named' + }, + ...commons + }, + { + input: './src/index.js', + output: { + file: `dist/umd/index.js/`, + name: capitalize('chakra'), + format: 'umd', + exports: 'named', + banner: bannerTxt, + globals: { + vue: 'Vue' + } + }, + ...commons } - // { - // input: entries, - // output: { - // dir: `dist/es/`, - // format: 'es' - // }, - // ...commons - // }, - // { - // input: entries, - // output: { - // dir: `dist/cjs/`, - // format: 'cjs', - // exports: 'named' - // }, - // ...commons - // }, - // { - // input: './src/index.js', - // output: { - // file: `dist/umd/index.js/`, - // name: capitalize('chakra'), - // format: 'umd', - // exports: 'named', - // banner: bannerTxt, - // globals: { - // vue: 'Vue' - // } - // }, - // ...commons - // } - // { - // input: './src/index.js', - // output: { - // file: 'dist/chakra-vui.esm.js', - // name: capitalize('chakra'), - // format: 'esm', - // exports: 'named', - // banner: bannerTxt - // }, - // ...commons - // } - // Individual components - // ...components.map((f) => mapComponent(f)).reduce((r, a) => r.concat(a), []) ] if (process.env.MINIFY === 'true') { config = config.filter((c) => !!c.output.file) diff --git a/packages/kiwi-core/rollup.dev.config.js b/packages/kiwi-core/rollup.dev.config.js new file mode 100644 index 00000000..3fc394d8 --- /dev/null +++ b/packages/kiwi-core/rollup.dev.config.js @@ -0,0 +1,96 @@ +import babel from 'rollup-plugin-babel' +import resolve from 'rollup-plugin-node-resolve' +import cjs from 'rollup-plugin-commonjs' +import { terser } from 'rollup-plugin-terser' +import buble from 'rollup-plugin-buble' +import vue from 'rollup-plugin-vue' +import pkg from './package.json' +import fs from 'fs' +import path from 'path' + +const production = !process.env.ROLLUP_WATCH + +// Plugins +const bubelConfig = buble({ + objectAssign: 'Object.assign', + jsx: 'h', + transforms: { + dangerousTaggedTemplateString: true, + dangerousForOf: true + } +}) + +const babelConfig = babel({ + exclude: /node_modules/, + runtimeHelpers: true, + babelrc: false, + presets: [ + [ + '@babel/preset-env', { + modules: false + } + ] + ], + plugins: [ + 'babel-plugin-transform-es2015-for-of' + ] +}) + +const vueConfig = vue({ + template: { + isProduction: true + } +}) + +// Externals +const externals = [ + ...Object.keys(pkg.peerDependencies || {}) +] + +const commons = { + external: externals, + plugins: [ + resolve({ + extensions: ['.vue', '.js'] + }), + bubelConfig, + babelConfig, + vueConfig, + cjs({ + namedExports: { + 'node_modules/object-assign/index.js': ['assign'] + }, + include: /node_modules/ + }), + production && terser() + ] +} + +const baseFolder = './src/' + +const components = fs.readdirSync(baseFolder) + .filter((f) => fs.statSync(path.join(baseFolder, f)).isDirectory()) + +const entries = { + 'index': './src/index.js', + ...components.reduce((obj, name) => { + obj[name] = (baseFolder + name + '/index.js') + return obj + }, {}) +} + +/** + * Configurations + */ +export default () => { + let config = [{ + input: entries, + output: { + dir: `dist/esm/`, + format: 'esm' + }, + ...commons + } + ] + return config +} diff --git a/packages/kiwi-core/src/FormControl/formcontrol.props.js b/packages/kiwi-core/src/FormControl/formcontrol.props.js new file mode 100644 index 00000000..15fd45ef --- /dev/null +++ b/packages/kiwi-core/src/FormControl/formcontrol.props.js @@ -0,0 +1,6 @@ +export const formControlProps = { + isInvalid: Boolean, + isRequired: Boolean, + isDisabled: Boolean, + isReadOnly: Boolean +} diff --git a/packages/kiwi-core/src/FormControl/index.js b/packages/kiwi-core/src/FormControl/index.js index 9df54667..f1ecc26e 100644 --- a/packages/kiwi-core/src/FormControl/index.js +++ b/packages/kiwi-core/src/FormControl/index.js @@ -1,15 +1,13 @@ import { baseProps } from '../config' import Box from '../Box' import { forwardProps } from '../utils' +import { formControlProps } from './formcontrol.props' const FormControl = { name: 'FormControl', props: { ...baseProps, - isInvalid: Boolean, - isRequired: Boolean, - isDisabled: Boolean, - isReadOnly: Boolean + ...formControlProps }, inject: { $FormControlContext: { @@ -28,7 +26,8 @@ const FormControl = { isInvalid: this.isInvalid, isRequired: this.isRequired, isDisabled: this.isDisabled, - isReadOnly: this.isReadOnly + isReadOnly: this.isReadOnly, + id: this.$attrs.id } } }, diff --git a/packages/kiwi-core/src/FormErrorMessage/index.js b/packages/kiwi-core/src/FormErrorMessage/index.js new file mode 100644 index 00000000..82364a43 --- /dev/null +++ b/packages/kiwi-core/src/FormErrorMessage/index.js @@ -0,0 +1,67 @@ +import { baseProps } from '../config' +import { formControlProps } from '../FormControl/formcontrol.props' +import Flex from '../Flex' +import Icon from '../Icon' +import Text from '../Text' +import { forwardProps } from '../utils' + +const FormErrorMessage = { + name: 'FormErrorMessage', + inject: ['$colorMode', '$useFormControl'], + props: { + ...baseProps, + icon: { + type: String, + default: 'warning' + }, + ...formControlProps + }, + computed: { + formControl () { + return this.$useFormControl(this.$props) + }, + colorMode () { + return this.$colorMode() + } + }, + render (h) { + if (!this.formControl.isInvalid) { + return null + } + + const color = { + light: 'red.500', + dark: 'red.300' + } + + return h(Flex, { + props: { + ...forwardProps(this.$props), + color: color[this.colorMode], + mt: 2, + fontSize: 'sm', + align: 'center' + }, + attrs: { + id: this.formControl.id ? `${this.formControl.id}-error-message` : null + } + }, [ + h(Icon, { + props: { + name: this.icon, + mr: '0.5em' + }, + attrs: { + 'aria-hidden': true + } + }), + h(Text, { + props: { + lineHeight: 'normal' + } + }, this.$slots.default) + ]) + } +} + +export default FormErrorMessage diff --git a/packages/kiwi-core/src/FormHelperText/index.js b/packages/kiwi-core/src/FormHelperText/index.js new file mode 100644 index 00000000..29d059f3 --- /dev/null +++ b/packages/kiwi-core/src/FormHelperText/index.js @@ -0,0 +1,35 @@ +import Text from '../Text' +import { baseProps } from '../config' +import { forwardProps } from '../utils' + +const FormHelperText = { + name: 'FormHelperText', + inject: ['$useFormControl', '$colorMode'], + props: baseProps, + computed: { + formControl () { + return this.$useFormControl(this.$props) + }, + colorMode () { + return this.$colorMode() + } + }, + render (h) { + const color = { light: 'gray.500', dark: 'whiteAlpha.600' } + + return h(Text, { + props: { + ...forwardProps(this.$props), + mt: 2, + color: color[this.colorMode], + lineHeight: 'normal', + fontSize: 'sm' + }, + attrs: { + id: this.formControl.id ? `${this.formControl.id}-help-text` : null + } + }, this.$slots.default) + } +} + +export default FormHelperText diff --git a/packages/kiwi-core/src/FormLabel/index.js b/packages/kiwi-core/src/FormLabel/index.js index c6238dae..b68062f5 100644 --- a/packages/kiwi-core/src/FormLabel/index.js +++ b/packages/kiwi-core/src/FormLabel/index.js @@ -1,6 +1,7 @@ import Box from '../Box' import { baseProps } from '../config' import { forwardProps } from '../utils' +import { formControlProps } from '../FormControl/formcontrol.props' const RequiredIndicator = { name: 'RequiredIndicator', @@ -33,10 +34,7 @@ const FormLabel = { inject: ['$useFormControl'], props: { ...baseProps, - isInvalid: Boolean, - isRequired: Boolean, - isDisabled: Boolean, - isReadOnly: Boolean + ...formControlProps }, computed: { formControlProps () { diff --git a/packages/kiwi-core/src/index.js b/packages/kiwi-core/src/index.js index b4842196..9ae20e10 100644 --- a/packages/kiwi-core/src/index.js +++ b/packages/kiwi-core/src/index.js @@ -55,3 +55,5 @@ export * from './InputAddon' export { default as InputElement } from './InputElement' export * from './InputElement' export { default as InputGroup } from './InputGroup' +export { default as FormErrorMessage } from './FormErrorMessage' +export { default as FormHelperText } from './FormHelperText' diff --git a/packages/kiwi-core/src/lib/internal-icons.js b/packages/kiwi-core/src/lib/internal-icons.js index 1e4387f5..9e112755 100644 --- a/packages/kiwi-core/src/lib/internal-icons.js +++ b/packages/kiwi-core/src/lib/internal-icons.js @@ -181,6 +181,13 @@ const icons = { ` + }, + warning: { + path: ` + ` } } diff --git a/src/App.vue b/src/App.vue index cd0f6577..57d1394c 100644 --- a/src/App.vue +++ b/src/App.vue @@ -8,12 +8,15 @@ - - - - - - + + + + + + + + Add your website here + @@ -31,7 +34,9 @@ import { Stack, Button, Heading, - useToast } from '../packages/kiwi-core/dist/esm' + useToast, + FormControl, + FormHelperText } from '../packages/kiwi-core/dist/esm' export default { name: 'App', @@ -45,7 +50,9 @@ export default { Icon, Stack, Button, - Heading + Heading, + FormControl, + FormHelperText }, data () { return { diff --git a/stories/33-FormControl.stories.js b/stories/33-FormControl.stories.js index e32854ee..99019436 100644 --- a/stories/33-FormControl.stories.js +++ b/stories/33-FormControl.stories.js @@ -1,5 +1,5 @@ import { storiesOf } from '@storybook/vue' -import { Input, FormControl, FormLabel } from '../packages/kiwi-core/src' +import { Input, FormControl, FormLabel, Icon, Stack, InputGroup, InputLeftElement, InputRightElement, FormHelperText, FormErrorMessage } from '../packages/kiwi-core/src' storiesOf('UI | FormControl', module) .add('Basic Usage', () => ({ @@ -11,3 +11,43 @@ storiesOf('UI | FormControl', module) ` })) + .add('With Form Helper Text', () => ({ + components: { Input, FormControl, Stack, Icon, InputGroup, InputLeftElement, InputRightElement, FormHelperText }, + template: ` +
+ + + + + + + Add your website here + +
+ `, + data () { + return { + shouldShowPassword: false + } + } + })) + .add('With Form Validation Message', () => ({ + components: { Input, FormControl, Stack, Icon, InputGroup, InputLeftElement, InputRightElement, FormErrorMessage }, + template: ` +
+ + + + + + + Website is invalid + +
+ `, + data () { + return { + shouldShowPassword: false + } + } + }))