Skip to content
This repository was archived by the owner on Sep 20, 2024. It is now read-only.

Commit 7d33a7c

Browse files
Merge pull request #233 from chakra-ui/release/chakra-directive
`v-chakra` directive
2 parents 45c9fb2 + ccd9f56 commit 7d33a7c

File tree

25 files changed

+461
-28
lines changed

25 files changed

+461
-28
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@
9696
"color": "^3.1.2",
9797
"copy-to-clipboard": "^3.3.1",
9898
"core-js": "^3.6.4",
99+
"defu": "^2.0.4",
99100
"dotenv-defaults": "^1.1.1",
100101
"emotion": "^10.0.27",
101102
"eslint": "^5.16.0",

packages/chakra-ui-core/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Change Log
22

3+
## 0.5.10
4+
5+
### Patch Changes
6+
7+
- Adds the `v-chakra` directive for styling HTML elements
8+
39
## 0.5.9
410

511
### Patch Changes

packages/chakra-ui-core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@chakra-ui/vue",
3-
"version": "0.5.9",
3+
"version": "0.5.10",
44
"description": "Build Accessible and Responsive Vue.js applications with ease",
55
"main": "dist/cjs/index.js",
66
"module": "dist/esm/index.js",

packages/chakra-ui-core/src/Chakra/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import VScrollLock from 'v-scroll-lock'
22
import { merge } from 'lodash-es'
33
import { parsePackIcons } from '../utils/icons'
44
import internalIcons from '../lib/internal-icons'
5+
import { createClientDirective } from '../directives'
56
import defaultTheme from '../../../chakra-ui-theme/src'
67
import useToast from '../CToast'
78

@@ -62,6 +63,8 @@ const Chakra = {
6263
// Recursively merge extended theme variables
6364
const mergedTheme = merge(defaultTheme, options.extendTheme)
6465

66+
Vue.directive('chakra', createClientDirective(mergedTheme))
67+
6568
// Bind theme and icons to prototype
6669
Vue.prototype.$chakra = {
6770
theme: mergedTheme,
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import { css } from 'emotion'
2+
import Css from '../Css'
3+
import styleProps from '../config/props'
4+
import { camelize, kebabify } from '../utils'
5+
6+
/** Filter attrs and return object of chakra props */
7+
function filterChakraProps (attrs) {
8+
const pure = {}
9+
for (const prop in attrs) {
10+
if (styleProps[camelize(prop)]) {
11+
pure[camelize(prop)] = attrs[prop]
12+
}
13+
}
14+
return pure
15+
}
16+
17+
/** Purify Chakra attributes */
18+
function purifyAttrs (el, props) {
19+
for (const attr in props) {
20+
el.removeAttribute(attr)
21+
}
22+
}
23+
24+
/** Purify's Chakra Attributes from VNode object */
25+
function purifyVNodeAttrs (vnode, props) {
26+
if (props && vnode.data.attrs) {
27+
for (const attr in props) {
28+
delete vnode.data.attrs[kebabify(attr)]
29+
}
30+
}
31+
}
32+
33+
/** Creates className from styles object */
34+
function createClassName (styleObject, theme, hasBindingValue = false) {
35+
const pure = filterChakraProps(styleObject)
36+
if (hasBindingValue) {
37+
const className = css(Css(styleObject)(theme))
38+
return [className, pure]
39+
}
40+
const className = css(Css(pure)(theme))
41+
return [className, pure]
42+
}
43+
44+
/** Creates SSR `v-chakra` directive for Nuxt */
45+
export function createServerDirective (theme) {
46+
return (vnode, directive) => {
47+
const [className, pure] = createClassName(vnode.data.attrs, theme)
48+
if (vnode.data.class) {
49+
vnode.data.class += ` ${className}`
50+
} else {
51+
vnode.data.class = className
52+
}
53+
purifyVNodeAttrs(vnode, pure)
54+
55+
if (directive.value) {
56+
if (typeof directive.value === 'object') {
57+
const [className, pure] = createClassName(directive.value, theme, true)
58+
if (vnode.data.class) {
59+
vnode.data.class += ` ${className}`
60+
} else {
61+
vnode.data.class = className
62+
}
63+
purifyVNodeAttrs(vnode, pure)
64+
}
65+
66+
if (typeof directive.value === 'function') {
67+
const styles = directive.value(theme)
68+
const [className, pure] = createClassName(styles, theme, true)
69+
if (vnode.data.class) {
70+
vnode.data.class += ` ${className}`
71+
} else {
72+
vnode.data.class = className
73+
}
74+
purifyVNodeAttrs(vnode, pure)
75+
}
76+
}
77+
}
78+
};
79+
80+
/** Creates Client `v-chakra` Directive */
81+
export function createClientDirective (theme) {
82+
return {
83+
bind (el, binding, vnode) {
84+
const [className, pure] = createClassName(vnode.data.attrs, theme)
85+
el.classList.add(className)
86+
purifyAttrs(el, pure)
87+
88+
if (binding.value) {
89+
if (typeof binding.value === 'object') {
90+
const [className, pure] = createClassName(binding.value, theme, true)
91+
el.classList.add(className)
92+
purifyAttrs(el, pure)
93+
}
94+
95+
if (typeof binding.value === 'function') {
96+
const styles = binding.value(theme)
97+
const [className, pure] = createClassName(styles, theme, true)
98+
el.classList.add(className)
99+
purifyAttrs(el, pure)
100+
}
101+
}
102+
}
103+
}
104+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { storiesOf } from '@storybook/vue'
2+
3+
storiesOf('Directives | Chakra', module)
4+
.add('Base usage - No arguments', () => ({
5+
template: `
6+
<div>
7+
<div v-chakra p="3" bg="red.100" rounded="md" color="red.500" font-weight="bold">Welcome to Chakra directive</div>
8+
</div>
9+
`
10+
}))
11+
.add('With value | Styles object', () => ({
12+
template: `
13+
<div>
14+
<div v-chakra="{
15+
p: 3,
16+
shadow: 'sm',
17+
h1: {
18+
bg: 'blue.100'
19+
},
20+
}">
21+
<h1>Title</h1>
22+
<p>Text</p>
23+
</div>
24+
</div>
25+
`
26+
}))
27+
.add('With value | Function', () => ({
28+
template: `
29+
<div>
30+
<div v-chakra="theme => ({
31+
shadow: 'sm',
32+
bg: theme.colors.blue[800],
33+
color: theme.colors.yellow[300],
34+
p: {
35+
fontWeight: 'bold',
36+
p: 3
37+
}
38+
})">
39+
<p>Computed styles</p>
40+
</div>
41+
</div>
42+
`
43+
}))
44+
.add('Demo button', () => ({
45+
template: `
46+
<div>
47+
<button v-chakra="{
48+
':hover': { bg: 'green.400' },
49+
':focus': { shadow: 'outline' }
50+
}" font-weight="bold" px="4" py="3" color="white" rounded="md" bg="blue.400" outline="none">
51+
Button
52+
</button>
53+
</div>
54+
`
55+
}))
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export { default as ClickOutsideDirective } from './clickoutside.directive'
2+
export * from './chakra.directive'

packages/chakra-ui-core/src/utils/strings.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,13 @@ export function kebabify (text) {
2727
.map(x => x.toLowerCase())
2828
.join('-')
2929
}
30+
31+
/**
32+
* Converts a kebab-case string into camel case
33+
* @param {String} string
34+
*/
35+
export function camelize (string) {
36+
return string.replace(/[.-](\w|$)/g, function (_, x) {
37+
return x.toUpperCase()
38+
})
39+
}

packages/chakra-ui-docs/CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Change Log
22

3+
## 0.4.8
4+
5+
### Patch Changes
6+
7+
- Adds the `v-chakra` directive for styling HTML elements
8+
- Updated dependencies [undefined]
9+
- @chakra-ui/vue@0.5.10
10+
311
## 0.4.7
412

513
### Patch Changes

packages/chakra-ui-docs/components/BottomLink.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<template>
22
<div v-show="visible === true">
3-
<CFlex justify="space-between">
3+
<CFlex justify="space-between" pb="20">
44
<div>
55
<CLink v-if="prevName" as="router-link" class="link" :to="prevPath">
66
<c-button left-icon="chevron-left" border-color="green.500" variant-color="green" variant="outline">

0 commit comments

Comments
 (0)