diff --git a/.changeset/spicy-doors-heal.md b/.changeset/spicy-doors-heal.md new file mode 100644 index 00000000..c9a2e893 --- /dev/null +++ b/.changeset/spicy-doors-heal.md @@ -0,0 +1,34 @@ +--- +"@chakra-ui/vue-composables": minor +"@chakra-ui/c-close-button": minor +"@chakra-ui/c-form-control": minor +"@chakra-ui/c-live-region": minor +"@chakra-ui/c-media-query": minor +"@chakra-ui/c-scroll-lock": minor +"@chakra-ui/c-breadcrumb": minor +"@chakra-ui/c-accordion": minor +"@chakra-ui/c-pin-input": minor +"@chakra-ui/c-checkbox": minor +"@chakra-ui/c-skip-nav": minor +"@chakra-ui/c-textarea": minor +"@chakra-ui/c-spinner": minor +"@chakra-ui/c-avatar": minor +"@chakra-ui/c-button": minor +"@chakra-ui/c-motion": minor +"@chakra-ui/vue-accessibilty": minor +"@chakra-ui/c-alert": minor +"@chakra-ui/c-image": minor +"@chakra-ui/c-input": minor +"@chakra-ui/c-modal": minor +"@chakra-ui/c-table": minor +"@chakra-ui/c-code": minor +"@chakra-ui/c-menu": minor +"@chakra-ui/vue-layout": minor +"@chakra-ui/vue-system": minor +"@chakra-ui/c-tag": minor +"@chakra-ui/vue-utils": minor +"@chakra-ui/vue-next": minor +--- + +Create Live Region, Textarea and useBreakpoint and useBreakpointValue hooks and +components diff --git a/@types/components.d.ts b/@types/components.d.ts index 3e0fc3ad..fbb2a07a 100644 --- a/@types/components.d.ts +++ b/@types/components.d.ts @@ -1,12 +1,12 @@ /** - * Typescript support for @chakra-ui/vue-next2.1.0-beta.2 auto-imported + * Typescript support for @chakra-ui/vue-next2.1.0-beta.3 auto-imported * components using `unplugin-vue-components,` * * @see: https://github.com/antfu/unplugin-vue-components/#typescript * * This is a generated file. Do not edit it's contents. * - * This file was generated on 2023-02-25T17:54:59.918Z + * This file was generated on 2023-02-26T20:07:20.175Z */ import { ChakraProps, chakra } from "@chakra-ui/vue-system" @@ -155,9 +155,19 @@ declare module "@vue/runtime-core" { CStack: typeof import("@chakra-ui/vue-next")["CStack"] CStackDivider: typeof import("@chakra-ui/vue-next")["CStackDivider"] CStackItem: typeof import("@chakra-ui/vue-next")["CStackItem"] + CTable: typeof import("@chakra-ui/vue-next")["CTable"] + CTableCaption: typeof import("@chakra-ui/vue-next")["CTableCaption"] + CTableContainer: typeof import("@chakra-ui/vue-next")["CTableContainer"] + CTbody: typeof import("@chakra-ui/vue-next")["CTbody"] + CTd: typeof import("@chakra-ui/vue-next")["CTd"] CText: typeof import("@chakra-ui/vue-next")["CText"] + CTextarea: typeof import("@chakra-ui/vue-next")["CTextarea"] + CTfoot: typeof import("@chakra-ui/vue-next")["CTfoot"] + CTh: typeof import("@chakra-ui/vue-next")["CTh"] + CThead: typeof import("@chakra-ui/vue-next")["CThead"] CThemeProvider: typeof import("@chakra-ui/vue-next")["CThemeProvider"] CToastContainer: typeof import("@chakra-ui/vue-next")["CToastContainer"] + CTr: typeof import("@chakra-ui/vue-next")["CTr"] CUnorderedList: typeof import("@chakra-ui/vue-next")["CUnorderedList"] CVStack: typeof import("@chakra-ui/vue-next")["CVStack"] CVisuallyHidden: typeof import("@chakra-ui/vue-next")["CVisuallyHidden"] diff --git a/_templates/generator/component/package.json.ejs.t b/_templates/generator/component/package.json.ejs.t index 6eba60b7..f13f61e4 100644 --- a/_templates/generator/component/package.json.ejs.t +++ b/_templates/generator/component/package.json.ejs.t @@ -5,19 +5,20 @@ to: packages/<%=h.changeCase.paramCase(name)%>/package.json { "name": "<%= '@chakra-ui/' + h.changeCase.paramCase(name)%>", "description": "<%= 'Chakra UI Vue | ' + h.changeCase.sentence(description) + ' component'%>", - "version": "0.0.0-next.0", - "main": "<%= 'dist/chakra-ui-' + h.changeCase.paramCase(name) + '.cjs.js' %>", - "module": "<%= 'dist/chakra-ui-' + h.changeCase.paramCase(name) + '.esm.js' %>", + "version": "0.0.0-beta.0", "author": "Jonathan Bakebwa ", "homepage": "https://github.com/chakra-ui/chakra-ui-vue-next#readme", "license": "MIT", + "main": "dist/index.js", + "module": "dist/index.mjs", + "typings": "dist/index.d.ts", "files": [ "dist" ], "exports": { ".": { - "require": "<%= './dist/chakra-ui-' + h.changeCase.paramCase(name) + '.cjs.js' %>", - "default": "<%= './dist/chakra-ui-' + h.changeCase.paramCase(name) + '.esm.js' %>" + "require": "./dist/index.js", + "default": "./dist/index.mjs" } }, "repository": { diff --git a/_templates/generator/component/tsup.config.ts.ejs.t b/_templates/generator/component/tsup.config.ts.ejs.t index 4816ed72..c499034e 100644 --- a/_templates/generator/component/tsup.config.ts.ejs.t +++ b/_templates/generator/component/tsup.config.ts.ejs.t @@ -8,20 +8,14 @@ import EsbuildPluginJSX from "unplugin-vue-jsx/esbuild" export default defineConfig({ clean: true, target: "es2019", - outExtension({ format }) { - return { - js: `.${format}.js`, - } - }, esbuildPlugins: [ - // @ts-expect-error `EsbuildPluginJSX` does not extend `tsup.Plugin` type. EsbuildPluginJSX({ include: [/.[jt]sx?$/], - }), + }) as any, ], + metafile: true, + external: ["lodash.mergewith"], format: ["esm", "cjs"], - entry: { - "<%=h.changeCase.paramCase(name)%>": "src/index.tsx", - }, + entry: ["src/**/*.(ts|tsx)"], keepNames: true, }) diff --git a/_templates/generator/module/package.json.ejs.t b/_templates/generator/module/package.json.ejs.t index 5cf87a99..e17bbebe 100644 --- a/_templates/generator/module/package.json.ejs.t +++ b/_templates/generator/module/package.json.ejs.t @@ -4,29 +4,37 @@ to: packages/<%=h.changeCase.paramCase(name)%>/package.json { "name": "<%= '@chakra-ui/' + h.changeCase.paramCase(name)%>", - "version": "0.0.0-next.0", - "main": "<%= 'dist/chakra-ui-' + h.changeCase.paramCase(name) + '.cjs.js' %>", - "module": "<%= 'dist/chakra-ui-' + h.changeCase.paramCase(name) + '.esm.js' %>", + "description": "<%= 'Chakra UI Vue | ' + h.changeCase.pascalCase(name) + ' module'%>", + "repository": "https://github.com/chakra-ui/chakra-ui-vue-next.git", + "author": "Jonathan Bakebwa codebender828@gmail.com", + "version": "0.0.0-beta.0", + "license": "MIT", + "main": "dist/index.js", + "module": "dist/index.mjs", + "typings": "dist/index.d.ts", "files": [ "dist" ], "exports": { ".": { - "require": "<%= './dist/chakra-ui-' + h.changeCase.paramCase(name) + '.cjs.js' %>", - "default": "<%= './dist/chakra-ui-' + h.changeCase.paramCase(name) + '.esm.js' %>" + "require": "./dist/index.js", + "default": "./dist/index.mjs" } }, - "description": "<%= 'Chakra UI Vue | ' + h.changeCase.pascalCase(name) + ' module'%>", - "repository": "https://github.com/chakra-ui/chakra-ui-vue-next.git", - "author": "Jonathan Bakebwa codebender828@gmail.com", - "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/chakra-ui/chakra-ui-vue-next.git" + }, + "bugs": { + "url": "https://github.com/chakra-ui/chakra-ui-vue-next/issues" + }, + "sideEffects": false, "scripts": { - "build": "rimraf ./dist && concurrently yarn:build:*", - "build:esm": "cross-env BABEL_ENV=esm babel src --root-mode upward --extensions .ts,.tsx -d dist/esm --source-maps", - "build:cjs": "cross-env BABEL_ENV=cjs babel src --root-mode upward --extensions .ts,.tsx -d dist/cjs --source-maps", - "watch": "concurrently yarn:watch:*", - "watch:esm": "cross-env BABEL_ENV=esm babel src --root-mode upward --extensions .ts,.tsx -d dist/esm --source-maps --watch", - "watch:cjs": "cross-env BABEL_ENV=cjs babel src --root-mode upward --extensions .ts,.tsx -d dist/cjs --source-maps --watch", - "watch:types": "cross-env tsc --emitDeclarationOnly --declaration --declarationDir dist/types --watch --incremental" + "clean": "rimraf dist .turbo", + "build": "tsup && pnpm build:types", + "build:fast": "tsup", + "build:types": "tsup src --dts-only", + "types:check": "tsc --noEmit", + "dev": "tsup --watch" } } diff --git a/_templates/generator/tooling/package.json.ejs.t b/_templates/generator/tooling/package.json.ejs.t index cffaa81e..38321c9f 100644 --- a/_templates/generator/tooling/package.json.ejs.t +++ b/_templates/generator/tooling/package.json.ejs.t @@ -5,15 +5,16 @@ to: tooling/<%=h.changeCase.paramCase(name)%>/package.json { "name": "<%= '@chakra-ui/' + h.changeCase.paramCase(name)%>", "version": "1.0.0", - "main": "dist/cjs/index.js", - "module": "dist/esm/index.js", + "main": "dist/index.js", + "module": "dist/index.mjs", + "typings": "dist/index.d.ts", "files": [ "dist" ], "exports": { ".": { - "require": "./dist/cjs/index.js", - "default": "./dist/esm/index.js" + "require": "./dist/index.js", + "default": "./dist/index.mjs" } }, "description": "<%= 'Chakra UI Vue | ' + h.changeCase.pascalCase(name) + ' module'%>", @@ -21,13 +22,11 @@ to: tooling/<%=h.changeCase.paramCase(name)%>/package.json "author": "Jonathan Bakebwa codebender828@gmail.com", "license": "MIT", "scripts": { - "build": "rimraf ./dist && concurrently yarn:build:*", - "build:esm": "cross-env BABEL_ENV=esm babel src --root-mode upward --extensions .ts,.tsx -d dist/esm --source-maps", - "build:cjs": "cross-env BABEL_ENV=cjs babel src --root-mode upward --extensions .ts,.tsx -d dist/cjs --source-maps", - "build:types": "cross-env tsc --emitDeclarationOnly --declaration --declarationDir dist/types", - "watch": "concurrently yarn:watch:*", - "watch:esm": "cross-env BABEL_ENV=esm babel src --root-mode upward --extensions .ts,.tsx -d dist/esm --source-maps --watch", - "watch:cjs": "cross-env BABEL_ENV=cjs babel src --root-mode upward --extensions .ts,.tsx -d dist/cjs --source-maps --watch", - "watch:types": "cross-env tsc --emitDeclarationOnly --declaration --declarationDir dist/types --watch --incremental" + "clean": "rimraf dist .turbo", + "build": "tsup && pnpm build:types", + "build:fast": "tsup", + "build:types": "tsup src --dts-only", + "types:check": "tsc --noEmit", + "dev": "tsup --watch" } } diff --git a/components.d.ts b/components.d.ts index 3e0fc3ad..fbb2a07a 100644 --- a/components.d.ts +++ b/components.d.ts @@ -1,12 +1,12 @@ /** - * Typescript support for @chakra-ui/vue-next2.1.0-beta.2 auto-imported + * Typescript support for @chakra-ui/vue-next2.1.0-beta.3 auto-imported * components using `unplugin-vue-components,` * * @see: https://github.com/antfu/unplugin-vue-components/#typescript * * This is a generated file. Do not edit it's contents. * - * This file was generated on 2023-02-25T17:54:59.918Z + * This file was generated on 2023-02-26T20:07:20.175Z */ import { ChakraProps, chakra } from "@chakra-ui/vue-system" @@ -155,9 +155,19 @@ declare module "@vue/runtime-core" { CStack: typeof import("@chakra-ui/vue-next")["CStack"] CStackDivider: typeof import("@chakra-ui/vue-next")["CStackDivider"] CStackItem: typeof import("@chakra-ui/vue-next")["CStackItem"] + CTable: typeof import("@chakra-ui/vue-next")["CTable"] + CTableCaption: typeof import("@chakra-ui/vue-next")["CTableCaption"] + CTableContainer: typeof import("@chakra-ui/vue-next")["CTableContainer"] + CTbody: typeof import("@chakra-ui/vue-next")["CTbody"] + CTd: typeof import("@chakra-ui/vue-next")["CTd"] CText: typeof import("@chakra-ui/vue-next")["CText"] + CTextarea: typeof import("@chakra-ui/vue-next")["CTextarea"] + CTfoot: typeof import("@chakra-ui/vue-next")["CTfoot"] + CTh: typeof import("@chakra-ui/vue-next")["CTh"] + CThead: typeof import("@chakra-ui/vue-next")["CThead"] CThemeProvider: typeof import("@chakra-ui/vue-next")["CThemeProvider"] CToastContainer: typeof import("@chakra-ui/vue-next")["CToastContainer"] + CTr: typeof import("@chakra-ui/vue-next")["CTr"] CUnorderedList: typeof import("@chakra-ui/vue-next")["CUnorderedList"] CVStack: typeof import("@chakra-ui/vue-next")["CVStack"] CVisuallyHidden: typeof import("@chakra-ui/vue-next")["CVisuallyHidden"] diff --git a/package.json b/package.json index aa4c70e8..18bfdd56 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,7 @@ "@babel/runtime": "^7.20.13", "@chakra-ui/anatomy": "^2.0.1", "@chakra-ui/nuxt-next": "workspace:*", - "@chakra-ui/styled-system": "2.5.1", + "@chakra-ui/styled-system": "2.6.1", "@chakra-ui/theme": "^2.2.5", "@chakra-ui/theme-tools": "^2.0.17", "@chakra-ui/theme-utils": "^2.0.6", diff --git a/packages/c-accordion/package.json b/packages/c-accordion/package.json index af7119aa..6d5fe9f8 100644 --- a/packages/c-accordion/package.json +++ b/packages/c-accordion/package.json @@ -32,7 +32,7 @@ "@chakra-ui/vue-system": "workspace:*", "@chakra-ui/vue-utils": "workspace:*", "@zag-js/accordion": "0.2.11", - "@chakra-ui/styled-system": "2.5.1", + "@chakra-ui/styled-system": "2.6.1", "@zag-js/vue": "^0.2.9" }, "peerDependencies": { diff --git a/packages/c-alert/package.json b/packages/c-alert/package.json index 2b6b2d7f..4623fe3f 100644 --- a/packages/c-alert/package.json +++ b/packages/c-alert/package.json @@ -25,7 +25,7 @@ "build:types": "tsup src --dts-only" }, "dependencies": { - "@chakra-ui/styled-system": "2.5.1", + "@chakra-ui/styled-system": "2.6.1", "@chakra-ui/c-icon": "workspace:*", "@chakra-ui/vue-system": "workspace:*", "@chakra-ui/vue-utils": "workspace:*" diff --git a/packages/c-avatar/package.json b/packages/c-avatar/package.json index dc81de7b..3c77e24f 100644 --- a/packages/c-avatar/package.json +++ b/packages/c-avatar/package.json @@ -32,7 +32,7 @@ "dependencies": { "@chakra-ui/c-icon": "workspace:*", "@chakra-ui/c-image": "workspace:*", - "@chakra-ui/styled-system": "2.5.1", + "@chakra-ui/styled-system": "2.6.1", "@chakra-ui/theme-tools": "^2.0.17", "@chakra-ui/utils": "2.0.15", "@chakra-ui/vue-layout": "workspace:*", diff --git a/packages/c-breadcrumb/package.json b/packages/c-breadcrumb/package.json index 193305d1..ed0a6961 100644 --- a/packages/c-breadcrumb/package.json +++ b/packages/c-breadcrumb/package.json @@ -33,7 +33,7 @@ "build:types": "tsup src --dts-only" }, "dependencies": { - "@chakra-ui/styled-system": "2.5.1", + "@chakra-ui/styled-system": "2.6.1", "@chakra-ui/utils": "2.0.15", "@chakra-ui/vue-system": "workspace:*", "@chakra-ui/vue-utils": "workspace:*" diff --git a/packages/c-button/package.json b/packages/c-button/package.json index 7c354b53..68a33ea2 100644 --- a/packages/c-button/package.json +++ b/packages/c-button/package.json @@ -30,7 +30,7 @@ "@chakra-ui/utils": "2.0.15", "@chakra-ui/vue-system": "workspace:*", "@chakra-ui/vue-utils": "workspace:*", - "@chakra-ui/styled-system": "2.5.1" + "@chakra-ui/styled-system": "2.6.1" }, "peerDependencies": { "vue": "3.2.47" diff --git a/packages/c-checkbox/package.json b/packages/c-checkbox/package.json index 6c6451fe..5be25c22 100644 --- a/packages/c-checkbox/package.json +++ b/packages/c-checkbox/package.json @@ -30,7 +30,7 @@ "build:types": "tsup src --dts-only" }, "dependencies": { - "@chakra-ui/styled-system": "2.5.1", + "@chakra-ui/styled-system": "2.6.1", "@chakra-ui/c-form-control": "workspace:*", "@chakra-ui/c-motion": "workspace:*", "@chakra-ui/utils": "2.0.15", diff --git a/packages/c-close-button/package.json b/packages/c-close-button/package.json index 8d7afba3..2d01977e 100644 --- a/packages/c-close-button/package.json +++ b/packages/c-close-button/package.json @@ -34,7 +34,7 @@ }, "dependencies": { "@chakra-ui/c-icon": "workspace:*", - "@chakra-ui/styled-system": "2.5.1", + "@chakra-ui/styled-system": "2.6.1", "@chakra-ui/utils": "2.0.15", "@chakra-ui/vue-system": "workspace:*", "@chakra-ui/vue-utils": "workspace:*" diff --git a/packages/c-code/package.json b/packages/c-code/package.json index 2b3963d1..2dfe4f6b 100644 --- a/packages/c-code/package.json +++ b/packages/c-code/package.json @@ -33,7 +33,7 @@ "build:types": "tsup src --dts-only" }, "dependencies": { - "@chakra-ui/styled-system": "2.5.1", + "@chakra-ui/styled-system": "2.6.1", "@chakra-ui/utils": "2.0.15", "@chakra-ui/vue-system": "workspace:*", "@chakra-ui/vue-utils": "workspace:*" diff --git a/packages/c-form-control/package.json b/packages/c-form-control/package.json index 413e55ac..7b127d82 100644 --- a/packages/c-form-control/package.json +++ b/packages/c-form-control/package.json @@ -35,7 +35,7 @@ "@chakra-ui/vue-composables": "workspace:*", "@chakra-ui/vue-system": "workspace:*", "@chakra-ui/vue-utils": "workspace:*", - "@chakra-ui/styled-system": "2.5.1", + "@chakra-ui/styled-system": "2.6.1", "csstype": "^3.1.1" }, "devDependencies": { diff --git a/packages/c-image/package.json b/packages/c-image/package.json index 879e11d1..3d661c66 100644 --- a/packages/c-image/package.json +++ b/packages/c-image/package.json @@ -30,7 +30,7 @@ "build:types": "tsup src --dts-only" }, "dependencies": { - "@chakra-ui/styled-system": "2.5.1", + "@chakra-ui/styled-system": "2.6.1", "@chakra-ui/utils": "2.0.15", "@chakra-ui/vue-system": "workspace:*", "@chakra-ui/vue-utils": "workspace:*" diff --git a/packages/c-input/package.json b/packages/c-input/package.json index 1a81502a..7410d855 100644 --- a/packages/c-input/package.json +++ b/packages/c-input/package.json @@ -30,7 +30,7 @@ "build:types": "tsup src --dts-only" }, "dependencies": { - "@chakra-ui/styled-system": "2.5.1", + "@chakra-ui/styled-system": "2.6.1", "@chakra-ui/utils": "2.0.15", "@chakra-ui/vue-system": "workspace:*", "@chakra-ui/vue-utils": "workspace:*", diff --git a/packages/c-live-region/README.md b/packages/c-live-region/README.md new file mode 100644 index 00000000..1359f787 --- /dev/null +++ b/packages/c-live-region/README.md @@ -0,0 +1,14 @@ +# `@chakra-ui/c-live-region` + +Creates a hidden live region with dynamic content based on triggered events to be read out by the screen reader on change of the content + +## Installation + +```sh +# with pnpm +pnpm add @chakra-ui/c-live-region +# or with Yarn +yarn i @chakra-ui/c-live-region +# or with npm +npm i @chakra-ui/c-live-region +``` \ No newline at end of file diff --git a/packages/c-live-region/examples/simple-live-region.vue b/packages/c-live-region/examples/simple-live-region.vue new file mode 100644 index 00000000..9bb78282 --- /dev/null +++ b/packages/c-live-region/examples/simple-live-region.vue @@ -0,0 +1,9 @@ + + diff --git a/packages/c-live-region/index.tsx b/packages/c-live-region/index.tsx new file mode 100644 index 00000000..46e72b16 --- /dev/null +++ b/packages/c-live-region/index.tsx @@ -0,0 +1 @@ +export * from "./src" diff --git a/packages/c-live-region/package.json b/packages/c-live-region/package.json new file mode 100644 index 00000000..c7446ab3 --- /dev/null +++ b/packages/c-live-region/package.json @@ -0,0 +1,48 @@ +{ + "name": "@chakra-ui/c-live-region", + "description": "Chakra UI Vue | Creates a hidden live region with dynamic content based on triggered events to be read out by the screen reader on change of the content component", + "version": "2.0.0-beta.0", + "author": "Jonathan Bakebwa ", + "homepage": "https://github.com/chakra-ui/chakra-ui-vue-next#readme", + "license": "MIT", + "main": "dist/index.js", + "module": "dist/index.mjs", + "typings": "dist/index.d.ts", + "files": [ + "dist" + ], + "exports": { + ".": { + "require": "./dist/index.js", + "default": "./dist/index.mjs" + } + }, + "repository": { + "type": "git", + "url": "git+https://github.com/chakra-ui/chakra-ui-vue-next.git" + }, + "bugs": { + "url": "https://github.com/chakra-ui/chakra-ui-vue-next/issues" + }, + "sideEffects": false, + "scripts": { + "clean": "rimraf dist .turbo", + "build": "tsup && pnpm build:types", + "build:fast": "tsup", + "build:types": "tsup src --dts-only", + "types:check": "tsc --noEmit", + "dev": "tsup --watch" + }, + "dependencies": { + "@chakra-ui/vue-system": "workspace:*" + }, + "devDependencies": { + "vue": "^3.2.37" + }, + "peerDependencies": { + "vue": "^3.1.4" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/packages/c-live-region/src/index.ts b/packages/c-live-region/src/index.ts new file mode 100644 index 00000000..cd4f7d8c --- /dev/null +++ b/packages/c-live-region/src/index.ts @@ -0,0 +1,3 @@ +export { LiveRegion } from "./live-region" + +export type { LiveRegionOptions } from "./live-region" diff --git a/packages/c-live-region/src/live-region.ts b/packages/c-live-region/src/live-region.ts new file mode 100644 index 00000000..5dc330ff --- /dev/null +++ b/packages/c-live-region/src/live-region.ts @@ -0,0 +1,139 @@ +import { HTMLAttributes } from "vue" + +function isDom() { + return Boolean(globalThis?.document) +} +const isBrowser = isDom() +export interface LiveRegionOptions { + /** + * A unique id for the created live region element + */ + id?: string + /** + * Used to mark a part of the page as "live" so that updates will + * be communicated to users by screen readers. + * + * - If set to `polite`: tells assistive technology to alert the user + * to this change when it has finished whatever it is currently doing + * + * - If set to `assertive`: tells assistive technology to interrupt whatever + * it is doing and alert the user to this change immediately + * + * @default "polite". + */ + "aria-live"?: "polite" | "assertive" + /** + * The desired value of the role attribute + * @default "status" + */ + role?: "status" | "alert" | "log" + /** + * Indicates what types of changes should be presented to the user. + * @default "all" + */ + "aria-relevant"?: HTMLAttributes["aria-relevant"] + /** + * Indicates whether the entire region should be + * considered as a whole when communicating updates + * + * @default true + */ + "aria-atomic"?: HTMLAttributes["aria-atomic"] + /** + * The node to append the live region node to + */ + parentNode?: HTMLElement +} + +export class LiveRegion { + region: HTMLElement | null + options: Required + parentNode: HTMLElement + + constructor(options?: LiveRegionOptions) { + this.options = getOptions(options) as any + this.region = getRegion(this.options) + this.parentNode = this.options.parentNode + if (this.region) { + this.parentNode.appendChild(this.region) + } + } + + /** + * Message provided to the region to be read out by the Screen Reader. + * + * Message can be supplied on trigger of some event (i.e. button click) + */ + public speak(message: string) { + this.clear() + if (this.region) { + this.region.innerText = message + } + } + + /** + * Removes the region. + */ + public destroy() { + if (this.region) { + this.region.parentNode?.removeChild(this.region) + } + } + + /** + * Clears the inner text of the region + */ + public clear() { + if (this.region) { + this.region.innerText = "" + } + } +} + +function getOptions(options?: LiveRegionOptions) { + const defaultOptions: LiveRegionOptions = { + "aria-live": "polite", + "aria-atomic": "true", + "aria-relevant": "all", + role: "status", + id: "chakra-a11y-live-region", + parentNode: isBrowser ? document.body : undefined, + } + if (options) { + return Object.assign(defaultOptions, options) + } + return defaultOptions +} + +function getRegion(options: Required) { + let region = isBrowser ? document.getElementById(options.id) : null + + if (region) return region + + if (isBrowser) { + region = document.createElement("div") + setup(region, options) + } + + return region +} + +function setup(region: HTMLElement, options: Required) { + region.id = options.id || "chakra-live-region" + region.className = "__chakra-live-region" + region.setAttribute("aria-live", options["aria-live"]) + region.setAttribute("role", options.role) + region.setAttribute("aria-relevant", options["aria-relevant"]) + region.setAttribute("aria-atomic", String(options["aria-atomic"])) + Object.assign(region.style, { + border: "0px", + clip: "rect(0px, 0px, 0px, 0px)", + height: "1px", + width: "1px", + margin: "-1px", + padding: "0px", + overflow: "hidden", + whiteSpace: "nowrap", + position: "absolute", + }) +} diff --git a/packages/c-live-region/src/use-live-region.ts b/packages/c-live-region/src/use-live-region.ts new file mode 100644 index 00000000..591f25ea --- /dev/null +++ b/packages/c-live-region/src/use-live-region.ts @@ -0,0 +1,13 @@ +import { reactive, watchEffect } from "vue" +import { LiveRegion, LiveRegionOptions } from "./live-region" + +/** + * Creates a hidden live region with dynamic content based on triggered events + * to be read out by the screen reader on change of the content. + */ +export function useLiveRegion(options?: LiveRegionOptions) { + const liveRegion = new LiveRegion(options) + + watchEffect((cleanup) => cleanup(() => liveRegion.destroy())) + return liveRegion +} diff --git a/packages/c-live-region/tests/__snapshots__/c-live-region.test.ts.snap b/packages/c-live-region/tests/__snapshots__/c-live-region.test.ts.snap new file mode 100644 index 00000000..28da2f7f --- /dev/null +++ b/packages/c-live-region/tests/__snapshots__/c-live-region.test.ts.snap @@ -0,0 +1,7 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render properly 1`] = ` + + + +`; diff --git a/packages/c-live-region/tests/c-live-region.test.ts b/packages/c-live-region/tests/c-live-region.test.ts new file mode 100644 index 00000000..36fb8ce5 --- /dev/null +++ b/packages/c-live-region/tests/c-live-region.test.ts @@ -0,0 +1,7 @@ +import { render } from "../../test-utils/src" +import { CLiveRegion } from "../src" + +it("should render properly", () => { + const { asFragment } = render(CLiveRegion) + expect(asFragment()).toMatchSnapshot() +}) diff --git a/packages/c-live-region/tsconfig.json b/packages/c-live-region/tsconfig.json new file mode 100644 index 00000000..baa32841 --- /dev/null +++ b/packages/c-live-region/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../../tsconfig.json", + "include": ["src", "./index.tsx"] +} \ No newline at end of file diff --git a/packages/c-live-region/tsup.config.ts b/packages/c-live-region/tsup.config.ts new file mode 100644 index 00000000..9a7cd043 --- /dev/null +++ b/packages/c-live-region/tsup.config.ts @@ -0,0 +1,17 @@ +import { defineConfig } from "tsup" +import EsbuildPluginJSX from "unplugin-vue-jsx/esbuild" + +export default defineConfig({ + clean: true, + target: "es2019", + esbuildPlugins: [ + EsbuildPluginJSX({ + include: [/.[jt]sx?$/], + }) as any, + ], + metafile: true, + external: ["lodash.mergewith"], + format: ["esm", "cjs"], + entry: ["src/**/*.(ts|tsx)"], + keepNames: true, +}) diff --git a/packages/c-media-query/package.json b/packages/c-media-query/package.json index 3b8e726f..fd555ce5 100644 --- a/packages/c-media-query/package.json +++ b/packages/c-media-query/package.json @@ -32,7 +32,8 @@ "dependencies": { "@chakra-ui/vue-composables": "workspace:*", "@chakra-ui/vue-system": "workspace:*", - "@chakra-ui/vue-utils": "workspace:*" + "@chakra-ui/vue-utils": "workspace:*", + "@chakra-ui/utils": "2.0.14" }, "devDependencies": { "vue": "3.2.47" diff --git a/packages/c-media-query/src/index.tsx b/packages/c-media-query/src/index.tsx index 019f3f83..c047bec3 100644 --- a/packages/c-media-query/src/index.tsx +++ b/packages/c-media-query/src/index.tsx @@ -2,8 +2,12 @@ export { CHide } from "./c-hide" export { CShow } from "./c-show" export { CVisibility } from "./c-visibility" export { useQuery } from "./use-query" +export { useBreakpointValue } from "./use-breakpoint-value" +export { useBreakpoint } from "./use-breakpoint" +export { getClosestValue } from "./media.utils" export type { CHideProps } from "./c-hide" export type { CShowProps } from "./c-show" export type { CVisbilityProps } from "./c-visibility" export type { UseQueryProps } from "./use-query" +export type { UseBreakpointOptions } from "./use-breakpoint" diff --git a/packages/c-media-query/src/media.utils.ts b/packages/c-media-query/src/media.utils.ts new file mode 100644 index 00000000..5852af72 --- /dev/null +++ b/packages/c-media-query/src/media.utils.ts @@ -0,0 +1,37 @@ +import { breakpoints as defaultBreakpoints } from "@chakra-ui/utils" + +/** + * Returns the closest value to the given breakpoint from + * the given set of breakpoints + */ +export function getClosestValue( + values: Record, + breakpoint: string, + breakpoints = defaultBreakpoints +) { + let index = Object.keys(values).indexOf(breakpoint) + + if (index !== -1) { + return values[breakpoint] + } + + let stopIndex = breakpoints.indexOf(breakpoint) + + while (stopIndex >= 0) { + const key = breakpoints[stopIndex] + + if (values.hasOwnProperty(key)) { + index = stopIndex + break + } + + stopIndex -= 1 + } + + if (index !== -1) { + const key = breakpoints[index] + return values[key] + } + + return undefined +} diff --git a/packages/c-media-query/src/use-breakpoint-value.ts b/packages/c-media-query/src/use-breakpoint-value.ts new file mode 100644 index 00000000..d6b0179f --- /dev/null +++ b/packages/c-media-query/src/use-breakpoint-value.ts @@ -0,0 +1,27 @@ +import { arrayToObjectNotation, isObject } from "@chakra-ui/utils" +import { useTheme } from "@chakra-ui/vue-system" +import { getClosestValue } from "./media.utils" +import { useBreakpoint, UseBreakpointOptions } from "./use-breakpoint" + +export function useBreakpointValue( + values: Partial> | T[], + arg?: UseBreakpointOptions | string +): T | undefined { + const opts = isObject(arg) ? arg : { fallback: arg ?? "base" } + const breakpoint = useBreakpoint(opts) + const theme = useTheme() + + if (!breakpoint) return + + const breakpoints: string[] = Array.from(theme.__breakpoints?.keys || []) + + const obj = Array.isArray(values) + ? Object.fromEntries( + Object.entries(arrayToObjectNotation(values, breakpoints)).map( + ([key, value]) => [key, value] + ) + ) + : values + + return getClosestValue(obj, breakpoint, breakpoints) +} diff --git a/packages/c-media-query/src/use-breakpoint.ts b/packages/c-media-query/src/use-breakpoint.ts new file mode 100644 index 00000000..caea7c48 --- /dev/null +++ b/packages/c-media-query/src/use-breakpoint.ts @@ -0,0 +1,39 @@ +import { unref } from "vue" +import { isObject } from "@chakra-ui/utils" +import { useTheme } from "@chakra-ui/vue-system" +import { useMediaQuery } from "@vueuse/core" + +export type UseBreakpointOptions = { + fallback?: string +} + +/** + * Composable used to get the current responsive media breakpoint + */ +export function useBreakpoint(arg?: string | UseBreakpointOptions) { + const opts = isObject(arg) ? arg : { fallback: arg ?? "base" } + const theme = useTheme() + + // Explicitly creating the type due to the typing of + // `theme.__breakpoints` not being deep enough to recognize it's properties + type BreakpointsObjectType = { + query: string + breakpoint: string + } + + const breakpoints: BreakpointsObjectType[] = theme.__breakpoints!.details.map( + ({ minMaxQuery, breakpoint }: any) => ({ + breakpoint, + query: minMaxQuery.replace("@media screen and ", ""), + }) + ) + const values = breakpoints.map((bp) => { + const bpQuery = useMediaQuery(bp.query) + + return bpQuery + }) + + const index = unref(values).findIndex((value) => value.value == true) + + return breakpoints[index]?.breakpoint ?? opts.fallback +} diff --git a/packages/c-media-query/tests/media.utils.test.ts b/packages/c-media-query/tests/media.utils.test.ts new file mode 100644 index 00000000..80b75cd3 --- /dev/null +++ b/packages/c-media-query/tests/media.utils.test.ts @@ -0,0 +1,47 @@ +/// + +import { getClosestValue } from "../src/media.utils" + +describe("`getClosestValue` function", () => { + test("should get the closest responsive value", () => { + expect(getClosestValue({ base: "40px", md: "500px" }, "xl")).toBe("500px") + expect(getClosestValue({ base: "40px", md: "500px" }, "sm")).toBe("40px") + expect(getClosestValue({ base: "40px" }, "lg")).toBe("40px") + expect(getClosestValue({ sm: "40px", md: "500px" }, "sm")).toBe("40px") + expect(getClosestValue({ sm: "40px", md: "500px" }, "base")).toBe(undefined) + expect(getClosestValue({}, "")).toBe(undefined) + }) + + test("should get the closest responsive value even if values contains nullable value", () => { + expect(getClosestValue({ base: "40px", md: undefined }, "xl")).toBe( + undefined + ) + expect(getClosestValue({ base: "40px", md: null }, "xl")).toBe(null) + expect(getClosestValue({ sm: "40px", md: undefined }, "xl")).toBe(undefined) + expect(getClosestValue({ sm: "40px", md: null }, "xl")).toBe(null) + }) + + test("should get the closest responsive value with custom breakpoints", () => { + const customBreakPoints = ["base", "sm", "md", "custom", "xl"] + expect( + getClosestValue( + { base: "40px", md: "500px", custom: "600px" }, + "xl", + customBreakPoints + ) + ).toBe("600px") + expect( + getClosestValue({ base: "40px", md: "500px" }, "sm", customBreakPoints) + ).toBe("40px") + expect(getClosestValue({ base: "40px" }, "custom", customBreakPoints)).toBe( + "40px" + ) + expect( + getClosestValue({ sm: "40px", md: "500px" }, "sm", customBreakPoints) + ).toBe("40px") + expect( + getClosestValue({ sm: "40px", md: "500px" }, "base", customBreakPoints) + ).toBe(undefined) + expect(getClosestValue({}, "")).toBe(undefined) + }) +}) diff --git a/packages/c-menu/package.json b/packages/c-menu/package.json index f09d2f99..845c7fd9 100644 --- a/packages/c-menu/package.json +++ b/packages/c-menu/package.json @@ -36,7 +36,7 @@ "@chakra-ui/vue-layout": "workspace:*", "@chakra-ui/vue-system": "workspace:*", "@chakra-ui/vue-utils": "workspace:*", - "@chakra-ui/styled-system": "2.5.1", + "@chakra-ui/styled-system": "2.6.1", "@zag-js/menu": "0.3.8", "@zag-js/vue": "^0.2.9" }, diff --git a/packages/c-modal/package.json b/packages/c-modal/package.json index 77a71516..15f90fd5 100644 --- a/packages/c-modal/package.json +++ b/packages/c-modal/package.json @@ -38,7 +38,7 @@ "@chakra-ui/c-motion": "workspace:*", "@chakra-ui/c-portal": "workspace:*", "@chakra-ui/c-scroll-lock": "workspace:*", - "@chakra-ui/styled-system": "2.5.1", + "@chakra-ui/styled-system": "2.6.1", "@chakra-ui/utils": "2.0.15", "@chakra-ui/vue-accessibilty": "workspace:*", "@chakra-ui/vue-composables": "workspace:*", diff --git a/packages/c-motion/examples/with-collapse.vue b/packages/c-motion/examples/with-collapse.vue index 9f4d0348..c61aaa9f 100644 --- a/packages/c-motion/examples/with-collapse.vue +++ b/packages/c-motion/examples/with-collapse.vue @@ -31,6 +31,7 @@ diff --git a/packages/c-table/examples/simple-table.vue b/packages/c-table/examples/simple-table.vue new file mode 100644 index 00000000..cd333305 --- /dev/null +++ b/packages/c-table/examples/simple-table.vue @@ -0,0 +1,51 @@ + + diff --git a/packages/c-table/index.tsx b/packages/c-table/index.tsx new file mode 100644 index 00000000..46e72b16 --- /dev/null +++ b/packages/c-table/index.tsx @@ -0,0 +1 @@ +export * from "./src" diff --git a/packages/c-table/package.json b/packages/c-table/package.json new file mode 100644 index 00000000..9f17e7fe --- /dev/null +++ b/packages/c-table/package.json @@ -0,0 +1,49 @@ +{ + "name": "@chakra-ui/c-table", + "description": "Chakra UI Vue | Table component is used to organize and display data efficiently it renders a table element by default component", + "version": "2.0.0-beta.0", + "author": "Jonathan Bakebwa ", + "homepage": "https://github.com/chakra-ui/chakra-ui-vue-next#readme", + "license": "MIT", + "main": "dist/index.js", + "module": "dist/index.mjs", + "typings": "dist/index.d.ts", + "files": [ + "dist" + ], + "exports": { + ".": { + "require": "./dist/index.js", + "default": "./dist/index.mjs" + } + }, + "repository": { + "type": "git", + "url": "git+https://github.com/chakra-ui/chakra-ui-vue-next.git" + }, + "bugs": { + "url": "https://github.com/chakra-ui/chakra-ui-vue-next/issues" + }, + "sideEffects": false, + "scripts": { + "clean": "rimraf dist .turbo", + "build": "tsup && pnpm build:types", + "build:fast": "tsup", + "build:types": "tsup src --dts-only", + "types:check": "tsc --noEmit", + "dev": "tsup --watch" + }, + "dependencies": { + "@chakra-ui/vue-system": "workspace:*", + "@chakra-ui/vue-utils": "workspace:*" + }, + "devDependencies": { + "vue": "^3.2.37" + }, + "peerDependencies": { + "vue": "^3.1.4" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/packages/c-table/src/c-table-caption.tsx b/packages/c-table/src/c-table-caption.tsx new file mode 100644 index 00000000..6d091b4b --- /dev/null +++ b/packages/c-table/src/c-table-caption.tsx @@ -0,0 +1,39 @@ +import { h, defineComponent, PropType } from "vue" +import { + chakra, + ComponentWithProps, + DeepPartial, + HTMLChakraProps, +} from "@chakra-ui/vue-system" +import { useTableStyles } from "./c-table" + +export interface CTableCaptionProps extends HTMLChakraProps<"caption"> { + /** + * The placement of the table caption. This sets the `caption-side` CSS attribute. + * @default "bottom" + */ + placement?: "top" | "bottom" +} + +export const CTableCaption = defineComponent({ + name: "CTableCaption", + props: { + placement: String as PropType, + }, + setup(props, { slots, attrs }) { + const styles = useTableStyles() + + return () => ( + + {slots} + + ) + }, +}) diff --git a/packages/c-table/src/c-table-container.tsx b/packages/c-table/src/c-table-container.tsx new file mode 100644 index 00000000..798cae01 --- /dev/null +++ b/packages/c-table/src/c-table-container.tsx @@ -0,0 +1,31 @@ +import { h, defineComponent, PropType } from "vue" +import { chakra, HTMLChakraProps } from "@chakra-ui/vue-system" +import type * as CSS from "csstype" + +export interface CTableContainerProps extends HTMLChakraProps<"div"> {} + +export const CTableContainer = defineComponent({ + name: "CTableContainer", + props: { + overflow: String as PropType, + overflowX: String as PropType, + }, + setup(props, { slots, attrs }) { + return () => ( + + {slots.default?.()} + + ) + }, +}) diff --git a/packages/c-table/src/c-table.tsx b/packages/c-table/src/c-table.tsx new file mode 100644 index 00000000..d1bb679a --- /dev/null +++ b/packages/c-table/src/c-table.tsx @@ -0,0 +1,67 @@ +/** + * Hey! Welcome to @chakra-ui/vue-next CTable + * + * Table component is used to organize and display data efficiently it renders a table element by default + * + * @see Docs https://next.vue.chakra-ui.com/c-table + * @see Source https://github.com/chakra-ui/chakra-ui-vue-next/blob/main/packages/c-table/src/c-table/c-table.ts + * @see WAI-ARIA https://www.w3.org/TR/wai-aria-practices-1.2 + */ + +import { h, defineComponent, computed, mergeProps, PropType } from "vue" +import { + chakra, + createStylesContext, + HTMLChakraProps, + omitThemingProps, + SystemStyleObject, + ThemingProps, + useMultiStyleConfig, +} from "@chakra-ui/vue-system" +import { vueThemingProps } from "@chakra-ui/vue-utils" +import type * as SS from "@chakra-ui/styled-system" + +export const [TableStylesProvider, useTableStyles] = + createStylesContext("Table") + +export interface TableOptions { + layout?: SystemStyleObject["tableLayout"] +} + +export interface CTableProps + extends HTMLChakraProps<"table">, + TableOptions, + ThemingProps<"Table"> {} + +/** + * The `CTable` component is used to organize and display data efficiently. It renders a `` element by default. + * + * @see Docs https://github.com/chakra-ui/chakra-ui-vue-next/tree/develop/packages/c-table + * @see WAI-ARIA https://www.w3.org/WAI/ARIA/apg/patterns/table/ + */ +export const CTable = defineComponent({ + name: "CTable", + props: { + layout: { + type: String as PropType, + }, + ...vueThemingProps, + }, + setup(props, { slots, attrs }) { + const styles = useMultiStyleConfig("Table", props) + const mergedProps = computed(() => mergeProps({}, props, attrs)) + const ownProps = computed(() => omitThemingProps(mergedProps.value)) + + TableStylesProvider(styles) + + return () => ( + + {slots} + + ) + }, +}) diff --git a/packages/c-table/src/c-tbody.tsx b/packages/c-table/src/c-tbody.tsx new file mode 100644 index 00000000..3585e5c2 --- /dev/null +++ b/packages/c-table/src/c-tbody.tsx @@ -0,0 +1,27 @@ +import { h, defineComponent } from "vue" +import { + chakra, + ComponentWithProps, + DeepPartial, + HTMLChakraProps, +} from "@chakra-ui/vue-system" +import { useTableStyles } from "./c-table" + +export interface CTableBodyProps extends HTMLChakraProps<"tbody"> {} + +export const CTbody = defineComponent({ + name: "CTbody", + setup(_, { slots, attrs }) { + const styles = useTableStyles() + + return () => ( + + {slots} + + ) + }, +}) diff --git a/packages/c-table/src/c-td.tsx b/packages/c-table/src/c-td.tsx new file mode 100644 index 00000000..6e528a43 --- /dev/null +++ b/packages/c-table/src/c-td.tsx @@ -0,0 +1,36 @@ +import { h, defineComponent, PropType } from "vue" +import { + chakra, + ComponentWithProps, + DeepPartial, + HTMLChakraProps, +} from "@chakra-ui/vue-system" +import { useTableStyles } from "./c-table" + +export interface CTableCellProps extends HTMLChakraProps<"th"> { + /** + * Aligns the cell content to the right + */ + isNumeric?: boolean +} + +export const CTd = defineComponent({ + name: "CTd", + props: { + isNumeric: Boolean as PropType, + }, + setup(props, { slots, attrs }) { + const styles = useTableStyles() + + return () => ( + + {slots} + + ) + }, +}) diff --git a/packages/c-table/src/c-tfoot.tsx b/packages/c-table/src/c-tfoot.tsx new file mode 100644 index 00000000..f6ca65c6 --- /dev/null +++ b/packages/c-table/src/c-tfoot.tsx @@ -0,0 +1,27 @@ +import { h, defineComponent } from "vue" +import { + chakra, + ComponentWithProps, + DeepPartial, + HTMLChakraProps, +} from "@chakra-ui/vue-system" +import { useTableStyles } from "./c-table" + +export interface CTableFooterProps extends HTMLChakraProps<"tbody"> {} + +export const CTfoot = defineComponent({ + name: "CTfoot", + setup(_, { slots, attrs }) { + const styles = useTableStyles() + + return () => ( + + {slots} + + ) + }, +}) diff --git a/packages/c-table/src/c-th.tsx b/packages/c-table/src/c-th.tsx new file mode 100644 index 00000000..653d8e33 --- /dev/null +++ b/packages/c-table/src/c-th.tsx @@ -0,0 +1,36 @@ +import { h, defineComponent, PropType } from "vue" +import { + chakra, + ComponentWithProps, + DeepPartial, + HTMLChakraProps, +} from "@chakra-ui/vue-system" +import { useTableStyles } from "./c-table" + +export interface CTableColumnHeaderProps extends HTMLChakraProps<"th"> { + /** + * Aligns the cell content to the right + */ + isNumeric?: boolean +} + +export const CTh = defineComponent({ + name: "CTh", + props: { + isNumeric: Boolean as PropType, + }, + setup(props, { slots, attrs }) { + const styles = useTableStyles() + + return () => ( + + {slots} + + ) + }, +}) diff --git a/packages/c-table/src/c-thead.tsx b/packages/c-table/src/c-thead.tsx new file mode 100644 index 00000000..5051b159 --- /dev/null +++ b/packages/c-table/src/c-thead.tsx @@ -0,0 +1,27 @@ +import { h, defineComponent } from "vue" +import { + chakra, + ComponentWithProps, + DeepPartial, + HTMLChakraProps, +} from "@chakra-ui/vue-system" +import { useTableStyles } from "./c-table" + +export interface CTHeadProps extends HTMLChakraProps<"thead"> {} + +export const CThead = defineComponent({ + name: "CThead", + setup(_, { slots, attrs }) { + const styles = useTableStyles() + + return () => ( + + {slots} + + ) + }, +}) diff --git a/packages/c-table/src/c-tr.tsx b/packages/c-table/src/c-tr.tsx new file mode 100644 index 00000000..a5f5e59e --- /dev/null +++ b/packages/c-table/src/c-tr.tsx @@ -0,0 +1,23 @@ +import { h, defineComponent } from "vue" +import { + chakra, + ComponentWithProps, + DeepPartial, + HTMLChakraProps, +} from "@chakra-ui/vue-system" +import { useTableStyles } from "./c-table" + +export interface CTableRowProps extends HTMLChakraProps<"tr"> {} + +export const CTr = defineComponent({ + name: "CTr", + setup(_, { slots, attrs }) { + const styles = useTableStyles() + + return () => ( + + {slots} + + ) + }, +}) diff --git a/packages/c-table/src/index.tsx b/packages/c-table/src/index.tsx new file mode 100644 index 00000000..c39bacd5 --- /dev/null +++ b/packages/c-table/src/index.tsx @@ -0,0 +1,19 @@ +export { CTable, TableStylesProvider, useTableStyles } from "./c-table" +export { CTableContainer } from "./c-table-container" +export { CTableCaption } from "./c-table-caption" +export { CTbody } from "./c-tbody" +export { CTd } from "./c-td" +export { CTfoot } from "./c-tfoot" +export { CTh } from "./c-th" +export { CThead } from "./c-thead" +export { CTr } from "./c-tr" + +export type { CTableProps } from "./c-table" +export type { CTableContainerProps } from "./c-table-container" +export type { CTableCaptionProps } from "./c-table-caption" +export type { CTableBodyProps } from "./c-tbody" +export type { CTableCellProps } from "./c-td" +export type { CTableFooterProps } from "./c-tfoot" +export type { CTableColumnHeaderProps } from "./c-th" +export type { CTHeadProps } from "./c-thead" +export type { CTableRowProps } from "./c-tr" diff --git a/packages/c-table/tests/c-table.test.ts b/packages/c-table/tests/c-table.test.ts new file mode 100644 index 00000000..de18da10 --- /dev/null +++ b/packages/c-table/tests/c-table.test.ts @@ -0,0 +1,56 @@ +import { + CTable, + CTableCaption, + CThead, + CTbody, + CTr, + CTh, + CTd, + CTfoot, +} from "../src" +import { render, testA11y } from "../../test-utils" + +describe("Table", () => { + it("should pass a11y test", async () => { + const renderComponent = () => + render({ + components: { + CTable, + CTableCaption, + CThead, + CTr, + CTh, + CTbody, + CTfoot, + }, + template: ` + + Imperial to metric conversion factors + + + To convert + into + multiply by + + + + + inches + millimetres (mm) + 25.4 + + + + + + + + + + + `, + }) + + await testA11y(renderComponent()) + }) +}) diff --git a/packages/c-table/tsconfig.json b/packages/c-table/tsconfig.json new file mode 100644 index 00000000..baa32841 --- /dev/null +++ b/packages/c-table/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../../tsconfig.json", + "include": ["src", "./index.tsx"] +} \ No newline at end of file diff --git a/packages/c-table/tsup.config.ts b/packages/c-table/tsup.config.ts new file mode 100644 index 00000000..9a7cd043 --- /dev/null +++ b/packages/c-table/tsup.config.ts @@ -0,0 +1,17 @@ +import { defineConfig } from "tsup" +import EsbuildPluginJSX from "unplugin-vue-jsx/esbuild" + +export default defineConfig({ + clean: true, + target: "es2019", + esbuildPlugins: [ + EsbuildPluginJSX({ + include: [/.[jt]sx?$/], + }) as any, + ], + metafile: true, + external: ["lodash.mergewith"], + format: ["esm", "cjs"], + entry: ["src/**/*.(ts|tsx)"], + keepNames: true, +}) diff --git a/packages/c-tag/package.json b/packages/c-tag/package.json index 1dd2ba59..8183a836 100644 --- a/packages/c-tag/package.json +++ b/packages/c-tag/package.json @@ -32,7 +32,7 @@ "dependencies": { "@chakra-ui/c-icon": "workspace:*", "@chakra-ui/utils": "2.0.15", - "@chakra-ui/styled-system": "2.5.1", + "@chakra-ui/styled-system": "2.6.1", "@chakra-ui/vue-system": "workspace:*", "@chakra-ui/vue-utils": "workspace:*" }, diff --git a/packages/c-textarea/README.md b/packages/c-textarea/README.md new file mode 100644 index 00000000..6baee5e7 --- /dev/null +++ b/packages/c-textarea/README.md @@ -0,0 +1,14 @@ +# `@chakra-ui/c-textarea` + +The textarea component allows you to easily create multi line text inputs + +## Installation + +```sh +# with pnpm +pnpm add @chakra-ui/c-textarea +# or with Yarn +yarn i @chakra-ui/c-textarea +# or with npm +npm i @chakra-ui/c-textarea +``` \ No newline at end of file diff --git a/packages/c-textarea/examples/simple-textarea.vue b/packages/c-textarea/examples/simple-textarea.vue new file mode 100644 index 00000000..2a5c09be --- /dev/null +++ b/packages/c-textarea/examples/simple-textarea.vue @@ -0,0 +1,14 @@ + + + diff --git a/packages/c-textarea/index.tsx b/packages/c-textarea/index.tsx new file mode 100644 index 00000000..46e72b16 --- /dev/null +++ b/packages/c-textarea/index.tsx @@ -0,0 +1 @@ +export * from "./src" diff --git a/packages/c-textarea/package.json b/packages/c-textarea/package.json new file mode 100644 index 00000000..34434dbc --- /dev/null +++ b/packages/c-textarea/package.json @@ -0,0 +1,50 @@ +{ + "name": "@chakra-ui/c-textarea", + "description": "Chakra UI Vue | The textarea component allows you to easily create multi line text inputs component", + "version": "0.0.0-beta.0", + "author": "Jonathan Bakebwa ", + "homepage": "https://github.com/chakra-ui/chakra-ui-vue-next#readme", + "license": "MIT", + "main": "dist/index.js", + "module": "dist/index.mjs", + "typings": "dist/index.d.ts", + "files": [ + "dist" + ], + "exports": { + ".": { + "require": "./dist/index.js", + "default": "./dist/index.mjs" + } + }, + "repository": { + "type": "git", + "url": "git+https://github.com/chakra-ui/chakra-ui-vue-next.git" + }, + "bugs": { + "url": "https://github.com/chakra-ui/chakra-ui-vue-next/issues" + }, + "sideEffects": false, + "scripts": { + "clean": "rimraf dist .turbo", + "build": "tsup && pnpm build:types", + "build:fast": "tsup", + "build:types": "tsup src --dts-only", + "types:check": "tsc --noEmit", + "dev": "tsup --watch" + }, + "dependencies": { + "@chakra-ui/c-form-control": "workspace:*", + "@chakra-ui/vue-system": "workspace:*", + "@chakra-ui/vue-utils": "workspace:*" + }, + "devDependencies": { + "vue": "^3.2.37" + }, + "peerDependencies": { + "vue": "^3.1.4" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/packages/c-textarea/src/c-textarea.tsx b/packages/c-textarea/src/c-textarea.tsx new file mode 100644 index 00000000..41f26d2d --- /dev/null +++ b/packages/c-textarea/src/c-textarea.tsx @@ -0,0 +1,105 @@ +/** + * Hey! Welcome to @chakra-ui/vue-next CTextarea + * + * C textarea + * + * @see Docs https://next.vue.chakra-ui.com/c-textarea + * @see Source https://github.com/chakra-ui/chakra-ui-vue-next/blob/master/packages/c-textarea/src/c-textarea/c-textarea.ts + * @see WAI-ARIA https://www.w3.org/TR/wai-aria-practices-1.2 + */ + +import { + h, + defineComponent, + PropType, + computed, + reactive, + toRefs, + ToRefs, +} from "vue" +import { + chakra, + HTMLChakraProps, + omitThemingProps, + ThemingProps, + useStyleConfig, +} from "@chakra-ui/vue-system" +import { omit } from "@chakra-ui/utils" +import { vueThemingProps } from "@chakra-ui/vue-utils" +import { + FormControlOptions, + formControlProps, + useFormControl, +} from "@chakra-ui/c-form-control" + +interface TextareaOptions { + /** + * The border color when the textarea is focused. Use color keys in `theme.colors` + * @example + * focusBorderColor = "blue.500" + */ + focusBorderColor?: string + /** + * The border color when the textarea is invalid. Use color keys in `theme.colors` + * @example + * errorBorderColor = "red.500" + */ + errorBorderColor?: string +} + +type Omitted = "disabled" | "required" | "readOnly" + +export interface CTextareaNativeProps + extends TextareaOptions, + FormControlOptions {} + +export interface CTextareaProps + extends Omit, Omitted>, + CTextareaNativeProps, + ThemingProps<"Textarea"> {} + +export const CTextarea = defineComponent({ + name: "CTextarea", + props: { + modelValue: String as PropType, + ...formControlProps, + rows: Number as PropType, + ...vueThemingProps, + }, + emits: ["update:modelValue", "input", "change"], + setup(props, { emit, attrs }) { + const styles = useStyleConfig("Textarea", props) + + const ownProps = computed(() => + toRefs(reactive(omitThemingProps(props as ThemingProps<"Textarea">))) + ) + + const textarea = useFormControl( + ownProps.value as ToRefs + ) + + const textareaStyles = computed(() => + props.rows + ? omit(styles.value, ["h", "minH", "height", "minHeight"]) + : styles.value + ) + + const handleInput = (e: Event) => { + emit("update:modelValue", (e?.currentTarget as HTMLInputElement)?.value) + emit("input", e, (e?.currentTarget as HTMLInputElement)?.value) + emit("change", e, (e?.currentTarget as HTMLInputElement)?.value) + } + + return () => ( + + ) + }, +}) diff --git a/packages/c-textarea/src/index.tsx b/packages/c-textarea/src/index.tsx new file mode 100644 index 00000000..d9aa3e71 --- /dev/null +++ b/packages/c-textarea/src/index.tsx @@ -0,0 +1,2 @@ +export { CTextarea } from "./c-textarea" +export type { CTextareaNativeProps, CTextareaProps } from "./c-textarea" diff --git a/packages/c-textarea/tests/__snapshots__/c-textarea.test.ts.snap b/packages/c-textarea/tests/__snapshots__/c-textarea.test.ts.snap new file mode 100644 index 00000000..b1b67b14 --- /dev/null +++ b/packages/c-textarea/tests/__snapshots__/c-textarea.test.ts.snap @@ -0,0 +1,9 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render properly 1`] = ` + +
To convertintomultiply by