diff --git a/.github/workflows/broken-links-check.yml b/.github/workflows/broken-links-check.yml index 1bced87a9..f43277e2c 100644 --- a/.github/workflows/broken-links-check.yml +++ b/.github/workflows/broken-links-check.yml @@ -6,7 +6,7 @@ on: jobs: broken_link_check: - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 name: Check react-ui.io for broken links steps: - name: Check for broken links diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b375c1090..02a7aa0e7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,7 +5,7 @@ on: [ pull_request ] jobs: build: name: Build distribution CSS and JS - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 strategy: matrix: node: [ 20, 22 ] diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index f41c6e6a0..b72003019 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -23,7 +23,7 @@ on: jobs: analyze: name: Analyze - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 permissions: # required for all workflows diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 4ad5b324e..d2216abb8 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -8,7 +8,7 @@ permissions: jobs: build: name: Build Docs - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 steps: - name: Clone repository uses: actions/checkout@v4 diff --git a/.github/workflows/external-links-check.yml b/.github/workflows/external-links-check.yml index 92344590e..c7378df9a 100644 --- a/.github/workflows/external-links-check.yml +++ b/.github/workflows/external-links-check.yml @@ -6,7 +6,7 @@ on: jobs: broken_link_check: name: Markdown link check - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - uses: gaurav-nelson/github-action-markdown-link-check@v1 diff --git a/.github/workflows/git.yml b/.github/workflows/git.yml index d1d25a465..855d0a7ea 100644 --- a/.github/workflows/git.yml +++ b/.github/workflows/git.yml @@ -5,7 +5,7 @@ on: [ pull_request ] jobs: block-merge-with-autosquash-commits: name: Block merge with autosquash commits - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 steps: - name: Block merge with autosquash commits diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 672a5af7e..06db22543 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -5,7 +5,7 @@ on: [ pull_request ] jobs: lint: name: Lint - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 steps: - name: Clone repository uses: actions/checkout@v4 diff --git a/.github/workflows/pull-request-meta.yml b/.github/workflows/pull-request-meta.yml index 98edccca6..98175f98f 100644 --- a/.github/workflows/pull-request-meta.yml +++ b/.github/workflows/pull-request-meta.yml @@ -7,7 +7,7 @@ on: jobs: process_pr_meta: name: Process PR meta - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 steps: - name: Assign to author uses: kentaro-m/auto-assign-action@v2.0.0 # Specify also the minor version because v2 does not exist diff --git a/.github/workflows/release-management.yml b/.github/workflows/release-management.yml index 83e304819..d1895b1e6 100644 --- a/.github/workflows/release-management.yml +++ b/.github/workflows/release-management.yml @@ -7,7 +7,7 @@ on: jobs: test_and_build: name: Test and build - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 outputs: version: ${{ steps.check_package_version.outputs.version }} version_changed: ${{ steps.check_package_version.outputs.changed }} @@ -51,7 +51,7 @@ jobs: contents: write needs: [test_and_build] if: needs.test_and_build.outputs.version_changed == 'false' - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 steps: - name: Draft release on GitHub uses: release-drafter/release-drafter@v6 @@ -62,7 +62,7 @@ jobs: name: Publish release draft needs: [test_and_build] if: needs.test_and_build.outputs.version_changed == 'true' - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 steps: - name: Clone repository uses: actions/checkout@v4 @@ -86,7 +86,7 @@ jobs: name: Publish to npm needs: [test_and_build, publish_release_draft_on_version_bump] if: needs.test_and_build.outputs.version_changed == 'true' - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 steps: - name: Clone repository uses: actions/checkout@v4 @@ -112,7 +112,7 @@ jobs: contents: write needs: [test_and_build, publish_release_draft_on_version_bump] if: needs.test_and_build.outputs.version_changed == 'true' - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 steps: - name: Clone repository uses: actions/checkout@v4 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 082adc4c6..5a94a3745 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -8,7 +8,7 @@ on: jobs: test: name: Test - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 steps: - name: Clone repository uses: actions/checkout@v4 diff --git a/README.md b/README.md index fc5c24999..59555147b 100644 --- a/README.md +++ b/README.md @@ -53,16 +53,7 @@ To install React UI in your app: npm install --save @react-ui-org/react-ui ``` -2. Load the Titillium Web font: - - ```html - - ``` - -3. Load React UI CSS in your app: +2. Load React UI CSS in your app: @@ -73,7 +64,7 @@ To install React UI in your app: -4. Import and use any of React UI components in your app: +3. Import and use any of React UI components in your app: ```jsx import { Button } from '@react-ui-org/react-ui'; diff --git a/RELEASING.md b/RELEASING.md index baf2eb577..3d4bb3496 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -12,9 +12,9 @@ In order for the automation to work properly, contributors must follow the 1. Pull requests are automatically labelled by branch name. Labels are then used for: - 1. resolving next [semantic version number][semver] - (BREAKING.FEATURE.PATCH), - 2. grouping changes in changelog. + 1. resolving next [semantic version number][semver] + (BREAKING.FEATURE.PATCH), + 2. grouping changes in changelog. 2. Release draft with changelog is generated as pull requests are merged into the `master` branch. Invididual PR names are listed and grouped by type based @@ -30,35 +30,36 @@ See the source of `.github/workflows` for details. [GitHub releases page][gh-releases] to see what the changelog looks like and what will be the next version number. - **Don't edit manually until you are ready to publish the release.** Release - draft is automatically overwritten everytime a change is merged to `master`. + **Don't edit manually until you are ready to publish the release.** Release + draft is automatically overwritten everytime a change is merged to `master`. 2. **Manual:** once you are ready to publish a release: - 1. **Bump the version number** in `package.json` and `package-lock.json`. - Make sure it matches the intended version number in the release draft. - **Don't combine this step with any other changes,** they wouldn't be - reflected in the changelog. + 1. **Bump the version number** in `package.json` and `package-lock.json`. + Make sure it matches the intended version number in the release draft. + **Don't combine this step with any other changes,** they wouldn't be + reflected in the changelog. - 2. Now is also your **chance to review and adjust (if necessary) the intended - version and actual changelog before the release is published.** - Automatic release drafting is skipped when a version change in - `package.json` is detected so this time your changes will not be - overwritten. Save your changes in release draft with the _Save draft_ - button, **do not publish** yet! + 2. Now is also your **chance to review and adjust (if necessary) the + intended + version and actual changelog before the release is published.** + Automatic release drafting is skipped when a version change in + `package.json` is detected so this time your changes will not be + overwritten. Save your changes in release draft with the _Save draft_ + button, **do not publish** yet! - 3. Get back to the repository, commit both files as - `Bump version to ` in `release/` branch, - create a pull request, hold your breath, and—merge it. + 3. Get back to the repository, commit both files as + `Bump version to ` in `release/` branch, + create a pull request, hold your breath, and—merge it. 3. **Automatic:** once the release pull request from step 2.3 is merged, the following actions are triggered automatically: - 1. GitHub release draft with name corresponding to the version number from - step 2 is published. - 2. Git tag with the version number from step 2 is added to `master` branch. - 3. Package is built and published to npm package registry. - 4. Documentation is built and deployed to production. + 1. GitHub release draft with name corresponding to the version number from + step 2 is published. + 2. Git tag with the version number from step 2 is added to `master` branch. + 3. Package is built and published to npm package registry. + 4. Documentation is built and deployed to production. **Note:** prefix version number with `v` everywhere except in `package.json` and `package-lock.json`. diff --git a/docker/node/Dockerfile b/docker/node/Dockerfile index 0cc062167..ff1346e36 100644 --- a/docker/node/Dockerfile +++ b/docker/node/Dockerfile @@ -1,3 +1,3 @@ -FROM node:20 +FROM node:22 RUN mkdir /workspace WORKDIR /workspace diff --git a/jest.config.js b/jest.config.js index c07a0aba6..548c153ec 100644 --- a/jest.config.js +++ b/jest.config.js @@ -13,7 +13,7 @@ module.exports = { setupFilesAfterEnv: [ '/tests/setupTestingLibrary.js', ], - testEnvironment: 'jsdom', + testEnvironment: '@happy-dom/jest-environment', transformIgnorePatterns: [ 'node_modules/(?!(@react-ui-org))', ], diff --git a/mkdocs.yml b/mkdocs.yml index e07315fd2..6c87a7896 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -29,8 +29,6 @@ theme: language: 'en' favicon: 'favicon.ico' custom_dir: 'src/docs/_overrides' - font: - text: 'Titillium Web' palette: - media: "(prefers-color-scheme: light)" scheme: default @@ -131,10 +129,11 @@ nav: - Spacing: 'docs/css-helpers/spacing.md' - Typography: 'docs/css-helpers/typography.md' - JS Helpers: - - Classnames: 'docs/js-helpers/classnames.md' - - Transferring Props: 'docs/js-helpers/transferProps.md' + - ClassNames: 'helpers/classNames/README.md' + - TransferProps: 'helpers/transferProps/README.md' - Guides: - Customize: + - Font: 'docs/customize/font.md' - Theming: - Overview: 'docs/customize/theming/overview.md' - Forms: 'docs/customize/theming/forms.md' diff --git a/package-lock.json b/package-lock.json index b3d2903e8..d9e78e4fa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@react-ui-org/react-ui", - "version": "0.58.0", + "version": "0.59.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@react-ui-org/react-ui", - "version": "0.58.0", + "version": "0.59.0", "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -21,10 +21,11 @@ "@babel/preset-env": "^7.24.7", "@babel/preset-react": "^7.24.7", "@babel/register": "^7.24.6", + "@happy-dom/jest-environment": "^16.6.0", "@stylistic/stylelint-config": "^1.0.1", "@svgr/webpack": "^8.1.0", - "@testing-library/jest-dom": "^6.4.6", - "@testing-library/react": "^16.0.0", + "@testing-library/jest-dom": "^6.6.3", + "@testing-library/react": "^16.1.0", "@testing-library/user-event": "^14.5.2", "@visionappscz/eslint-config-visionapps": "^1.7.0", "@visionappscz/stylelint-config": "^4.0.0", @@ -42,7 +43,6 @@ "eslint-plugin-react-hooks": "^4.6.2", "identity-obj-proxy": "^3.0.0", "jest": "^29.7.0", - "jest-environment-jsdom": "^29.7.0", "markdownlint-cli2": "^0.13.0", "mini-css-extract-plugin": "^2.9.0", "postcss": "^8.4.39", @@ -2231,6 +2231,24 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@happy-dom/jest-environment": { + "version": "16.6.0", + "resolved": "https://registry.npmjs.org/@happy-dom/jest-environment/-/jest-environment-16.6.0.tgz", + "integrity": "sha512-uf47TEf1eL2oiDf9aBPtb4OjR7hoCyHoGLr00W56KlrkV+KwskIcmf5b7dzlNtI9MBSbW33DK/BYQKYdGlF0Iw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.4.0", + "@jest/fake-timers": "^29.4.0", + "@jest/types": "^29.4.0", + "happy-dom": "^16.6.0", + "jest-mock": "^29.4.0", + "jest-util": "^29.4.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.14", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", @@ -3578,13 +3596,13 @@ } }, "node_modules/@testing-library/jest-dom": { - "version": "6.4.8", - "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.4.8.tgz", - "integrity": "sha512-JD0G+Zc38f5MBHA4NgxQMR5XtO5Jx9g86jqturNTt2WUfRmLDIY7iKkWHDCCTiDuFMre6nxAD5wHw9W5kI4rGw==", + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.6.3.tgz", + "integrity": "sha512-IteBhl4XqYNkM54f4ejhLRJiZNqcSCoXUOG2CPK7qbD322KjQozM4kHQOfkG2oln9b9HTYqs+Sae8vBATubxxA==", "dev": true, + "license": "MIT", "dependencies": { "@adobe/css-tools": "^4.4.0", - "@babel/runtime": "^7.9.2", "aria-query": "^5.0.0", "chalk": "^3.0.0", "css.escape": "^1.5.1", @@ -3672,10 +3690,11 @@ } }, "node_modules/@testing-library/react": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.0.0.tgz", - "integrity": "sha512-guuxUKRWQ+FgNX0h0NS0FIq3Q3uLtWVpBzcLOggmfMoUpgBnzBzvLLd4fbm6yS8ydJd94cIfY4yP9qUQjM2KwQ==", + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.1.0.tgz", + "integrity": "sha512-Q2ToPvg0KsVL0ohND9A3zLJWcOXXcO8IDu3fj11KhNt0UlCWyFyvnCIBkd12tidB2lkiVRG8VFqdhcqhqnAQtg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/runtime": "^7.12.5" }, @@ -3684,10 +3703,10 @@ }, "peerDependencies": { "@testing-library/dom": "^10.0.0", - "@types/react": "^18.0.0", - "@types/react-dom": "^18.0.0", - "react": "^18.0.0", - "react-dom": "^18.0.0" + "@types/react": "^18.0.0 || ^19.0.0", + "@types/react-dom": "^18.0.0 || ^19.0.0", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" }, "peerDependenciesMeta": { "@types/react": { @@ -3703,6 +3722,7 @@ "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.5.2.tgz", "integrity": "sha512-YAh82Wh4TIrxYLmfGcixwD18oIjyC1pFQC2Y01F2lzV2HTMiYrI0nze0FD0ocB//CKS/7jIUgae+adPqxK5yCQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=12", "npm": ">=6" @@ -3711,15 +3731,6 @@ "@testing-library/dom": ">=7.21.4" } }, - "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, "node_modules/@trysound/sax": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", @@ -3836,17 +3847,6 @@ "@types/istanbul-lib-report": "*" } }, - "node_modules/@types/jsdom": { - "version": "20.0.1", - "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.1.tgz", - "integrity": "sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==", - "dev": true, - "dependencies": { - "@types/node": "*", - "@types/tough-cookie": "*", - "parse5": "^7.0.0" - } - }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -3883,12 +3883,6 @@ "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", "dev": true }, - "node_modules/@types/tough-cookie": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", - "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", - "dev": true - }, "node_modules/@types/unist": { "version": "2.0.10", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", @@ -4150,13 +4144,6 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, - "node_modules/abab": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", - "deprecated": "Use your platform's native atob() and btoa() methods instead", - "dev": true - }, "node_modules/acorn": { "version": "8.12.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", @@ -4169,16 +4156,6 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-globals": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz", - "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", - "dev": true, - "dependencies": { - "acorn": "^8.1.0", - "acorn-walk": "^8.0.2" - } - }, "node_modules/acorn-import-attributes": { "version": "1.9.5", "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", @@ -4197,30 +4174,6 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/acorn-walk": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", - "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", - "dev": true, - "dependencies": { - "acorn": "^8.11.0" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -4526,12 +4479,6 @@ "node": ">=8" } }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true - }, "node_modules/autoprefixer": { "version": "10.4.19", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.19.tgz", @@ -4607,6 +4554,7 @@ "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", "dev": true, + "license": "MIT", "dependencies": { "@jest/transform": "^29.7.0", "@types/babel__core": "^7.1.14", @@ -5272,18 +5220,6 @@ "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", "dev": true }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/commander": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", @@ -5644,30 +5580,6 @@ "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", "dev": true }, - "node_modules/cssom": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", - "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", - "dev": true - }, - "node_modules/cssstyle": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", - "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", - "dev": true, - "dependencies": { - "cssom": "~0.3.6" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cssstyle/node_modules/cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true - }, "node_modules/d3": { "version": "3.5.17", "resolved": "https://registry.npmjs.org/d3/-/d3-3.5.17.tgz", @@ -5680,20 +5592,6 @@ "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", "dev": true }, - "node_modules/data-urls": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", - "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", - "dev": true, - "dependencies": { - "abab": "^2.0.6", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^11.0.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/data-view-buffer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", @@ -5762,12 +5660,6 @@ } } }, - "node_modules/decimal.js": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", - "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", - "dev": true - }, "node_modules/dedent": { "version": "1.5.3", "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", @@ -5863,15 +5755,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", @@ -5956,19 +5839,6 @@ } ] }, - "node_modules/domexception": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", - "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", - "deprecated": "Use your platform's native DOMException instead", - "dev": true, - "dependencies": { - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/domhandler": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", @@ -6289,27 +6159,6 @@ "node": ">=0.8.0" } }, - "node_modules/escodegen": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", - "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", - "dev": true, - "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=6.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" - } - }, "node_modules/eslint": { "version": "8.57.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", @@ -7186,20 +7035,6 @@ "is-callable": "^1.1.3" } }, - "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/fraction.js": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", @@ -7526,6 +7361,20 @@ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, + "node_modules/happy-dom": { + "version": "16.6.0", + "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-16.6.0.tgz", + "integrity": "sha512-Zz5S9sog8a3p8XYZbO+eI1QMOAvCNnIoyrH8A8MLX+X2mJrzADTy+kdETmc4q+uD9AGAvQYGn96qBAn2RAciKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "webidl-conversions": "^7.0.0", + "whatwg-mimetype": "^3.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/harmony-reflect": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/harmony-reflect/-/harmony-reflect-1.6.2.tgz", @@ -7613,18 +7462,6 @@ "node": ">= 0.4" } }, - "node_modules/html-encoding-sniffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", - "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", - "dev": true, - "dependencies": { - "whatwg-encoding": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", @@ -7643,33 +7480,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, - "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -7679,18 +7489,6 @@ "node": ">=10.17.0" } }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/icss-utils": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", @@ -8179,12 +7977,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true - }, "node_modules/is-regex": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", @@ -8478,6 +8270,7 @@ "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/core": "^29.7.0", "@jest/types": "^29.6.3", @@ -9161,33 +8954,6 @@ "node": ">=8" } }, - "node_modules/jest-environment-jsdom": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.7.0.tgz", - "integrity": "sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA==", - "dev": true, - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/jsdom": "^20.0.0", - "@types/node": "*", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0", - "jsdom": "^20.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "canvas": "^2.5.0" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } - } - }, "node_modules/jest-environment-node": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", @@ -10415,51 +10181,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/jsdom": { - "version": "20.0.3", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz", - "integrity": "sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==", - "dev": true, - "dependencies": { - "abab": "^2.0.6", - "acorn": "^8.8.1", - "acorn-globals": "^7.0.0", - "cssom": "^0.5.0", - "cssstyle": "^2.3.0", - "data-urls": "^3.0.2", - "decimal.js": "^10.4.2", - "domexception": "^4.0.0", - "escodegen": "^2.0.0", - "form-data": "^4.0.0", - "html-encoding-sniffer": "^3.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.1", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.2", - "parse5": "^7.1.1", - "saxes": "^6.0.0", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.1.2", - "w3c-xmlserializer": "^4.0.0", - "webidl-conversions": "^7.0.0", - "whatwg-encoding": "^2.0.0", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^11.0.0", - "ws": "^8.11.0", - "xml-name-validator": "^4.0.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "canvas": "^2.5.0" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } - } - }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -11153,12 +10874,6 @@ "url": "https://github.com/fb55/nth-check?sponsor=1" } }, - "node_modules/nwsapi": { - "version": "2.2.12", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.12.tgz", - "integrity": "sha512-qXDmcVlZV4XRtKFzddidpfVP4oMSGhga+xdMc25mv8kaLUHtgzCDhUxkrN8exkGdTlLNaXj7CV3GtON7zuGZ+w==", - "dev": true - }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -11426,18 +11141,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "dev": true, - "dependencies": { - "entities": "^4.4.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -11931,12 +11634,6 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "dev": true }, - "node_modules/psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", - "dev": true - }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -11971,12 +11668,6 @@ } ] }, - "node_modules/querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true - }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -12203,12 +11894,6 @@ "node": ">=0.10.0" } }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true - }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -12360,12 +12045,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, "node_modules/sass": { "version": "1.77.8", "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.8.tgz", @@ -12423,18 +12102,6 @@ } } }, - "node_modules/saxes": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", - "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", - "dev": true, - "dependencies": { - "xmlchars": "^2.2.0" - }, - "engines": { - "node": ">=v12.22.7" - } - }, "node_modules/scheduler": { "version": "0.23.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", @@ -13443,12 +13110,6 @@ "node": ">= 10" } }, - "node_modules/symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true - }, "node_modules/table": { "version": "6.8.2", "resolved": "https://registry.npmjs.org/table/-/table-6.8.2.tgz", @@ -13657,33 +13318,6 @@ "node": ">=8.0" } }, - "node_modules/tough-cookie": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", - "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", - "dev": true, - "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/tr46": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", - "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", - "dev": true, - "dependencies": { - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/tsconfig-paths": { "version": "3.15.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", @@ -13921,15 +13555,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/universalify": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, "node_modules/update-browserslist-db": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", @@ -13969,16 +13594,6 @@ "punycode": "^2.1.0" } }, - "node_modules/url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dev": true, - "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -13999,18 +13614,6 @@ "node": ">=10.12.0" } }, - "node_modules/w3c-xmlserializer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", - "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==", - "dev": true, - "dependencies": { - "xml-name-validator": "^4.0.0" - }, - "engines": { - "node": ">=14" - } - }, "node_modules/walker": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", @@ -14237,18 +13840,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/whatwg-encoding": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", - "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", - "dev": true, - "dependencies": { - "iconv-lite": "0.6.3" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/whatwg-mimetype": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", @@ -14258,19 +13849,6 @@ "node": ">=12" } }, - "node_modules/whatwg-url": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", - "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", - "dev": true, - "dependencies": { - "tr46": "^3.0.0", - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -14449,42 +14027,6 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xml-name-validator": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", - "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/xmlchars": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true - }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", diff --git a/package.json b/package.json index bae0e39ac..d1c1faccf 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@react-ui-org/react-ui", "description": "React UI is a themeable UI library for React apps.", - "version": "0.58.0", + "version": "0.59.0", "keywords": [ "react", "ui", @@ -56,7 +56,7 @@ "precopy": "rm -rf dist && mkdir dist", "prepublishOnly": "npm run build", "start": "webpack --watch --mode=development", - "stylelint": "stylelint \"src/**/*.scss\" --config stylelint.config.js", + "stylelint": "stylelint \"src/**/*.{css,scss}\" \"!src/docs/_assets/generated/**\" --config stylelint.config.js", "test": "npm run jest" }, "dependencies": { @@ -76,10 +76,11 @@ "@babel/preset-env": "^7.24.7", "@babel/preset-react": "^7.24.7", "@babel/register": "^7.24.6", + "@happy-dom/jest-environment": "^16.6.0", "@stylistic/stylelint-config": "^1.0.1", "@svgr/webpack": "^8.1.0", - "@testing-library/jest-dom": "^6.4.6", - "@testing-library/react": "^16.0.0", + "@testing-library/jest-dom": "^6.6.3", + "@testing-library/react": "^16.1.0", "@testing-library/user-event": "^14.5.2", "@visionappscz/eslint-config-visionapps": "^1.7.0", "@visionappscz/stylelint-config": "^4.0.0", @@ -97,7 +98,6 @@ "eslint-plugin-react-hooks": "^4.6.2", "identity-obj-proxy": "^3.0.0", "jest": "^29.7.0", - "jest-environment-jsdom": "^29.7.0", "markdownlint-cli2": "^0.13.0", "mini-css-extract-plugin": "^2.9.0", "postcss": "^8.4.39", diff --git a/src/components/Alert/Alert.jsx b/src/components/Alert/Alert.jsx index fd74236dd..fa25e4853 100644 --- a/src/components/Alert/Alert.jsx +++ b/src/components/Alert/Alert.jsx @@ -2,8 +2,8 @@ import PropTypes from 'prop-types'; import React, { useContext } from 'react'; import { withGlobalProps } from '../../providers/globalProps'; import { TranslationsContext } from '../../providers/translations'; -import { classNames } from '../../utils/classNames'; -import { transferProps } from '../../utils/transferProps'; +import { classNames } from '../../helpers/classNames/classNames'; +import { transferProps } from '../../helpers/transferProps'; import { getRootColorClassName } from '../_helpers/getRootColorClassName'; import styles from './Alert.module.scss'; @@ -69,9 +69,9 @@ Alert.propTypes = { children: PropTypes.node.isRequired, /** * Color variant to clarify importance and meaning of the alert. Implements - * [Feedback and Neutral color collections](/docs/foundation/collections#colors). + * [Feedback color collection](/docs/foundation/collections#colors). */ - color: PropTypes.oneOf(['success', 'warning', 'danger', 'help', 'info', 'note', 'light', 'dark']), + color: PropTypes.oneOf(['success', 'warning', 'danger', 'help', 'info', 'note']), /** * Optional element to be displayed next to the alert body. */ diff --git a/src/components/Alert/README.md b/src/components/Alert/README.md index 7b5e2dfa9..d431f3fd5 100644 --- a/src/components/Alert/README.md +++ b/src/components/Alert/README.md @@ -111,32 +111,6 @@ Neutral informative alert. ``` -### Light - -Light alert variant. - -```docoff-react-preview - - - Light alert: Stands out on dark backgrounds. - {' '} - - - -``` - -### Dark - -Dark alert variant. - -```docoff-react-preview - - Dark alert: Stands out on light backgrounds. - {' '} - - -``` - ## Alerts with Icons An icon can (and should) accompany the message. diff --git a/src/components/Alert/__tests__/Alert.test.jsx b/src/components/Alert/__tests__/Alert.test.jsx index 591cca145..1f58f671e 100644 --- a/src/components/Alert/__tests__/Alert.test.jsx +++ b/src/components/Alert/__tests__/Alert.test.jsx @@ -6,7 +6,6 @@ import { } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { feedbackColorPropTest } from '../../../../tests/propTests/feedbackColorPropTest'; -import { neutralColorPropTest } from '../../../../tests/propTests/neutralColorPropTest'; import defaultTranslations from '../../../translations/en'; import { Alert } from '../Alert'; @@ -22,7 +21,6 @@ describe('rendering', () => { (rootElement) => expect(within(rootElement).getByText('content text')), ], ...feedbackColorPropTest, - ...neutralColorPropTest, [ { icon: (
icon
) }, (rootElement) => expect(within(rootElement).getByText('icon')), diff --git a/src/components/Alert/_settings.scss b/src/components/Alert/_settings.scss index b7ab4487e..e9b852fd6 100644 --- a/src/components/Alert/_settings.scss +++ b/src/components/Alert/_settings.scss @@ -1,4 +1,3 @@ -@use "sass:list"; @use "sass:map"; @use "../../styles/settings/collections"; @use "../../styles/theme/typography"; @@ -8,5 +7,5 @@ $font-size: map.get(typography.$font-size-values, 1); $line-height: typography.$line-height-base; $min-height: calc(#{$font-size} * #{$line-height} + 2 * #{theme.$padding}); -$colors: list.join(collections.$feedback-colors, collections.$neutral-colors); +$colors: collections.$feedback-colors; $themeable-properties: color, foreground-color, background-color; diff --git a/src/components/Badge/Badge.jsx b/src/components/Badge/Badge.jsx index aa887a5ad..67ccda582 100644 --- a/src/components/Badge/Badge.jsx +++ b/src/components/Badge/Badge.jsx @@ -1,8 +1,8 @@ import PropTypes from 'prop-types'; import React from 'react'; import { withGlobalProps } from '../../providers/globalProps'; -import { classNames } from '../../utils/classNames'; -import { transferProps } from '../../utils/transferProps'; +import { classNames } from '../../helpers/classNames/classNames'; +import { transferProps } from '../../helpers/transferProps'; import { getRootColorClassName } from '../_helpers/getRootColorClassName'; import { getRootPriorityClassName } from '../_helpers/getRootPriorityClassName'; import styles from './Badge.module.scss'; diff --git a/src/components/Button/Button.jsx b/src/components/Button/Button.jsx index 320563181..9b4499f6b 100644 --- a/src/components/Button/Button.jsx +++ b/src/components/Button/Button.jsx @@ -1,8 +1,8 @@ import PropTypes from 'prop-types'; import React, { useContext } from 'react'; import { withGlobalProps } from '../../providers/globalProps'; -import { classNames } from '../../utils/classNames'; -import { transferProps } from '../../utils/transferProps'; +import { classNames } from '../../helpers/classNames/classNames'; +import { transferProps } from '../../helpers/transferProps'; import { getRootColorClassName } from '../_helpers/getRootColorClassName'; import { getRootPriorityClassName } from '../_helpers/getRootPriorityClassName'; import { getRootSizeClassName } from '../_helpers/getRootSizeClassName'; diff --git a/src/components/ButtonGroup/ButtonGroup.jsx b/src/components/ButtonGroup/ButtonGroup.jsx index 450a42ddd..3752f6315 100644 --- a/src/components/ButtonGroup/ButtonGroup.jsx +++ b/src/components/ButtonGroup/ButtonGroup.jsx @@ -3,8 +3,8 @@ import React, { useMemo, } from 'react'; import { withGlobalProps } from '../../providers/globalProps'; -import { classNames } from '../../utils/classNames'; -import { transferProps } from '../../utils/transferProps'; +import { classNames } from '../../helpers/classNames/classNames'; +import { transferProps } from '../../helpers/transferProps'; import { getRootPriorityClassName } from '../_helpers/getRootPriorityClassName'; import { isChildrenEmpty } from '../_helpers/isChildrenEmpty'; import styles from './ButtonGroup.module.scss'; diff --git a/src/components/Card/Card.jsx b/src/components/Card/Card.jsx index 69045a962..69acb7366 100644 --- a/src/components/Card/Card.jsx +++ b/src/components/Card/Card.jsx @@ -1,8 +1,8 @@ import PropTypes from 'prop-types'; import React from 'react'; import { withGlobalProps } from '../../providers/globalProps'; -import { classNames } from '../../utils/classNames'; -import { transferProps } from '../../utils/transferProps'; +import { classNames } from '../../helpers/classNames/classNames'; +import { transferProps } from '../../helpers/transferProps'; import { getRootColorClassName } from '../_helpers/getRootColorClassName'; import styles from './Card.module.scss'; @@ -18,7 +18,7 @@ export const Card = ({ {...transferProps(restProps)} className={classNames( styles.root, - getRootColorClassName(color, styles), + color && getRootColorClassName(color, styles), dense && styles.isRootDense, raised && styles.isRootRaised, disabled && styles.isRootDisabled, @@ -29,7 +29,7 @@ export const Card = ({ ); Card.defaultProps = { - color: 'light', + color: undefined, dense: false, disabled: false, raised: false, @@ -45,9 +45,9 @@ Card.propTypes = { children: PropTypes.node.isRequired, /** * Color to clarify importance and meaning of the card. Implements - * [Feedback and Neutral color collections](/docs/foundation/collections#colors). + * [Feedback color collection](/docs/foundation/collections#colors). */ - color: PropTypes.oneOf(['success', 'warning', 'danger', 'help', 'info', 'note', 'light', 'dark']), + color: PropTypes.oneOf(['success', 'warning', 'danger', 'help', 'info', 'note']), /** * Make the card more compact. */ diff --git a/src/components/Card/Card.module.scss b/src/components/Card/Card.module.scss index 92032d794..cdfcf559f 100644 --- a/src/components/Card/Card.module.scss +++ b/src/components/Card/Card.module.scss @@ -12,9 +12,9 @@ flex-direction: column; min-width: 0; // 1. color: var(--rui-local-color); - border: theme.$border-width solid var(--rui-local-border-color); + border: theme.$border-width solid var(--rui-local-border-color, transparent); border-radius: theme.$border-radius; - background-color: var(--rui-local-background-color); + background-color: var(--rui-local-background-color, theme.$background-color); } .body { diff --git a/src/components/Card/CardBody.jsx b/src/components/Card/CardBody.jsx index 9037f1eca..e14eb8501 100644 --- a/src/components/Card/CardBody.jsx +++ b/src/components/Card/CardBody.jsx @@ -1,7 +1,7 @@ import PropTypes from 'prop-types'; import React from 'react'; import { withGlobalProps } from '../../providers/globalProps'; -import { transferProps } from '../../utils/transferProps'; +import { transferProps } from '../../helpers/transferProps'; import styles from './Card.module.scss'; export const CardBody = ({ diff --git a/src/components/Card/CardFooter.jsx b/src/components/Card/CardFooter.jsx index 953c8141c..3d08ad38d 100644 --- a/src/components/Card/CardFooter.jsx +++ b/src/components/Card/CardFooter.jsx @@ -1,6 +1,6 @@ import PropTypes from 'prop-types'; import React from 'react'; -import { transferProps } from '../../utils/transferProps'; +import { transferProps } from '../../helpers/transferProps'; import { withGlobalProps } from '../../providers/globalProps'; import { isChildrenEmpty } from '../_helpers/isChildrenEmpty'; import styles from './Card.module.scss'; diff --git a/src/components/Card/README.md b/src/components/Card/README.md index 42b2d3a1a..b59653a09 100644 --- a/src/components/Card/README.md +++ b/src/components/Card/README.md @@ -148,7 +148,7 @@ for card content. ## Color Variants To cover all possible needs of your project, Card is available in colors from -[Feedback and Neutral color collections](/docs/foundation/collections#colors). +[Feedback color collection](/docs/foundation/collections#colors). ```docoff-react-preview @@ -211,26 +211,6 @@ To cover all possible needs of your project, Card is available in colors from {helpText && (
{helpText}
@@ -72,13 +183,13 @@ export const FileInputField = React.forwardRef((props, ref) => { {validationText && (
{validationText}
)} - + ); }); @@ -86,10 +197,11 @@ FileInputField.defaultProps = { disabled: false, fullWidth: false, helpText: null, - id: undefined, isLabelVisible: true, layout: 'vertical', + multiple: false, required: false, + size: 'medium', validationState: null, validationText: null, }; @@ -116,7 +228,7 @@ FileInputField.propTypes = { * * `__helpText` * * `__validationText` */ - id: PropTypes.string, + id: PropTypes.string.isRequired, /** * If `false`, the label will be visually hidden (but remains accessible by assistive * technologies). @@ -134,10 +246,24 @@ FileInputField.propTypes = { * */ layout: PropTypes.oneOf(['horizontal', 'vertical']), + /** + * If `true`, the input will accept multiple files. + */ + multiple: PropTypes.bool, + /** + * Callback fired when the value of the input changes. + */ + onFilesChanged: PropTypes.func.isRequired, /** * If `true`, the input will be required. */ required: PropTypes.bool, + /** + * Size of the field. + * + * Ignored if the component is rendered within `InputGroup` component as the value is inherited in such case. + */ + size: PropTypes.oneOf(['small', 'medium', 'large']), /** * Alter the field to provide feedback based on validation result. */ diff --git a/src/components/FileInputField/FileInputField.module.scss b/src/components/FileInputField/FileInputField.module.scss index fe1da7768..e71e75a9d 100644 --- a/src/components/FileInputField/FileInputField.module.scss +++ b/src/components/FileInputField/FileInputField.module.scss @@ -1,8 +1,16 @@ +// 1. The drop zone is constructed as a button to support keyboard operation. +// 2. Prevent pointer events on all children of the root element to not to trigger drag events on children. + @use "../../styles/tools/form-fields/box-field-elements"; @use "../../styles/tools/form-fields/box-field-layout"; +@use "../../styles/tools/form-fields/box-field-sizes"; @use "../../styles/tools/form-fields/foundation"; @use "../../styles/tools/form-fields/variants"; @use "../../styles/tools/accessibility"; +@use "../../styles/tools/links"; +@use "../../styles/tools/transition"; +@use "../../styles/tools/reset"; +@use "settings"; @layer components.file-input-field { // Foundation @@ -18,6 +26,54 @@ @include box-field-elements.input-container(); } + .input { + @include accessibility.hide-text(); + } + + .dropZone { + --rui-local-color: #{settings.$drop-zone-color}; + --rui-local-border-color: #{settings.$drop-zone-border-color}; + --rui-local-background: #{settings.$drop-zone-background-color}; + + @include reset.button(); // 1. + @include box-field-elements.base(); + + display: flex; + align-items: center; + justify-content: start; + font-weight: settings.$drop-zone-font-weight; + font-size: var(--rui-local-font-size); + line-height: settings.$drop-zone-line-height; + font-family: settings.$drop-zone-font-family; + border-style: dashed; + } + + .isRootDragging .dropZone { + --rui-local-border-color: #{settings.$drop-zone-dragging-border-color}; + } + + .isRootDisabled .dropZone { + cursor: settings.$drop-zone-disabled-cursor; + } + + .root:not(.isRootDisabled, .isRootDragging) .dropZone:hover { + --rui-local-border-color: #{settings.$drop-zone-hover-border-color}; + } + + .root:not(.isRootDisabled, .isRootDragging) .dropZone:active { + --rui-local-border-color: #{settings.$drop-zone-active-border-color}; + } + + .dropZoneLink { + @include links.base(); + + &::before { + content: ""; + position: absolute; + inset: 0; + } + } + .helpText, .validationText { @include foundation.help-text(); @@ -28,6 +84,18 @@ } // States + .isRootDisabled { + --rui-local-color: #{settings.$drop-zone-disabled-color}; + --rui-local-border-color: #{settings.$drop-zone-disabled-border-color}; + --rui-local-background: #{settings.$drop-zone-disabled-background-color}; + + @include variants.disabled-state(); + } + + .isRootDisabled .dropZoneLink { + cursor: inherit; + } + .isRootStateInvalid { @include variants.validation(invalid); } @@ -56,10 +124,28 @@ } .isRootFullWidth { - @include box-field-layout.full-width(); + @include box-field-layout.full-width($input-element-selector: ".dropZone"); } .isRootInFormLayout { @include box-field-layout.in-form-layout(); } + + // Sizes + .isRootSizeSmall { + @include box-field-sizes.size(small); + } + + .isRootSizeMedium { + @include box-field-sizes.size(medium); + } + + .isRootSizeLarge { + @include box-field-sizes.size(large); + } + + // Groups + .isRootGrouped { + @include box-field-elements.in-group-layout($input-element-selector: ".dropZone"); + } } diff --git a/src/components/FileInputField/README.md b/src/components/FileInputField/README.md index 87bc22574..8f80aef26 100644 --- a/src/components/FileInputField/README.md +++ b/src/components/FileInputField/README.md @@ -13,7 +13,7 @@ import { FileInputField } from '@react-ui-org/react-ui'; And use it: ```docoff-react-preview - + {}} /> ``` See [API](#api) for all available options. @@ -48,12 +48,37 @@ layout perspective, FileInputFields work just like any other form fields. ## Sizes +Aside from the default (medium) size, two additional sizes are available: small +and large. + +```docoff-react-preview + {}} + size="small" +/> + {}} +/> + {}} + size="large" +/> +``` + Full-width fields span the full width of a parent: ```docoff-react-preview {}} /> ``` @@ -68,8 +93,10 @@ dangerous to hide labels from users in most cases. Keep in mind you should ```docoff-react-preview {}} /> ``` @@ -81,14 +108,18 @@ supports this kind of layout as well. ```docoff-react-preview {}} /> {}} /> ``` @@ -100,18 +131,24 @@ filled. ```docoff-react-preview {}} /> {}} /> {}} /> ``` @@ -126,17 +163,23 @@ have. ```docoff-react-preview {}} validationState="valid" validationText="Looks good!" /> {}} validationState="invalid" validationText="Your file is too big. Please select something smaller." /> {}} validationState="warning" validationText={` You selected more than 10 files. @@ -152,7 +195,44 @@ It's possible to disable the whole input. ```docoff-react-preview {}} +/> +``` + +## Handling Files + +Files selected by the user are handled by providing a custom function to the +`onFilesChanged` prop. The `onFilesChanged` function is then called on the +`change` event of the `input` element and on the `drop` event of the root +`div` element. + +```docoff-react-preview + { + // Do something with the files… + console.log('Files selected:', files); + }} +/> +``` + +### Multiple Files + +By default, users can select only one file. To allow selecting multiple files, +set the `multiple` prop to `true`. + +```docoff-react-preview + { + // Do something with the files… + console.log('Files selected:', files); + }} /> ``` @@ -172,8 +252,9 @@ to improve its accessibility. Choose up to 10 files. Allowed extensions are .pdf, .jpg, .jpeg, or .png. Size limit is 10 MB. `} + id="my-file" label="Attachment" - multiple + onFilesChanged={() => {}} /> ``` diff --git a/src/components/FileInputField/__tests__/FileInputField.test.jsx b/src/components/FileInputField/__tests__/FileInputField.test.jsx index 66f579520..77881c584 100644 --- a/src/components/FileInputField/__tests__/FileInputField.test.jsx +++ b/src/components/FileInputField/__tests__/FileInputField.test.jsx @@ -13,13 +13,16 @@ import { formLayoutProviderTest } from '../../../../tests/providerTests/formLayo import { isLabelVisibleTest } from '../../../../tests/propTests/isLabelVisibleTest'; import { labelPropTest } from '../../../../tests/propTests/labelPropTest'; import { layoutPropTest } from '../../../../tests/propTests/layoutPropTest'; +import { sizePropTest } from '../../../../tests/propTests/sizePropTest'; import { requiredPropTest } from '../../../../tests/propTests/requiredPropTest'; import { validationStatePropTest } from '../../../../tests/propTests/validationStatePropTest'; import { validationTextPropTest } from '../../../../tests/propTests/validationTextPropTest'; import { FileInputField } from '../FileInputField'; const mandatoryProps = { + id: 'id', label: 'label', + onFilesChanged: () => {}, }; describe('rendering', () => { @@ -33,7 +36,6 @@ describe('rendering', () => { [ { helpText: 'help text', - id: 'id', validationText: 'validation text', }, (rootElement) => { @@ -41,13 +43,14 @@ describe('rendering', () => { expect(within(rootElement).getByText('label')).toHaveAttribute('id', 'id__labelText'); expect(within(rootElement).getByText('help text')).toHaveAttribute('id', 'id__helpText'); expect(within(rootElement).getByText('validation text')).toHaveAttribute('id', 'id__validationText'); - expect(rootElement).toHaveAttribute('id', 'id__label'); + expect(rootElement).toHaveAttribute('id', 'id__root'); }, ], ...isLabelVisibleTest(), ...labelPropTest(), ...layoutPropTest, ...requiredPropTest, + ...sizePropTest, ...validationStatePropTest, ...validationTextPropTest, ])('renders with props: "%s"', (testedProps, assert) => { @@ -68,12 +71,13 @@ describe('functionality', () => { render(( )); const file = new File(['hello'], 'hello.png', { type: 'image/png' }); - await userEvent.upload(screen.getByLabelText('label'), file); + await userEvent.upload(screen.getByTestId('id'), file); expect(spy).toHaveBeenCalled(); }); }); diff --git a/src/components/FileInputField/_settings.scss b/src/components/FileInputField/_settings.scss new file mode 100644 index 000000000..1b882d49f --- /dev/null +++ b/src/components/FileInputField/_settings.scss @@ -0,0 +1,15 @@ +@use "../../styles/theme/typography"; + +$drop-zone-color: var(--rui-color-text-primary); +$drop-zone-disabled-color: var(--rui-color-text-primary-disabled); +$drop-zone-border-color: var(--rui-color-border-primary); +$drop-zone-hover-border-color: var(--rui-color-border-primary-hover); +$drop-zone-active-border-color: var(--rui-color-border-primary-active); +$drop-zone-dragging-border-color: var(--rui-color-border-primary-active); +$drop-zone-disabled-border-color: var(--rui-color-border-primary); +$drop-zone-background-color: var(--rui-color-background-basic); +$drop-zone-disabled-background-color: var(--rui-color-background-disabled); +$drop-zone-disabled-cursor: var(--rui-cursor-not-allowed); +$drop-zone-font-weight: typography.$font-weight-base; +$drop-zone-line-height: typography.$line-height-base; +$drop-zone-font-family: typography.$font-family-base; diff --git a/src/components/FormLayout/FormLayout.jsx b/src/components/FormLayout/FormLayout.jsx index 2b385c5d1..b6a76f26f 100644 --- a/src/components/FormLayout/FormLayout.jsx +++ b/src/components/FormLayout/FormLayout.jsx @@ -1,8 +1,8 @@ import PropTypes from 'prop-types'; import React, { useMemo } from 'react'; import { withGlobalProps } from '../../providers/globalProps'; -import { classNames } from '../../utils/classNames'; -import { transferProps } from '../../utils/transferProps'; +import { classNames } from '../../helpers/classNames/classNames'; +import { transferProps } from '../../helpers/transferProps'; import { isChildrenEmpty } from '../_helpers/isChildrenEmpty'; import { FormLayoutContext } from './FormLayoutContext'; import styles from './FormLayout.module.scss'; diff --git a/src/components/FormLayout/FormLayoutCustomField.jsx b/src/components/FormLayout/FormLayoutCustomField.jsx index 933d8210c..095d56d87 100644 --- a/src/components/FormLayout/FormLayoutCustomField.jsx +++ b/src/components/FormLayout/FormLayoutCustomField.jsx @@ -1,8 +1,8 @@ import PropTypes from 'prop-types'; import React, { useContext } from 'react'; import { withGlobalProps } from '../../providers/globalProps'; -import { classNames } from '../../utils/classNames'; -import { transferProps } from '../../utils/transferProps'; +import { classNames } from '../../helpers/classNames/classNames'; +import { transferProps } from '../../helpers/transferProps'; import { getRootSizeClassName } from '../_helpers/getRootSizeClassName'; import { getRootValidationStateClassName } from '../_helpers/getRootValidationStateClassName'; import { isChildrenEmpty } from '../_helpers/isChildrenEmpty'; diff --git a/src/components/FormLayout/README.md b/src/components/FormLayout/README.md index 8c9f713d0..7bacef204 100644 --- a/src/components/FormLayout/README.md +++ b/src/components/FormLayout/README.md @@ -389,6 +389,7 @@ React.createElement(() => { /> {}} /> { { children:
content text
}, (rootElement) => expect(within(rootElement).getByText('content text')), ], + // The following tests must use `rootElement.outerHTML.includes()` to test presence of CSS variables in the DOM, + // because the `toHaveStyle` matcher does not support reading CSS variables via the `var()` function. [ { columnGap: responsiveSpacingBreakpoints }, - (rootElement) => expect(rootElement).toHaveStyle(responsiveSpacingStyles('column-gap')), + (rootElement) => { + Object.entries(responsiveSpacingStyles('column-gap')).forEach(([ccsAttribute, cssValue]) => { + expect(rootElement.outerHTML.includes(`${ccsAttribute}: ${cssValue}`)).toBeTruthy(); + }); + }, ], [ { columnGap: 0 }, - (rootElement) => expect(rootElement).toHaveStyle({ '--rui-local-column-gap-xs': 'var(--rui-dimension-space-0)' }), + (rootElement) => expect(rootElement.outerHTML.includes('--rui-local-column-gap-xs: var(--rui-dimension-space-0)')).toBeTruthy(), ], [ { columns: responsiveBreakpoints }, @@ -116,13 +122,19 @@ describe('rendering', () => { { justifyItems: 'placeholder' }, (rootElement) => expect(rootElement).toHaveStyle({ '--rui-local-justify-items-xs': 'placeholder' }), ], + // The following tests must use `rootElement.outerHTML.includes()` to test presence of CSS variables in the DOM, + // because the `toHaveStyle` matcher does not support reading CSS variables via the `var()` function. [ { rowGap: responsiveSpacingBreakpoints }, - (rootElement) => expect(rootElement).toHaveStyle(responsiveSpacingStyles('row-gap')), + (rootElement) => { + Object.entries(responsiveSpacingStyles('row-gap')).forEach(([cssAttribute, cssValue]) => { + expect(rootElement.outerHTML.includes(`${cssAttribute}: ${cssValue}`)).toBeTruthy(); + }); + }, ], [ { rowGap: 0 }, - (rootElement) => expect(rootElement).toHaveStyle({ '--rui-local-row-gap-xs': 'var(--rui-dimension-space-0)' }), + (rootElement) => expect(rootElement.outerHTML.includes('--rui-local-row-gap-xs: var(--rui-dimension-space-0)')).toBeTruthy(), ], [ { rows: responsiveBreakpoints }, diff --git a/src/components/InputGroup/InputGroup.jsx b/src/components/InputGroup/InputGroup.jsx index dcb230bec..cad554b60 100644 --- a/src/components/InputGroup/InputGroup.jsx +++ b/src/components/InputGroup/InputGroup.jsx @@ -4,8 +4,8 @@ import React, { useMemo, } from 'react'; import { withGlobalProps } from '../../providers/globalProps'; -import { classNames } from '../../utils/classNames'; -import { transferProps } from '../../utils/transferProps'; +import { classNames } from '../../helpers/classNames/classNames'; +import { transferProps } from '../../helpers/transferProps'; import { getRootSizeClassName } from '../_helpers/getRootSizeClassName'; import { getRootValidationStateClassName } from '../_helpers/getRootValidationStateClassName'; import { isChildrenEmpty } from '../_helpers/isChildrenEmpty'; diff --git a/src/components/InputGroup/InputGroup.module.scss b/src/components/InputGroup/InputGroup.module.scss index 16ac95ebe..0751322d9 100644 --- a/src/components/InputGroup/InputGroup.module.scss +++ b/src/components/InputGroup/InputGroup.module.scss @@ -84,14 +84,14 @@ // Sizes .isRootSizeSmall { - @include box-field-sizes.size(small, $has-input: false); + @include box-field-sizes.size(small); } .isRootSizeMedium { - @include box-field-sizes.size(medium, $has-input: false); + @include box-field-sizes.size(medium); } .isRootSizeLarge { - @include box-field-sizes.size(large, $has-input: false); + @include box-field-sizes.size(large); } } diff --git a/src/components/InputGroup/README.md b/src/components/InputGroup/README.md index dd16362d2..2bbd8e1f3 100644 --- a/src/components/InputGroup/README.md +++ b/src/components/InputGroup/README.md @@ -145,7 +145,7 @@ supports this kind of layout as well. label="Horizontal layout" layout="horizontal" > - + {}} />