diff --git a/.yarn/cache/@rollup-plugin-replace-npm-4.0.0-4c483d297f-b61701e612.zip b/.yarn/cache/@rollup-plugin-replace-npm-4.0.0-4c483d297f-b61701e612.zip deleted file mode 100644 index d99a173485bf..000000000000 Binary files a/.yarn/cache/@rollup-plugin-replace-npm-4.0.0-4c483d297f-b61701e612.zip and /dev/null differ diff --git a/.yarn/cache/@rollup-plugin-replace-npm-5.0.1-681fe3a569-d5f98a93dd.zip b/.yarn/cache/@rollup-plugin-replace-npm-5.0.1-681fe3a569-d5f98a93dd.zip new file mode 100644 index 000000000000..964effd4678e Binary files /dev/null and b/.yarn/cache/@rollup-plugin-replace-npm-5.0.1-681fe3a569-d5f98a93dd.zip differ diff --git a/.yarn/cache/@rollup-pluginutils-npm-5.0.2-6aa9d0ddd4-edea15e543.zip b/.yarn/cache/@rollup-pluginutils-npm-5.0.2-6aa9d0ddd4-edea15e543.zip new file mode 100644 index 000000000000..d898c5035c87 Binary files /dev/null and b/.yarn/cache/@rollup-pluginutils-npm-5.0.2-6aa9d0ddd4-edea15e543.zip differ diff --git a/.yarn/cache/@types-estree-npm-1.0.0-eddde5b631-910d97fb70.zip b/.yarn/cache/@types-estree-npm-1.0.0-eddde5b631-910d97fb70.zip new file mode 100644 index 000000000000..8b03b040a651 Binary files /dev/null and b/.yarn/cache/@types-estree-npm-1.0.0-eddde5b631-910d97fb70.zip differ diff --git a/.yarn/cache/@types-prop-types-npm-15.7.4-592896a9fe-ef6e1899e5.zip b/.yarn/cache/@types-prop-types-npm-15.7.4-592896a9fe-ef6e1899e5.zip deleted file mode 100644 index 482f0927eec8..000000000000 Binary files a/.yarn/cache/@types-prop-types-npm-15.7.4-592896a9fe-ef6e1899e5.zip and /dev/null differ diff --git a/.yarn/cache/@types-prop-types-npm-15.7.5-2aa48aa177-5b43b8b154.zip b/.yarn/cache/@types-prop-types-npm-15.7.5-2aa48aa177-5b43b8b154.zip new file mode 100644 index 000000000000..38bb2b470787 Binary files /dev/null and b/.yarn/cache/@types-prop-types-npm-15.7.5-2aa48aa177-5b43b8b154.zip differ diff --git a/.yarn/cache/magic-string-npm-0.26.7-07281acc06-89b0d60cbb.zip b/.yarn/cache/magic-string-npm-0.26.7-07281acc06-89b0d60cbb.zip new file mode 100644 index 000000000000..483252326cb9 Binary files /dev/null and b/.yarn/cache/magic-string-npm-0.26.7-07281acc06-89b0d60cbb.zip differ diff --git a/config/eslint-config-carbon/package.json b/config/eslint-config-carbon/package.json index 0d25d634b0d8..825b24c8cebf 100644 --- a/config/eslint-config-carbon/package.json +++ b/config/eslint-config-carbon/package.json @@ -1,7 +1,7 @@ { "name": "eslint-config-carbon", "description": "ESLint configuration for Carbon", - "version": "2.18.0-rc.0", + "version": "2.18.0", "license": "Apache-2.0", "main": "index.js", "repository": { diff --git a/config/jest-config-carbon/package.json b/config/jest-config-carbon/package.json index c64b20d37c35..8340250729c1 100644 --- a/config/jest-config-carbon/package.json +++ b/config/jest-config-carbon/package.json @@ -2,7 +2,7 @@ "name": "jest-config-carbon", "private": true, "description": "Jest configuration and preset for Carbon", - "version": "1.5.0-rc.0", + "version": "1.5.0", "license": "Apache-2.0", "main": "index.js", "repository": { diff --git a/docs/guides/adding-component-types.md b/docs/guides/adding-component-types.md new file mode 100644 index 000000000000..1d8e679628de --- /dev/null +++ b/docs/guides/adding-component-types.md @@ -0,0 +1,150 @@ +# Adding component types + +This document lays out the goal, strategy, and guidelines for adding +[TypeScript](https://www.TypeScriptlang.org/) types for components within +`@carbon/react`. + + + + +## Table of Contents + +- [Goal](#goal) + - [Purpose](#purpose) +- [Strategy](#strategy) + - [Steps to provide baseline type definitions for components](#steps-to-provide-baseline-type-definitions-for-components) +- [FAQ](#faq) + - [How do I know what's part of the public api?](#how-do-i-know-whats-part-of-the-public-api) + - [Should components have both prototypes and ts interface?](#should-components-have-both-prototypes-and-ts-interface) + - [Should comment docs be duplicated into the ts interface?](#should-comment-docs-be-duplicated-into-the-ts-interface) + - [Where should I put the ts interface in the file?](#where-should-i-put-the-ts-interface-in-the-file) + + + + +## Goal + +The goal of this workstream is to provide as much downstream value to consumers +who are using TypeScript, as quickly as possible, while writing the least amount +of TypeScript. + +The goal is _not_ to convert the entire codebase to TypeScript right now. + +### Purpose + +By adding TypeScript types to components we anticipate a number of benefits: + +- Developer productivity will increase due to Component API's being + self-documenting and providing tight integration with code editor + intellisense. +- The qualtiy of products developed will increase due to more stable, correct, + and thorough component API typings provided first-party through + `@carbon/react` itself. +- Maintenance of the types themselves will be simplified by not having to go + through the DefinitelyTyped contribution process/system. + +Despite these benefits, adding TypeScript to the codebase is still a large shift +for the developer community surrounding the Carbon Design System. Most projects +are not using TypeScript, and contributors are more likely to not have in-depth +knowledge of TypeScript. + +The bar to contribute to Carbon should be as low as possible to facilitate +experimentation, innovation, and progress within the system. Adding TypeScript +raises this bar of contribution adding additional friction to even the smallest +of pull requests. + +We believe the majority of the benefits of TypeScript can be provided to +consumers without needing to convert the entire codebase to use TypeScript. +Overall, this effort will be focused on limiting the amount of TypeScript within +the repository for now. + +## Strategy + +TypeScript will be incrementally adopted, focusing first on adding types to +components prop APIs that are included as part of the public API of +`@carbon/react`. + +Internal components, helpers, function, etc. will not initially be typed. These +internal files/components not included in the public API should be left as +`.js`, given a +[jsdoc type annotation](https://www.typescriptlang.org/docs/handbook/intro-to-js-ts.html#providing-type-hints-in-js-via-jsdoc) +of `/** @type any */`, and +[errors should be enabled](https://www.typescriptlang.org/docs/handbook/intro-to-js-ts.html#ts-check) +by adding `// @ts-check` to the first line in the file. + +Other packages, such as `@carbon/icons-react`, `@carbon/elements`, etc will not +initially be typed. + +Within this incremental adoption strategy, **for now types will not be bound to +semver**. + +This means that types are provided on an as-is basis. Ideally types will be +stable and not ship breaking changes, but the reality is typings may at times be +incorrect, outdated, or missing. Full details available within our +[versioning documentation](https://github.com/carbon-design-system/carbon/blob/main/docs/guides/versioning.md#a-change-is-made-to-component-typingsdefinitions). + +### Steps to provide baseline type definitions for components + +Below is a general outline of what needs to be done for each component within +the repository. There is an issue tracking curring status of this effort, +[#12513](https://github.com/carbon-design-system/carbon/issues/12513) + +- Change extension to `.tsx` +- Copying the proptypes def to above the component definition +- Retool the proptypes to be a ts interface +- Fix errors as they appear +- Do not add types to internal components or functions that are not exported as + part of the Public API. + + - Leave internals as `.js` + - Add a + [jsdoc type annotation](https://www.typescriptlang.org/docs/handbook/intro-to-js-ts.html#providing-type-hints-in-js-via-jsdoc) + of `/** @type any */` + - [Enable errors](https://www.typescriptlang.org/docs/handbook/intro-to-js-ts.html#ts-check) + by adding `// @ts-check` to the first line in the file. + +- Test your changes - there are a few options here: + - At the bottom of a file, write a dummy component that uses the component + that you’re converting to ensure that you can still pass all appropriate + props that you need to. + - Take a storybook example for a component, copy and paste it into the bottom + of the .tsx file and validate whether or not it accepts the props as you’ve + defined them +- Submit a pull request for the changes + - Please keep pull requests as small as possible + - Avoid adding additional components to a single PR unless necessary + - [Link to close the related issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword#linking-a-pull-request-to-an-issue-using-a-keyword), + e.g. `Closes #12513` +- Ask questions if you get stuck! + - The team is available on slack + [`#carbon-wg-typescript`](https://ibm-studios.slack.com/archives/C03C8VASVED), + [discord](https://discord.gg/J7JEUEkTRX), or on + [the issue itself](https://github.com/carbon-design-system/carbon/issues/12513). + +## FAQ + +### How do I know what's part of the public api? + +- If it's not on [the storybook](https://react.carbondesignsystem.com), it's + probably not public. +- The entire Public API is snapshotted, you can + [search the snapshot here](https://github.com/carbon-design-system/carbon/blob/main/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap). + If it's not included there, it's not part of the public API. + +### Should components have both prototypes and ts interface? + +- Yes + +### Should comment docs be duplicated into the ts interface? + +- Yes + - Duplicate comments between the proptypes definition and ts interface + - Storybook prefers react-docgen for now + - Once we have ts interfaces for everything we can switch out the storybook + config to favor TypeScript docs + +### Where should I put the ts interface in the file? + +- Above the component definition (likely the top of the file) + - The component implementation should be sandwiched inbetween the ts interface + and the proptypes definition diff --git a/docs/guides/versioning.md b/docs/guides/versioning.md index 4f8721b4fd36..71f238180065 100644 --- a/docs/guides/versioning.md +++ b/docs/guides/versioning.md @@ -6,9 +6,10 @@ ## Table of Contents - [Overview](#overview) -- [`carbon-components-react`](#carbon-components-react) +- [`carbon-components-react`, `@carbon/react`](#carbon-components-react-carbonreact) - [Changes](#changes) - [Examples](#examples) + - [A change is made to component typings/definitions](#a-change-is-made-to-component-typingsdefinitions) - [A new prop is added to a component](#a-new-prop-is-added-to-a-component) - [An existing prop is deprecated](#an-existing-prop-is-deprecated) - [An existing prop is removed](#an-existing-prop-is-removed) @@ -17,6 +18,8 @@ - [A `PropTypes.func` prop type is changed to have different arguments](#a-proptypesfunc-prop-type-is-changed-to-have-different-arguments) - [A `PropTypes.func` prop type is changed to have additional arguments](#a-proptypesfunc-prop-type-is-changed-to-have-additional-arguments) - [A `PropTypes.func` prop type is changed to have fewer arguments](#a-proptypesfunc-prop-type-is-changed-to-have-fewer-arguments) + - [The DOM node that an `id` corresponds to is changed](#the-dom-node-that-an-id-corresponds-to-is-changed) + - [The DOM node that an `aria-label` corresponds to is changed](#the-dom-node-that-an-aria-label-corresponds-to-is-changed) diff --git a/e2e/components/FluidDatePicker/FluidDatePicker-test.e2e.js b/e2e/components/FluidDatePicker/FluidDatePicker-test.e2e.js new file mode 100644 index 000000000000..558358d080c1 --- /dev/null +++ b/e2e/components/FluidDatePicker/FluidDatePicker-test.e2e.js @@ -0,0 +1,67 @@ +/** + * Copyright IBM Corp. 2022 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +'use strict'; + +const { expect, test } = require('@playwright/test'); +const { themes } = require('../../test-utils/env'); +const { snapshotStory, visitStory } = require('../../test-utils/storybook'); + +test.describe('FluidDatePicker', () => { + themes.forEach((theme) => { + test.describe(theme, () => { + test('fluid date picker (range) @vrt', async ({ page }) => { + await snapshotStory(page, { + component: 'FluidDatePicker', + id: 'experimental-unstable-fluiddatepicker--range-with-calendar', + theme, + }); + }); + + test('fluid date picker (single) @vrt', async ({ page }) => { + await snapshotStory(page, { + component: 'FluidDatePicker', + id: 'experimental-unstable-fluiddatepicker--single', + theme, + }); + }); + + test('fluid date picker (simple) @vrt', async ({ page }) => { + await snapshotStory(page, { + component: 'FluidDatePicker', + id: 'experimental-unstable-fluiddatepicker--simple', + theme, + }); + }); + }); + }); + + test('accessibility-checker @avt', async ({ page }) => { + await visitStory(page, { + component: 'FluidDatePicker', + id: 'experimental-unstable-fluiddatepicker--range-with-calendar', + globals: { + theme: 'white', + }, + }); + await visitStory(page, { + component: 'FluidDatePicker', + id: 'experimental-unstable-fluiddatepicker--single', + globals: { + theme: 'white', + }, + }); + await visitStory(page, { + component: 'FluidDatePicker', + id: 'experimental-unstable-fluiddatepicker--simple', + globals: { + theme: 'white', + }, + }); + await expect(page).toHaveNoACViolations('FluidDatePicker'); + }); +}); diff --git a/examples/codesandbox-styles/package.json b/examples/codesandbox-styles/package.json index 5874dd497917..f44e54b7fda9 100644 --- a/examples/codesandbox-styles/package.json +++ b/examples/codesandbox-styles/package.json @@ -1,7 +1,7 @@ { "name": "codesandbox-styles", "private": true, - "version": "0.20.0-rc.1", + "version": "0.20.0", "scripts": { "develop": "vite" }, @@ -9,7 +9,7 @@ "vite": "^2.8.0" }, "dependencies": { - "@carbon/styles": "^1.17.0-rc.1", + "@carbon/styles": "^1.17.0", "sass": "^1.51.0" } } diff --git a/examples/codesandbox-with-sass-compilation/package.json b/examples/codesandbox-with-sass-compilation/package.json index b3ad27d6bfa7..5a17cf6731f8 100644 --- a/examples/codesandbox-with-sass-compilation/package.json +++ b/examples/codesandbox-with-sass-compilation/package.json @@ -1,9 +1,9 @@ { "name": "codesandbox-with-sass-compilation", - "version": "0.18.0-rc.1", + "version": "0.18.0", "private": true, "dependencies": { - "@carbon/react": "^1.17.0-rc.1", + "@carbon/react": "^1.17.0", "react": "^17.0.0", "react-dom": "^17.0.0" }, diff --git a/examples/codesandbox/package.json b/examples/codesandbox/package.json index 507f322f9d44..1594979554b4 100644 --- a/examples/codesandbox/package.json +++ b/examples/codesandbox/package.json @@ -1,9 +1,9 @@ { "name": "codesandbox", - "version": "0.18.0-rc.1", + "version": "0.18.0", "private": true, "dependencies": { - "@carbon/react": "^1.17.0-rc.1", + "@carbon/react": "^1.17.0", "react": "^17.0.0", "react-dom": "^17.0.0" }, diff --git a/examples/custom-theme/package.json b/examples/custom-theme/package.json index a61a1db719a8..24cbc1900c39 100644 --- a/examples/custom-theme/package.json +++ b/examples/custom-theme/package.json @@ -1,14 +1,14 @@ { "name": "custom-theme", "private": true, - "version": "0.15.0-rc.1", + "version": "0.15.0", "scripts": { "dev": "vite", "build": "vite build", "preview": "vite preview" }, "dependencies": { - "@carbon/react": "^1.17.0-rc.1", + "@carbon/react": "^1.17.0", "react": "^17.0.0", "react-dom": "^17.0.0" }, diff --git a/examples/incremental-migration/package.json b/examples/incremental-migration/package.json index ed67f67e2a59..71ab729c0287 100644 --- a/examples/incremental-migration/package.json +++ b/examples/incremental-migration/package.json @@ -1,7 +1,7 @@ { "name": "incremental-migration", "private": true, - "version": "0.17.0-rc.1", + "version": "0.17.0", "scripts": { "build": "next build", "dev": "next dev", @@ -13,7 +13,7 @@ }, "dependencies": { "@carbon/icons-react": "^10.49.0", - "@carbon/react": "^1.17.0-rc.1", + "@carbon/react": "^1.17.0", "carbon-components": "^10.57.0", "carbon-components-react": "^7.57.0", "carbon-icons": "^7.0.7", diff --git a/examples/light-dark-mode/package.json b/examples/light-dark-mode/package.json index 00efffa95cc4..c2baaa5a8169 100644 --- a/examples/light-dark-mode/package.json +++ b/examples/light-dark-mode/package.json @@ -1,7 +1,7 @@ { "name": "examples-light-dark", "private": true, - "version": "0.15.0-rc.1", + "version": "0.15.0", "scripts": { "build": "next build", "dev": "next dev", @@ -9,7 +9,7 @@ "start": "next start" }, "dependencies": { - "@carbon/react": "^1.17.0-rc.1", + "@carbon/react": "^1.17.0", "next": "12.1.4", "react": "18.0.0", "react-dom": "18.0.0" diff --git a/examples/nextjs/package.json b/examples/nextjs/package.json index 53f3f0739a20..ecc6c43af342 100644 --- a/examples/nextjs/package.json +++ b/examples/nextjs/package.json @@ -1,7 +1,7 @@ { "name": "examples-nextjs", "private": true, - "version": "0.17.0-rc.1", + "version": "0.17.0", "scripts": { "build": "next build", "dev": "next dev", @@ -9,7 +9,7 @@ "start": "next start" }, "dependencies": { - "@carbon/react": "^1.17.0-rc.1", + "@carbon/react": "^1.17.0", "next": "12.1.4", "react": "18.0.0", "react-dom": "18.0.0" diff --git a/examples/vite/package.json b/examples/vite/package.json index 55fd1ef5ef5f..7033bc8ee78f 100644 --- a/examples/vite/package.json +++ b/examples/vite/package.json @@ -1,14 +1,14 @@ { "name": "vite", "private": true, - "version": "0.15.0-rc.1", + "version": "0.15.0", "scripts": { "dev": "vite", "build": "vite build", "preview": "vite preview" }, "dependencies": { - "@carbon/react": "^1.17.0-rc.1", + "@carbon/react": "^1.17.0", "react": "^17.0.0", "react-dom": "^17.0.0" }, diff --git a/package.json b/package.json index 0a13e7bf479b..b0f5098e62a0 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ }, "resolutions": { "@types/react": "~17.0.2", - "@types/prop-types": "15.7.4", + "@types/prop-types": "15.7.5", "ast-types": "^0.14.0", "node-sass": "^6.0.0", "react": "~17.0.2", diff --git a/packages/carbon-components-react/package.json b/packages/carbon-components-react/package.json index d00113a6dcd6..d1f47094ccf4 100644 --- a/packages/carbon-components-react/package.json +++ b/packages/carbon-components-react/package.json @@ -1,7 +1,7 @@ { "name": "carbon-components-react", "description": "The Carbon Design System is IBM’s open-source design system for products and experiences.", - "version": "8.17.0-rc.1", + "version": "8.17.0", "license": "Apache-2.0", "main": "lib/index.js", "module": "es/index.js", @@ -39,8 +39,8 @@ "sass": "^1.33.0" }, "dependencies": { - "@carbon/react": "^1.17.0-rc.1", - "@carbon/styles": "^1.17.0-rc.1", + "@carbon/react": "^1.17.0", + "@carbon/styles": "^1.17.0", "@carbon/telemetry": "0.1.0" }, "devDependencies": { diff --git a/packages/carbon-components-react/scss/components/fluid-date-picker/_fluid-date-picker.scss b/packages/carbon-components-react/scss/components/fluid-date-picker/_fluid-date-picker.scss new file mode 100644 index 000000000000..48feea2e339c --- /dev/null +++ b/packages/carbon-components-react/scss/components/fluid-date-picker/_fluid-date-picker.scss @@ -0,0 +1,9 @@ +// Code generated by carbon-components-react. DO NOT EDIT. +// +// Copyright IBM Corp. 2018, 2018 +// +// This source code is licensed under the Apache-2.0 license found in the +// LICENSE file in the root directory of this source tree. +// + +@forward '@carbon/styles/scss/components/fluid-date-picker/fluid-date-picker'; diff --git a/packages/carbon-components-react/scss/components/fluid-date-picker/_index.scss b/packages/carbon-components-react/scss/components/fluid-date-picker/_index.scss new file mode 100644 index 000000000000..3f06534772d3 --- /dev/null +++ b/packages/carbon-components-react/scss/components/fluid-date-picker/_index.scss @@ -0,0 +1,9 @@ +// Code generated by carbon-components-react. DO NOT EDIT. +// +// Copyright IBM Corp. 2018, 2018 +// +// This source code is licensed under the Apache-2.0 license found in the +// LICENSE file in the root directory of this source tree. +// + +@forward '@carbon/styles/scss/components/fluid-date-picker'; diff --git a/packages/carbon-components/package.json b/packages/carbon-components/package.json index 72ff93c7330f..09b8098a39fd 100644 --- a/packages/carbon-components/package.json +++ b/packages/carbon-components/package.json @@ -1,7 +1,7 @@ { "name": "carbon-components", "description": "The Carbon Design System is IBM’s open-source design system for products and experiences.", - "version": "11.17.0-rc.1", + "version": "11.17.0", "license": "Apache-2.0", "repository": { "type": "git", @@ -40,7 +40,7 @@ "sass": "^1.33.0" }, "dependencies": { - "@carbon/styles": "^1.17.0-rc.1", + "@carbon/styles": "^1.17.0", "@carbon/telemetry": "0.1.0" }, "devDependencies": { diff --git a/packages/carbon-components/scss/components/fluid-date-picker/_fluid-date-picker.scss b/packages/carbon-components/scss/components/fluid-date-picker/_fluid-date-picker.scss new file mode 100644 index 000000000000..64deceede606 --- /dev/null +++ b/packages/carbon-components/scss/components/fluid-date-picker/_fluid-date-picker.scss @@ -0,0 +1,9 @@ +// Code generated by carbon-components. DO NOT EDIT. +// +// Copyright IBM Corp. 2018, 2018 +// +// This source code is licensed under the Apache-2.0 license found in the +// LICENSE file in the root directory of this source tree. +// + +@forward '@carbon/styles/scss/components/fluid-date-picker/fluid-date-picker'; diff --git a/packages/carbon-components/scss/components/fluid-date-picker/_index.scss b/packages/carbon-components/scss/components/fluid-date-picker/_index.scss new file mode 100644 index 000000000000..489faea12362 --- /dev/null +++ b/packages/carbon-components/scss/components/fluid-date-picker/_index.scss @@ -0,0 +1,9 @@ +// Code generated by carbon-components. DO NOT EDIT. +// +// Copyright IBM Corp. 2018, 2018 +// +// This source code is licensed under the Apache-2.0 license found in the +// LICENSE file in the root directory of this source tree. +// + +@forward '@carbon/styles/scss/components/fluid-date-picker'; diff --git a/packages/colors/package.json b/packages/colors/package.json index 6d3c0ede9f24..fc133d1209ec 100644 --- a/packages/colors/package.json +++ b/packages/colors/package.json @@ -1,7 +1,7 @@ { "name": "@carbon/colors", "description": "Colors for digital and software products using the Carbon Design System", - "version": "11.7.1-rc.0", + "version": "11.8.0", "license": "Apache-2.0", "main": "lib/index.js", "module": "es/index.js", diff --git a/packages/elements/package.json b/packages/elements/package.json index 0e72cb9e766f..0081444157de 100644 --- a/packages/elements/package.json +++ b/packages/elements/package.json @@ -1,7 +1,7 @@ { "name": "@carbon/elements", "description": "A collection of design elements in code for the IBM Design Language", - "version": "11.13.1-rc.0", + "version": "11.14.0", "license": "Apache-2.0", "main": "lib/index.js", "module": "es/index.js", @@ -35,12 +35,12 @@ "clean": "rimraf es lib umd" }, "dependencies": { - "@carbon/colors": "^11.7.1-rc.0", + "@carbon/colors": "^11.8.0", "@carbon/grid": "^11.7.0", - "@carbon/icons": "^11.10.0", + "@carbon/icons": "^11.11.0", "@carbon/layout": "^11.7.0", "@carbon/motion": "^11.5.0", - "@carbon/themes": "^11.11.1-rc.0", + "@carbon/themes": "^11.12.0", "@carbon/type": "^11.11.0" }, "devDependencies": { diff --git a/packages/icon-build-helpers/package.json b/packages/icon-build-helpers/package.json index 9af27fa42a29..696f7b539f1b 100644 --- a/packages/icon-build-helpers/package.json +++ b/packages/icon-build-helpers/package.json @@ -2,7 +2,7 @@ "name": "@carbon/icon-build-helpers", "private": true, "description": "Build helpers for the Carbon Design System icon library", - "version": "1.5.0", + "version": "1.6.0", "license": "Apache-2.0", "main": "src/index.js", "repository": { @@ -31,7 +31,7 @@ "@carbon/cli-reporter": "^10.5.0", "@carbon/icon-helpers": "^10.34.0", "@rollup/plugin-babel": "^5.3.0", - "@rollup/plugin-replace": "^4.0.0", + "@rollup/plugin-replace": "^5.0.0", "browserslist-config-carbon": "^11.0.0", "change-case": "^4.1.1", "core-js": "^3.16.0", diff --git a/packages/icons-react/package.json b/packages/icons-react/package.json index 590300755b1b..f8a90fbfe47e 100644 --- a/packages/icons-react/package.json +++ b/packages/icons-react/package.json @@ -1,7 +1,7 @@ { "name": "@carbon/icons-react", "description": "React components for icons in digital and software products using the Carbon Design System", - "version": "11.10.0", + "version": "11.11.0", "license": "Apache-2.0", "main": "lib/index.js", "module": "es/index.js", @@ -41,8 +41,8 @@ "prop-types": "^15.7.2" }, "devDependencies": { - "@carbon/icon-build-helpers": "^1.5.0", - "@carbon/icons": "^11.10.0", + "@carbon/icon-build-helpers": "^1.6.0", + "@carbon/icons": "^11.11.0", "rimraf": "^3.0.2" }, "sideEffects": false diff --git a/packages/icons-vue/package.json b/packages/icons-vue/package.json index 0046ca76b5cc..f79848e14f7f 100644 --- a/packages/icons-vue/package.json +++ b/packages/icons-vue/package.json @@ -1,7 +1,7 @@ { "name": "@carbon/icons-vue", "description": "Vue components for icons in digital and software products using the Carbon Design System", - "version": "10.59.0", + "version": "10.60.0", "license": "Apache-2.0", "main": "lib/index.js", "module": "es/index.js", @@ -32,7 +32,7 @@ }, "devDependencies": { "@carbon/cli-reporter": "^10.5.0", - "@carbon/icons": "^11.10.0", + "@carbon/icons": "^11.11.0", "fs-extra": "^10.0.0", "prettier": "^2.7.1", "rimraf": "^3.0.0", diff --git a/packages/icons/examples/preview/.yarn/install-state.gz b/packages/icons/examples/preview/.yarn/install-state.gz new file mode 100644 index 000000000000..0679070d1784 Binary files /dev/null and b/packages/icons/examples/preview/.yarn/install-state.gz differ diff --git a/packages/icons/examples/preview/yarn.lock b/packages/icons/examples/preview/yarn.lock index 59891eeb9fd8..72c4fc4a1cb6 100644 --- a/packages/icons/examples/preview/yarn.lock +++ b/packages/icons/examples/preview/yarn.lock @@ -4271,13 +4271,13 @@ fsevents@~2.3.2: linkType: hard "loader-utils@npm:^1.1.0": - version: 1.4.0 - resolution: "loader-utils@npm:1.4.0" + version: 1.4.1 + resolution: "loader-utils@npm:1.4.1" dependencies: big.js: ^5.2.2 emojis-list: ^3.0.0 json5: ^1.0.1 - checksum: d150b15e7a42ac47d935c8b484b79e44ff6ab4c75df7cc4cb9093350cf014ec0b17bdb60c5d6f91a37b8b218bd63b973e263c65944f58ca2573e402b9a27e717 + checksum: ea0b648cba0194e04a90aab6270619f0e35be009e33a443d9e642e93056cd49e6ca4c9678bd1c777a2392551bc5f4d0f24a87f5040608da1274aa84c6eebb502 languageName: node linkType: hard diff --git a/packages/icons/package.json b/packages/icons/package.json index 13285f169fce..8dd265ef3fca 100644 --- a/packages/icons/package.json +++ b/packages/icons/package.json @@ -1,7 +1,7 @@ { "name": "@carbon/icons", "description": "Icons for digital and software products using the Carbon Design System", - "version": "11.10.0", + "version": "11.11.0", "license": "Apache-2.0", "main": "lib/index.js", "module": "es/index.js", @@ -39,7 +39,7 @@ }, "devDependencies": { "@carbon/cli": "^11.5.0", - "@carbon/icon-build-helpers": "^1.5.0", + "@carbon/icon-build-helpers": "^1.6.0", "rimraf": "^3.0.2" } } diff --git a/packages/layout/examples/preview/.yarn/install-state.gz b/packages/layout/examples/preview/.yarn/install-state.gz new file mode 100644 index 000000000000..0db8c37d13db Binary files /dev/null and b/packages/layout/examples/preview/.yarn/install-state.gz differ diff --git a/packages/layout/examples/preview/yarn.lock b/packages/layout/examples/preview/yarn.lock index a818eb6d05a6..0b397109e59c 100644 --- a/packages/layout/examples/preview/yarn.lock +++ b/packages/layout/examples/preview/yarn.lock @@ -4137,13 +4137,13 @@ fsevents@~2.3.2: linkType: hard "loader-utils@npm:^1.1.0": - version: 1.4.0 - resolution: "loader-utils@npm:1.4.0" + version: 1.4.1 + resolution: "loader-utils@npm:1.4.1" dependencies: big.js: ^5.2.2 emojis-list: ^3.0.0 json5: ^1.0.1 - checksum: d150b15e7a42ac47d935c8b484b79e44ff6ab4c75df7cc4cb9093350cf014ec0b17bdb60c5d6f91a37b8b218bd63b973e263c65944f58ca2573e402b9a27e717 + checksum: ea0b648cba0194e04a90aab6270619f0e35be009e33a443d9e642e93056cd49e6ca4c9678bd1c777a2392551bc5f4d0f24a87f5040608da1274aa84c6eebb502 languageName: node linkType: hard diff --git a/packages/pictograms-react/package.json b/packages/pictograms-react/package.json index 2ecda21e5a23..6654253acd4d 100644 --- a/packages/pictograms-react/package.json +++ b/packages/pictograms-react/package.json @@ -1,7 +1,7 @@ { "name": "@carbon/pictograms-react", "description": "React components for pictograms in digital and software products using the Carbon Design System", - "version": "11.33.0", + "version": "11.34.0", "license": "Apache-2.0", "main": "lib/index.js", "module": "es/index.js", @@ -42,8 +42,8 @@ "prop-types": "^15.7.2" }, "devDependencies": { - "@carbon/icon-build-helpers": "^1.5.0", - "@carbon/pictograms": "^12.7.0" + "@carbon/icon-build-helpers": "^1.6.0", + "@carbon/pictograms": "^12.8.0" }, "sideEffects": false } diff --git a/packages/pictograms/examples/preview/.yarn/install-state.gz b/packages/pictograms/examples/preview/.yarn/install-state.gz new file mode 100644 index 000000000000..0679070d1784 Binary files /dev/null and b/packages/pictograms/examples/preview/.yarn/install-state.gz differ diff --git a/packages/pictograms/examples/preview/yarn.lock b/packages/pictograms/examples/preview/yarn.lock index 59891eeb9fd8..72c4fc4a1cb6 100644 --- a/packages/pictograms/examples/preview/yarn.lock +++ b/packages/pictograms/examples/preview/yarn.lock @@ -4271,13 +4271,13 @@ fsevents@~2.3.2: linkType: hard "loader-utils@npm:^1.1.0": - version: 1.4.0 - resolution: "loader-utils@npm:1.4.0" + version: 1.4.1 + resolution: "loader-utils@npm:1.4.1" dependencies: big.js: ^5.2.2 emojis-list: ^3.0.0 json5: ^1.0.1 - checksum: d150b15e7a42ac47d935c8b484b79e44ff6ab4c75df7cc4cb9093350cf014ec0b17bdb60c5d6f91a37b8b218bd63b973e263c65944f58ca2573e402b9a27e717 + checksum: ea0b648cba0194e04a90aab6270619f0e35be009e33a443d9e642e93056cd49e6ca4c9678bd1c777a2392551bc5f4d0f24a87f5040608da1274aa84c6eebb502 languageName: node linkType: hard diff --git a/packages/pictograms/package.json b/packages/pictograms/package.json index 324d4fc7ea26..79b959320d79 100644 --- a/packages/pictograms/package.json +++ b/packages/pictograms/package.json @@ -1,7 +1,7 @@ { "name": "@carbon/pictograms", "description": "Pictograms for digital and software products using the Carbon Design System", - "version": "12.7.0", + "version": "12.8.0", "license": "Apache-2.0", "main": "lib/index.js", "module": "es/index.js", @@ -31,7 +31,7 @@ "prepublishOnly": "yarn build" }, "devDependencies": { - "@carbon/icon-build-helpers": "^1.5.0", + "@carbon/icon-build-helpers": "^1.6.0", "rimraf": "^3.0.0" } } diff --git a/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap b/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap index ed941f208d35..95e718146d54 100644 --- a/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap +++ b/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap @@ -2367,6 +2367,12 @@ Map { "inline": Object { "type": "bool", }, + "invalid": Object { + "type": "bool", + }, + "invalidText": Object { + "type": "node", + }, "light": [Function], "locale": Object { "args": Array [ @@ -2501,6 +2507,12 @@ Map { ], "type": "oneOfType", }, + "warn": Object { + "type": "bool", + }, + "warnText": Object { + "type": "node", + }, }, "render": [Function], }, @@ -4917,6 +4929,9 @@ Map { "open": Object { "type": "bool", }, + "readOnly": Object { + "type": "bool", + }, "selectedItems": Object { "type": "array", }, @@ -6693,24 +6708,96 @@ Map { "render": [Function], }, "StructuredListBody" => Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], + "defaultProps": Object { + "onKeyDown": [Function], + }, + "propTypes": Object { + "children": Object { + "type": "node", + }, + "className": Object { + "type": "string", + }, + "head": Object { + "type": "bool", + }, + "onKeyDown": Object { + "type": "func", + }, + }, }, "StructuredListCell" => Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], + "defaultProps": Object { + "head": false, + "noWrap": false, + }, + "propTypes": Object { + "children": Object { + "type": "node", + }, + "className": Object { + "type": "string", + }, + "head": Object { + "type": "bool", + }, + "noWrap": Object { + "type": "bool", + }, + }, }, "StructuredListHead" => Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], + "propTypes": Object { + "children": Object { + "type": "node", + }, + "className": Object { + "type": "string", + }, + }, }, "StructuredListInput" => Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], + "defaultProps": Object { + "title": "title", + }, + "propTypes": Object { + "className": Object { + "type": "string", + }, + "defaultChecked": [Function], + "id": Object { + "type": "string", + }, + "name": Object { + "type": "string", + }, + "onChange": [Function], + "title": Object { + "type": "string", + }, + "value": [Function], + }, }, "StructuredListRow" => Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], + "defaultProps": Object { + "head": false, + "onKeyDown": [Function], + }, + "propTypes": Object { + "children": Object { + "type": "node", + }, + "className": Object { + "type": "string", + }, + "head": Object { + "type": "bool", + }, + "label": [Function], + "onKeyDown": Object { + "type": "func", + }, + }, }, "StructuredListSkeleton" => Object { "defaultProps": Object { @@ -6730,8 +6817,32 @@ Map { }, }, "StructuredListWrapper" => Object { - "$$typeof": Symbol(react.forward_ref), - "render": [Function], + "defaultProps": Object { + "ariaLabel": "Structured list section", + "isCondensed": false, + "isFlush": false, + "selection": false, + }, + "propTypes": Object { + "ariaLabel": Object { + "type": "string", + }, + "children": Object { + "type": "node", + }, + "className": Object { + "type": "string", + }, + "isCondensed": Object { + "type": "bool", + }, + "isFlush": Object { + "type": "bool", + }, + "selection": Object { + "type": "bool", + }, + }, }, "Switch" => Object { "$$typeof": Symbol(react.forward_ref), @@ -7636,7 +7747,6 @@ Map { "TextArea" => Object { "$$typeof": Symbol(react.forward_ref), "defaultProps": Object { - "cols": 50, "disabled": false, "enableCounter": false, "helperText": "", @@ -9403,6 +9513,51 @@ Map { }, }, }, + "unstable__FluidDatePicker" => Object { + "$$typeof": Symbol(react.forward_ref), + "propTypes": Object { + "children": Object { + "type": "node", + }, + "className": Object { + "type": "string", + }, + "invalid": Object { + "type": "bool", + }, + "invalidText": Object { + "type": "node", + }, + "warn": Object { + "type": "bool", + }, + "warnText": Object { + "type": "node", + }, + }, + "render": [Function], + }, + "unstable__FluidDatePickerInput" => Object { + "$$typeof": Symbol(react.forward_ref), + "render": [Function], + }, + "unstable__FluidDatePickerSkeleton" => Object { + "propTypes": Object { + "className": Object { + "type": "string", + }, + "datePickerType": Object { + "args": Array [ + Array [ + "simple", + "single", + "range", + ], + ], + "type": "oneOf", + }, + }, + }, "unstable__FluidDropdown" => Object { "$$typeof": Symbol(react.forward_ref), "propTypes": Object { diff --git a/packages/react/package.json b/packages/react/package.json index 977629c998c4..ff840cb209d2 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -1,7 +1,7 @@ { "name": "@carbon/react", "description": "React components for the Carbon Design System", - "version": "1.17.0-rc.1", + "version": "1.17.0", "license": "Apache-2.0", "main": "lib/index.js", "module": "es/index.js", @@ -44,9 +44,9 @@ "dependencies": { "@babel/runtime": "^7.18.3", "@carbon/feature-flags": "^0.9.0", - "@carbon/icons-react": "^11.10.0", + "@carbon/icons-react": "^11.11.0", "@carbon/layout": "^11.7.0", - "@carbon/styles": "^1.17.0-rc.1", + "@carbon/styles": "^1.17.0", "@carbon/telemetry": "0.1.0", "classnames": "2.3.2", "copy-to-clipboard": "^3.3.1", @@ -73,7 +73,7 @@ "@babel/preset-env": "^7.18.2", "@babel/preset-react": "^7.17.12", "@carbon/test-utils": "^10.26.0", - "@carbon/themes": "^11.11.1-rc.0", + "@carbon/themes": "^11.12.0", "@rollup/plugin-babel": "^5.3.0", "@rollup/plugin-commonjs": "^21.0.0", "@rollup/plugin-node-resolve": "^13.0.0", diff --git a/packages/react/scss/components/fluid-date-picker/_fluid-date-picker.scss b/packages/react/scss/components/fluid-date-picker/_fluid-date-picker.scss new file mode 100644 index 000000000000..a4a1b765aa35 --- /dev/null +++ b/packages/react/scss/components/fluid-date-picker/_fluid-date-picker.scss @@ -0,0 +1,9 @@ +// Code generated by @carbon/react. DO NOT EDIT. +// +// Copyright IBM Corp. 2018, 2018 +// +// This source code is licensed under the Apache-2.0 license found in the +// LICENSE file in the root directory of this source tree. +// + +@forward '@carbon/styles/scss/components/fluid-date-picker/fluid-date-picker'; diff --git a/packages/react/scss/components/fluid-date-picker/_index.scss b/packages/react/scss/components/fluid-date-picker/_index.scss new file mode 100644 index 000000000000..0659b6549a33 --- /dev/null +++ b/packages/react/scss/components/fluid-date-picker/_index.scss @@ -0,0 +1,9 @@ +// Code generated by @carbon/react. DO NOT EDIT. +// +// Copyright IBM Corp. 2018, 2018 +// +// This source code is licensed under the Apache-2.0 license found in the +// LICENSE file in the root directory of this source tree. +// + +@forward '@carbon/styles/scss/components/fluid-date-picker'; diff --git a/packages/react/src/__tests__/index-test.js b/packages/react/src/__tests__/index-test.js index 10ef4678fb5f..b9c972bbd041 100644 --- a/packages/react/src/__tests__/index-test.js +++ b/packages/react/src/__tests__/index-test.js @@ -231,6 +231,9 @@ describe('Carbon Components React', () => { "unstable_TextDirection", "unstable__FluidComboBox", "unstable__FluidComboBoxSkeleton", + "unstable__FluidDatePicker", + "unstable__FluidDatePickerInput", + "unstable__FluidDatePickerSkeleton", "unstable__FluidDropdown", "unstable__FluidDropdownSkeleton", "unstable__FluidMultiSelect", diff --git a/packages/react/src/components/ContentSwitcher/next/ContentSwitcher-story.js b/packages/react/src/components/ContentSwitcher/next/ContentSwitcher-story.js deleted file mode 100644 index c0cf8ff5ea84..000000000000 --- a/packages/react/src/components/ContentSwitcher/next/ContentSwitcher-story.js +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Copyright IBM Corp. 2016, 2018 - * - * This source code is licensed under the Apache-2.0 license found in the - * LICENSE file in the root directory of this source tree. - */ - -/* eslint-disable storybook/story-exports */ - -import React from 'react'; -import { - ContentSwitcher, - ContentTabs, - ContentTab, - ContentPanels, - ContentPanel, -} from './'; - -export default { - title: 'Experimental/unstable_ContentSwitcher', - component: ContentSwitcher, - subcomponents: { - ContentTabs, - ContentTab, - ContentPanels, - ContentPanel, - }, - includeStories: [], -}; - -export const Default = () => { - return ( - - - Tab 1 - Tab 2 - Tab 3 - - - Panel 1 - Panel 2 - Panel 3 - - - ); -}; diff --git a/packages/react/src/components/ContentSwitcher/next/index.js b/packages/react/src/components/ContentSwitcher/next/index.js deleted file mode 100644 index 4df9fe28484b..000000000000 --- a/packages/react/src/components/ContentSwitcher/next/index.js +++ /dev/null @@ -1,313 +0,0 @@ -/** - * Copyright IBM Corp. 2016, 2018 - * - * This source code is licensed under the Apache-2.0 license found in the - * LICENSE file in the root directory of this source tree. - */ - -import PropTypes from 'prop-types'; -import React from 'react'; -import cx from 'classnames'; -import { match, matches, keys } from '../../../internal/keyboard'; -import { useId } from '../../../internal/useId'; -import { useControllableState } from '../../../internal/useControllableState'; -import { usePrefix } from '../../../internal/usePrefix'; - -// Used to manage the overall state of the ContentSwitcher -const ContentSwitcherContext = React.createContext(); - -// Used to keep track of position in a tablist -const ContentTabContext = React.createContext(); - -// Used to keep track of position in a list of tab panels -const ContentPanelContext = React.createContext(); - -function ContentSwitcher({ - children, - defaultSelectedIndex = 0, - onChange, - selectedIndex: controlledSelectedIndex, -}) { - const baseId = useId('ccs'); - // The active index is used to track the element which has focus in our tablist - const [activeIndex, setActiveIndex] = React.useState(defaultSelectedIndex); - // The selected index is used for the tab/panel pairing which is "visible" - const [selectedIndex, setSelectedIndex] = useControllableState({ - value: controlledSelectedIndex, - defaultValue: defaultSelectedIndex, - onChange: (value) => { - if (onChange) { - onChange({ selectedIndex: value }); - } - }, - }); - const value = { - baseId, - activeIndex, - setActiveIndex, - selectedIndex, - setSelectedIndex, - }; - - return ( - - {children} - - ); -} - -ContentSwitcher.propTypes = { - /** - * Provide child elements to be rendered inside of the `ContentSwitcher`. - * These elements should render either `ContentTabs` or `ContentPanels` - */ - children: PropTypes.node, - - /** - * Specify which content tab should be initially selected when the component - * is first rendered - */ - defaultSelectedIndex: PropTypes.number, - - /** - * Provide an optional function which is called whenever the state of the - * `ContentSwitcher` changes - */ - onChange: PropTypes.func, - - /** - * Control which content panel is currently selected. This puts the component - * in a controlled mode and should be used along with `onChange` - */ - selectedIndex: PropTypes.number, -}; - -/** - * A `ContentPanel` corresponds to a tablist in the Tabs pattern as written in - * WAI-ARIA Authoring Practices. - * - * @see https://w3c.github.io/aria-practices/#tabpanel - */ -function ContentTabs({ - activation = 'automatic', - 'aria-label': label, - children, - className: customClassName, - size = 'md', - ...rest -}) { - const { activeIndex, selectedIndex, setSelectedIndex, setActiveIndex } = - React.useContext(ContentSwitcherContext); - const ref = React.useRef(null); - const prefix = usePrefix(); - const className = cx(customClassName, `${prefix}--content-switcher`, { - [`${prefix}--content-switcher--${size}`]: size, - }); - const count = React.Children.count(children); - const tabs = []; - - function onKeyDown(event) { - if ( - matches(event, [keys.ArrowRight, keys.ArrowLeft, keys.Home, keys.End]) - ) { - const nextIndex = getNextIndex( - event, - count, - activation === 'automatic' ? selectedIndex : activeIndex - ); - - if (activation === 'automatic') { - setSelectedIndex(nextIndex); - } else if (activation === 'manual') { - setActiveIndex(nextIndex); - } - - tabs[nextIndex].current.focus(); - } - } - - return ( - // eslint-disable-next-line jsx-a11y/interactive-supports-focus -
- {React.Children.map(children, (child, index) => { - const ref = React.createRef(); - tabs.push(ref); - return ( - - {React.cloneElement(child, { - ref, - })} - - ); - })} -
- ); -} - -ContentTabs.propTypes = { - /** - * Specify whether the content tab should be activated automatically or - * manually - */ - activation: PropTypes.oneOf(['automatic', 'manual']), - - /** - * Provide an accessible label to be read when a user interacts with this - * component - */ - 'aria-label': PropTypes.string.isRequired, - - /** - * Provide child elements to be rendered inside of `ContentTabs`. - * These elements should render a `ContentTab` - */ - children: PropTypes.node, - - /** - * Specify an optional className to be added to the container node - */ - className: PropTypes.string, - - /** - * Specify the size of the Content Switcher. Currently supports either `sm`, 'md' (default) or 'lg` as an option. - */ - size: PropTypes.oneOf(['sm', 'md', 'lg']), -}; - -/** - * Get the next index for a givne keyboard event given a count of the total - * items and the current index - * @param {Event} event - * @param {number} total - * @param {number} index - * @returns {number} - */ -function getNextIndex(event, total, index) { - if (match(event, keys.ArrowRight)) { - return (index + 1) % total; - } else if (match(event, keys.ArrowLeft)) { - return (total + index - 1) % total; - } else if (match(event, keys.Home)) { - return 0; - } else if (match(event, keys.End)) { - return total - 1; - } -} - -const ContentTab = React.forwardRef(function ContentTab( - { children, ...rest }, - ref -) { - const { selectedIndex, setSelectedIndex, baseId } = React.useContext( - ContentSwitcherContext - ); - const index = React.useContext(ContentTabContext); - const id = `${baseId}-tab-${index}`; - const panelId = `${baseId}-tabpanel-${index}`; - const prefix = usePrefix(); - const className = cx(`${prefix}--content-switcher-btn`, { - [`${prefix}--content-switcher--selected`]: selectedIndex === index, - }); - - return ( - - ); -}); - -ContentTab.propTypes = { - /** - * Provide child elements to be rendered inside of `ContentTab`. - * These elements must be noninteractive - */ - children: PropTypes.node, -}; - -/** - * Used to display all of the tab panels inside of a Content Switcher. This - * components keeps track of position in for each ContentPanel. - * - * Note: children should either be a `ContentPanel` or should render a - * `ContentPanel`. Fragments are not currently supported. - */ -function ContentPanels({ children }) { - return React.Children.map(children, (child, index) => { - return ( - - {child} - - ); - }); -} - -ContentPanels.propTypes = { - /** - * Provide child elements to be rendered inside of `ContentPanels`. - * These elements should render a `ContentPanel` - */ - children: PropTypes.node, -}; - -/** - * A `ContentPanel` corresponds to a tabpanel in the Tabs pattern as written in - * WAI-ARIA Authoring Practices. This component reads the selected - * index and base id from context in order to determine the correct `id` and - * display status of the component. - * - * @see https://w3c.github.io/aria-practices/#tabpanel - */ -const ContentPanel = React.forwardRef(function ContentPanel(props, ref) { - const { children, ...rest } = props; - const { selectedIndex, baseId } = React.useContext(ContentSwitcherContext); - const index = React.useContext(ContentPanelContext); - const id = `${baseId}-tabpanel-${index}`; - const tabId = `${baseId}-tab-${index}`; - - // TODO: tabindex should only be 0 if no interactive content in children - return ( - - ); -}); - -ContentPanel.propTypes = { - /** - * Provide child elements to be rendered inside of `ContentPanel`. - */ - children: PropTypes.node, -}; - -export { - ContentSwitcher, - ContentTabs, - ContentTab, - ContentPanels, - ContentPanel, -}; diff --git a/packages/react/src/components/DataTable/__tests__/__snapshots__/DataTable-test.js.snap b/packages/react/src/components/DataTable/__tests__/__snapshots__/DataTable-test.js.snap index 041dc78208b4..b1c00a31dcf8 100644 --- a/packages/react/src/components/DataTable/__tests__/__snapshots__/DataTable-test.js.snap +++ b/packages/react/src/components/DataTable/__tests__/__snapshots__/DataTable-test.js.snap @@ -2406,20 +2406,11 @@ exports[`DataTable should render 1`] = ` } } > - - - - - + + + + + + + + + + - - + + + + + + + + + + - - + + + + + + + + + `; diff --git a/packages/react/src/components/DataTable/stories/DataTable-toolbar.stories.js b/packages/react/src/components/DataTable/stories/DataTable-toolbar.stories.js index fbc007392f6c..fab8e53d3a34 100644 --- a/packages/react/src/components/DataTable/stories/DataTable-toolbar.stories.js +++ b/packages/react/src/components/DataTable/stories/DataTable-toolbar.stories.js @@ -271,10 +271,10 @@ export const WithOverflowMenu = () => ( {cell.value} ))} - - Action 1 - Action 2 - Action 3 + + + + @@ -334,9 +334,9 @@ export const Playground = (args) => ( ))} - Action 1 - Action 2 - Action 3 + + + diff --git a/packages/react/src/components/DataTableSkeleton/DataTableSkeleton-story.js b/packages/react/src/components/DataTableSkeleton/DataTableSkeleton-story.js deleted file mode 100644 index cf18dfe85cb1..000000000000 --- a/packages/react/src/components/DataTableSkeleton/DataTableSkeleton-story.js +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Copyright IBM Corp. 2016, 2018 - * - * This source code is licensed under the Apache-2.0 license found in the - * LICENSE file in the root directory of this source tree. - */ - -/* eslint-disable no-console */ - -import React from 'react'; -import { withKnobs, boolean } from '@storybook/addon-knobs'; -import DataTableSkeleton from '../DataTableSkeleton'; -import { headers } from '../DataTable/stories/shared'; - -const props = () => ({ - showHeaders: boolean('Show table headers', true), - zebra: boolean('Use zebra stripe (zebra)', false), - compact: boolean('Compact variant (compact)', false), - showHeader: boolean('Show the Table Header (showHeader)', true), - showToolbar: boolean('Show the Table Toolbar (showToolbar)', true), -}); - -export default { - title: 'Components/DataTable/Skeleton', - component: DataTableSkeleton, - decorators: [withKnobs], -}; - -export const Skeleton = () => { - const { showHeaders, ...rest } = props(); - return ( -
- -
-
- ); -}; diff --git a/packages/react/src/components/DataTableSkeleton/next/DataTableSkeleton.stories.js b/packages/react/src/components/DataTableSkeleton/DataTableSkeleton.stories.js similarity index 89% rename from packages/react/src/components/DataTableSkeleton/next/DataTableSkeleton.stories.js rename to packages/react/src/components/DataTableSkeleton/DataTableSkeleton.stories.js index 7af57be95419..de5ad05662a3 100644 --- a/packages/react/src/components/DataTableSkeleton/next/DataTableSkeleton.stories.js +++ b/packages/react/src/components/DataTableSkeleton/DataTableSkeleton.stories.js @@ -9,8 +9,8 @@ import React from 'react'; import { withKnobs, boolean } from '@storybook/addon-knobs'; -import DataTableSkeleton from '../DataTableSkeleton'; -import { headers } from '../../DataTable/stories/shared'; +import DataTableSkeleton from './DataTableSkeleton'; +import { headers } from '../DataTable/stories/shared'; const props = () => ({ showHeaders: boolean('Show table headers', true), diff --git a/packages/react/src/components/DatePicker/DatePicker.js b/packages/react/src/components/DatePicker/DatePicker.js index 88b03ea95eb9..0e5b758e3d6d 100644 --- a/packages/react/src/components/DatePicker/DatePicker.js +++ b/packages/react/src/components/DatePicker/DatePicker.js @@ -6,7 +6,7 @@ */ import PropTypes from 'prop-types'; -import React, { useEffect, useRef } from 'react'; +import React, { useContext, useEffect, useRef } from 'react'; import cx from 'classnames'; import flatpickr from 'flatpickr'; import l10n from 'flatpickr/dist/l10n/index'; @@ -18,6 +18,8 @@ import deprecate from '../../prop-types/deprecate'; import { match, keys } from '../../internal/keyboard'; import { usePrefix } from '../../internal/usePrefix'; import { useSavedCallback } from '../../internal/useSavedCallback'; +import { FormContext } from '../FluidForm'; +import { WarningFilled, WarningAltFilled } from '@carbon/icons-react'; // Weekdays shorthand for english locale l10n.en.weekdays.shorthand.forEach((_day, index) => { @@ -187,6 +189,10 @@ const DatePicker = React.forwardRef(function DatePicker( disable, enable, inline, + invalid, + invalidText, + warn, + warnText, light = false, locale = 'en', maxDate, @@ -201,6 +207,7 @@ const DatePicker = React.forwardRef(function DatePicker( ref ) { const prefix = usePrefix(); + const { isFluid } = useContext(FormContext); const startInputField = useRef(null); const endInputField = useRef(null); const calendarRef = useRef(null); @@ -343,6 +350,10 @@ const DatePicker = React.forwardRef(function DatePicker( calendarRef.current = calendar; function handleArrowDown(event) { + if (match(event, keys.Escape)) { + calendar.calendarContainer.classList.remove('open'); + } + if (match(event, keys.ArrowDown)) { const { calendarContainer, @@ -363,6 +374,10 @@ const DatePicker = React.forwardRef(function DatePicker( } function handleOnChange() { + if (datePickerType == 'single') { + calendar.calendarContainer.classList.remove('open'); + } + if (start.value !== '') { return; } @@ -439,7 +454,7 @@ const DatePicker = React.forwardRef(function DatePicker( useEffect(() => { if (calendarRef.current && disable) { - calendarRef.current.set('disbale', disable); + calendarRef.current.set('disable', disable); } }, [disable]); @@ -467,9 +482,37 @@ const DatePicker = React.forwardRef(function DatePicker( } }, [value, prefix]); + let fluidError; + if (isFluid) { + if (invalid) { + fluidError = ( + <> + +
+
{invalidText}
+ + ); + } + + if (warn && !invalid) { + fluidError = ( + <> + +
+
{warnText}
+ + ); + } + } + return (
{childrenWithProps}
+ {fluidError}
); }); @@ -530,6 +573,16 @@ DatePicker.propTypes = { */ inline: PropTypes.bool, + /** + * Specify whether or not the control is invalid (Fluid only) + */ + invalid: PropTypes.bool, + + /** + * Provide the text that is displayed when the control is in error state (Fluid Only) + */ + invalidText: PropTypes.node, + /** * `true` to use the light version. */ @@ -654,6 +707,16 @@ DatePicker.propTypes = { PropTypes.object, PropTypes.number, ]), + + /** + * Specify whether the control is currently in warning state (Fluid only) + */ + warn: PropTypes.bool, + + /** + * Provide the text that is displayed when the control is in warning state (Fluid only) + */ + warnText: PropTypes.node, }; export default DatePicker; diff --git a/packages/react/src/components/DatePickerInput/DatePickerInput.js b/packages/react/src/components/DatePickerInput/DatePickerInput.js index dad8c5c2ce2d..5f5aad11972b 100644 --- a/packages/react/src/components/DatePickerInput/DatePickerInput.js +++ b/packages/react/src/components/DatePickerInput/DatePickerInput.js @@ -8,8 +8,9 @@ import { Calendar, WarningFilled, WarningAltFilled } from '@carbon/icons-react'; import cx from 'classnames'; import PropTypes from 'prop-types'; -import React from 'react'; +import React, { useContext } from 'react'; import { usePrefix } from '../../internal/usePrefix'; +import { FormContext } from '../FluidForm'; const DatePickerInput = React.forwardRef(function DatePickerInput(props, ref) { const { @@ -32,6 +33,7 @@ const DatePickerInput = React.forwardRef(function DatePickerInput(props, ref) { ...rest } = props; const prefix = usePrefix(); + const { isFluid } = useContext(FormContext); const datePickerInputProps = { id, onChange: (event) => { @@ -62,9 +64,12 @@ const DatePickerInput = React.forwardRef(function DatePickerInput(props, ref) { const inputClasses = cx(`${prefix}--date-picker__input`, { [`${prefix}--date-picker__input--${size}`]: size, [`${prefix}--date-picker__input--invalid`]: invalid, + [`${prefix}--date-picker__input--warn`]: warn, }); const containerClasses = cx(`${prefix}--date-picker-container`, { [`${prefix}--date-picker--nolabel`]: !labelText, + [`${prefix}--date-picker--fluid--invalid`]: isFluid && invalid, + [`${prefix}--date-picker--fluid--warn`]: isFluid && warn, }); const input = invalid ? ( @@ -95,6 +100,7 @@ const DatePickerInput = React.forwardRef(function DatePickerInput(props, ref) { )}
{input} + {isFluid && }
{invalid && ( -
{invalidText}
+ <> + {isFluid &&
} +
{invalidText}
+ + )} + {warn && ( + <> + {isFluid &&
} +
{warnText}
+ )} - {warn &&
{warnText}
} {helperText &&
{helperText}
} ); @@ -211,9 +225,12 @@ DatePickerInput.propTypes = { function DatePickerIcon({ datePickerType, invalid, warn }) { const prefix = usePrefix(); + const { isFluid } = useContext(FormContext); if (datePickerType === 'simple' && !invalid && !warn) { - return null; + if (!isFluid) { + return null; + } } if (invalid) { diff --git a/packages/react/src/components/FluidDatePicker/FluidDatePicker.Skeleton.js b/packages/react/src/components/FluidDatePicker/FluidDatePicker.Skeleton.js new file mode 100644 index 000000000000..6b3ace7c6629 --- /dev/null +++ b/packages/react/src/components/FluidDatePicker/FluidDatePicker.Skeleton.js @@ -0,0 +1,71 @@ +/** + * Copyright IBM Corp. 2016, 2018 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +import PropTypes from 'prop-types'; +import React from 'react'; +import classnames from 'classnames'; +import { usePrefix } from '../../internal/usePrefix'; +import { FormContext } from '../FluidForm/FormContext'; +import { Calendar } from '@carbon/icons-react'; + +function FluidDatePickerSkeleton({ + className, + datePickerType = 'single', + ...other +}) { + const prefix = usePrefix(); + + const classNames = classnames( + className, + `${prefix}--form-item ${prefix}--date-picker--fluid__skeleton`, + { + [`${prefix}--date-picker--fluid__skeleton--range`]: + datePickerType === 'range', + } + ); + + return ( + +
+
+ +
+ {datePickerType !== 'simple' && ( + + )} +
+ {datePickerType === 'range' && ( +
+ +
+ +
+ )} +
+ + ); +} + +FluidDatePickerSkeleton.propTypes = { + /** + * Specify an optional className to be applied to the outer FluidForm wrapper + */ + className: PropTypes.string, + + /** + * Specify which variant of the DatePicker the skeleton should mimic + */ + datePickerType: PropTypes.oneOf(['simple', 'single', 'range']), +}; + +export default FluidDatePickerSkeleton; diff --git a/packages/react/src/components/FluidDatePicker/FluidDatePicker.js b/packages/react/src/components/FluidDatePicker/FluidDatePicker.js new file mode 100644 index 000000000000..42d5794e3f88 --- /dev/null +++ b/packages/react/src/components/FluidDatePicker/FluidDatePicker.js @@ -0,0 +1,74 @@ +/** + * Copyright IBM Corp. 2022 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +import PropTypes from 'prop-types'; +import React from 'react'; +import classnames from 'classnames'; +import DatePicker from '../DatePicker'; +import { usePrefix } from '../../internal/usePrefix'; +import { FormContext } from '../FluidForm/FormContext'; + +const FluidDatePicker = React.forwardRef(function FluidDatePicker( + { className, children, invalid, invalidText, warn, warnText, ...other }, + ref +) { + const prefix = usePrefix(); + const classNames = classnames(className, { + [`${prefix}--date-picker--fluid`]: true, + [`${prefix}--date-picker--fluid--invalid`]: invalid, + [`${prefix}--date-picker--fluid--warn`]: warn, + }); + + return ( + + + {children} + + + ); +}); + +FluidDatePicker.propTypes = { + /** + * The child node(s) + */ + children: PropTypes.node, + + /** + * Specify an optional className to be applied to the outer FluidForm wrapper + */ + className: PropTypes.string, + + /** + * Specify whether or not the control is invalid + */ + invalid: PropTypes.bool, + + /** + * Provide the text that is displayed when the control is in error state + */ + invalidText: PropTypes.node, + + /** + * Specify whether the control is currently in warning state + */ + warn: PropTypes.bool, + + /** + * Provide the text that is displayed when the control is in warning state + */ + warnText: PropTypes.node, +}; + +export default FluidDatePicker; diff --git a/packages/react/src/components/FluidDatePicker/FluidDatePicker.stories.js b/packages/react/src/components/FluidDatePicker/FluidDatePicker.stories.js new file mode 100644 index 000000000000..0022126ab5d0 --- /dev/null +++ b/packages/react/src/components/FluidDatePicker/FluidDatePicker.stories.js @@ -0,0 +1,252 @@ +/** + * Copyright IBM Corp. 2022 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +import React from 'react'; +import FluidDatePicker from '../FluidDatePicker'; +import FluidDatePickerInput from '../FluidDatePickerInput'; +import FluidDatePickerSkeleton from './FluidDatePicker.Skeleton'; +import { + ToggletipLabel, + Toggletip, + ToggletipButton, + ToggletipContent, +} from '../Toggletip'; +import { Information } from '@carbon/icons-react'; + +export default { + title: 'Experimental/unstable__FluidDatePicker', + component: FluidDatePicker, +}; + +const ToggleTip = ( + <> + Label + + + + + +

Additional field information here.

+
+
+ +); + +export const Simple = () => ( +
+ + + +
+); + +export const Single = () => ( +
+ + + +
+); + +export const RangeWithCalendar = () => { + return ( +
+ + + + +
+ ); +}; + +export const Skeleton = () => ( +
+ +
+
+ +
+
+ +
+); + +export const Playground = (args) => { + const { invalid, invalidText, warn, warnText, disabled } = args; + return ( +
+ + + + +
+
+ + + +
+ ); +}; + +Playground.argTypes = { + appendTo: { + table: { + disable: true, + }, + }, + children: { + table: { + disable: true, + }, + }, + className: { + table: { + disable: true, + }, + }, + disable: { + table: { + disable: true, + }, + }, + enable: { + table: { + disable: true, + }, + }, + inline: { + table: { + disable: true, + }, + }, + light: { + table: { + disable: true, + }, + }, + locale: { + table: { + disable: true, + }, + }, + onChange: { + action: 'clicked', + table: { + disable: true, + }, + }, + onClose: { + action: 'clicked', + table: { + disable: true, + }, + }, + onOpen: { + action: 'clicked', + table: { + disable: true, + }, + }, + disabled: { + control: { type: 'boolean' }, + table: { + category: 'DatePickerInput', + }, + }, + invalid: { + control: { type: 'boolean' }, + table: { + category: 'DatePickerInput', + }, + }, + invalidText: { + control: { type: 'text' }, + table: { + category: 'DatePickerInput', + }, + defaultValue: + 'Error message that is really long can wrap to more lines but should not be excessively long.', + }, + placeholder: { + control: { type: 'text' }, + table: { + category: 'DatePickerInput', + }, + }, + warn: { + control: { type: 'boolean' }, + table: { + category: 'DatePickerInput', + }, + }, + warnText: { + control: { type: 'text' }, + table: { + category: 'DatePickerInput', + }, + defaultValue: + 'Warning message that is really long can wrap to more lines but should not be excessively long.', + }, +}; diff --git a/packages/react/src/components/FluidDatePicker/__tests__/FluidDatePicker-test.js b/packages/react/src/components/FluidDatePicker/__tests__/FluidDatePicker-test.js new file mode 100644 index 000000000000..8e3d514b0cff --- /dev/null +++ b/packages/react/src/components/FluidDatePicker/__tests__/FluidDatePicker-test.js @@ -0,0 +1,65 @@ +/** + * Copyright IBM Corp. 2022 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +import React from 'react'; +import FluidDatePicker from '../FluidDatePicker'; +import FluidDatePickerInput from '../../FluidDatePickerInput'; +import { render, screen } from '@testing-library/react'; + +const prefix = 'cds'; + +describe('FluidDatePicker', () => { + describe('renders as expected - Component API', () => { + it('should add extra classes that are passed via className', () => { + render( + {}} + className="custom-class" + dateFormat="m/d/Y" + data-testid="datePicker-1"> + + + + ); + + expect(screen.getByTestId('datePicker-1')).toHaveClass('custom-class'); + }); + + it('should add fluid classes by default', () => { + render( + {}} + className="custom-class" + dateFormat="m/d/Y" + data-testid="datePicker-1"> + + + + ); + + expect(screen.getByTestId('datePicker-1')).toHaveClass( + `${prefix}--date-picker--fluid` + ); + }); + }); +}); diff --git a/packages/react/src/components/FluidDatePicker/index.js b/packages/react/src/components/FluidDatePicker/index.js new file mode 100644 index 000000000000..4b3107e9f0d0 --- /dev/null +++ b/packages/react/src/components/FluidDatePicker/index.js @@ -0,0 +1,11 @@ +/** + * Copyright IBM Corp. 2022 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +export default from './FluidDatePicker'; +export FluidDatePicker from './FluidDatePicker'; + +export { default as FluidDatePickerSkeleton } from './FluidDatePicker.Skeleton'; diff --git a/packages/react/src/components/FluidDatePickerInput/FluidDatePickerInput.js b/packages/react/src/components/FluidDatePickerInput/FluidDatePickerInput.js new file mode 100644 index 000000000000..35dabebc1189 --- /dev/null +++ b/packages/react/src/components/FluidDatePickerInput/FluidDatePickerInput.js @@ -0,0 +1,23 @@ +/** + * Copyright IBM Corp. 2022 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +import React from 'react'; +import DatePickerInput from '../DatePickerInput'; +import { FormContext } from '../FluidForm/FormContext'; + +const FluidDatePickerInput = React.forwardRef(function FluidDatePickerInput( + { ...other }, + ref +) { + return ( + + + + ); +}); + +export default FluidDatePickerInput; diff --git a/packages/react/src/components/FluidDatePickerInput/index.js b/packages/react/src/components/FluidDatePickerInput/index.js new file mode 100644 index 000000000000..5384e51e32d0 --- /dev/null +++ b/packages/react/src/components/FluidDatePickerInput/index.js @@ -0,0 +1,9 @@ +/** + * Copyright IBM Corp. 2022 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +export default from './FluidDatePickerInput'; +export FluidDatePickerInput from './FluidDatePickerInput'; diff --git a/packages/react/src/components/FluidForm/FluidForm.stories.js b/packages/react/src/components/FluidForm/FluidForm.stories.js index 849632a11420..e882d9f49335 100644 --- a/packages/react/src/components/FluidForm/FluidForm.stories.js +++ b/packages/react/src/components/FluidForm/FluidForm.stories.js @@ -8,6 +8,11 @@ import React from 'react'; import FluidForm from '.'; +import FluidDatePicker from '../FluidDatePicker'; +import FluidDatePickerInput from '../FluidDatePickerInput'; +import FluidSelect from '../FluidSelect'; +import SelectItem from '../SelectItem'; +import SelectItemGroup from '../SelectItemGroup'; import FluidTextInput from '../FluidTextInput'; import FluidTextArea from '../FluidTextArea'; import ModalWrapper from '../ModalWrapper'; @@ -45,6 +50,39 @@ export default { export const Default = () => ( <> +
+ + + + + + +
( +
+ + + +
+); + const PlaygroundStory = (props) => { const { align, defaultOpen, disabled, kind, label, size } = props; return ( diff --git a/packages/react/src/components/Icons/Icons.stories.js b/packages/react/src/components/Icons/Icons.stories.js index 4c0b8b8d3b60..ebfb2fb8945b 100644 --- a/packages/react/src/components/Icons/Icons.stories.js +++ b/packages/react/src/components/Icons/Icons.stories.js @@ -34,3 +34,15 @@ export const Default = () => { ); }; + +export const Playground = (args) => { + return ; +}; + +Playground.argTypes = { + size: { + options: ['16', '20', '32'], + control: { type: 'select' }, + defaultValue: 16, + }, +}; diff --git a/packages/react/src/components/Icons/Icons.stories.scss b/packages/react/src/components/Icons/Icons.stories.scss index 18617f4cb8b8..482e2644abcc 100644 --- a/packages/react/src/components/Icons/Icons.stories.scss +++ b/packages/react/src/components/Icons/Icons.stories.scss @@ -6,7 +6,19 @@ // .demo-icon-example { display: flex; - width: 10rem; + width: 15rem; justify-content: space-between; margin: 2rem; } + +.demo-icon-example:nth-child(1) svg { + min-width: 1rem; +} + +.demo-icon-example:nth-child(2) svg { + min-width: 1.25rem; +} + +.demo-icon-example:nth-child(3) svg { + min-width: 2rem; +} diff --git a/packages/react/src/components/ListBox/ListBoxSelection.js b/packages/react/src/components/ListBox/ListBoxSelection.js index d05822d80055..da6f19a3e12f 100644 --- a/packages/react/src/components/ListBox/ListBoxSelection.js +++ b/packages/react/src/components/ListBox/ListBoxSelection.js @@ -23,6 +23,7 @@ function ListBoxSelection({ translateWithId: t, disabled, onClearSelection, + readOnly, }) { const prefix = usePrefix(); const className = cx(`${prefix}--list-box__selection`, { @@ -31,7 +32,7 @@ function ListBoxSelection({ }); const handleOnClick = (event) => { event.stopPropagation(); - if (disabled) { + if (disabled || readOnly) { return; } clearSelection(event); @@ -41,7 +42,7 @@ function ListBoxSelection({ }; const handleOnKeyDown = (event) => { event.stopPropagation(); - if (disabled) { + if (disabled || readOnly) { return; } @@ -75,7 +76,8 @@ function ListBoxSelection({ onKeyDown={handleOnKeyDown} disabled={disabled} aria-label={t('clear.all')} - title={description}> + title={description} + aria-disabled={readOnly ? true : undefined}>
@@ -134,6 +136,11 @@ ListBoxSelection.propTypes = { */ onKeyDown: PropTypes.func, + /** + * Whether or not the Dropdown is readonly + */ + readOnly: PropTypes.bool, + /** * Specify an optional `selectionCount` value that will be used to determine * whether the selection should display a badge or a single clear icon. diff --git a/packages/react/src/components/MultiSelect/MultiSelect.js b/packages/react/src/components/MultiSelect/MultiSelect.js index ae686e941029..b0d1aa5d2d9e 100644 --- a/packages/react/src/components/MultiSelect/MultiSelect.js +++ b/packages/react/src/components/MultiSelect/MultiSelect.js @@ -70,6 +70,7 @@ const MultiSelect = React.forwardRef(function MultiSelect( onMenuChange, direction, selectedItems: selected, + readOnly, }, ref ) { @@ -169,6 +170,7 @@ const MultiSelect = React.forwardRef(function MultiSelect( [`${prefix}--multi-select--selected`]: selectedItems && selectedItems.length > 0, [`${prefix}--list-box--up`]: direction === 'top', + [`${prefix}--multi-select--readonly`]: readOnly, } ); @@ -234,6 +236,24 @@ const MultiSelect = React.forwardRef(function MultiSelect( : setIsFocused(evt.type === 'focus' ? true : false); }; + const readOnlyEventHandlers = readOnly + ? { + onClick: (evt) => { + // NOTE: does not prevent click + evt.preventDefault(); + // focus on the element as per readonly input behavior + evt.target.focus(); + }, + onKeyDown: (evt) => { + const selectAccessKeys = ['ArrowDown', 'ArrowUp', ' ', 'Enter']; + // This prevents the select from opening for the above keys + if (selectAccessKeys.includes(evt.key)) { + evt.preventDefault(); + } + }, + } + : {}; + return (