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

Commit 9244cf7

Browse files
committed
feat(system): extract attrs and props from higher-level component
1 parent deca8b6 commit 9244cf7

File tree

8 files changed

+9009
-23
lines changed

8 files changed

+9009
-23
lines changed

package.json

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
"c-alert": "yarn workspace @chakra-ui/c-alert",
2020
"c-box": "yarn workspace @chakra-ui/c-box",
2121
"c-button": "yarn workspace @chakra-ui/c-button",
22-
2322
"system": "yarn workspace @chakra-ui/system-vue",
2423
"nuxt": "yarn workspace @chakra-ui/nuxt-next"
2524
},
@@ -35,7 +34,10 @@
3534
"@typescript-eslint/eslint-plugin": "^2.34.0",
3635
"@typescript-eslint/parser": "4.0.1",
3736
"@vitejs/plugin-vue": "^1.0.6",
37+
"@vue/compiler-sfc": "^3.0.5",
3838
"@vue/eslint-config-typescript": "^5.1.0",
39+
"@vuedx/typecheck": "^0.4.1",
40+
"@vuedx/typescript-plugin-vue": "^0.4.1",
3941
"concurrently": "^5.3.0",
4042
"consola": "^2.15.0",
4143
"cross-env": "^7.0.2",
@@ -55,9 +57,6 @@
5557
"recursive-readdir": "^2.2.2",
5658
"ts-node": "^9.0.0",
5759
"typescript": "^4.1.2",
58-
"@vue/compiler-sfc": "^3.0.5",
59-
"@vuedx/typecheck": "^0.4.1",
60-
"@vuedx/typescript-plugin-vue": "^0.4.1",
6160
"vite": "^2.0.0-beta.12",
6261
"vue": "^3.0.5",
6362
"vue-router": "4.0.0-beta.10"
@@ -66,11 +65,15 @@
6665
"@chakra-ui/styled-system": "^1.4.1",
6766
"@emotion/css": "^11.1.3",
6867
"@emotion/server": "^11.0.0",
68+
"@types/lodash.camelcase": "^4.3.6",
69+
"@types/lodash.kebabcase": "^4.1.6",
6970
"@types/lodash.mergewith": "^4.6.6",
7071
"@types/tinycolor2": "^1.4.2",
7172
"change-case": "^4.1.1",
7273
"css-get-unit": "^1.0.1",
7374
"csstype": "^3.0.5",
75+
"lodash.camelcase": "^4.3.0",
76+
"lodash.kebabcase": "^4.1.1",
7477
"lodash.mergewith": "^4.6.2",
7578
"object-assign": "^4.1.1",
7679
"react": "^17.0.1",

packages/c-alert/examples/base-alert.vue

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
<template>
2-
<c-alert> HELLO ALERT </c-alert>
2+
<c-alert
3+
font-weight="bold"
4+
px="4"
5+
py="3"
6+
bg="yellow.300"
7+
aria-role="alert"
8+
rounded="md"
9+
>
10+
HELLO ALERT
11+
</c-alert>
312
<p>Alert paragraph</p>
413
</template>
514

packages/c-alert/src/index.ts

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
11
import { h, defineComponent, PropType } from 'vue'
2-
3-
import { css } from '@chakra-ui/styled-system'
4-
import { css as emotionCss, cx } from '@emotion/css'
5-
import theme from '@chakra-ui/vue-theme'
62
import { chakra } from '@chakra-ui/system-vue'
73
import { DOMElements } from '@chakra-ui/system-vue/dist/types/system.utils'
84

@@ -15,23 +11,12 @@ const CAlert = defineComponent({
1511
},
1612
},
1713
setup(props, { slots, attrs }) {
18-
const alertStyles = css({
19-
bg: 'blue.400',
20-
p: 4,
21-
color: 'white',
22-
_hover: {
23-
bg: 'green.400',
24-
},
25-
})({ theme })
26-
27-
const className = emotionCss(alertStyles)
28-
2914
return () =>
3015
h(
3116
chakra[props.as],
3217
{
3318
...attrs,
34-
class: cx('chakra-alert', className),
19+
class: 'chakra-alert',
3520
role: 'alert',
3621
},
3722
slots

packages/system/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
"watch:types": "tsc --emitDeclarationOnly --declaration --declarationDir dist/types --watch"
2121
},
2222
"dependencies": {
23-
"@chakra-ui/vue-styled-system": "^1.0.0"
23+
"@chakra-ui/vue-styled-system": "^1.0.0",
24+
"lodash.camelcase": "^4.3.0",
25+
"lodash.kebabcase": "^4.1.1"
2426
}
2527
}

packages/system/src/index.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
import { defineComponent, h } from 'vue'
2+
import { css } from '@chakra-ui/styled-system'
3+
import theme from '@chakra-ui/vue-theme'
4+
import { css as _css, cx } from '@emotion/css'
5+
import { extractStyleAttrs } from './system.attrs'
26
import { domElements, DOMElements } from './system.utils'
37

48
/**
@@ -15,12 +19,18 @@ export const chakra: IChakraFactory = (
1519
inheritAttrs: false,
1620
props: componentProps,
1721
setup(props, { slots, attrs }) {
22+
const { class: inheritedClass, ...rest } = attrs
23+
const { styles, attrs: _attrs } = extractStyleAttrs(rest)
24+
25+
console.log(styles, attrs)
26+
const className = _css(css(styles)({ theme }))
1827
return () =>
1928
h(
2029
tag,
2130
{
31+
class: cx(inheritedClass as string, className),
2232
...props,
23-
...attrs,
33+
..._attrs,
2434
},
2535
slots
2636
)

packages/system/src/system.attrs.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import kebabCase from 'lodash.kebabcase'
2+
import camelCase from 'lodash.camelcase'
3+
import { propNames, StyleObjectOrFn } from '@chakra-ui/styled-system'
4+
import { HTMLAttributes } from 'vue'
5+
6+
type StyleAndHTMLAttibutes = StyleObjectOrFn &
7+
Record<string, string | number | boolean | unknown> &
8+
HTMLAttributes
9+
10+
export const allStylePropNames = propNames.reduce(
11+
(acc: StyleAndHTMLAttibutes, curr: string) => {
12+
acc[curr] = true
13+
acc[kebabCase(curr)] = true
14+
return acc
15+
},
16+
{}
17+
)
18+
19+
interface ExtractedStyleAttrs {
20+
styles: Partial<StyleAndHTMLAttibutes>
21+
attrs: Partial<HTMLAttributes>
22+
}
23+
24+
/** Extracts CSS style properties and HTML attributes from merged component attributs */
25+
export const extractStyleAttrs = <
26+
T extends StyleAndHTMLAttibutes,
27+
U extends Partial<HTMLAttributes> | Record<string, string | number | boolean>
28+
>(
29+
styleProps: T
30+
): ExtractedStyleAttrs => {
31+
const styles = {} as T
32+
const attrs = {} as U
33+
34+
for (const prop in styleProps) {
35+
// TODO: Cache style prop names so that that camelCases is only computed once for eahc property
36+
const _attr = camelCase(prop)
37+
if (_attr in allStylePropNames) {
38+
// @ts-expect-error Not sure how to cast returned string into typeof key of U
39+
styles[_attr] = styleProps[prop]
40+
} else {
41+
// @ts-expect-error Not sure how to cast returned string into typeof key of U
42+
attrs[prop] = styleProps[prop]
43+
}
44+
}
45+
46+
return {
47+
styles,
48+
attrs,
49+
}
50+
}

0 commit comments

Comments
 (0)