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

Commit af45ecf

Browse files
committed
Merge branch 'develop' of https://github.com/chakra-ui/chakra-ui-vue-next into feat/css-reset
2 parents 3536b9a + f5fc776 commit af45ecf

File tree

8 files changed

+228
-29
lines changed

8 files changed

+228
-29
lines changed

.gitignore

Lines changed: 95 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,99 @@
1-
node_modules
21
dist
32
# playground/src/.generated/*
43
.vercel
54
yarn-error.log
6-
test-vite-project
5+
test-vite-project
6+
7+
# Logs
8+
logs
9+
*.log
10+
npm-debug.log*
11+
yarn-debug.log*
12+
yarn-error.log*
13+
lerna-debug.log*
14+
15+
# Diagnostic reports (https://nodejs.org/api/report.html)
16+
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
17+
18+
# Runtime data
19+
pids
20+
*.pid
21+
*.seed
22+
*.pid.lock
23+
24+
# Directory for instrumented libs generated by jscoverage/JSCover
25+
lib-cov
26+
27+
# Coverage directory used by tools like istanbul
28+
coverage
29+
*.lcov
30+
31+
# nyc test coverage
32+
.nyc_output
33+
34+
# Compiled binary addons (https://nodejs.org/api/addons.html)
35+
build/Release
36+
37+
# Dependency directories
38+
node_modules/
39+
jspm_packages/
40+
41+
# Snowpack dependency directory (https://snowpack.dev/)
42+
web_modules/
43+
44+
# TypeScript cache
45+
*.tsbuildinfo
46+
47+
# Optional npm cache directory
48+
.npm
49+
50+
# Optional eslint cache
51+
.eslintcache
52+
53+
# Microbundle cache
54+
.rpt2_cache/
55+
.rts2_cache_cjs/
56+
.rts2_cache_es/
57+
.rts2_cache_umd/
58+
59+
# Optional REPL history
60+
.node_repl_history
61+
62+
# Output of 'npm pack'
63+
*.tgz
64+
65+
# Yarn Integrity file
66+
.yarn-integrity
67+
68+
# dotenv environment variables file
69+
.env
70+
.env.test
71+
72+
# Next.js build output
73+
.next
74+
out
75+
76+
# Nuxt.js build / generate output
77+
.nuxt
78+
dist
79+
80+
.cache/
81+
82+
# vuepress build output
83+
.vuepress/dist
84+
85+
# Serverless directories
86+
.serverless/
87+
88+
# Stores VSCode versions used for testing VSCode extensions
89+
.vscode-test
90+
91+
# yarn v2
92+
.yarn/cache
93+
.yarn/unplugged
94+
.yarn/build-state.yml
95+
.yarn/install-state.gz
96+
.pnp.*
97+
98+
# vscode history extension
99+
.history

packages/c-alert/src/alert.ts

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
1-
import { h, defineComponent, PropType, provide, inject, computed } from 'vue'
1+
import { h, defineComponent, PropType, computed } from 'vue'
22
import {
33
chakra,
44
ColorScheme,
55
DeepComponentThemeConfig,
66
ThemingProps,
77
useMultiStyleConfig,
8-
provideComponentStyles,
9-
useComponentStyles,
8+
useStyles,
9+
StylesProvider,
1010
DOMElements,
1111
} from '@chakra-ui/vue-system'
1212
import { SystemStyleObject } from '@chakra-ui/styled-system'
13+
import { createContext } from '@chakra-ui/vue-utils'
1314
import { CIcon } from '@chakra-ui/c-icon'
1415

1516
const STATUSES = {
@@ -34,10 +35,16 @@ const STATUSES = {
3435
type AlertStatus = keyof typeof STATUSES
3536
export type AlertVariant = 'solid' | 'subtle' | 'left-accent' | 'top-accent'
3637

37-
interface AlertState {
38+
interface AlertContext {
3839
status: AlertStatus
3940
}
4041

42+
const [AlertProvider, useAlertContext] = createContext<AlertContext>({
43+
name: 'AlertContext',
44+
errorMessage:
45+
'useAlertContext: `context` is undefined. Seems you forgot to wrap alert components in `<c-alert />`',
46+
})
47+
4148
/**
4249
* CAlert component
4350
*
@@ -84,8 +91,8 @@ export const CAlert = defineComponent({
8491
...styles.value.container,
8592
}
8693

87-
provideComponentStyles('Alert', styles.value)
88-
provide('$AlertState', { status: props.status } as AlertState)
94+
StylesProvider(styles.value)
95+
AlertProvider({ status: props.status })
8996

9097
return () =>
9198
h(
@@ -108,7 +115,7 @@ export const CAlert = defineComponent({
108115
export const CAlertTitle = defineComponent({
109116
name: 'CAlertTitle',
110117
setup(_, { attrs, slots }) {
111-
const styles = useComponentStyles('Alert')
118+
const styles = useStyles()
112119

113120
return () =>
114121
h(
@@ -130,7 +137,7 @@ export const CAlertTitle = defineComponent({
130137
export const CAlertDescription = defineComponent({
131138
name: 'CAlertDescription',
132139
setup(_, { attrs, slots }) {
133-
const styles = useComponentStyles('Alert')
140+
const styles = useStyles()
134141

135142
return () =>
136143
h(
@@ -157,9 +164,9 @@ export const CAlertIcon = defineComponent({
157164
},
158165
},
159166
setup(props, { attrs }) {
160-
const alertState = inject<AlertState>('$AlertState')
161-
const { icon } = STATUSES[alertState?.status as AlertStatus]
162-
const styles = useComponentStyles('Alert')
167+
const { status } = useAlertContext()
168+
const { icon } = STATUSES[status]
169+
const styles = useStyles()
163170

164171
const alertIcon = computed(() => props.icon || icon)
165172

packages/system/src/composables/use-style-config.ts

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { computed, ComputedRef, inject, provide, ref } from 'vue'
1+
import { computed, ComputedRef } from 'vue'
22

33
import { SystemStyleObject } from '@chakra-ui/styled-system'
44
import { ChakraComponentName, ComponentThemeConfig } from '@chakra-ui/vue-theme'
@@ -83,18 +83,3 @@ export function useMultiStyleConfig(
8383
) {
8484
return useStyleConfig(themeKey, themingProps, { isMultiPart: true })
8585
}
86-
87-
/** Provides Chakra Multi-parted component styles to descendants */
88-
export const provideComponentStyles = (
89-
component: AllThemedComponents,
90-
styles: SystemStyleObject
91-
) => {
92-
provide<SystemStyleObject>(`$chakra${component}Styles`, styles)
93-
}
94-
95-
/** Injects Chakra Multi-parted component styles from ancestor */
96-
export const useComponentStyles = (component: AllThemedComponents) => {
97-
return inject<Record<string, SystemStyleObject> & SystemStyleObject & any>(
98-
`$chakra${component}Styles`
99-
)
100-
}

packages/system/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export * from './chakra'
2+
export * from './providers'
23
export * from './system.attrs'
34
export * from './system.types'
45
export * from './system.utils'

packages/system/src/providers.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { createContext, Dict } from '@chakra-ui/vue-utils'
2+
import { SystemStyleObject } from '@chakra-ui/styled-system'
3+
4+
const [StylesProvider, useStyles] = createContext<Dict<SystemStyleObject>>({
5+
name: 'StylesContext',
6+
errorMessage:
7+
'useStyles: `styles` is undefined. Seems you forgot to provide `StylesProvider(...)` ',
8+
})
9+
10+
export { StylesProvider, useStyles }

packages/utils/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export * from './tabbable'
99
export * from './assertion'
1010
export * from 'css-box-model'
1111
export * from './responsive'
12+
export * from './vue-helpers'
1213

1314
export function orient(options: {
1415
orientation?: 'vertical' | 'horizontal'

packages/utils/src/vue-helpers.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { inject, InjectionKey, provide } from 'vue'
2+
3+
export interface CreateContextOptions {
4+
/**
5+
* If `true`, Vue will throw if context is `null` or `undefined`
6+
* In some cases, you might want to support nested context, so you can set it to `false`
7+
*/
8+
strict?: boolean
9+
/**
10+
* Error message to throw if the context is `undefined`
11+
*/
12+
errorMessage?: string
13+
/**
14+
* The display name of the context
15+
*/
16+
name?: string
17+
}
18+
19+
type CreateContextReturn<T> = [(opts: T) => void, () => T]
20+
21+
/**
22+
* Creates a named context, provider, and hook.
23+
*
24+
* @param options create context options
25+
*/
26+
export function createContext<ContextType>(options: CreateContextOptions = {}) {
27+
const {
28+
strict = true,
29+
errorMessage = 'useContext: `context` is undefined. Seems you forgot to wrap component within the Provider',
30+
name,
31+
} = options
32+
33+
let contextSymbol = Symbol(`${name}Symbol`) as InjectionKey<ContextType>
34+
35+
function Provider(payload: ContextType) {
36+
provide<ContextType>(contextSymbol, payload)
37+
}
38+
39+
function useContext() {
40+
const context = inject(contextSymbol, null)
41+
42+
if (!context && strict) {
43+
throw new Error(errorMessage)
44+
}
45+
46+
return context
47+
}
48+
49+
return [Provider, useContext] as CreateContextReturn<ContextType>
50+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { createContext } from '@chakra-ui/vue-utils/src'
2+
import { defineComponent, h } from 'vue'
3+
import { render } from '@chakra-ui/vue-test-utils/src'
4+
5+
interface ExampleContext {
6+
example: string
7+
}
8+
9+
const [ExampleProvider, useExampleContext] = createContext<ExampleContext>({
10+
name: 'ExampleContext',
11+
errorMessage:
12+
'useContext: `context` is undefined. Seems you forgot to wrap component within the Provider',
13+
})
14+
15+
const ExampleComponent = defineComponent({
16+
setup() {
17+
const { example } = useExampleContext()
18+
return () => h('div', `injected: ${example}`)
19+
},
20+
})
21+
22+
beforeEach(() => {
23+
// disable console.warn
24+
jest.spyOn(console, 'warn').mockImplementation(() => {})
25+
})
26+
27+
it('should provide and inject a context', () => {
28+
const { getByText } = render({
29+
components: { ExampleComponent },
30+
template: `
31+
<div>
32+
<ExampleComponent />
33+
</div>
34+
`,
35+
setup() {
36+
ExampleProvider({ example: 'works' })
37+
},
38+
})
39+
getByText(/works/)
40+
})
41+
42+
it('should throw an error when there is no provider', () => {
43+
expect(() => {
44+
render({
45+
components: { ExampleComponent },
46+
template: `<ExampleComponent />`,
47+
setup() {},
48+
})
49+
}).toThrowError(
50+
'useContext: `context` is undefined. Seems you forgot to wrap component within the Provider'
51+
)
52+
})

0 commit comments

Comments
 (0)