diff --git a/.changeset/little-dingos-study.md b/.changeset/little-dingos-study.md new file mode 100644 index 0000000000..2defb8ed1f --- /dev/null +++ b/.changeset/little-dingos-study.md @@ -0,0 +1,14 @@ +--- +'@backstage/ui': minor +--- + +**BREAKING**: Removed central `componentDefinitions` object and related type utilities (`ComponentDefinitionName`, `ComponentClassNames`). + +Component definitions are primarily intended for documenting the CSS class API for theming purposes, not for programmatic use in JavaScript/TypeScript. + +**Migration Guide:** + +If you were using component definitions or class names to build custom components, we recommend migrating to either: + +- Use Backstage UI components directly as building blocks, or +- Duplicate the component CSS in your own stylesheets instead of relying on internal class names diff --git a/.changeset/lucky-parrots-yell.md b/.changeset/lucky-parrots-yell.md new file mode 100644 index 0000000000..7533ed6e56 --- /dev/null +++ b/.changeset/lucky-parrots-yell.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': patch +--- + +Fixed responsiveness issues with catalog entity content layout using the new frontend system. diff --git a/.changeset/plenty-spiders-lead.md b/.changeset/plenty-spiders-lead.md new file mode 100644 index 0000000000..48db0d5522 --- /dev/null +++ b/.changeset/plenty-spiders-lead.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-plugin-api': minor +--- + +Renamed `ExtensionDefinition` to `OverridableExtensionDefinition` and introduced a slimmer `ExtensionDefinition` type that does not include override methods. The overridable type is generally used as an output type, while plain `ExtensionDefinition`s are used for input. This reduces type conflicts across different of `@backstage/frontend-plugin-api`, improving long-term compatibility. diff --git a/.changeset/pre.json b/.changeset/pre.json index f068415e9f..f65042692e 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -1,5 +1,5 @@ { - "mode": "pre", + "mode": "exit", "tag": "next", "initialVersions": { "example-app": "0.2.114", diff --git a/.changeset/purple-pants-speak.md b/.changeset/purple-pants-speak.md new file mode 100644 index 0000000000..b46c4b991f --- /dev/null +++ b/.changeset/purple-pants-speak.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': patch +--- + +Fixed missing margins for entity warning content area on catalog entity page in NFS. diff --git a/.changeset/sad-rockets-rule.md b/.changeset/sad-rockets-rule.md new file mode 100644 index 0000000000..fe15580f99 --- /dev/null +++ b/.changeset/sad-rockets-rule.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-notifications-backend-module-slack': patch +--- + +When an error message is logged due to inability to send a message with the Slack SDK, include the Slack Channel ID in the message to aid debugging. diff --git a/.changeset/tidy-lines-hear.md b/.changeset/tidy-lines-hear.md new file mode 100644 index 0000000000..4cb28dfbac --- /dev/null +++ b/.changeset/tidy-lines-hear.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-import': patch +--- + +Fixed missing `catalog.entity.create` permission authorization in the default page extension. diff --git a/.changeset/warm-dancers-battle.md b/.changeset/warm-dancers-battle.md new file mode 100644 index 0000000000..8aa3f765e8 --- /dev/null +++ b/.changeset/warm-dancers-battle.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-react': patch +--- + +Fixed catalog filter "all" not appearing as selected when set as the initially selected filter. diff --git a/.github/workflows/api-breaking-changes-comment.yml b/.github/workflows/api-breaking-changes-comment.yml index 981d5cb4d6..9b20cf80fb 100644 --- a/.github/workflows/api-breaking-changes-comment.yml +++ b/.github/workflows/api-breaking-changes-comment.yml @@ -23,7 +23,7 @@ jobs: comment-cache-key: ${{ steps.hash.outputs.COMMENT_FILE_HASH }} steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: disable-sudo: true egress-policy: block @@ -32,7 +32,7 @@ jobs: - name: 'Download artifacts' # Fetch output (zip archive) from the workflow run that triggered this workflow. - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 with: script: | let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({ @@ -74,7 +74,7 @@ jobs: - name: Cache Comment if: ${{ steps.event.outputs.ACTION != 'closed' }} - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: comment.md key: ${{ steps.hash.outputs.COMMENT_FILE_HASH }} diff --git a/.github/workflows/api-breaking-changes.yml b/.github/workflows/api-breaking-changes.yml index f72d9c29bf..458aa621dc 100644 --- a/.github/workflows/api-breaking-changes.yml +++ b/.github/workflows/api-breaking-changes.yml @@ -14,11 +14,11 @@ jobs: if: ${{ github.event_name != 'pull_request' || github.event.action != 'closed' }} steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 with: # Fetch the commit that's merged into the base rather than the target ref # This will let us diff only the contents of the PR, without fetching more history diff --git a/.github/workflows/automate_area-labels.yml b/.github/workflows/automate_area-labels.yml index f21ef62d8d..b1663d1629 100644 --- a/.github/workflows/automate_area-labels.yml +++ b/.github/workflows/automate_area-labels.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit diff --git a/.github/workflows/automate_changeset_feedback.yml b/.github/workflows/automate_changeset_feedback.yml index c41f4dd8f3..99ffe2f62d 100644 --- a/.github/workflows/automate_changeset_feedback.yml +++ b/.github/workflows/automate_changeset_feedback.yml @@ -23,11 +23,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 with: # Fetch the commit that's merged into the base rather than the target ref # This will let us diff only the contents of the PR, without fetching more history diff --git a/.github/workflows/automate_merge_message.yml b/.github/workflows/automate_merge_message.yml index 59da292109..3dfb3e222e 100644 --- a/.github/workflows/automate_merge_message.yml +++ b/.github/workflows/automate_merge_message.yml @@ -24,11 +24,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 with: ref: '${{ github.event.pull_request.merge_commit_sha }}' @@ -44,7 +44,7 @@ jobs: node generate.js ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }} > message.txt - name: Post Message - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 env: ISSUE_NUMBER: ${{ github.event.pull_request.number }} with: diff --git a/.github/workflows/automate_stale.yml b/.github/workflows/automate_stale.yml index 5b92c6211b..cbdab4414a 100644 --- a/.github/workflows/automate_stale.yml +++ b/.github/workflows/automate_stale.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit diff --git a/.github/workflows/ci-noop.yml b/.github/workflows/ci-noop.yml index 0fce9ad6b9..d046686002 100644 --- a/.github/workflows/ci-noop.yml +++ b/.github/workflows/ci-noop.yml @@ -40,7 +40,7 @@ jobs: name: Test ${{ matrix.node-version }} steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8aabe7de58..db71826ef4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,11 +28,11 @@ jobs: name: Install ${{ matrix.node-version }} steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - name: use node.js ${{ matrix.node-version }} uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 @@ -64,11 +64,11 @@ jobs: name: Verify ${{ matrix.node-version }} steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - name: use node.js ${{ matrix.node-version }} uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 @@ -210,7 +210,7 @@ jobs: INTEGRATION_TEST_AZURE_TOKEN: ${{ secrets.INTEGRATION_TEST_AZURE_TOKEN }} steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - name: fetch master branch run: git fetch origin master diff --git a/.github/workflows/cron.yml b/.github/workflows/cron.yml index 285c2e6c41..bb759971b7 100644 --- a/.github/workflows/cron.yml +++ b/.github/workflows/cron.yml @@ -10,7 +10,7 @@ jobs: timeout-minutes: 10 steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit diff --git a/.github/workflows/deploy_docker-image.yml b/.github/workflows/deploy_docker-image.yml index e0f4ec29ed..ee4866d7af 100644 --- a/.github/workflows/deploy_docker-image.yml +++ b/.github/workflows/deploy_docker-image.yml @@ -20,12 +20,12 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit - name: checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 with: path: backstage ref: ${{ github.event.client_payload.version && env.RELEASE_VERSION || github.ref }} diff --git a/.github/workflows/deploy_microsite.yml b/.github/workflows/deploy_microsite.yml index 2d61bcc19b..acf0cb7776 100644 --- a/.github/workflows/deploy_microsite.yml +++ b/.github/workflows/deploy_microsite.yml @@ -23,7 +23,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit @@ -54,7 +54,7 @@ jobs: result-encoding: string - name: checkout latest release - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 with: ref: refs/tags/${{ steps.find-release.outputs.result }} @@ -135,12 +135,12 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit - name: checkout master - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - name: Use Node.js 20.x uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 @@ -240,7 +240,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit @@ -252,7 +252,7 @@ jobs: # Stable docs - name: checkout latest release - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 with: ref: refs/tags/${{ needs.stable.outputs.release }} @@ -286,7 +286,7 @@ jobs: # Next docs - name: checkout master - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 with: clean: false diff --git a/.github/workflows/deploy_packages.yml b/.github/workflows/deploy_packages.yml index 9e4e504e60..4b35921b42 100644 --- a/.github/workflows/deploy_packages.yml +++ b/.github/workflows/deploy_packages.yml @@ -68,7 +68,7 @@ jobs: INTEGRATION_TEST_AZURE_TOKEN: ${{ secrets.INTEGRATION_TEST_AZURE_TOKEN }} steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - name: use node.js ${{ matrix.node-version }} uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 @@ -151,7 +151,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit diff --git a/.github/workflows/issue.yaml b/.github/workflows/issue.yaml index a759adcb46..2eefcfcd88 100644 --- a/.github/workflows/issue.yaml +++ b/.github/workflows/issue.yaml @@ -16,7 +16,7 @@ jobs: if: github.repository == 'backstage/backstage' steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit diff --git a/.github/workflows/mui-migration-tracker.yml b/.github/workflows/mui-migration-tracker.yml index 4754ec51b0..8c91e0e8a0 100644 --- a/.github/workflows/mui-migration-tracker.yml +++ b/.github/workflows/mui-migration-tracker.yml @@ -18,7 +18,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit diff --git a/.github/workflows/pr-review-comment-trigger.yaml b/.github/workflows/pr-review-comment-trigger.yaml index d5970deae8..968bc4ab12 100644 --- a/.github/workflows/pr-review-comment-trigger.yaml +++ b/.github/workflows/pr-review-comment-trigger.yaml @@ -20,7 +20,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit diff --git a/.github/workflows/pr-review-comment.yaml b/.github/workflows/pr-review-comment.yaml index 9db0792eaa..122eb4fcce 100644 --- a/.github/workflows/pr-review-comment.yaml +++ b/.github/workflows/pr-review-comment.yaml @@ -17,13 +17,13 @@ jobs: steps: # Inspired by https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#using-data-from-the-triggering-workflow - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit - name: Read PR Number id: pr-number - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 33dd3d00ce..4067326890 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -18,7 +18,7 @@ jobs: if: github.repository == 'backstage/backstage' && ( github.event.pull_request || github.event.issue.pull_request ) steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 0766d1c8a5..d42fb0af6c 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -29,12 +29,12 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit - name: 'Checkout code' - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 with: persist-credentials: false diff --git a/.github/workflows/sync_canon.yml b/.github/workflows/sync_canon.yml index 3b85c1c49d..db8bfb6b19 100644 --- a/.github/workflows/sync_canon.yml +++ b/.github/workflows/sync_canon.yml @@ -8,12 +8,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - name: Use Node.js 20.x uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 @@ -27,7 +27,7 @@ jobs: cache-prefix: ${{ runner.os }}-v20.x - name: Checkout backstage/docs-ui - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 with: repository: backstage/docs-ui path: bui-external-docs diff --git a/.github/workflows/sync_code-formatting.yml b/.github/workflows/sync_code-formatting.yml index 33cab94280..478c8a0cf2 100644 --- a/.github/workflows/sync_code-formatting.yml +++ b/.github/workflows/sync_code-formatting.yml @@ -10,11 +10,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 with: # Fetch changes to previous commit - required for 'only_changed' in Prettier action fetch-depth: 0 diff --git a/.github/workflows/sync_dependabot-changesets.yml b/.github/workflows/sync_dependabot-changesets.yml index 181d48eb38..2ddde5ca4b 100644 --- a/.github/workflows/sync_dependabot-changesets.yml +++ b/.github/workflows/sync_dependabot-changesets.yml @@ -11,12 +11,12 @@ jobs: if: github.actor == 'dependabot[bot]' && github.repository == 'backstage/backstage' steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 with: fetch-depth: 2 ref: ${{ github.head_ref }} @@ -26,7 +26,7 @@ jobs: git config --global user.email noreply@backstage.io git config --global user.name 'Github changeset workflow' - name: Generate changeset - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 with: script: | const { promises: fs } = require('fs'); diff --git a/.github/workflows/sync_release-manifest.yml b/.github/workflows/sync_release-manifest.yml index a9c4b3722b..0e9aa213c0 100644 --- a/.github/workflows/sync_release-manifest.yml +++ b/.github/workflows/sync_release-manifest.yml @@ -8,12 +8,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 with: # 'v' prefix is added here for the tag, we keep it out of the manifest logic ref: v${{ github.event.client_payload.version }} @@ -35,7 +35,7 @@ jobs: # Checkout backstage/versions into /backstage/versions, which is where store the output - name: Checkout versions - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 with: repository: backstage/versions path: versions @@ -71,7 +71,7 @@ jobs: git push - name: Dispatch update-helper update - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 with: github-token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }} # TODO(Rugvip): Remove the create-app dispatch once we've been on the release version for a while diff --git a/.github/workflows/sync_renovate-changesets.yml b/.github/workflows/sync_renovate-changesets.yml index 2331e2c30f..5f98f80615 100644 --- a/.github/workflows/sync_renovate-changesets.yml +++ b/.github/workflows/sync_renovate-changesets.yml @@ -11,12 +11,12 @@ jobs: if: github.actor == 'renovate[bot]' && github.repository == 'backstage/backstage' steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 with: fetch-depth: 2 ref: ${{ github.head_ref }} @@ -26,7 +26,7 @@ jobs: git config --global user.email noreply@backstage.io git config --global user.name 'Github changeset workflow' - name: Generate changeset - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 with: script: | const { promises: fs } = require("fs"); diff --git a/.github/workflows/sync_snyk-github-issues.yml b/.github/workflows/sync_snyk-github-issues.yml index f18455f5fc..d56fac654a 100644 --- a/.github/workflows/sync_snyk-github-issues.yml +++ b/.github/workflows/sync_snyk-github-issues.yml @@ -12,11 +12,11 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - name: Use Node.js 20.x uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 diff --git a/.github/workflows/sync_snyk-monitor.yml b/.github/workflows/sync_snyk-monitor.yml index b928586aa8..0d7befd3b7 100644 --- a/.github/workflows/sync_snyk-monitor.yml +++ b/.github/workflows/sync_snyk-monitor.yml @@ -25,11 +25,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - name: Monitor and Synchronize Snyk Policies uses: snyk/actions/node@9adf32b1121593767fc3c057af55b55db032dc04 # master with: diff --git a/.github/workflows/sync_version-packages.yml b/.github/workflows/sync_version-packages.yml index 66a798bd58..7ca74c6aeb 100644 --- a/.github/workflows/sync_version-packages.yml +++ b/.github/workflows/sync_version-packages.yml @@ -14,11 +14,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 with: fetch-depth: 20000 fetch-tags: true diff --git a/.github/workflows/verify_accessibility-noop.yml b/.github/workflows/verify_accessibility-noop.yml index df6f004171..abb3abc665 100644 --- a/.github/workflows/verify_accessibility-noop.yml +++ b/.github/workflows/verify_accessibility-noop.yml @@ -26,7 +26,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit diff --git a/.github/workflows/verify_accessibility.yml b/.github/workflows/verify_accessibility.yml index 48e243b002..3b624c96bc 100644 --- a/.github/workflows/verify_accessibility.yml +++ b/.github/workflows/verify_accessibility.yml @@ -20,11 +20,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - name: Use Node.js 20.x uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: diff --git a/.github/workflows/verify_chromatic-noop.yml b/.github/workflows/verify_chromatic-noop.yml index 4de52a3258..2a2ad7d43d 100644 --- a/.github/workflows/verify_chromatic-noop.yml +++ b/.github/workflows/verify_chromatic-noop.yml @@ -20,7 +20,7 @@ jobs: name: Chromatic steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit diff --git a/.github/workflows/verify_chromatic.yml b/.github/workflows/verify_chromatic.yml index e6649c3e55..e9f34e35ac 100644 --- a/.github/workflows/verify_chromatic.yml +++ b/.github/workflows/verify_chromatic.yml @@ -24,12 +24,12 @@ jobs: name: Chromatic steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit - name: Checkout code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 with: fetch-depth: 10000 # Required to retrieve git history diff --git a/.github/workflows/verify_codeql.yml b/.github/workflows/verify_codeql.yml index 254938ecc8..7dad08fa01 100644 --- a/.github/workflows/verify_codeql.yml +++ b/.github/workflows/verify_codeql.yml @@ -42,12 +42,12 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit - name: Checkout repository - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 with: # We must fetch at least the immediate parents so that if this is # a pull request then we can checkout the head. diff --git a/.github/workflows/verify_docs-quality.yml b/.github/workflows/verify_docs-quality.yml index 6c855eeea4..5f31c7a289 100644 --- a/.github/workflows/verify_docs-quality.yml +++ b/.github/workflows/verify_docs-quality.yml @@ -12,11 +12,11 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 # Vale does not support file excludes, so we use the script to generate a list of files instead # The action also does not allow args or a local config file to be passed in, so the files array diff --git a/.github/workflows/verify_e2e-linux-noop.yml b/.github/workflows/verify_e2e-linux-noop.yml index aa3358f2f7..cc25b2db58 100644 --- a/.github/workflows/verify_e2e-linux-noop.yml +++ b/.github/workflows/verify_e2e-linux-noop.yml @@ -29,7 +29,7 @@ jobs: name: E2E Linux ${{ matrix.node-version }} steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit diff --git a/.github/workflows/verify_e2e-linux.yml b/.github/workflows/verify_e2e-linux.yml index dc81d42e8a..25d71eb641 100644 --- a/.github/workflows/verify_e2e-linux.yml +++ b/.github/workflows/verify_e2e-linux.yml @@ -43,11 +43,11 @@ jobs: name: E2E Linux ${{ matrix.node-version }} steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - name: Configure Git run: | diff --git a/.github/workflows/verify_e2e-techdocs.yml b/.github/workflows/verify_e2e-techdocs.yml index e933efe3f8..6bb8f11651 100644 --- a/.github/workflows/verify_e2e-techdocs.yml +++ b/.github/workflows/verify_e2e-techdocs.yml @@ -32,11 +32,11 @@ jobs: name: Techdocs steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: python-version: '3.9' diff --git a/.github/workflows/verify_e2e-windows-noop.yml b/.github/workflows/verify_e2e-windows-noop.yml index b1a4344bfc..f8681e8b10 100644 --- a/.github/workflows/verify_e2e-windows-noop.yml +++ b/.github/workflows/verify_e2e-windows-noop.yml @@ -25,7 +25,7 @@ jobs: name: E2E Windows ${{ matrix.node-version }} steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit diff --git a/.github/workflows/verify_e2e-windows.yml b/.github/workflows/verify_e2e-windows.yml index eefcf22b35..f98fc98745 100644 --- a/.github/workflows/verify_e2e-windows.yml +++ b/.github/workflows/verify_e2e-windows.yml @@ -33,7 +33,7 @@ jobs: name: E2E Windows ${{ matrix.node-version }} steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit @@ -44,7 +44,7 @@ jobs: git config --global core.autocrlf false git config --global core.eol lf - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - name: Configure Git run: | diff --git a/.github/workflows/verify_fossa.yml b/.github/workflows/verify_fossa.yml index 9c811fbe9f..732e53988a 100644 --- a/.github/workflows/verify_fossa.yml +++ b/.github/workflows/verify_fossa.yml @@ -14,12 +14,12 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - name: Install Fossa run: "curl -H 'Cache-Control: no-cache' https://raw.githubusercontent.com/fossas/fossa-cli/master/install.sh | bash" diff --git a/.github/workflows/verify_microsite-noop.yml b/.github/workflows/verify_microsite-noop.yml index 3466826cae..a6edeb8415 100644 --- a/.github/workflows/verify_microsite-noop.yml +++ b/.github/workflows/verify_microsite-noop.yml @@ -21,7 +21,7 @@ jobs: name: Microsite steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit diff --git a/.github/workflows/verify_microsite.yml b/.github/workflows/verify_microsite.yml index 67ac397d43..689b85fe9f 100644 --- a/.github/workflows/verify_microsite.yml +++ b/.github/workflows/verify_microsite.yml @@ -28,7 +28,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit @@ -59,7 +59,7 @@ jobs: result-encoding: string - name: checkout latest release - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 with: ref: refs/tags/${{ steps.find-release.outputs.result }} @@ -137,12 +137,12 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit - name: checkout master - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - name: Use Node.js 20.x uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 @@ -234,11 +234,11 @@ jobs: name: Microsite steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - name: Use Node.js 20.x uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 @@ -295,7 +295,7 @@ jobs: run: yarn build:api-docs - name: checkout master - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 with: clean: false diff --git a/.github/workflows/verify_microsite_accessibility-noop.yml b/.github/workflows/verify_microsite_accessibility-noop.yml index 5e0bc35cc0..f4263e1398 100644 --- a/.github/workflows/verify_microsite_accessibility-noop.yml +++ b/.github/workflows/verify_microsite_accessibility-noop.yml @@ -24,7 +24,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit diff --git a/.github/workflows/verify_microsite_accessibility.yml b/.github/workflows/verify_microsite_accessibility.yml index 40e1866b5f..86196f7953 100644 --- a/.github/workflows/verify_microsite_accessibility.yml +++ b/.github/workflows/verify_microsite_accessibility.yml @@ -15,11 +15,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - name: Use Node.js 20.x uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 diff --git a/.github/workflows/verify_windows.yml b/.github/workflows/verify_windows.yml index 363bc075b8..ba24410145 100644 --- a/.github/workflows/verify_windows.yml +++ b/.github/workflows/verify_windows.yml @@ -29,11 +29,11 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 with: egress-policy: audit - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - name: use node.js ${{ matrix.node-version }} uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 diff --git a/docs-ui/README.md b/docs-ui/README.md index 41b9921413..b943f1ce7c 100644 --- a/docs-ui/README.md +++ b/docs-ui/README.md @@ -13,3 +13,28 @@ yarn start ## Deployment Deployments are done automatically when a PR is merged into the `master` branch. We host the website using Github pages. + +## Maintaining Component Changelogs + +After a `@backstage/ui` release, sync the component changelogs to keep documentation up-to-date: + +```bash +yarn sync:changelog +``` + +This script: + +- Parses `packages/ui/CHANGELOG.md` for new versions +- Extracts entries tagged with "Affected components: ..." +- Updates `src/utils/changelog.ts` with new entries +- Handles both component-specific and general package changes + +After running, review the changes in `src/utils/changelog.ts` and commit them. + +**Preview changes before writing:** + +```bash +yarn sync:changelog:dry-run +``` + +Running this gives you a summary of what would be written, without actually adding or changing any files. diff --git a/docs-ui/package.json b/docs-ui/package.json index d05fdf81bb..319c0e130f 100644 --- a/docs-ui/package.json +++ b/docs-ui/package.json @@ -8,6 +8,8 @@ "lint": "next lint", "prestart": "yarn sync:css", "start": "next dev", + "sync:changelog": "node scripts/sync-changelog.mjs", + "sync:changelog:dry-run": "node scripts/sync-changelog.mjs --dry-run", "sync:css": "node scripts/sync-css.js", "sync:css:watch": "node scripts/sync-css.js --watch" }, @@ -39,6 +41,7 @@ "storybook": "^8.6.12" }, "devDependencies": { + "@octokit/rest": "^22.0.1", "@shikijs/transformers": "^3.13.0", "@types/mdx": "^2.0.13", "@types/node": "^20", @@ -48,6 +51,7 @@ "eslint": "^8", "eslint-config-next": "15.3.4", "lightningcss": "^1.28.2", - "typescript": "^5" + "typescript": "^5", + "unified": "^11.0.4" } } diff --git a/docs-ui/scripts/sync-changelog.mjs b/docs-ui/scripts/sync-changelog.mjs new file mode 100644 index 0000000000..5eab3616dd --- /dev/null +++ b/docs-ui/scripts/sync-changelog.mjs @@ -0,0 +1,991 @@ +#!/usr/bin/env node +/* eslint-disable no-restricted-syntax */ + +import fs from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; +import { unified } from 'unified'; +import remarkParse from 'remark-parse'; +import { Octokit } from '@octokit/rest'; +import { execSync } from 'child_process'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +/** + * Compare two semantic versions. + * Returns: 1 if versionA > versionB, -1 if versionA < versionB, 0 if equal + * Handles pre-release versions (e.g., "0.9.0-next.2") + */ +function compareVersions(versionA, versionB) { + // Strip 'v' prefix if present + versionA = versionA.replace(/^v/, ''); + versionB = versionB.replace(/^v/, ''); + + // Split into [major.minor.patch, prerelease] + const [versionABase, versionAPre] = versionA.split('-'); + const [versionBBase, versionBPre] = versionB.split('-'); + + // Compare base versions + const versionAParts = versionABase.split('.').map(Number); + const versionBParts = versionBBase.split('.').map(Number); + + for ( + let i = 0; + i < Math.max(versionAParts.length, versionBParts.length); + i++ + ) { + const versionAPart = versionAParts[i] || 0; + const versionBPart = versionBParts[i] || 0; + + if (versionAPart > versionBPart) return 1; + if (versionAPart < versionBPart) return -1; + } + + // If base versions equal, compare pre-release + if (!versionAPre && !versionBPre) return 0; + if (!versionAPre) return 1; // versionA is release, versionB is pre-release + if (!versionBPre) return -1; // versionA is pre-release, versionB is release + + // Both have pre-release, compare them + return versionAPre.localeCompare(versionBPre); +} + +/** + * Check if versionA is newer than versionB + */ +function isNewerVersion(versionA, versionB) { + return compareVersions(versionA, versionB) > 0; +} + +/** + * Normalize version to base version (remove pre-release suffix) + * "0.9.0-next.3" → "0.9.0" + * "0.9.0" → "0.9.0" + */ +function normalizeVersion(version) { + return version.split('-')[0]; +} + +/** + * Read the existing changelog.ts and find the highest version number + * by scanning the changelogs/ directory for version files + */ +function getLastSyncedVersion(changelogPath) { + try { + // Scan changelogs/ directory for latest version file + const changelogsDir = path.join(path.dirname(changelogPath), 'changelogs'); + + if (!fs.existsSync(changelogsDir)) { + return null; + } + + // Read all version files (v0.1.0.ts, v0.2.0.ts, etc.) + const files = fs + .readdirSync(changelogsDir) + .filter(f => f.match(/^v\d+\.\d+\.\d+\.ts$/)) + .map(f => f.replace(/^v/, '').replace(/\.ts$/, '')); + + if (files.length === 0) { + return null; + } + + // Find highest version + let highest = files[0]; + for (const version of files) { + if (compareVersions(version, highest) > 0) { + highest = version; + } + } + + return highest; + } catch (error) { + console.error(`Error reading changelog file: ${error.message}`); + return null; + } +} + +/** + * Convert PascalCase component name to kebab-case slug + * Avatar -> avatar + * ButtonIcon -> button-icon + * SearchField -> searchfield (special case per existing data) + */ +function pascalToKebab(str) { + // Special cases observed in changelog.ts + const specialCases = { + SearchField: 'searchfield', + TextField: 'textfield', + DataTable: 'datatable', + ScrollArea: 'scrollarea', + }; + + if (specialCases[str]) { + return specialCases[str]; + } + + // General conversion: insert hyphen before uppercase letters + return str + .replace(/([A-Z])/g, '-$1') + .toLowerCase() + .replace(/^-/, ''); // Remove leading hyphen +} + +/** + * Map component name to valid Component type slug + * Returns null if component not recognized + */ +function mapComponentName(name, validComponents) { + const kebab = pascalToKebab(name.trim()); + const kebabLower = kebab.toLowerCase(); + + // Check if it's a valid component + const valid = validComponents.find(c => c.toLowerCase() === kebabLower); + + return valid || null; +} + +/** + * Get valid component names from types.ts Component type + */ +function getValidComponents(changelogPath) { + // Read from types.ts instead of changelog.ts + const typesPath = changelogPath.replace('changelog.ts', 'types.ts'); + const content = fs.readFileSync(typesPath, 'utf-8'); + + // Extract Component type union + const typeMatch = content.match(/export type Component =([^;]+);/s); + if (!typeMatch) { + throw new Error('Could not find Component type definition'); + } + + // Extract string literals from the union + const components = typeMatch[1] + .match(/['"]([^'"]+)['"]/g) + .map(s => s.replace(/['"]/g, '')); + + return components; +} + +/** + * Parse CHANGELOG.md and extract entries newer than sinceVersion + */ +async function parseChangelogMd(changelogPath, sinceVersion, validComponents) { + const content = fs.readFileSync(changelogPath, 'utf-8'); + const tree = unified().use(remarkParse).parse(content); + + const entries = []; + let currentVersion = null; + let currentSection = null; // 'Minor Changes', 'Patch Changes', 'Major Changes' + let processedCount = 0; + + // Walk through the markdown AST + async function walk(node, depth = 0) { + // Version headers (## 0.9.0) + if (node.type === 'heading' && node.depth === 2) { + const versionText = extractText(node).trim(); + // Validate that this is actually a version number (X.Y.Z or X.Y.Z-pre.N) + // Skip headings that are just markdown content within changelog entries + if (/^\d+\.\d+\.\d+/.test(versionText)) { + currentVersion = versionText; + currentSection = null; + } + return; + } + + // Section headers (### Minor Changes) + if (node.type === 'heading' && node.depth === 3) { + const sectionText = extractText(node); + currentSection = sectionText.trim(); + return; + } + + // List items (- 539cf26: description) + if (node.type === 'listItem' && currentVersion && currentSection) { + // Only process if version is newer than sinceVersion + if (!sinceVersion || isNewerVersion(currentVersion, sinceVersion)) { + const entry = await parseListItem( + node, + currentVersion, + currentSection, + validComponents, + content, + ); + if (entry) { + entries.push(entry); + processedCount++; + // Progress logging every 50 entries + if (processedCount % 50 === 0) { + process.stdout.write(`\r Processed ${processedCount} entries...`); + } + } + } + } + + // Recurse into children + if (node.children) { + for (const child of node.children) { + await walk(child, depth + 1); + } + } + } + + await walk(tree); + + // Clear progress line + if (processedCount > 0) { + process.stdout.write(`\r Processed ${processedCount} entries - done!\n`); + } + + return entries; +} + +/** + * Extract plain text from a markdown node + */ +function extractText(node) { + if (node.type === 'text') { + return node.value; + } + if (node.children) { + return node.children.map(extractText).join(''); + } + return ''; +} + +/** + * Extract raw markdown content from a node using position offsets + * This preserves all formatting: code blocks, lists, bold/italic, etc. + */ +function extractMarkdown(node, sourceText) { + if (!node.position) { + return extractText(node); // Fallback to text extraction + } + + const start = node.position.start.offset; + const end = node.position.end.offset; + + if (start === undefined || end === undefined) { + return extractText(node); + } + + return sourceText.slice(start, end).trim(); +} + +/** + * Parse a list item to extract changelog entry + * NOTE: PR numbers are NOT fetched here - they're fetched later only for new entries + */ +async function parseListItem( + node, + version, + section, + validComponents, + sourceText, +) { + // Extract the full text content for SHA parsing + const fullText = extractText(node); + + // Parse commit SHA and description + // Format: "- 539cf26: description..." + const match = fullText.match(/^-?\s*([a-f0-9]+):\s*(.+)/s); + if (!match) { + return null; + } + + const commitSha = match[1]; + + // Extract full markdown content from the list item + let fullMarkdown = extractMarkdown(node, sourceText); + + // Remove the commit SHA prefix from markdown + let description = fullMarkdown.replace(/^-?\s*[a-f0-9]+:\s*/, '').trim(); + + // Auto-detect components from "Affected components:" line + let components = []; + const componentMatch = description.match(/Affected components?:\s*([^\n]+)/i); + if (componentMatch) { + const componentNames = componentMatch[1] + .split(',') + .map(name => name.trim()) + .filter(Boolean); + + components = componentNames + .map(name => mapComponentName(name, validComponents)) + .filter(Boolean); + + // Optionally strip "Affected components:" line from description + description = description + .replace(/\n*Affected components?:[ \t]*[^\n]+/i, '') + .trim(); + } + + const prs = []; // Will be populated later by fetchPRNumbers() + + // Infer type from section and description + const type = inferChangeType(section, description, version); + + return { + version: normalizeVersion(version), + section, + commitSha, + description, + components, + prs, + type, + }; +} + +/** + * Infer change type from section and description + */ +function inferChangeType(section, description, version) { + const isPre1 = version.startsWith('0.'); + + // Check description keywords first + if (description.match(/^(New|Add(ed)?)\s/i)) { + return 'new'; + } + if (description.includes('BREAKING')) { + return 'breaking'; + } + + // Infer from section + if (section === 'Minor Changes') { + return isPre1 ? 'breaking' : undefined; + } else if (section === 'Major Changes') { + return 'breaking'; + } else if (section === 'Patch Changes') { + return 'fix'; + } + + return undefined; +} + +/** + * Generate new changelog entries and update changelog.ts + */ +/** + * Fetch PR numbers for entries that need them + * Only fetches for entries with empty prs array (new entries) + */ +async function fetchPRNumbers(entries, dryRun = false) { + const entriesNeedingPRs = entries.filter( + e => e.prs.length === 0 && e.commitSha, + ); + + if (entriesNeedingPRs.length === 0) { + return; + } + + console.log( + `\nšŸ” Fetching PR numbers for ${entriesNeedingPRs.length} new entries...`, + ); + + let fetchedCount = 0; + const startTime = Date.now(); + + for (const entry of entriesNeedingPRs) { + const prNumber = await findPRNumber(entry.commitSha); + if (prNumber) { + entry.prs.push(prNumber); + } + + fetchedCount++; + // Progress every 10 lookups + if (fetchedCount % 10 === 0 || fetchedCount === entriesNeedingPRs.length) { + const elapsed = ((Date.now() - startTime) / 1000).toFixed(1); + const rate = ((fetchedCount / (Date.now() - startTime)) * 1000).toFixed( + 1, + ); + process.stdout.write( + `\r Fetched ${fetchedCount}/${entriesNeedingPRs.length} PR numbers (${elapsed}s, ~${rate} req/s)`, + ); + } + } + + const totalTime = ((Date.now() - startTime) / 1000).toFixed(1); + const foundCount = entriesNeedingPRs.filter(e => e.prs.length > 0).length; + console.log( + `\n āœ“ Found ${foundCount}/${entriesNeedingPRs.length} PR numbers in ${totalTime}s`, + ); +} + +/** + * Generate per-version changelog files in changelogs/ directory + */ +async function generateVersionFiles(entries, changelogsDir, dryRun = false) { + // Group entries by normalized version + const byVersion = {}; + entries.forEach(entry => { + const version = entry.version; + if (!byVersion[version]) { + byVersion[version] = []; + } + byVersion[version].push(entry); + }); + + const versionFiles = []; + const skippedVersions = []; + const generatedVersions = []; + + for (const [version, versionEntries] of Object.entries(byVersion)) { + const fileName = `v${version}.ts`; + const filePath = path.join(changelogsDir, fileName); + const varName = `changelog_${version.replace(/\./g, '_')}`; + + // Check if file already exists - skip if it does + if (fs.existsSync(filePath)) { + skippedVersions.push(version); + // Still add to versionFiles array so main changelog.ts can import it + versionFiles.push({ + version, + fileName, + filePath, + varName, + content: null, // No content needed for existing files + skipped: true, + }); + continue; + } + + // Generate TypeScript code for this version + const entryObjects = versionEntries + .map(entry => { + const componentsStr = `[${entry.components + .map(c => `'${c}'`) + .join(', ')}]`; + const prsStr = `[${entry.prs.map(pr => `'${pr}'`).join(', ')}]`; + const typeStr = entry.type ? `type: '${entry.type}',` : ''; + const shaStr = entry.commitSha + ? `commitSha: '${entry.commitSha}',` + : ''; + + // Escape description for template literal + const descEscaped = entry.description + .replace(/\\/g, '\\\\') + .replace(/`/g, '\\`') + .replace(/\${/g, '\\${'); + + return ` { + components: ${componentsStr}, + version: '${entry.version}', + prs: ${prsStr}, + description: \`${descEscaped}\`, + ${typeStr} + ${shaStr} + }`; + }) + .join(',\n'); + + const fileContent = `import type { ChangelogProps } from '../types'; + +export const ${varName}: ChangelogProps[] = [ +${entryObjects} +]; +`; + + generatedVersions.push(version); + versionFiles.push({ + version, + fileName, + filePath, + varName, + content: fileContent, + skipped: false, + }); + + if (!dryRun) { + fs.writeFileSync(filePath, fileContent, 'utf-8'); + } + } + + // Log summary + if (skippedVersions.length > 0) { + console.log( + `\nā­ļø Skipped ${ + skippedVersions.length + } existing version files: ${skippedVersions + .sort((a, b) => compareVersions(a, b)) + .join(', ')}`, + ); + } + if (generatedVersions.length > 0) { + console.log( + `\n✨ ${dryRun ? 'Would generate' : 'Generated'} ${ + generatedVersions.length + } new version files: ${generatedVersions + .sort((a, b) => compareVersions(a, b)) + .join(', ')}`, + ); + } + + return versionFiles; +} + +/** + * Generate main changelog.ts that imports and spreads all version files + */ +async function generateMainChangelog( + versionFiles, + changelogPath, + dryRun = false, +) { + // Get the changelogs directory path + const changelogsDir = path.join(path.dirname(changelogPath), 'changelogs'); + + // Read all version files from the changelogs directory + const allVersionFiles = new Map(); + + // First, add all files from the directory (if it exists) + if (fs.existsSync(changelogsDir)) { + const files = fs.readdirSync(changelogsDir); + files.forEach(file => { + if (file.match(/^v\d+\.\d+\.\d+\.ts$/)) { + const version = file.replace(/^v/, '').replace(/\.ts$/, ''); + const varName = `changelog_${version.replace(/\./g, '_')}`; + allVersionFiles.set(version, { + version, + fileName: file, + varName, + }); + } + }); + } + + // Then, add/update with files from this run (in case new ones were generated) + versionFiles.forEach(vf => { + allVersionFiles.set(vf.version, { + version: vf.version, + fileName: vf.fileName, + varName: vf.varName, + }); + }); + + // Sort versions in descending order + const sortedVersions = Array.from(allVersionFiles.values()).sort((a, b) => + compareVersions(b.version, a.version), + ); + + const imports = sortedVersions + .map( + v => + `import { ${v.varName} } from './changelogs/${v.fileName.replace( + '.ts', + '', + )}';`, + ) + .join('\n'); + + const spreads = sortedVersions.map(v => ` ...${v.varName},`).join('\n'); + + const content = `export * from './types'; +${imports} + +export const changelog = [ +${spreads} +]; +`; + + console.log( + `\nšŸ“ Main changelog.ts will import all ${sortedVersions.length} version files`, + ); + + if (!dryRun) { + fs.writeFileSync(changelogPath, content, 'utf-8'); + } + + return content; +} + +/** + * Check if an entry already exists in changelog.ts + */ +function isDuplicate(entry, existingContent) { + // Simple check: look for version + description substring + const descStart = entry.description.substring(0, 50); + const pattern = `version: '${entry.version}'`; + + const versionIndex = existingContent.indexOf(pattern); + if (versionIndex === -1) return false; + + // Check if description appears near this version + const contextWindow = existingContent.substring( + Math.max(0, versionIndex - 200), + versionIndex + 500, + ); + + return contextWindow.includes(descStart); +} + +/** + * Detect GitHub authentication method + * Priority: gh CLI → GITHUB_TOKEN env → unauthenticated + */ +function getGitHubAuth() { + // 1. Try gh CLI (preferred - uses keyring auth) + try { + // Check specifically for github.com authentication + const output = execSync('gh auth status -h github.com 2>&1', { + encoding: 'utf-8', + }); + if (output.includes('Logged in to github.com')) { + console.log('āœ“ Using gh CLI authentication'); + return { method: 'gh-cli' }; + } + } catch { + // gh not installed or not authenticated to github.com + } + + // 2. Try GITHUB_TOKEN env var + if (process.env.GITHUB_TOKEN) { + console.log('āœ“ Using GITHUB_TOKEN authentication'); + return { method: 'token', token: process.env.GITHUB_TOKEN }; + } + + // 3. Fallback to unauthenticated (60 req/hour limit) + console.warn('āš ļø Using unauthenticated GitHub API (60 requests/hour)'); + console.warn(' For higher limits: authenticate gh CLI or set GITHUB_TOKEN'); + return { method: 'unauthenticated' }; +} + +// Initialize auth and Octokit +const githubAuth = getGitHubAuth(); +const octokit = + githubAuth.method === 'token' + ? new Octokit({ auth: githubAuth.token }) + : new Octokit(); + +// Cache for PR lookups +const prCache = new Map(); + +/** + * Expand a truncated SHA to full SHA using local git repository + * Falls back to GitHub API if git rev-parse fails + */ +async function expandCommitSha(shortSha) { + try { + // First try local git repository (fastest, works for all commits) + // We need to run this from the backstage monorepo root + const repoRoot = path.join(__dirname, '../../'); + + try { + const fullSha = execSync(`git rev-parse ${shortSha}`, { + encoding: 'utf-8', + cwd: repoRoot, + stdio: ['pipe', 'pipe', 'pipe'], + }).trim(); + + if (fullSha && fullSha.length === 40) { + return fullSha; + } + } catch (gitError) { + // Handle ambiguous SHA - parse git's error output to find commit candidates + if (gitError.stderr && gitError.stderr.includes('ambiguous')) { + const stderr = gitError.stderr.toString(); + // Extract commit SHAs from git's hint output + // Format: "hint: 83c100e6accfb commit 2025-10-22 - message" + const commitMatch = stderr.match(/hint:\s+([a-f0-9]+)\s+commit\s+/); + if (commitMatch && commitMatch[1]) { + // Found the commit SHA from the ambiguous candidates + const candidateSha = commitMatch[1]; + // Verify this is a valid commit + try { + const fullSha = execSync(`git rev-parse ${candidateSha}`, { + encoding: 'utf-8', + cwd: repoRoot, + }).trim(); + if (fullSha && fullSha.length === 40) { + return fullSha; + } + } catch { + // Candidate didn't work, continue to GitHub API + } + } + } + // Commit not in local repo, try GitHub API + } + } catch (error) { + // Error setting up git command, try GitHub API + } + + try { + // Fallback to GitHub API + if (githubAuth.method === 'gh-cli') { + const result = execSync( + `gh api repos/backstage/backstage/commits/${shortSha} --jq '.sha' 2>/dev/null`, + { encoding: 'utf-8' }, + ).trim(); + return result || null; + } else { + // Use Octokit + const { data: commit } = await octokit.rest.repos.getCommit({ + owner: 'backstage', + repo: 'backstage', + ref: shortSha, + }); + return commit.sha; + } + } catch (error) { + // Commit not found or other error - return null silently + return null; + } +} + +/** + * Find PR number for a commit SHA using GitHub API + */ +async function findPRNumber(commitSha) { + // Check cache first + if (prCache.has(commitSha)) { + return prCache.get(commitSha); + } + + try { + // If SHA is truncated (7 chars), expand it first + let fullSha = commitSha; + if (commitSha.length === 7) { + fullSha = await expandCommitSha(commitSha); + if (!fullSha) { + // Commit not found + console.warn(`āš ļø Commit not found: ${commitSha}`); + prCache.set(commitSha, null); + return null; + } + } + + let prNumber = null; + + // Use gh CLI if available (faster, uses existing auth) + if (githubAuth.method === 'gh-cli') { + try { + const result = execSync( + `gh api repos/backstage/backstage/commits/${fullSha}/pulls --jq '.[0].number' 2>/dev/null`, + { encoding: 'utf-8' }, + ).trim(); + prNumber = result || null; + } catch (ghError) { + // Handle gh CLI errors gracefully - commit exists but has no PR + prNumber = null; + } + } else { + // Otherwise use Octokit (token or unauthenticated) + const { data: prs } = + await octokit.rest.repos.listPullRequestsAssociatedWithCommit({ + owner: 'backstage', + repo: 'backstage', + commit_sha: fullSha, + }); + prNumber = prs.length > 0 ? prs[0].number.toString() : null; + } + + // Cache the result + prCache.set(commitSha, prNumber); + return prNumber; + } catch (error) { + if (error.message?.includes('rate limit')) { + console.error('āš ļø GitHub API rate limit exceeded'); + console.error( + ' Authenticate gh CLI or set GITHUB_TOKEN for higher limits', + ); + } else { + console.warn(`āš ļø Error finding PR for ${commitSha}: ${error.message}`); + } + prCache.set(commitSha, null); + return null; + } +} + +/** + * Main sync function + */ +async function main() { + const args = process.argv.slice(2); + const dryRun = args.includes('--dry-run'); + + const changelogTsPath = path.join(__dirname, '../src/utils/changelog.ts'); + const changelogMdPath = path.join( + __dirname, + '../../packages/ui/CHANGELOG.md', + ); + + // Validate files exist + if (!fs.existsSync(changelogTsPath)) { + throw new Error(`changelog.ts not found at: ${changelogTsPath}`); + } + if (!fs.existsSync(changelogMdPath)) { + throw new Error(`CHANGELOG.md not found at: ${changelogMdPath}`); + } + + console.log('šŸ“‹ Syncing UI component changelogs...\n'); + + // Get last synced version + const lastVersion = getLastSyncedVersion(changelogTsPath); + console.log(`Last synced version: ${lastVersion || '(none)'}`); + + // Get valid components + const validComponents = getValidComponents(changelogTsPath); + console.log(`Valid components: ${validComponents.length}`); + + // Parse CHANGELOG.md + console.log('\nšŸ“– Parsing CHANGELOG.md...'); + const allEntries = await parseChangelogMd( + changelogMdPath, + lastVersion, + validComponents, + ); + console.log(`Found ${allEntries.length} total entries since ${lastVersion}`); + + // Read existing changelog content for duplicate detection + const existingContent = fs.readFileSync(changelogTsPath, 'utf-8'); + + // Filter to only new, non-duplicate entries + const relevantEntries = allEntries.filter(e => { + const hasComponents = e.components.length > 0 || e.components.length === 0; + const notDuplicate = !isDuplicate(e, existingContent); + return hasComponents && notDuplicate; + }); + + const duplicatesCount = allEntries.length - relevantEntries.length; + if (duplicatesCount > 0) { + console.log(`Skipped ${duplicatesCount} duplicate entries`); + } + + console.log( + `Relevant entries (with or without components): ${relevantEntries.length}`, + ); + + if (relevantEntries.length === 0) { + console.log('\nāœ… No new entries to sync'); + return; + } + + // Fetch PR numbers for new entries (lazy fetch - only for entries that will be written) + await fetchPRNumbers(relevantEntries, dryRun); + + // Show summary + console.log('\nšŸ“ New entries by component:'); + const byComponent = {}; + relevantEntries.forEach(entry => { + if (entry.components.length === 0) { + byComponent['(general)'] = (byComponent['(general)'] || 0) + 1; + } else { + entry.components.forEach(comp => { + byComponent[comp] = (byComponent[comp] || 0) + 1; + }); + } + }); + Object.entries(byComponent).forEach(([comp, count]) => { + console.log(` - ${comp}: ${count} ${count === 1 ? 'entry' : 'entries'}`); + }); + + // Warn about unknown components + const unknownComponents = []; + allEntries.forEach(entry => { + const fullText = entry.description; + const componentMatch = fullText.match( + /Affected components?:[ \t]*([^\n]+)/i, + ); + if (componentMatch) { + const names = componentMatch[1].split(',').map(n => n.trim()); + names.forEach(name => { + if (!mapComponentName(name, validComponents)) { + unknownComponents.push(name); + } + }); + } + }); + + if (unknownComponents.length > 0) { + console.log('\nāš ļø Unknown components (skipped):'); + [...new Set(unknownComponents)].forEach(name => { + console.log(` - ${name}`); + }); + } + + // Create changelogs directory if it doesn't exist + const changelogsDir = path.join(__dirname, '../src/utils/changelogs'); + if (!fs.existsSync(changelogsDir) && !dryRun) { + fs.mkdirSync(changelogsDir, { recursive: true }); + } + + // Generate version files + console.log( + `\n${ + dryRun ? 'šŸ” Dry run - would generate' : 'āœļø Generating' + } version files...`, + ); + + const versionFiles = await generateVersionFiles( + relevantEntries, + changelogsDir, + dryRun, + ); + + // Generate main changelog.ts + const mainContent = await generateMainChangelog( + versionFiles, + changelogTsPath, + dryRun, + ); + + if (!dryRun) { + console.log('\nāœ… Changelog sync complete!'); + const newFiles = versionFiles.filter(vf => !vf.skipped).length; + const skippedFiles = versionFiles.filter(vf => vf.skipped).length; + if (newFiles > 0) { + console.log( + ` Generated ${newFiles} new version file${newFiles === 1 ? '' : 's'}`, + ); + } + if (skippedFiles > 0) { + console.log( + ` Preserved ${skippedFiles} existing version file${ + skippedFiles === 1 ? '' : 's' + }`, + ); + } + console.log(` Updated ${changelogTsPath}`); + } else { + console.log('\nšŸ“„ Sample version file content:\n'); + // Find first non-skipped version file for sample + const sampleFile = versionFiles.find(vf => !vf.skipped && vf.content); + if (sampleFile) { + const sample = sampleFile.content.split('\n').slice(0, 30).join('\n'); + console.log(sample); + console.log('...\n'); + } else { + console.log('(No new version files to generate)\n'); + } + + console.log('\nšŸ“„ Main changelog.ts content:\n'); + console.log(mainContent); + + const newFiles = versionFiles.filter(vf => !vf.skipped).length; + const skippedFiles = versionFiles.filter(vf => vf.skipped).length; + + console.log('\nāœ… Dry run complete - no files were modified'); + if (newFiles > 0) { + console.log( + ` Run without --dry-run to generate ${newFiles} new version file${ + newFiles === 1 ? '' : 's' + }`, + ); + } + if (skippedFiles > 0) { + console.log( + ` ${skippedFiles} existing version file${ + skippedFiles === 1 ? '' : 's' + } will be preserved`, + ); + } + } +} + +// Run main if executed directly +if (import.meta.url === `file://${process.argv[1]}`) { + main().catch(error => { + console.error('āŒ Error:', error.message); + process.exit(1); + }); +} diff --git a/docs-ui/src/components/Changelog/index.tsx b/docs-ui/src/components/Changelog/index.tsx index 224e23d668..d7a547b901 100644 --- a/docs-ui/src/components/Changelog/index.tsx +++ b/docs-ui/src/components/Changelog/index.tsx @@ -52,14 +52,15 @@ export function Changelog() { ${bumpEntries .map(e => { const prs = - e.prs.length > 0 && - e.prs - .map( - pr => - `[#${pr}](https://github.com/backstage/backstage/pull/${pr})`, - ) - .join(', '); - return `- ${e.description} ${prs}`; + e.prs.length > 0 + ? e.prs + .map( + pr => + `[#${pr}](https://github.com/backstage/backstage/pull/${pr})`, + ) + .join(', ') + : ''; + return `- ${e.description}${prs ? ` ${prs}` : ''}`; }) .join('\n')}`; }) diff --git a/docs-ui/src/components/ChangelogComponent/index.tsx b/docs-ui/src/components/ChangelogComponent/index.tsx index f8832b0731..ff86433268 100644 --- a/docs-ui/src/components/ChangelogComponent/index.tsx +++ b/docs-ui/src/components/ChangelogComponent/index.tsx @@ -17,14 +17,17 @@ export const ChangelogComponent = ({ component }: { component: Component }) => { ${componentChangelog ?.map(change => { const prs = - change.prs.length > 0 && - change.prs - .map( - pr => - `[#${pr}](https://github.com/backstage/backstage/pull/${pr})`, - ) - .join(', '); - return `- \`${change.version}\` - ${change.description} ${prs}`; + change.prs.length > 0 + ? change.prs + .map( + pr => + `[#${pr}](https://github.com/backstage/backstage/pull/${pr})`, + ) + .join(', ') + : ''; + return `- \`${change.version}\` - ${change.description}${ + prs ? ` ${prs}` : '' + }`; }) .join('\n')}`} /> diff --git a/docs-ui/src/components/Theming/index.tsx b/docs-ui/src/components/Theming/index.tsx index fb669253a2..d06f51348b 100644 --- a/docs-ui/src/components/Theming/index.tsx +++ b/docs-ui/src/components/Theming/index.tsx @@ -1,18 +1,13 @@ import { MDXRemote } from 'next-mdx-remote-client/rsc'; import { formattedMDXComponents } from '@/mdx-components'; -import { Component } from '@/utils/changelog'; -import { componentDefinitions } from '../../../../packages/ui/src/utils/componentDefinitions'; -import type { DataAttributeValues } from '../../../../packages/ui/src/types'; +import type { + ComponentDefinition, + DataAttributeValues, +} from '../../../../packages/ui/src/types'; -export function Theming({ component }: { component: Component }) { - const componentDefinition = componentDefinitions[component]; - - if (!componentDefinition) { - return null; - } - - const classNames = componentDefinition.classNames; - const dataAttributes = componentDefinition.dataAttributes; +export function Theming({ definition }: { definition: ComponentDefinition }) { + const classNames = definition.classNames; + const dataAttributes = definition.dataAttributes; // Get the first class name const firstClassName = Object.values(classNames)[0]; diff --git a/docs-ui/src/content/accordion.mdx b/docs-ui/src/content/accordion.mdx index 2694f8d144..fc4bad1f8e 100644 --- a/docs-ui/src/content/accordion.mdx +++ b/docs-ui/src/content/accordion.mdx @@ -16,6 +16,7 @@ import { } from './accordion.props'; import { PageTitle } from '@/components/PageTitle'; import { Theming } from '@/components/Theming'; +import { AccordionDefinition } from '../utils/definitions'; import { ChangelogComponent } from '@/components/ChangelogComponent'; - + diff --git a/docs-ui/src/content/avatar.mdx b/docs-ui/src/content/avatar.mdx index 6e0b550101..047485c2cc 100644 --- a/docs-ui/src/content/avatar.mdx +++ b/docs-ui/src/content/avatar.mdx @@ -11,6 +11,7 @@ import { } from './avatar.props'; import { PageTitle } from '@/components/PageTitle'; import { Theming } from '@/components/Theming'; +import { AvatarDefinition } from '../utils/definitions'; import { ChangelogComponent } from '@/components/ChangelogComponent'; - + diff --git a/docs-ui/src/content/box.mdx b/docs-ui/src/content/box.mdx index d1a9dd43fe..66e99ec19a 100644 --- a/docs-ui/src/content/box.mdx +++ b/docs-ui/src/content/box.mdx @@ -12,6 +12,7 @@ import { import { spacingPropDefs } from '@/utils/propDefs'; import { PageTitle } from '@/components/PageTitle'; import { Theming } from '@/components/Theming'; +import { BoxDefinition } from '../utils/definitions'; import { ChangelogComponent } from '@/components/ChangelogComponent'; - + diff --git a/docs-ui/src/content/button-icon.mdx b/docs-ui/src/content/button-icon.mdx index fbc0c8c54c..b0595cc9bc 100644 --- a/docs-ui/src/content/button-icon.mdx +++ b/docs-ui/src/content/button-icon.mdx @@ -15,6 +15,7 @@ import { } from './button-icon.props'; import { PageTitle } from '@/components/PageTitle'; import { Theming } from '@/components/Theming'; +import { ButtonIconDefinition } from '../utils/definitions'; import { ChangelogComponent } from '@/components/ChangelogComponent'; - + diff --git a/docs-ui/src/content/button-link.mdx b/docs-ui/src/content/button-link.mdx index 5ce538838d..4f3f376aee 100644 --- a/docs-ui/src/content/button-link.mdx +++ b/docs-ui/src/content/button-link.mdx @@ -13,6 +13,7 @@ import { } from './button-link.props'; import { PageTitle } from '@/components/PageTitle'; import { Theming } from '@/components/Theming'; +import { ButtonLinkDefinition } from '../utils/definitions'; import { ChangelogComponent } from '@/components/ChangelogComponent'; - + diff --git a/docs-ui/src/content/button.mdx b/docs-ui/src/content/button.mdx index b60f32ff07..d161c97edf 100644 --- a/docs-ui/src/content/button.mdx +++ b/docs-ui/src/content/button.mdx @@ -16,6 +16,7 @@ import { import { ChangelogComponent } from '@/components/ChangelogComponent'; import { PageTitle } from '@/components/PageTitle'; import { Theming } from '@/components/Theming'; +import { ButtonDefinition } from '../utils/definitions'; - + diff --git a/docs-ui/src/content/card.mdx b/docs-ui/src/content/card.mdx index 06c3a5bc2e..c38a07e920 100644 --- a/docs-ui/src/content/card.mdx +++ b/docs-ui/src/content/card.mdx @@ -14,6 +14,7 @@ import { } from './card.props'; import { PageTitle } from '@/components/PageTitle'; import { Theming } from '@/components/Theming'; +import { CardDefinition } from '../utils/definitions'; import { ChangelogComponent } from '@/components/ChangelogComponent'; - + diff --git a/docs-ui/src/content/checkbox.mdx b/docs-ui/src/content/checkbox.mdx index 5770396ebb..c574e8fed4 100644 --- a/docs-ui/src/content/checkbox.mdx +++ b/docs-ui/src/content/checkbox.mdx @@ -10,6 +10,7 @@ import { } from './checkbox.props'; import { PageTitle } from '@/components/PageTitle'; import { Theming } from '@/components/Theming'; +import { CheckboxDefinition } from '../utils/definitions'; import { ChangelogComponent } from '@/components/ChangelogComponent'; - + diff --git a/docs-ui/src/content/container.mdx b/docs-ui/src/content/container.mdx index 05615cb1c2..56c2d5d405 100644 --- a/docs-ui/src/content/container.mdx +++ b/docs-ui/src/content/container.mdx @@ -11,6 +11,7 @@ import { } from './container.props'; import { PageTitle } from '@/components/PageTitle'; import { Theming } from '@/components/Theming'; +import { ContainerDefinition } from '../utils/definitions'; import { ChangelogComponent } from '@/components/ChangelogComponent'; - + diff --git a/docs-ui/src/content/dialog.mdx b/docs-ui/src/content/dialog.mdx index 4aa43c69de..e1e4ec436e 100644 --- a/docs-ui/src/content/dialog.mdx +++ b/docs-ui/src/content/dialog.mdx @@ -18,6 +18,7 @@ import { } from './dialog.props'; import { PageTitle } from '@/components/PageTitle'; import { Theming } from '@/components/Theming'; +import { DialogDefinition } from '../utils/definitions'; import { ChangelogComponent } from '@/components/ChangelogComponent'; - + diff --git a/docs-ui/src/content/flex.mdx b/docs-ui/src/content/flex.mdx index 89cd2e380a..36284f1f0b 100644 --- a/docs-ui/src/content/flex.mdx +++ b/docs-ui/src/content/flex.mdx @@ -14,6 +14,7 @@ import { import { spacingPropDefs } from '@/utils/propDefs'; import { PageTitle } from '@/components/PageTitle'; import { Theming } from '@/components/Theming'; +import { FlexDefinition } from '../utils/definitions'; import { ChangelogComponent } from '@/components/ChangelogComponent'; - + diff --git a/docs-ui/src/content/grid.mdx b/docs-ui/src/content/grid.mdx index 0ffdba6a66..5f179b9e14 100644 --- a/docs-ui/src/content/grid.mdx +++ b/docs-ui/src/content/grid.mdx @@ -16,6 +16,7 @@ import { } from './grid.props'; import { PageTitle } from '@/components/PageTitle'; import { Theming } from '@/components/Theming'; +import { GridDefinition } from '../utils/definitions'; import { ChangelogComponent } from '@/components/ChangelogComponent'; - + diff --git a/docs-ui/src/content/header-page.mdx b/docs-ui/src/content/header-page.mdx index d3f93058ee..12ef2c32ee 100644 --- a/docs-ui/src/content/header-page.mdx +++ b/docs-ui/src/content/header-page.mdx @@ -14,6 +14,7 @@ import { } from './header-page.props'; import { PageTitle } from '@/components/PageTitle'; import { Theming } from '@/components/Theming'; +import { HeaderPageDefinition } from '../utils/definitions'; import { ChangelogComponent } from '@/components/ChangelogComponent'; - + diff --git a/docs-ui/src/content/header.mdx b/docs-ui/src/content/header.mdx index af4e8010c5..eb505d7a62 100644 --- a/docs-ui/src/content/header.mdx +++ b/docs-ui/src/content/header.mdx @@ -13,6 +13,7 @@ import { } from './header.props'; import { PageTitle } from '@/components/PageTitle'; import { Theming } from '@/components/Theming'; +import { HeaderDefinition } from '../utils/definitions'; import { ChangelogComponent } from '@/components/ChangelogComponent'; - + diff --git a/docs-ui/src/content/link.mdx b/docs-ui/src/content/link.mdx index e0c1be353f..486c06b298 100644 --- a/docs-ui/src/content/link.mdx +++ b/docs-ui/src/content/link.mdx @@ -19,6 +19,7 @@ import { import { PageTitle } from '@/components/PageTitle'; import { Theming } from '@/components/Theming'; import { ChangelogComponent } from '@/components/ChangelogComponent'; +import { LinkDefinition } from '../utils/definitions'; - + diff --git a/docs-ui/src/content/menu.mdx b/docs-ui/src/content/menu.mdx index 743d884809..9ede0885e2 100644 --- a/docs-ui/src/content/menu.mdx +++ b/docs-ui/src/content/menu.mdx @@ -27,6 +27,7 @@ import { import { PageTitle } from '@/components/PageTitle'; import { Theming } from '@/components/Theming'; import { ChangelogComponent } from '@/components/ChangelogComponent'; +import { MenuDefinition } from '../utils/definitions'; - + diff --git a/docs-ui/src/content/password-field.mdx b/docs-ui/src/content/password-field.mdx index 14fbc9e34d..8dda2b4f2a 100644 --- a/docs-ui/src/content/password-field.mdx +++ b/docs-ui/src/content/password-field.mdx @@ -12,6 +12,7 @@ import { PageTitle } from '@/components/PageTitle'; import { Theming } from '@/components/Theming'; import { ChangelogComponent } from '@/components/ChangelogComponent'; import { CodeBlock } from '@/components/CodeBlock'; +import { PasswordFieldDefinition } from '../utils/definitions'; - + diff --git a/docs-ui/src/content/radio-group.mdx b/docs-ui/src/content/radio-group.mdx index ab3d28ad81..ba9352c026 100644 --- a/docs-ui/src/content/radio-group.mdx +++ b/docs-ui/src/content/radio-group.mdx @@ -16,6 +16,7 @@ import { PageTitle } from '@/components/PageTitle'; import { Theming } from '@/components/Theming'; import { ChangelogComponent } from '@/components/ChangelogComponent'; import { CodeBlock } from '@/components/CodeBlock'; +import { RadioGroupDefinition } from '../utils/definitions'; - + diff --git a/docs-ui/src/content/search-field.mdx b/docs-ui/src/content/search-field.mdx index 2a2d93f262..6b33feea42 100644 --- a/docs-ui/src/content/search-field.mdx +++ b/docs-ui/src/content/search-field.mdx @@ -13,6 +13,7 @@ import { PageTitle } from '@/components/PageTitle'; import { Theming } from '@/components/Theming'; import { ChangelogComponent } from '@/components/ChangelogComponent'; import { CodeBlock } from '@/components/CodeBlock'; +import { SearchFieldDefinition } from '../utils/definitions'; - + diff --git a/docs-ui/src/content/select.mdx b/docs-ui/src/content/select.mdx index eb53e9ea35..436129d749 100644 --- a/docs-ui/src/content/select.mdx +++ b/docs-ui/src/content/select.mdx @@ -18,6 +18,7 @@ import { import { PageTitle } from '@/components/PageTitle'; import { Theming } from '@/components/Theming'; import { ChangelogComponent } from '@/components/ChangelogComponent'; +import { SelectDefinition } from '../utils/definitions'; - + diff --git a/docs-ui/src/content/skeleton.mdx b/docs-ui/src/content/skeleton.mdx index f0d3fbc39a..07cd4b3332 100644 --- a/docs-ui/src/content/skeleton.mdx +++ b/docs-ui/src/content/skeleton.mdx @@ -12,6 +12,7 @@ import { import { PageTitle } from '@/components/PageTitle'; import { Theming } from '@/components/Theming'; import { ChangelogComponent } from '@/components/ChangelogComponent'; +import { SkeletonDefinition } from '../utils/definitions'; - + diff --git a/docs-ui/src/content/switch.mdx b/docs-ui/src/content/switch.mdx index acf588e37d..965cc7832b 100644 --- a/docs-ui/src/content/switch.mdx +++ b/docs-ui/src/content/switch.mdx @@ -6,6 +6,7 @@ import { switchPropDefs, snippetUsage } from './switch.props'; import { PageTitle } from '@/components/PageTitle'; import { Theming } from '@/components/Theming'; import { ChangelogComponent } from '@/components/ChangelogComponent'; +import { SwitchDefinition } from '../utils/definitions'; `} /> - + diff --git a/docs-ui/src/content/table.mdx b/docs-ui/src/content/table.mdx index 4ea5fd1677..d1a190e9dd 100644 --- a/docs-ui/src/content/table.mdx +++ b/docs-ui/src/content/table.mdx @@ -22,6 +22,7 @@ import { import { ChangelogComponent } from '@/components/ChangelogComponent'; import { PageTitle } from '@/components/PageTitle'; import { Theming } from '@/components/Theming'; +import { TableDefinition } from '../utils/definitions'; + diff --git a/docs-ui/src/content/tabs.mdx b/docs-ui/src/content/tabs.mdx index 26905d4733..1fc7448eba 100644 --- a/docs-ui/src/content/tabs.mdx +++ b/docs-ui/src/content/tabs.mdx @@ -13,6 +13,7 @@ import { } from './tabs.props'; import { PageTitle } from '@/components/PageTitle'; import { Theming } from '@/components/Theming'; +import { TabsDefinition } from '../utils/definitions'; import { ChangelogComponent } from '@/components/ChangelogComponent'; - + diff --git a/docs-ui/src/content/tag-group.mdx b/docs-ui/src/content/tag-group.mdx index 8d7fb3c3d0..88e60b31f5 100644 --- a/docs-ui/src/content/tag-group.mdx +++ b/docs-ui/src/content/tag-group.mdx @@ -15,6 +15,7 @@ import { } from './tag-group.props'; import { PageTitle } from '@/components/PageTitle'; import { Theming } from '@/components/Theming'; +import { TagGroupDefinition } from '../utils/definitions'; import { ChangelogComponent } from '@/components/ChangelogComponent'; - + diff --git a/docs-ui/src/content/text-field.mdx b/docs-ui/src/content/text-field.mdx index ad90783ffb..9f14a82975 100644 --- a/docs-ui/src/content/text-field.mdx +++ b/docs-ui/src/content/text-field.mdx @@ -10,6 +10,7 @@ import { } from './text-field.props'; import { PageTitle } from '@/components/PageTitle'; import { Theming } from '@/components/Theming'; +import { TextFieldDefinition } from '../utils/definitions'; import { ChangelogComponent } from '@/components/ChangelogComponent'; import { CodeBlock } from '@/components/CodeBlock'; @@ -59,6 +60,6 @@ Here's a simple TextField with a description. code={textFieldDescriptionSnippet} /> - + diff --git a/docs-ui/src/content/text.mdx b/docs-ui/src/content/text.mdx index 48b461aa8c..c987b8e5f7 100644 --- a/docs-ui/src/content/text.mdx +++ b/docs-ui/src/content/text.mdx @@ -14,6 +14,7 @@ import { } from './text.props'; import { PageTitle } from '@/components/PageTitle'; import { Theming } from '@/components/Theming'; +import { TextDefinition } from '../utils/definitions'; import { ChangelogComponent } from '@/components/ChangelogComponent'; - + diff --git a/docs-ui/src/content/tooltip.mdx b/docs-ui/src/content/tooltip.mdx index dd2add5308..8ebf6539d6 100644 --- a/docs-ui/src/content/tooltip.mdx +++ b/docs-ui/src/content/tooltip.mdx @@ -10,6 +10,7 @@ import { } from './tooltip.props'; import { PageTitle } from '@/components/PageTitle'; import { Theming } from '@/components/Theming'; +import { TooltipDefinition } from '../utils/definitions'; import { ChangelogComponent } from '@/components/ChangelogComponent'; - + diff --git a/docs-ui/src/content/visually-hidden.mdx b/docs-ui/src/content/visually-hidden.mdx index 26a609b245..72ffc7a1d4 100644 --- a/docs-ui/src/content/visually-hidden.mdx +++ b/docs-ui/src/content/visually-hidden.mdx @@ -10,6 +10,7 @@ import { } from './visually-hidden.props'; import { PageTitle } from '@/components/PageTitle'; import { Theming } from '@/components/Theming'; +import { VisuallyHiddenDefinition } from '../utils/definitions'; import { ChangelogComponent } from '@/components/ChangelogComponent'; - + diff --git a/docs-ui/src/utils/changelog.ts b/docs-ui/src/utils/changelog.ts index 05a06fdb9f..1179d7e189 100644 --- a/docs-ui/src/utils/changelog.ts +++ b/docs-ui/src/utils/changelog.ts @@ -1,538 +1,30 @@ -export type Component = - | 'avatar' - | 'box' - | 'button' - | 'button-link' - | 'heading' - | 'text' - | 'button-icon' - | 'icon' - | 'tabs' - | 'menu' - | 'textfield' - | 'datatable' - | 'select' - | 'collapsible' - | 'accordion' - | 'checkbox' - | 'container' - | 'link' - | 'tooltip' - | 'scrollarea' - | 'flex' - | 'switch' - | 'grid' - | 'searchfield' - | 'radio-group' - | 'card' - | 'skeleton' - | 'header' - | 'passwordfield'; +export * from './types'; +import { changelog_0_8_2 } from './changelogs/v0.8.2'; +import { changelog_0_8_0 } from './changelogs/v0.8.0'; +import { changelog_0_7_2 } from './changelogs/v0.7.2'; +import { changelog_0_7_1 } from './changelogs/v0.7.1'; +import { changelog_0_7_0 } from './changelogs/v0.7.0'; +import { changelog_0_6_0 } from './changelogs/v0.6.0'; +import { changelog_0_5_0 } from './changelogs/v0.5.0'; +import { changelog_0_4_0 } from './changelogs/v0.4.0'; +import { changelog_0_3_2 } from './changelogs/v0.3.2'; +import { changelog_0_3_0 } from './changelogs/v0.3.0'; +import { changelog_0_2_1 } from './changelogs/v0.2.1'; +import { changelog_0_2_0 } from './changelogs/v0.2.0'; +import { changelog_0_1_0 } from './changelogs/v0.1.0'; -export type Version = `${number}.${number}.${number}`; - -export interface ChangelogProps { - components: Component[]; - description: string; - version: Version; - prs: string[]; - type?: 'breaking' | 'new' | 'fix'; -} - -export const changelog: ChangelogProps[] = [ - { - components: ['tooltip'], - version: '0.6.0', - description: 'New `Tooltip` component.', - prs: ['30461'], - type: 'new', - }, - { - components: ['card'], - version: '0.6.0', - description: 'New `Card` component.', - prs: ['30467'], - type: 'new', - }, - { - components: ['header'], - version: '0.6.0', - description: 'New `Header` component.', - prs: ['30410', '30459', '30493'], - type: 'new', - }, - { - components: ['button', 'button-link', 'button-icon'], - version: '0.6.0', - description: 'Improve `Button`, `ButtonIcon` and `ButtonLink` styling.', - prs: ['30448'], - type: 'fix', - }, - { - components: ['text', 'heading'], - version: '0.6.0', - description: - 'Update return types for `Heading` & `Text` components for React 19.', - prs: ['30440'], - type: 'fix', - }, - { - components: ['button', 'button-link', 'button-icon'], - version: '0.6.0', - description: - 'New `tertiary` variant to `Button`, `ButtonIcon` and `ButtonLink`.', - prs: ['30453'], - type: 'new', - }, - { - components: ['skeleton'], - version: '0.6.0', - description: 'New `Skeleton` component.', - prs: ['30466'], - type: 'new', - }, - { - components: ['button-icon'], - version: '0.6.0', - description: 'Rename `IconButton` to `ButtonIcon`.', - prs: ['30297'], - type: 'breaking', - }, - { - components: ['button-link'], - version: '0.6.0', - description: - 'New `ButtonLink`, which replaces the previous render prop pattern on `Button` and `IconButton`.', - prs: ['30297'], - type: 'new', - }, - { - components: ['button', 'button-link', 'button-icon'], - version: '0.6.0', - description: 'Remove the `render` prop from all button-related components.', - prs: ['30297'], - type: 'breaking', - }, - { - components: [], - version: '0.6.0', - description: 'We are consolidating all css files into a single styles.css.', - prs: ['30325'], - type: 'fix', - }, - { - components: ['searchfield'], - version: '0.6.0', - description: 'New `SearchField` component.', - prs: ['30357'], - type: 'new', - }, - { - components: ['radio-group'], - version: '0.6.0', - description: 'New `RadioGroup` + `Radio` component.', - prs: ['30327'], - type: 'new', - }, - { - components: ['textfield'], - version: '0.6.0', - description: 'Added placeholder prop back to `TextField` component.', - prs: ['30286'], - type: 'fix', - }, - { - components: ['textfield'], - version: '0.5.0', - description: '`TextField` now has multiple label sizes.', - prs: ['30249'], - type: 'breaking', - }, - { - components: ['textfield'], - version: '0.5.0', - description: - '`TextField` can now hide label and description while keeping them available for screen readers.', - prs: ['30249'], - type: 'breaking', - }, - { - components: ['textfield'], - version: '0.5.0', - description: - 'We are removing the `render` prop in favour of the `as` prop on `Heading` and `Text`.', - prs: ['30291'], - type: 'breaking', - }, - { - components: ['textfield'], - version: '0.5.0', - description: 'Move `TextField` component to use react Aria under the hood.', - prs: ['30286'], - type: 'breaking', - }, - { - components: ['button', 'button-link'], - version: '0.5.0', - description: - 'Added a render prop to the `Button` component to use it as a link.', - prs: ['30165'], - type: 'new', - }, - { - components: ['heading'], - version: '0.5.0', - description: 'Fix styling for the title4 prop on the Heading component.', - prs: ['30167'], - type: 'fix', - }, - { - components: ['flex'], - version: '0.5.0', - description: - 'Add `min-width: 0;` by default on Flex components to support truncated text.', - prs: ['30168'], - type: 'fix', - }, - { - components: ['button', 'button-link', 'button-icon'], - version: '0.5.0', - description: - '`Button`, `ButtonLink`, `ButtonIcon` now default to size `small` instead of `medium`', - prs: ['30085', '30097'], - type: 'breaking', - }, - { - components: ['grid'], - version: '0.5.0', - description: 'Rename Grid component to ``', - prs: ['30013'], - type: 'breaking', - }, - { - components: ['flex', 'container', 'grid', 'box'], - version: '0.5.0', - description: 'Fixes spacing props on layout components', - prs: ['30013'], - type: 'fix', - }, - { - components: ['switch'], - version: '0.5.0', - description: 'New `Switch` component', - prs: ['30251'], - type: 'new', - }, - { - components: ['tabs'], - version: '0.4.0', - description: 'New `Tabs` component', - prs: ['29996'], - type: 'new', - }, - { - components: ['text', 'heading'], - version: '0.4.0', - description: 'Add `truncate` prop to `Text` and `Heading`', - prs: ['29988'], - type: 'new', - }, - { - components: ['menu'], - version: '0.4.0', - description: 'Add combobox option to `Menu`', - prs: ['29986'], - type: 'new', - }, - { - components: ['textfield'], - version: '0.4.0', - description: 'Add icon prop on `TextField`', - prs: ['29820'], - type: 'new', - }, - { - components: ['button', 'button-icon'], - version: '0.4.0', - description: 'Improve icon props on `Button` and `IconButton`', - prs: ['29667'], - }, - { - components: ['text', 'heading'], - version: '0.4.0', - description: - 'Improve the way we treat custom render on `Text` and `Heading`', - prs: ['29989'], - }, - { - components: ['menu'], - version: '0.4.0', - description: 'Improve `Menu` styles', - prs: ['29986'], - }, - { - components: ['textfield'], - version: '0.4.0', - description: 'Improve `TextField` styles', - prs: ['29974'], - }, - { - components: ['textfield'], - version: '0.4.0', - description: 'Improve clear button on `TextField`', - prs: ['29878'], - }, - { - components: ['flex'], - version: '0.4.0', - description: 'Fix spacing props on all layout components', - prs: ['30013'], - }, - { - components: [], - version: '0.4.0', - description: 'Fix - Pin Base UI version', - prs: ['29782'], - }, - { - components: ['select'], - version: '0.4.0', - description: 'Fix - Clicking `Select` label moves focus to trigger', - prs: ['29755'], - }, - { - components: ['datatable'], - version: '0.4.0', - description: 'Fix `DataTable.Pagination` count issue', - prs: ['29688'], - }, - { - components: ['datatable'], - version: '0.3.0', - description: 'Add `DataTable` component', - prs: ['29484', '29603'], - type: 'new', - }, - { - components: ['select'], - version: '0.3.0', - description: 'Add `Select` component', - prs: ['29440'], - type: 'new', - }, - { - components: ['avatar'], - version: '0.3.0', - description: 'Add `Avatar` component', - prs: ['29594'], - type: 'new', - }, - { - components: ['collapsible'], - version: '0.3.0', - description: 'Add `Collapsible` component', - prs: ['29617'], - type: 'new', - }, - { - components: ['textfield'], - version: '0.3.0', - description: 'Add `TextField` component instead of `Field` + `Input`', - prs: ['29364'], - type: 'new', - }, - { - components: ['datatable'], - version: '0.3.0', - description: 'Add `TableCellProfile`', - prs: ['29600'], - type: 'new', - }, - { - components: [], - version: '0.3.0', - description: 'Add breakpoint hooks - `up()` and `down()`', - prs: ['29564'], - type: 'new', - }, - { - components: [], - version: '0.3.0', - description: 'Add gray scale css tokens', - prs: ['29543'], - type: 'new', - }, - { - components: [], - version: '0.3.0', - description: - 'Update CSS styling API using `[data-___]` instead of class names for props', - prs: ['29560'], - }, - { - components: ['checkbox'], - version: '0.3.0', - description: 'Update `Checkbox` dark mode', - prs: ['29544'], - }, - { - components: ['container'], - version: '0.3.0', - description: 'Update `Container` styles', - prs: ['29475'], - }, - { - components: ['menu'], - version: '0.3.0', - description: 'Update `Menu` styles', - prs: ['29351'], - }, - { - components: ['select'], - version: '0.3.0', - description: 'Fix `Select` styles on small sizes + with long option names', - prs: ['29545'], - }, - { - components: ['link'], - version: '0.3.0', - description: 'Fix render prop on `Link`', - prs: ['29247'], - }, - { - components: ['textfield', 'select'], - version: '0.3.0', - description: 'Remove `Field` from `TextField` + `Select`', - prs: ['29482'], - }, - { - components: ['text', 'heading'], - version: '0.3.0', - description: 'Update `textDecoration` to `none` on `Text` / `Heading`', - prs: ['29357'], - }, - { - components: ['text', 'heading'], - version: '0.3.0', - description: 'Update `textDecoration` to `none` on `Text` / `Heading`', - prs: ['29357'], - }, - { - components: [], - version: '0.3.0', - description: 'Docs - Use stories from Storybook for all examples in Nextjs', - prs: ['29306'], - }, - { - components: [], - version: '0.3.0', - description: 'Docs - Add release page (this one šŸ¤—)', - prs: ['29461'], - }, - { - components: [], - version: '0.3.0', - description: 'Docs - Add docs for Menu, Link', - prs: ['29576'], - }, - { - components: [], - version: '0.3.0', - description: 'Fix CSS watch mode', - prs: ['29352'], - }, - { - components: ['menu'], - version: '0.2.0', - description: 'New `Menu` component', - prs: ['29151'], - type: 'new', - }, - { - components: ['button-icon'], - version: '0.2.0', - description: 'New `IconButton` component', - prs: ['29239'], - type: 'new', - }, - { - components: ['scrollarea'], - version: '0.2.0', - description: 'New `ScrollArea` component', - prs: ['29240'], - type: 'new', - }, - { - components: ['button', 'checkbox'], - version: '0.2.0', - description: 'Improve `Button` & `Checkbox` styles', - prs: ['29127', '28789'], - }, - { - components: ['text'], - version: '0.2.0', - description: 'Improve `Text` styles', - prs: ['29200'], - }, - { - components: ['icon'], - version: '0.2.0', - description: 'Renamed `CanonProvider` to `IconProvider`', - prs: ['29002'], - }, - { - components: ['icon'], - version: '0.2.0', - description: 'Added about 40+ new icons', - prs: ['29264'], - }, - { - components: [], - version: '0.2.0', - description: 'Simplified styling into a unique styles.css file', - prs: ['29199'], - }, - { - components: [], - version: '0.2.0', - description: 'Added global styles to Backstage', - prs: ['29137'], - type: 'new', - }, - { - components: [], - version: '0.2.0', - description: 'Update global CSS tokens', - prs: ['28804'], - }, - { - components: ['flex'], - version: '0.2.0', - description: 'Merge Stack + Inline into Flex', - prs: ['28634'], - }, - { - components: ['button'], - version: '0.2.0', - description: 'Improve `Button` types', - prs: ['29205'], - }, - { - components: [], - version: '0.2.0', - description: 'Move font weight and family back to each components', - prs: ['28972'], - }, - { - components: [], - version: '0.2.0', - description: 'Fix custom values in spacing props', - prs: ['28770'], - }, - { - components: [], - version: '0.2.0', - description: 'Multiple updates on the docs site', - prs: ['28760'], - }, +export const changelog = [ + ...changelog_0_8_2, + ...changelog_0_8_0, + ...changelog_0_7_2, + ...changelog_0_7_1, + ...changelog_0_7_0, + ...changelog_0_6_0, + ...changelog_0_5_0, + ...changelog_0_4_0, + ...changelog_0_3_2, + ...changelog_0_3_0, + ...changelog_0_2_1, + ...changelog_0_2_0, + ...changelog_0_1_0, ]; diff --git a/docs-ui/src/utils/changelogs/v0.1.0.ts b/docs-ui/src/utils/changelogs/v0.1.0.ts new file mode 100644 index 0000000000..cf333e92e9 --- /dev/null +++ b/docs-ui/src/utils/changelogs/v0.1.0.ts @@ -0,0 +1,116 @@ +import type { ChangelogProps } from '../types'; + +export const changelog_0_1_0: ChangelogProps[] = [ + { + components: [], + version: '0.1.0', + description: `**BREAKING**: Merged the Stack and Inline component into a single component called Flex.`, + prs: ['28634'], + type: 'breaking', + commitSha: '72c9800', + }, + { + components: [], + version: '0.1.0', + description: `This is the first alpha release for Canon. As part of this release we are introducing 5 layout components and 7 components. All theming is done through CSS variables.`, + prs: ['28562'], + type: 'breaking', + commitSha: '65f4acc', + }, + { + components: [], + version: '0.1.0', + description: `**BREAKING**: Fixing css structure and making sure that props are applying the correct styles for all responsive values.`, + prs: ['28630'], + type: 'breaking', + commitSha: '1e4ccce', + }, + { + components: [], + version: '0.1.0', + description: `Updated core CSS tokens and fixing the Button component accordingly.`, + prs: ['28789'], + type: 'breaking', + commitSha: '8309bdb', + }, + { + components: [], + version: '0.1.0', + description: `Removed client directive as they are not needed in React 18.`, + prs: ['28626'], + type: 'fix', + commitSha: '989af25', + }, + { + components: [], + version: '0.1.0', + description: `Fix spacing props not being applied for custom values.`, + prs: ['28770'], + type: 'fix', + commitSha: 'f44e5cf', + }, + { + components: [], + version: '0.1.0', + description: `Removed older versions of React packages as a preparatory step for upgrading to React 19. This commit does not introduce any functional changes, but removes dependencies on previous React versions, allowing for a cleaner upgrade path in subsequent commits.`, + prs: ['28579'], + type: 'fix', + commitSha: '58ec9e7', + }, + { + components: [], + version: '0.1.0', + description: `Updated core CSS tokens and fixing the Button component accordingly.`, + prs: ['28789'], + type: 'breaking', + commitSha: '8309bdb', + }, + { + components: [], + version: '0.1.0', + description: `Fix spacing props not being applied for custom values.`, + prs: ['28770'], + type: 'fix', + commitSha: 'f44e5cf', + }, + { + components: [], + version: '0.1.0', + description: `**BREAKING**: Merged the Stack and Inline component into a single component called Flex.`, + prs: ['28634'], + type: 'breaking', + commitSha: '72c9800', + }, + { + components: [], + version: '0.1.0', + description: `**BREAKING**: Fixing css structure and making sure that props are applying the correct styles for all responsive values.`, + prs: ['28630'], + type: 'breaking', + commitSha: '1e4ccce', + }, + { + components: [], + version: '0.1.0', + description: `Removed client directive as they are not needed in React 18.`, + prs: ['28626'], + type: 'fix', + commitSha: '989af25', + }, + { + components: [], + version: '0.1.0', + description: `Removed older versions of React packages as a preparatory step for upgrading to React 19. This commit does not introduce any functional changes, but removes dependencies on previous React versions, allowing for a cleaner upgrade path in subsequent commits.`, + prs: ['28579'], + type: 'fix', + commitSha: '58ec9e7', + }, + { + components: [], + version: '0.1.0', + description: `This is the first alpha release for Canon. As part of this release we are introducing 5 layout components and 7 components. All theming is done through CSS variables.`, + prs: ['28562'], + type: 'breaking', + commitSha: '65f4acc', + }, +]; diff --git a/docs-ui/src/utils/changelogs/v0.2.0.ts b/docs-ui/src/utils/changelogs/v0.2.0.ts new file mode 100644 index 0000000000..b90cec0309 --- /dev/null +++ b/docs-ui/src/utils/changelogs/v0.2.0.ts @@ -0,0 +1,98 @@ +import type { ChangelogProps } from '../types'; + +export const changelog_0_2_0: ChangelogProps[] = [ + { + components: ['menu'], + version: '0.2.0', + description: 'New `Menu` component', + prs: ['29151'], + type: 'new', + }, + { + components: ['button-icon'], + version: '0.2.0', + description: 'New `IconButton` component', + prs: ['29239'], + type: 'new', + }, + { + components: ['scrollarea'], + version: '0.2.0', + description: 'New `ScrollArea` component', + prs: ['29240'], + type: 'new', + }, + { + components: ['button', 'checkbox'], + version: '0.2.0', + description: 'Improve `Button` & `Checkbox` styles', + prs: ['29127', '28789'], + }, + { + components: ['text'], + version: '0.2.0', + description: 'Improve `Text` styles', + prs: ['29200'], + }, + { + components: ['icon'], + version: '0.2.0', + description: 'Renamed `CanonProvider` to `IconProvider`', + prs: ['29002'], + }, + { + components: ['icon'], + version: '0.2.0', + description: 'Added about 40+ new icons', + prs: ['29264'], + }, + { + components: [], + version: '0.2.0', + description: 'Simplified styling into a unique styles.css file', + prs: ['29199'], + }, + { + components: [], + version: '0.2.0', + description: 'Added global styles to Backstage', + prs: ['29137'], + type: 'new', + }, + { + components: [], + version: '0.2.0', + description: 'Update global CSS tokens', + prs: ['28804'], + }, + { + components: ['flex'], + version: '0.2.0', + description: 'Merge Stack + Inline into Flex', + prs: ['28634'], + }, + { + components: ['button'], + version: '0.2.0', + description: 'Improve `Button` types', + prs: ['29205'], + }, + { + components: [], + version: '0.2.0', + description: 'Move font weight and family back to each components', + prs: ['28972'], + }, + { + components: [], + version: '0.2.0', + description: 'Fix custom values in spacing props', + prs: ['28770'], + }, + { + components: [], + version: '0.2.0', + description: 'Multiple updates on the docs site', + prs: ['28760'], + }, +]; diff --git a/docs-ui/src/utils/changelogs/v0.2.1.ts b/docs-ui/src/utils/changelogs/v0.2.1.ts new file mode 100644 index 0000000000..cbf0f9be0f --- /dev/null +++ b/docs-ui/src/utils/changelogs/v0.2.1.ts @@ -0,0 +1,44 @@ +import type { ChangelogProps } from '../types'; + +export const changelog_0_2_1: ChangelogProps[] = [ + { + components: [], + version: '0.2.1', + description: `Internal refactor and fixes to the prop extraction logic for layout components.`, + prs: ['29389'], + type: 'fix', + commitSha: 'f7cb538', + }, + { + components: [], + version: '0.2.1', + description: `Fix types on the Icon component.`, + prs: ['29306'], + type: 'fix', + commitSha: '5e80f0b', + }, + { + components: [], + version: '0.2.1', + description: `Updated styles for the Menu component in Canon.`, + prs: ['29351'], + type: 'fix', + commitSha: '6af7b16', + }, + { + components: [], + version: '0.2.1', + description: `Add global CSS reset for anchor tags.`, + prs: ['29357'], + type: 'new', + commitSha: '513477f', + }, + { + components: [], + version: '0.2.1', + description: `Fix the Icon component when the name is not found to return null instead of an empty SVG.`, + prs: ['29280'], + type: 'fix', + commitSha: '05a5003', + }, +]; diff --git a/docs-ui/src/utils/changelogs/v0.3.0.ts b/docs-ui/src/utils/changelogs/v0.3.0.ts new file mode 100644 index 0000000000..750ad292cf --- /dev/null +++ b/docs-ui/src/utils/changelogs/v0.3.0.ts @@ -0,0 +1,139 @@ +import type { ChangelogProps } from '../types'; + +export const changelog_0_3_0: ChangelogProps[] = [ + { + components: ['datatable'], + version: '0.3.0', + description: 'Add `DataTable` component', + prs: ['29484', '29603'], + type: 'new', + }, + { + components: ['select'], + version: '0.3.0', + description: 'Add `Select` component', + prs: ['29440'], + type: 'new', + }, + { + components: ['avatar'], + version: '0.3.0', + description: 'Add `Avatar` component', + prs: ['29594'], + type: 'new', + }, + { + components: ['collapsible'], + version: '0.3.0', + description: 'Add `Collapsible` component', + prs: ['29617'], + type: 'new', + }, + { + components: ['textfield'], + version: '0.3.0', + description: 'Add `TextField` component instead of `Field` + `Input`', + prs: ['29364'], + type: 'new', + }, + { + components: ['datatable'], + version: '0.3.0', + description: 'Add `TableCellProfile`', + prs: ['29600'], + type: 'new', + }, + { + components: [], + version: '0.3.0', + description: 'Add breakpoint hooks - `up()` and `down()`', + prs: ['29564'], + type: 'new', + }, + { + components: [], + version: '0.3.0', + description: 'Add gray scale css tokens', + prs: ['29543'], + type: 'new', + }, + { + components: [], + version: '0.3.0', + description: + 'Update CSS styling API using `[data-___]` instead of class names for props', + prs: ['29560'], + }, + { + components: ['checkbox'], + version: '0.3.0', + description: 'Update `Checkbox` dark mode', + prs: ['29544'], + }, + { + components: ['container'], + version: '0.3.0', + description: 'Update `Container` styles', + prs: ['29475'], + }, + { + components: ['menu'], + version: '0.3.0', + description: 'Update `Menu` styles', + prs: ['29351'], + }, + { + components: ['select'], + version: '0.3.0', + description: 'Fix `Select` styles on small sizes + with long option names', + prs: ['29545'], + }, + { + components: ['link'], + version: '0.3.0', + description: 'Fix render prop on `Link`', + prs: ['29247'], + }, + { + components: ['textfield', 'select'], + version: '0.3.0', + description: 'Remove `Field` from `TextField` + `Select`', + prs: ['29482'], + }, + { + components: ['text', 'heading'], + version: '0.3.0', + description: 'Update `textDecoration` to `none` on `Text` / `Heading`', + prs: ['29357'], + }, + { + components: ['text', 'heading'], + version: '0.3.0', + description: 'Update `textDecoration` to `none` on `Text` / `Heading`', + prs: ['29357'], + }, + { + components: [], + version: '0.3.0', + description: 'Docs - Use stories from Storybook for all examples in Nextjs', + prs: ['29306'], + }, + { + components: [], + version: '0.3.0', + description: 'Docs - Add release page (this one šŸ¤—)', + prs: ['29461'], + }, + { + components: [], + version: '0.3.0', + description: 'Docs - Add docs for Menu, Link', + prs: ['29576'], + }, + { + components: [], + version: '0.3.0', + description: 'Fix CSS watch mode', + prs: ['29352'], + }, +]; diff --git a/docs-ui/src/utils/changelogs/v0.3.2.ts b/docs-ui/src/utils/changelogs/v0.3.2.ts new file mode 100644 index 0000000000..26dd225299 --- /dev/null +++ b/docs-ui/src/utils/changelogs/v0.3.2.ts @@ -0,0 +1,12 @@ +import type { ChangelogProps } from '../types'; + +export const changelog_0_3_2: ChangelogProps[] = [ + { + components: [], + version: '0.3.2', + description: `Fix Canon missing dependencies`, + prs: ['29642'], + type: 'fix', + commitSha: 'e996368', + }, +]; diff --git a/docs-ui/src/utils/changelogs/v0.4.0.ts b/docs-ui/src/utils/changelogs/v0.4.0.ts new file mode 100644 index 0000000000..91cd641f4d --- /dev/null +++ b/docs-ui/src/utils/changelogs/v0.4.0.ts @@ -0,0 +1,87 @@ +import type { ChangelogProps } from '../types'; + +export const changelog_0_4_0: ChangelogProps[] = [ + { + components: ['tabs'], + version: '0.4.0', + description: 'New `Tabs` component', + prs: ['29996'], + type: 'new', + }, + { + components: ['text', 'heading'], + version: '0.4.0', + description: 'Add `truncate` prop to `Text` and `Heading`', + prs: ['29988'], + type: 'new', + }, + { + components: ['menu'], + version: '0.4.0', + description: 'Add combobox option to `Menu`', + prs: ['29986'], + type: 'new', + }, + { + components: ['textfield'], + version: '0.4.0', + description: 'Add icon prop on `TextField`', + prs: ['29820'], + type: 'new', + }, + { + components: ['button', 'button-icon'], + version: '0.4.0', + description: 'Improve icon props on `Button` and `IconButton`', + prs: ['29667'], + }, + { + components: ['text', 'heading'], + version: '0.4.0', + description: + 'Improve the way we treat custom render on `Text` and `Heading`', + prs: ['29989'], + }, + { + components: ['menu'], + version: '0.4.0', + description: 'Improve `Menu` styles', + prs: ['29986'], + }, + { + components: ['textfield'], + version: '0.4.0', + description: 'Improve `TextField` styles', + prs: ['29974'], + }, + { + components: ['textfield'], + version: '0.4.0', + description: 'Improve clear button on `TextField`', + prs: ['29878'], + }, + { + components: ['flex'], + version: '0.4.0', + description: 'Fix spacing props on all layout components', + prs: ['30013'], + }, + { + components: [], + version: '0.4.0', + description: 'Fix - Pin Base UI version', + prs: ['29782'], + }, + { + components: ['select'], + version: '0.4.0', + description: 'Fix - Clicking `Select` label moves focus to trigger', + prs: ['29755'], + }, + { + components: ['datatable'], + version: '0.4.0', + description: 'Fix `DataTable.Pagination` count issue', + prs: ['29688'], + }, +]; diff --git a/docs-ui/src/utils/changelogs/v0.5.0.ts b/docs-ui/src/utils/changelogs/v0.5.0.ts new file mode 100644 index 0000000000..a48cb96dcc --- /dev/null +++ b/docs-ui/src/utils/changelogs/v0.5.0.ts @@ -0,0 +1,86 @@ +import type { ChangelogProps } from '../types'; + +export const changelog_0_5_0: ChangelogProps[] = [ + { + components: ['textfield'], + version: '0.5.0', + description: '`TextField` now has multiple label sizes.', + prs: ['30249'], + type: 'breaking', + }, + { + components: ['textfield'], + version: '0.5.0', + description: + '`TextField` can now hide label and description while keeping them available for screen readers.', + prs: ['30249'], + type: 'breaking', + }, + { + components: ['textfield'], + version: '0.5.0', + description: + 'We are removing the `render` prop in favour of the `as` prop on `Heading` and `Text`.', + prs: ['30291'], + type: 'breaking', + }, + { + components: ['textfield'], + version: '0.5.0', + description: 'Move `TextField` component to use react Aria under the hood.', + prs: ['30286'], + type: 'breaking', + }, + { + components: ['button', 'button-link'], + version: '0.5.0', + description: + 'Added a render prop to the `Button` component to use it as a link.', + prs: ['30165'], + type: 'new', + }, + { + components: ['heading'], + version: '0.5.0', + description: 'Fix styling for the title4 prop on the Heading component.', + prs: ['30167'], + type: 'fix', + }, + { + components: ['flex'], + version: '0.5.0', + description: + 'Add `min-width: 0;` by default on Flex components to support truncated text.', + prs: ['30168'], + type: 'fix', + }, + { + components: ['button', 'button-link', 'button-icon'], + version: '0.5.0', + description: + '`Button`, `ButtonLink`, `ButtonIcon` now default to size `small` instead of `medium`', + prs: ['30085', '30097'], + type: 'breaking', + }, + { + components: ['grid'], + version: '0.5.0', + description: 'Rename Grid component to ``', + prs: ['30013'], + type: 'breaking', + }, + { + components: ['flex', 'container', 'grid', 'box'], + version: '0.5.0', + description: 'Fixes spacing props on layout components', + prs: ['30013'], + type: 'fix', + }, + { + components: ['switch'], + version: '0.5.0', + description: 'New `Switch` component', + prs: ['30251'], + type: 'new', + }, +]; diff --git a/docs-ui/src/utils/changelogs/v0.6.0.ts b/docs-ui/src/utils/changelogs/v0.6.0.ts new file mode 100644 index 0000000000..d892f2a78d --- /dev/null +++ b/docs-ui/src/utils/changelogs/v0.6.0.ts @@ -0,0 +1,105 @@ +import type { ChangelogProps } from '../types'; + +export const changelog_0_6_0: ChangelogProps[] = [ + { + components: ['tooltip'], + version: '0.6.0', + description: 'New `Tooltip` component.', + prs: ['30461'], + type: 'new', + }, + { + components: ['card'], + version: '0.6.0', + description: 'New `Card` component.', + prs: ['30467'], + type: 'new', + }, + { + components: ['header'], + version: '0.6.0', + description: 'New `Header` component.', + prs: ['30410', '30459', '30493'], + type: 'new', + }, + { + components: ['button', 'button-link', 'button-icon'], + version: '0.6.0', + description: 'Improve `Button`, `ButtonIcon` and `ButtonLink` styling.', + prs: ['30448'], + type: 'fix', + }, + { + components: ['text', 'heading'], + version: '0.6.0', + description: + 'Update return types for `Heading` & `Text` components for React 19.', + prs: ['30440'], + type: 'fix', + }, + { + components: ['button', 'button-link', 'button-icon'], + version: '0.6.0', + description: + 'New `tertiary` variant to `Button`, `ButtonIcon` and `ButtonLink`.', + prs: ['30453'], + type: 'new', + }, + { + components: ['skeleton'], + version: '0.6.0', + description: 'New `Skeleton` component.', + prs: ['30466'], + type: 'new', + }, + { + components: ['button-icon'], + version: '0.6.0', + description: 'Rename `IconButton` to `ButtonIcon`.', + prs: ['30297'], + type: 'breaking', + }, + { + components: ['button-link'], + version: '0.6.0', + description: + 'New `ButtonLink`, which replaces the previous render prop pattern on `Button` and `IconButton`.', + prs: ['30297'], + type: 'new', + }, + { + components: ['button', 'button-link', 'button-icon'], + version: '0.6.0', + description: 'Remove the `render` prop from all button-related components.', + prs: ['30297'], + type: 'breaking', + }, + { + components: [], + version: '0.6.0', + description: 'We are consolidating all css files into a single styles.css.', + prs: ['30325'], + type: 'fix', + }, + { + components: ['searchfield'], + version: '0.6.0', + description: 'New `SearchField` component.', + prs: ['30357'], + type: 'new', + }, + { + components: ['radio-group'], + version: '0.6.0', + description: 'New `RadioGroup` + `Radio` component.', + prs: ['30327'], + type: 'new', + }, + { + components: ['textfield'], + version: '0.6.0', + description: 'Added placeholder prop back to `TextField` component.', + prs: ['30286'], + type: 'fix', + }, +]; diff --git a/docs-ui/src/utils/changelogs/v0.7.0.ts b/docs-ui/src/utils/changelogs/v0.7.0.ts new file mode 100644 index 0000000000..be49afc931 --- /dev/null +++ b/docs-ui/src/utils/changelogs/v0.7.0.ts @@ -0,0 +1,212 @@ +import type { ChangelogProps } from '../types'; + +export const changelog_0_7_0: ChangelogProps[] = [ + { + components: ['datatable', 'table'], + version: '0.7.0', + description: `We are moving our DataTable component to React Aria. We removed our DataTable to only use Table as a single and opinionated option for tables. This new structure is made possible by using React Aria under the hood.`, + prs: ['30654'], + type: 'breaking', + commitSha: '0615e54', + }, + { + components: ['header-page'], + version: '0.7.0', + description: `Backstage UI - HeaderPage - We are updating the breadcrumb to be more visible and accessible.`, + prs: ['30874'], + type: 'breaking', + commitSha: 'b245c9d', + }, + { + components: ['menu'], + version: '0.7.0', + description: `**Breaking change** We are updating the Menu component to use React Aria under the hood. The structure and all props are changing to follow React Aria's guidance.`, + prs: ['30908'], + type: 'breaking', + commitSha: '800f593', + }, + { + components: ['text', 'heading', 'link'], + version: '0.7.0', + description: `**Breaking** We are upgrading our \`Text\` component to support all font sizes making the \`Heading\` component redundant. The new \`Text\` component introduces 4 sizes for title and 4 sizes for body text. All of these work in multiple colors and font weights. We improved the \`as\` prop to include all possible values. The \`Link\` component has also been updated to match the new \`Text\` component.`, + prs: ['30592'], + type: 'breaking', + commitSha: 'b0e47f3', + }, + { + components: ['select'], + version: '0.7.0', + description: `Fixes some styles on the Select component in BUI.`, + prs: ['30642'], + type: 'fix', + commitSha: 'de89a3d', + }, + { + components: ['card'], + version: '0.7.0', + description: `Export CardHeader, CardBody and CardFooter from Card component index`, + prs: ['30882'], + type: 'fix', + commitSha: 'a251b3e', + }, + { + components: ['tag-group'], + version: '0.7.0', + description: `Add new TagGroup component to Backstage UI.`, + prs: ['30919'], + type: 'new', + commitSha: 'f761306', + }, + { + components: ['header', 'header-page'], + version: '0.7.0', + description: `Fixes a couple of small bugs in BUI including setting H1 and H2 correctly on the Header and HeaderPage.`, + prs: ['30636'], + type: 'fix', + commitSha: '75fead9', + }, + { + components: ['tooltip'], + version: '0.7.0', + description: `Update styling of Tooltip element`, + prs: ['30591'], + type: 'fix', + commitSha: 'e7ff178', + }, + { + components: ['header-page', 'header'], + version: '0.7.0', + description: `**Breaking change** Move breadcrumb to fit in the \`HeaderPage\` instead of the \`Header\` in Backstage UI.`, + prs: ['30701'], + type: 'fix', + commitSha: '230b410', + }, + { + components: [], + version: '0.7.0', + description: `We are motion away from \`motion\` to use \`gsap\` instead to make Backstage UI backward compatible with React 17.`, + prs: ['30626'], + type: 'fix', + commitSha: '2f9a084', + }, + { + components: ['menu'], + version: '0.7.0', + description: `Updated Menu component in Backstage UI to use useId() from React Aria instead of React to support React 17.`, + prs: ['30675'], + type: 'fix', + commitSha: 'd4e603e', + }, + { + components: ['select'], + version: '0.7.0', + description: `Remove stylesheet import from Select component.`, + prs: ['30800'], + type: 'fix', + commitSha: '8bdc491', + }, + { + components: ['searchfield'], + version: '0.7.0', + description: `Add \`startCollapsed\` prop on the \`SearchField\` component in BUI.`, + prs: ['30729'], + type: 'new', + commitSha: '404b426', + }, + { + components: ['header'], + version: '0.7.0', + description: `Adds onTabSelectionChange to ui header component.`, + prs: ['30588'], + type: 'fix', + commitSha: 'e0e886f', + }, + { + components: ['datatable', 'table'], + version: '0.7.0', + description: `We are moving our DataTable component to React Aria. We removed our DataTable to only use Table as a single and opinionated option for tables. This new structure is made possible by using React Aria under the hood.`, + prs: ['30654'], + type: 'breaking', + commitSha: '0615e54', + }, + { + components: ['header-page', 'header'], + version: '0.7.0', + description: `**Breaking change** Move breadcrumb to fit in the \`HeaderPage\` instead of the \`Header\` in Backstage UI.`, + prs: ['30701'], + type: 'fix', + commitSha: '230b410', + }, + { + components: ['select'], + version: '0.7.0', + description: `Remove stylesheet import from Select component.`, + prs: ['30800'], + type: 'fix', + commitSha: '8bdc491', + }, + { + components: ['searchfield'], + version: '0.7.0', + description: `Add \`startCollapsed\` prop on the \`SearchField\` component in BUI.`, + prs: ['30729'], + type: 'new', + commitSha: '404b426', + }, + { + components: ['menu'], + version: '0.7.0', + description: `Updated Menu component in Backstage UI to use useId() from React Aria instead of React to support React 17.`, + prs: ['30675'], + type: 'fix', + commitSha: 'd4e603e', + }, + { + components: ['select'], + version: '0.7.0', + description: `Fixes some styles on the Select component in BUI.`, + prs: ['30642'], + type: 'fix', + commitSha: 'de89a3d', + }, + { + components: ['header', 'header-page'], + version: '0.7.0', + description: `Fixes a couple of small bugs in BUI including setting H1 and H2 correctly on the Header and HeaderPage.`, + prs: ['30636'], + type: 'fix', + commitSha: '75fead9', + }, + { + components: [], + version: '0.7.0', + description: `We are motion away from \`motion\` to use \`gsap\` instead to make Backstage UI backward compatible with React 17.`, + prs: ['30626'], + type: 'fix', + commitSha: '2f9a084', + }, + { + components: ['text', 'heading', 'link'], + version: '0.7.0', + description: `**Breaking** We are upgrading our \`Text\` component to support all font sizes making the \`Heading\` component redundant. The new \`Text\` component introduces 4 sizes for title and 4 sizes for body text. All of these work in multiple colors and font weights. We improved the \`as\` prop to include all possible values. The \`Link\` component has also been updated to match the new \`Text\` component.`, + prs: ['30592'], + type: 'breaking', + commitSha: 'b0e47f3', + }, + { + components: ['tooltip'], + version: '0.7.0', + description: `Update styling of Tooltip element`, + prs: ['30591'], + type: 'fix', + commitSha: 'e7ff178', + }, + { + components: ['header'], + version: '0.7.0', + description: `Adds onTabSelectionChange to ui header component.`, + prs: ['30588'], + type: 'fix', + commitSha: 'e0e886f', + }, +]; diff --git a/docs-ui/src/utils/changelogs/v0.7.1.ts b/docs-ui/src/utils/changelogs/v0.7.1.ts new file mode 100644 index 0000000000..0f9f4cec5c --- /dev/null +++ b/docs-ui/src/utils/changelogs/v0.7.1.ts @@ -0,0 +1,44 @@ +import type { ChangelogProps } from '../types'; + +export const changelog_0_7_1: ChangelogProps[] = [ + { + components: ['flex'], + version: '0.7.1', + description: `Add missing class for flex: baseline`, + prs: ['31013'], + type: 'new', + commitSha: '7307930', + }, + { + components: ['select'], + version: '0.7.1', + description: `Fix Select component to properly attach aria-label and aria-labelledby props to the rendered element for improved accessibility.`, + prs: ['31037'], + type: 'fix', + commitSha: '89da341', + }, + { + components: [], + version: '0.7.1', + description: `Removed the need to mock \`window.matchMedia\` in tests, falling back to default breakpoint values instead.`, + prs: ['31148'], + type: 'fix', + commitSha: '0ffa4c7', + }, + { + components: ['flex'], + version: '0.7.1', + description: `Add missing class for flex: baseline`, + prs: ['31013'], + type: 'new', + commitSha: '7307930', + }, + { + components: ['select'], + version: '0.7.1', + description: `Fix Select component to properly attach aria-label and aria-labelledby props to the rendered element for improved accessibility.`, + prs: ['31037'], + type: 'fix', + commitSha: '89da341', + }, +]; diff --git a/docs-ui/src/utils/changelogs/v0.7.2.ts b/docs-ui/src/utils/changelogs/v0.7.2.ts new file mode 100644 index 0000000000..4a47d3d0e9 --- /dev/null +++ b/docs-ui/src/utils/changelogs/v0.7.2.ts @@ -0,0 +1,68 @@ +import type { ChangelogProps } from '../types'; + +export const changelog_0_7_2: ChangelogProps[] = [ + { + components: ['tabs', 'header'], + version: '0.7.2', + description: `Making href mandatory in tabs that are part of a Header component`, + prs: ['31343'], + type: 'fix', + commitSha: '3c921c5', + }, + { + components: ['button-link'], + version: '0.7.2', + description: `Add react router for internal routing for ButtonLinks`, + prs: ['31276'], + type: 'new', + commitSha: '5c21e45', + }, + { + components: ['tabs'], + version: '0.7.2', + description: `Remove auto selection of tabs for tabs that all have href defined`, + prs: ['31281'], + type: 'fix', + commitSha: '9781815', + }, + { + components: ['menu'], + version: '0.7.2', + description: `Using react router for internal links in the Menu component`, + prs: ['31339'], + type: 'fix', + commitSha: 'f6dff5b', + }, + { + components: ['button', 'tooltip'], + version: '0.7.2', + description: `Enable tooltips on disabled buttons with automatic wrapper`, + prs: ['31230'], + type: 'fix', + commitSha: 'a9b88be', + }, + { + components: [], + version: '0.7.2', + description: `Avoid overriding onChange when spreading props`, + prs: ['31232'], + type: 'fix', + commitSha: '4adbb03', + }, + { + components: ['tabs'], + version: '0.7.2', + description: `remove default selection of tab`, + prs: ['31216'], + type: 'fix', + commitSha: '827340f', + }, + { + components: ['searchfield', 'header'], + version: '0.7.2', + description: `Improved SearchField component flex layout and animations. Fixed SearchField behavior in Header components by switching from width-based transitions to flex-basis transitions for better responsive behavior. Added new Storybook stories to test SearchField integration with Header component.`, + prs: ['31158'], + type: 'fix', + commitSha: '9a47125', + }, +]; diff --git a/docs-ui/src/utils/changelogs/v0.8.0.ts b/docs-ui/src/utils/changelogs/v0.8.0.ts new file mode 100644 index 0000000000..8a76937150 --- /dev/null +++ b/docs-ui/src/utils/changelogs/v0.8.0.ts @@ -0,0 +1,172 @@ +import type { ChangelogProps } from '../types'; + +export const changelog_0_8_0: ChangelogProps[] = [ + { + components: ['password-field', 'textfield'], + version: '0.8.0', + description: `**BREAKING**: Added a new \`PasswordField\` component. As part of this change, the \`password\` and \`search\` types have been removed from \`TextField\`.`, + prs: ['31238'], + type: 'breaking', + commitSha: '9acc1d6', + }, + { + components: [], + version: '0.8.0', + description: `**BREAKING** Restructure Backstage UI component styling to use CSS Modules instead of pure CSS. We don't expect this to be an issue in practice but it is important to call out that all styles are now loaded through CSS modules with generated class names. We are still providing fixed class names for all components to allow anyone to style their Backstage instance.`, + prs: ['31399'], + type: 'breaking', + commitSha: 'b0d11b5', + }, + { + components: ['scrollarea'], + version: '0.8.0', + description: `**BREAKING** The ScrollArea component has been removed from Backstage UI because it did not meet our accessibility standards.`, + prs: ['31409'], + type: 'breaking', + commitSha: '0c53517', + }, + { + components: ['icon'], + version: '0.8.0', + description: `**BREAKING** Remove Icon component in Backstage UI. This component was creating issue for tree-shaking. It is recommended to use icons from @remixicon/react until we found a better alternative in Backstage UI.`, + prs: ['31407'], + type: 'breaking', + commitSha: '7b319c5', + }, + { + components: ['dialog'], + version: '0.8.0', + description: `Adding a new Dialog component to Backstage UI.`, + prs: ['31371'], + type: 'fix', + commitSha: '2591b42', + }, + { + components: ['tabs'], + version: '0.8.0', + description: `remove default selection of tab`, + prs: ['31216'], + type: 'fix', + commitSha: '827340f', + }, + { + components: [], + version: '0.8.0', + description: `Fix margin utility classes in Backstage UI.`, + prs: ['31389'], + type: 'fix', + commitSha: '5dc17cc', + }, + { + components: ['menu'], + version: '0.8.0', + description: `Fix scroll jumping when opening menu in Backstage UI.`, + prs: ['31394'], + type: 'fix', + commitSha: '85faee0', + }, + { + components: ['tabs', 'header'], + version: '0.8.0', + description: `Making href mandatory in tabs that are part of a Header component`, + prs: ['31343'], + type: 'fix', + commitSha: '3c921c5', + }, + { + components: [], + version: '0.8.0', + description: `Update react-aria-components to version 1.13.0`, + prs: ['31367'], + type: 'fix', + commitSha: 'df7d2cf', + }, + { + components: ['table'], + version: '0.8.0', + description: `Fix table sorting icon position in Backstage UI.`, + prs: ['31393'], + type: 'fix', + commitSha: '507ee55', + }, + { + components: ['menu'], + version: '0.8.0', + description: `Add new \`virtualized\`, \`maxWidth\` and \`maxHeight\` props to \`Menu\`, \`MenuListBox\`, \`MenuAutocomplete\` and \`MenuAutocompleteListBox\` to allow for virtalization of long lists inside menus.`, + prs: ['31375'], + type: 'new', + commitSha: '8b7c3c9', + }, + { + components: ['box', 'container', 'flex', 'grid'], + version: '0.8.0', + description: `Added support for data attributes in \`\`, \`\`, \`\`, and \`\` components, ensuring they are correctly applied to the rendered elements.`, + prs: ['31374'], + type: 'new', + commitSha: 'b940062', + }, + { + components: ['scrollarea', 'card'], + version: '0.8.0', + description: `Cleaning up Backstage UI props definitions as well as removing ScrollArea in Card to improve accessibility.`, + prs: ['31404'], + type: 'fix', + commitSha: '206c801', + }, + { + components: ['button-link'], + version: '0.8.0', + description: `Add react router for internal routing for ButtonLinks`, + prs: ['31276'], + type: 'new', + commitSha: '5c21e45', + }, + { + components: [], + version: '0.8.0', + description: `Added a background color default on the body`, + prs: ['31365'], + type: 'new', + commitSha: '865bce8', + }, + { + components: [], + version: '0.8.0', + description: `We are restructuring our CSS to have a better layer structure.`, + prs: ['31362'], + type: 'fix', + commitSha: 'af4d9b4', + }, + { + components: ['searchfield', 'header'], + version: '0.8.0', + description: `Improved SearchField component flex layout and animations. Fixed SearchField behavior in Header components by switching from width-based transitions to flex-basis transitions for better responsive behavior. Added new Storybook stories to test SearchField integration with Header component.`, + prs: ['31158'], + type: 'fix', + commitSha: '9a47125', + }, + { + components: ['tabs'], + version: '0.8.0', + description: `Remove auto selection of tabs for tabs that all have href defined`, + prs: ['31281'], + type: 'fix', + commitSha: '9781815', + }, + { + components: [], + version: '0.8.0', + description: `Avoid overriding onChange when spreading props`, + prs: ['31232'], + type: 'fix', + commitSha: '4adbb03', + }, + { + components: ['menu'], + version: '0.8.0', + description: `Using react router for internal links in the Menu component`, + prs: ['31339'], + type: 'fix', + commitSha: 'f6dff5b', + }, +]; diff --git a/docs-ui/src/utils/changelogs/v0.8.2.ts b/docs-ui/src/utils/changelogs/v0.8.2.ts new file mode 100644 index 0000000000..1f78c7385b --- /dev/null +++ b/docs-ui/src/utils/changelogs/v0.8.2.ts @@ -0,0 +1,44 @@ +import type { ChangelogProps } from '../types'; + +export const changelog_0_8_2: ChangelogProps[] = [ + { + components: ['text'], + version: '0.8.2', + description: `Fix default text color in Backstage UI`, + prs: ['31429'], + type: 'fix', + commitSha: '26c6a78', + }, + { + components: ['text'], + version: '0.8.2', + description: `Fix the default font size in Backstage UI.`, + prs: ['31435'], + type: 'fix', + commitSha: 'dac851f', + }, + { + components: [], + version: '0.8.2', + description: `Fix CSS layer ordering in Backstage UI to make sure component styles are loaded after tokens and base declarations.`, + prs: ['31448'], + type: 'fix', + commitSha: '3c0ea67', + }, + { + components: [], + version: '0.8.2', + description: `Fix font smoothing as default in Backstage UI.`, + prs: ['31444'], + type: 'fix', + commitSha: '4eb455c', + }, + { + components: ['text'], + version: '0.8.2', + description: `Fix default font wight and font family in Backstage UI.`, + prs: ['31432'], + type: 'fix', + commitSha: '00bfb83', + }, +]; diff --git a/docs-ui/src/utils/definitions.ts b/docs-ui/src/utils/definitions.ts new file mode 100644 index 0000000000..d279d73775 --- /dev/null +++ b/docs-ui/src/utils/definitions.ts @@ -0,0 +1 @@ +export * from '../../../packages/ui/src/definitions'; diff --git a/docs-ui/src/utils/types.ts b/docs-ui/src/utils/types.ts new file mode 100644 index 0000000000..f2f773ebc2 --- /dev/null +++ b/docs-ui/src/utils/types.ts @@ -0,0 +1,46 @@ +export type Component = + | 'avatar' + | 'box' + | 'button' + | 'button-link' + | 'heading' + | 'text' + | 'button-icon' + | 'icon' + | 'tabs' + | 'menu' + | 'textfield' + | 'datatable' + | 'select' + | 'collapsible' + | 'accordion' + | 'checkbox' + | 'container' + | 'link' + | 'tooltip' + | 'scrollarea' + | 'flex' + | 'switch' + | 'grid' + | 'searchfield' + | 'radio-group' + | 'card' + | 'skeleton' + | 'header' + | 'header-page' + | 'password-field' + | 'table' + | 'visually-hidden' + | 'dialog' + | 'tag-group'; + +export type Version = `${number}.${number}.${number}`; + +export interface ChangelogProps { + components: Component[]; + description: string; + version: Version; + prs: string[]; + type?: 'breaking' | 'new' | 'fix'; + commitSha?: string; +} diff --git a/docs-ui/yarn.lock b/docs-ui/yarn.lock index 480f7592f8..7ebaeaf001 100644 --- a/docs-ui/yarn.lock +++ b/docs-ui/yarn.lock @@ -31,16 +31,16 @@ __metadata: linkType: hard "@base-ui-components/react@npm:^1.0.0-beta.4": - version: 1.0.0-beta.4 - resolution: "@base-ui-components/react@npm:1.0.0-beta.4" + version: 1.0.0-beta.5 + resolution: "@base-ui-components/react@npm:1.0.0-beta.5" dependencies: "@babel/runtime": "npm:^7.28.4" - "@base-ui-components/utils": "npm:0.1.2" + "@base-ui-components/utils": "npm:0.2.0" "@floating-ui/react-dom": "npm:^2.1.6" "@floating-ui/utils": "npm:^0.2.10" reselect: "npm:^5.1.1" - tabbable: "npm:^6.2.0" - use-sync-external-store: "npm:^1.5.0" + tabbable: "npm:^6.3.0" + use-sync-external-store: "npm:^1.6.0" peerDependencies: "@types/react": ^17 || ^18 || ^19 react: ^17 || ^18 || ^19 @@ -48,18 +48,18 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: 10/d2c6a779aaefa3454cc130244e839f0428460997f3ca8bbcd9636056bc5a4c77436cc0ceac064f34bdc7cb01489a4cbc4d8b0bf9668a023fa754e5a24bd3af4e + checksum: 10/db53c9fc05301263419ac0f3c7f655aa67262a434b7f752e3af879430e75aa5d0d808ecf8c40d38b70fb699df8028b68baa11a9608e3153bcc4a5c57d6fab1f1 languageName: node linkType: hard -"@base-ui-components/utils@npm:0.1.2": - version: 0.1.2 - resolution: "@base-ui-components/utils@npm:0.1.2" +"@base-ui-components/utils@npm:0.2.0": + version: 0.2.0 + resolution: "@base-ui-components/utils@npm:0.2.0" dependencies: "@babel/runtime": "npm:^7.28.4" "@floating-ui/utils": "npm:^0.2.10" reselect: "npm:^5.1.1" - use-sync-external-store: "npm:^1.5.0" + use-sync-external-store: "npm:^1.6.0" peerDependencies: "@types/react": ^17 || ^18 || ^19 react: ^17 || ^18 || ^19 @@ -67,7 +67,7 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: 10/b8408f5ad55886f793fb7580ffe2bb9565ff0713bec324f726b88ee1d135d75b26a1312338b19af743adf52e5b9d46892a47fb225e6abfe1077e75d32e88fb6e + checksum: 10/b5eae460e3f45fdb2c5116c94612c5b0c00190d4f0763836ba121e36e5c46c1caad862f4aa05827d90a8ebe924c29e42a7561c124de23ce3dc565dba2a6dff98 languageName: node linkType: hard @@ -999,6 +999,130 @@ __metadata: languageName: node linkType: hard +"@octokit/auth-token@npm:^6.0.0": + version: 6.0.0 + resolution: "@octokit/auth-token@npm:6.0.0" + checksum: 10/a30f5c4c984964b57193de5b6f67169f74e4779fedbe716157dd3558dd9de3ca5c105cae521b7bd8ce1ae180773a2ef01afe2306ad5a329f4fd291eba2b7c7d1 + languageName: node + linkType: hard + +"@octokit/core@npm:^7.0.6": + version: 7.0.6 + resolution: "@octokit/core@npm:7.0.6" + dependencies: + "@octokit/auth-token": "npm:^6.0.0" + "@octokit/graphql": "npm:^9.0.3" + "@octokit/request": "npm:^10.0.6" + "@octokit/request-error": "npm:^7.0.2" + "@octokit/types": "npm:^16.0.0" + before-after-hook: "npm:^4.0.0" + universal-user-agent: "npm:^7.0.0" + checksum: 10/852d41fc3150d2a891156427dd0575c77889f1c7a109894ee541594e3fd47c0d4e0a93fee22966c507dfd6158b522e42846c2ac46b9d896078194c95fa81f4ae + languageName: node + linkType: hard + +"@octokit/endpoint@npm:^11.0.2": + version: 11.0.2 + resolution: "@octokit/endpoint@npm:11.0.2" + dependencies: + "@octokit/types": "npm:^16.0.0" + universal-user-agent: "npm:^7.0.2" + checksum: 10/0d088747baf94eafbba69da23ba840b40cd3f5d0bfbc51c692ff9d9d78de6d81f06366e6e30df8c1783355be826c27d38ab9ab0708396af8f430b06cfa29db35 + languageName: node + linkType: hard + +"@octokit/graphql@npm:^9.0.3": + version: 9.0.3 + resolution: "@octokit/graphql@npm:9.0.3" + dependencies: + "@octokit/request": "npm:^10.0.6" + "@octokit/types": "npm:^16.0.0" + universal-user-agent: "npm:^7.0.0" + checksum: 10/7b16f281f8571dce55280b3986fbb8d15465a7236164a5f6497ded7597ff9ee95d5796924555b979903fe8c6706fe6be1b3e140d807297f85ac8edeadc28f9fe + languageName: node + linkType: hard + +"@octokit/openapi-types@npm:^27.0.0": + version: 27.0.0 + resolution: "@octokit/openapi-types@npm:27.0.0" + checksum: 10/5cd2cdf4e41fdf522e15e3d53f3ece8380d98dda9173a6fc905828fb2c33e8733d5f5d2a757ae3a572525f4749748e66cb40e7939372132988d8eb4ba978d54f + languageName: node + linkType: hard + +"@octokit/plugin-paginate-rest@npm:^14.0.0": + version: 14.0.0 + resolution: "@octokit/plugin-paginate-rest@npm:14.0.0" + dependencies: + "@octokit/types": "npm:^16.0.0" + peerDependencies: + "@octokit/core": ">=6" + checksum: 10/57ddd857528dad9c02431bc6254c2374c06057872cf9656a4a88b162ebe1c2bc9f34fbec360f2ccff72c940f29b120758ce14e8135bd027223d381eb1b8b6579 + languageName: node + linkType: hard + +"@octokit/plugin-request-log@npm:^6.0.0": + version: 6.0.0 + resolution: "@octokit/plugin-request-log@npm:6.0.0" + peerDependencies: + "@octokit/core": ">=6" + checksum: 10/8a79973b1429bfead9113c4117f418aaef5ff368795daded3415ba14623d97d5fc08d1e822dbd566ecc9f041119e1a48a11853a9c48d9eb1caa62baa79c17f83 + languageName: node + linkType: hard + +"@octokit/plugin-rest-endpoint-methods@npm:^17.0.0": + version: 17.0.0 + resolution: "@octokit/plugin-rest-endpoint-methods@npm:17.0.0" + dependencies: + "@octokit/types": "npm:^16.0.0" + peerDependencies: + "@octokit/core": ">=6" + checksum: 10/e9d9ad4d9755cc7fb82fdcbfa870ddea8a432180f0f76c8469095557fd1e26f8caea8cae58401209be17c4f3d8cc48c0e16a3643e37e48f4d23c39e058bf2c55 + languageName: node + linkType: hard + +"@octokit/request-error@npm:^7.0.2": + version: 7.0.2 + resolution: "@octokit/request-error@npm:7.0.2" + dependencies: + "@octokit/types": "npm:^16.0.0" + checksum: 10/8edfaca9f5271115b090f470ebfe1006841ee152dd52cb39786e026236e2c13545aa3cf3187b7b1de717167696a42f91d8fa2f870bf9be0832fb2b11d11a741d + languageName: node + linkType: hard + +"@octokit/request@npm:^10.0.6": + version: 10.0.6 + resolution: "@octokit/request@npm:10.0.6" + dependencies: + "@octokit/endpoint": "npm:^11.0.2" + "@octokit/request-error": "npm:^7.0.2" + "@octokit/types": "npm:^16.0.0" + fast-content-type-parse: "npm:^3.0.0" + universal-user-agent: "npm:^7.0.2" + checksum: 10/b8c5cd43d3225c8c3b803e889ff251808ae180c953ca92642522843123dafcd84d919b20ca2969b6e4080ee3c2197a99afda15b5649ee51d0715f8249a5c9ca4 + languageName: node + linkType: hard + +"@octokit/rest@npm:^22.0.1": + version: 22.0.1 + resolution: "@octokit/rest@npm:22.0.1" + dependencies: + "@octokit/core": "npm:^7.0.6" + "@octokit/plugin-paginate-rest": "npm:^14.0.0" + "@octokit/plugin-request-log": "npm:^6.0.0" + "@octokit/plugin-rest-endpoint-methods": "npm:^17.0.0" + checksum: 10/ec2e94cfa8766716faeb3ca18527d9af746482d35aaa6e4265a30cb669ae3f31f4ebb6235edebe5ae62bc2cec2b8e88902584f698df2e7cabac3a15fd27da665 + languageName: node + linkType: hard + +"@octokit/types@npm:^16.0.0": + version: 16.0.0 + resolution: "@octokit/types@npm:16.0.0" + dependencies: + "@octokit/openapi-types": "npm:^27.0.0" + checksum: 10/03d5cfc29556a9b53eae8beb1bf15c0b704dc722db2c51b53f093f3c3ee6c1d8e20b682be8117a3a17034b458be7746d1b22aaefb959ceb5152ad7589b39e2c9 + languageName: node + linkType: hard + "@pkgjs/parseargs@npm:^0.11.0": version: 0.11.0 resolution: "@pkgjs/parseargs@npm:0.11.0" @@ -1007,11 +1131,11 @@ __metadata: linkType: hard "@remixicon/react@npm:^4.6.0": - version: 4.6.0 - resolution: "@remixicon/react@npm:4.6.0" + version: 4.7.0 + resolution: "@remixicon/react@npm:4.7.0" peerDependencies: react: ">=18.2.0" - checksum: 10/d92c8131734062fca8d82d55dd8f3f4e28cb72c5eefda528c8aba5f3298f0c847342eecdbd7787d6da5af21b699d735f6cf27f151f0c982c1c9f06a78b235c94 + checksum: 10/9ecee093dd4aec3744bcc7562eddb987bf9c7c059787dfecfbcc25a64c2f4833dc815dff715aa2a7f75011d65f877b3751a401d19cf2d725b5bcc685587d37f4 languageName: node linkType: hard @@ -1946,6 +2070,13 @@ __metadata: languageName: node linkType: hard +"before-after-hook@npm:^4.0.0": + version: 4.0.0 + resolution: "before-after-hook@npm:4.0.0" + checksum: 10/9fd52bc0c3cca0fb115e04dacbeeaacff38fa23e1af725d62392254c31ef433b15da60efcba61552e44d64e26f25ea259f72dba005115924389e88d2fd56e19f + languageName: node + linkType: hard + "better-opn@npm:^3.0.2": version: 3.0.2 resolution: "better-opn@npm:3.0.2" @@ -2385,6 +2516,7 @@ __metadata: "@mdx-js/loader": "npm:^3.1.0" "@mdx-js/react": "npm:^3.1.0" "@next/mdx": "npm:15.3.4" + "@octokit/rest": "npm:^22.0.1" "@remixicon/react": "npm:^4.6.0" "@shikijs/transformers": "npm:^3.13.0" "@storybook/react": "npm:^8.6.12" @@ -2409,6 +2541,7 @@ __metadata: shiki: "npm:^3.13.0" storybook: "npm:^8.6.12" typescript: "npm:^5" + unified: "npm:^11.0.4" languageName: unknown linkType: soft @@ -3178,6 +3311,13 @@ __metadata: languageName: node linkType: hard +"fast-content-type-parse@npm:^3.0.0": + version: 3.0.0 + resolution: "fast-content-type-parse@npm:3.0.0" + checksum: 10/8616a8aa6c9b4f8f4f3c90eaa4e7bfc2240cfa6f41f0eef5b5aa2b2c8b38bd9ad435f1488b6d817ffd725c54651e2777b882ae9dd59366e71e7896f1ec11d473 + languageName: node + linkType: hard + "fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3": version: 3.1.3 resolution: "fast-deep-equal@npm:3.1.3" @@ -3664,31 +3804,31 @@ __metadata: languageName: node linkType: hard -"html-dom-parser@npm:5.1.1": - version: 5.1.1 - resolution: "html-dom-parser@npm:5.1.1" +"html-dom-parser@npm:5.1.2": + version: 5.1.2 + resolution: "html-dom-parser@npm:5.1.2" dependencies: domhandler: "npm:5.0.3" htmlparser2: "npm:10.0.0" - checksum: 10/85bbaa8699d40d54fd64f5472088199178a6c3dd6a907358ac476d9c511cb8ab10bff1469a785411e8b831a73ac08348392e56076eab6d100a3ec19dccc722ad + checksum: 10/d54fcdafbc0b2881c441a396965ad285072d2e4df62bebe7074d7aaa2a1fffc95e9286bcb81d6f241c4cdb10a84435fa623738985b635574acb3c84e994e8bb6 languageName: node linkType: hard "html-react-parser@npm:^5.2.5": - version: 5.2.8 - resolution: "html-react-parser@npm:5.2.8" + version: 5.2.10 + resolution: "html-react-parser@npm:5.2.10" dependencies: domhandler: "npm:5.0.3" - html-dom-parser: "npm:5.1.1" + html-dom-parser: "npm:5.1.2" react-property: "npm:2.0.2" - style-to-js: "npm:1.1.19" + style-to-js: "npm:1.1.21" peerDependencies: "@types/react": 0.14 || 15 || 16 || 17 || 18 || 19 react: 0.14 || 15 || 16 || 17 || 18 || 19 peerDependenciesMeta: "@types/react": optional: true - checksum: 10/492d44f65c2a8647bb7d6db3865363739a00696687024b978f5f5e29475c40bd470c91e9ddefe0f1a846c85761f046e9a92fa3fe0e5581df43ac587787703b31 + checksum: 10/3b0debac58e4b39d853731fd117b323a5d9582482cdc0b6dc5179d0c469acf63e64b8fdb3b678e758673633c579b09fd21d75d256c32104c65355f4434ba7f59 languageName: node linkType: hard @@ -3795,10 +3935,10 @@ __metadata: languageName: node linkType: hard -"inline-style-parser@npm:0.2.6": - version: 0.2.6 - resolution: "inline-style-parser@npm:0.2.6" - checksum: 10/0be8356fcd766b7b170991293c9ad953f057ac9719960f51f4eb54af1a79c34638f591691f2ab43f57bef2e28e9c1239b8ae5f6b72bff2c652f828ccc621c08c +"inline-style-parser@npm:0.2.7": + version: 0.2.7 + resolution: "inline-style-parser@npm:0.2.7" + checksum: 10/cdfe719bd694b53bfbad20a645a9a4dda89c3ff56ee2b95945ad4eea86c541501f49f852d23bc2f73cd8127b6b62ea9027f697838e323a7f7d0d9b760e27a632 languageName: node linkType: hard @@ -4213,13 +4353,13 @@ __metadata: linkType: hard "js-yaml@npm:^4.1.0": - version: 4.1.0 - resolution: "js-yaml@npm:4.1.0" + version: 4.1.1 + resolution: "js-yaml@npm:4.1.1" dependencies: argparse: "npm:^2.0.1" bin: js-yaml: bin/js-yaml.js - checksum: 10/c138a34a3fd0d08ebaf71273ad4465569a483b8a639e0b118ff65698d257c2791d3199e3f303631f2cb98213fa7b5f5d6a4621fd0fff819421b990d30d967140 + checksum: 10/a52d0519f0f4ef5b4adc1cde466cb54c50d56e2b4a983b9d5c9c0f2f99462047007a6274d7e95617a21d3c91fde3ee6115536ed70991cd645ba8521058b78f77 languageName: node linkType: hard @@ -6502,21 +6642,21 @@ __metadata: languageName: node linkType: hard -"style-to-js@npm:1.1.19, style-to-js@npm:^1.0.0": - version: 1.1.19 - resolution: "style-to-js@npm:1.1.19" +"style-to-js@npm:1.1.21, style-to-js@npm:^1.0.0": + version: 1.1.21 + resolution: "style-to-js@npm:1.1.21" dependencies: - style-to-object: "npm:1.0.12" - checksum: 10/c25f3a96368f258c90a886ec20b8a15ae035664e46eeea6c36f105fbc1e099ee81eaac355b7f5f948d8bb9d103c048a97b3d09e785c680ff2b4dd6d77cb76a95 + style-to-object: "npm:1.0.14" + checksum: 10/5e30b4c52ed4e0294324adab2a43a0438b5495a77a72a6b1258637eebfc4dc8e0614f5ac7bf38a2f514879b3b448215d01fecf1f8d7468b8b95d90bed1d05d57 languageName: node linkType: hard -"style-to-object@npm:1.0.12": - version: 1.0.12 - resolution: "style-to-object@npm:1.0.12" +"style-to-object@npm:1.0.14": + version: 1.0.14 + resolution: "style-to-object@npm:1.0.14" dependencies: - inline-style-parser: "npm:0.2.6" - checksum: 10/97b91c2056f4fedb573224accba080aaa96b48a7b120a007b83415c9b18b727d0d6588b9168a1b85da06dd1abacc328f6dd774e907721901e40503a2e7a78c89 + inline-style-parser: "npm:0.2.7" + checksum: 10/06b86a5cf435dafac908d19082842983f9052d8cf3682915b1bd9251e3fe9b8065dbd2aef060dc5dfa0fa2ee24d717b587a5205f571513a10f30e3947f9d28ff languageName: node linkType: hard @@ -6552,7 +6692,7 @@ __metadata: languageName: node linkType: hard -"tabbable@npm:^6.2.0": +"tabbable@npm:^6.3.0": version: 6.3.0 resolution: "tabbable@npm:6.3.0" checksum: 10/3e54a0b770d26bc20c3de5837652be19f5efa8bfa869f580af24bcf60de934506e9401a577213186b5e86ebcf6b5290a5429d354cc3041471815f5095e44e51a @@ -6763,7 +6903,7 @@ __metadata: languageName: node linkType: hard -"unified@npm:^11.0.0": +"unified@npm:^11.0.0, unified@npm:^11.0.4": version: 11.0.5 resolution: "unified@npm:11.0.5" dependencies: @@ -6864,6 +7004,13 @@ __metadata: languageName: node linkType: hard +"universal-user-agent@npm:^7.0.0, universal-user-agent@npm:^7.0.2": + version: 7.0.3 + resolution: "universal-user-agent@npm:7.0.3" + checksum: 10/c497e85f8b11eb8fa4dce584d7a39cc98710164959f494cafc3c269b51abb20fff269951838efd7424d15f6b3d001507f3cb8b52bb5676fdb642019dfd17e63e + languageName: node + linkType: hard + "unrs-resolver@npm:^1.6.2": version: 1.11.1 resolution: "unrs-resolver@npm:1.11.1" @@ -6940,7 +7087,7 @@ __metadata: languageName: node linkType: hard -"use-sync-external-store@npm:^1.5.0": +"use-sync-external-store@npm:^1.6.0": version: 1.6.0 resolution: "use-sync-external-store@npm:1.6.0" peerDependencies: diff --git a/microsite/data/plugins/announcements.yaml b/microsite/data/plugins/announcements.yaml index a9c66d6203..f24965f10a 100644 --- a/microsite/data/plugins/announcements.yaml +++ b/microsite/data/plugins/announcements.yaml @@ -1,7 +1,7 @@ --- title: Announcements -author: procore-oss -authorUrl: https://github.com/procore-oss +author: kurtaking +authorUrl: https://github.com/kurtaking category: Discovery description: Write and share announcements within Backstage. documentation: https://github.com/backstage/community-plugins/tree/main/workspaces/announcements/ diff --git a/package.json b/package.json index 5039c29e2b..31429c425a 100644 --- a/package.json +++ b/package.json @@ -65,8 +65,8 @@ "test": "NODE_OPTIONS='--no-node-snapshot --experimental-vm-modules' backstage-cli repo test", "test:all": "NODE_OPTIONS='--no-node-snapshot --experimental-vm-modules' backstage-cli repo test --coverage", "test:e2e": "NODE_OPTIONS=--no-node-snapshot playwright test", - "tsc": "tsc", - "tsc:full": "backstage-cli repo clean && tsc --skipLibCheck false --incremental false" + "tsc": "NODE_OPTIONS='--max-old-space-size=8192' tsc", + "tsc:full": "backstage-cli repo clean && NODE_OPTIONS='--max-old-space-size=8192' tsc --skipLibCheck false --incremental false" }, "lint-staged": { "*.{js,jsx,ts,tsx,mjs,cjs}": [ diff --git a/packages/app-next-example-plugin/report.api.md b/packages/app-next-example-plugin/report.api.md index 12346d908c..bfcafbe2d2 100644 --- a/packages/app-next-example-plugin/report.api.md +++ b/packages/app-next-example-plugin/report.api.md @@ -5,9 +5,9 @@ ```ts import { AnyRouteRefParams } from '@backstage/frontend-plugin-api'; import { ExtensionDataRef } from '@backstage/frontend-plugin-api'; -import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; import { JSX as JSX_2 } from 'react'; import { JSX as JSX_3 } from 'react/jsx-runtime'; +import { OverridableExtensionDefinition } from '@backstage/frontend-plugin-api'; import { OverridableFrontendPlugin } from '@backstage/frontend-plugin-api'; import { RouteRef } from '@backstage/frontend-plugin-api'; @@ -16,7 +16,7 @@ const examplePlugin: OverridableFrontendPlugin< {}, {}, { - 'page:example': ExtensionDefinition<{ + 'page:example': OverridableExtensionDefinition<{ kind: 'page'; name: undefined; config: { diff --git a/packages/frontend-internal/src/wiring/InternalExtensionDefinition.ts b/packages/frontend-internal/src/wiring/InternalExtensionDefinition.ts index 54953c169a..b7c3674f9a 100644 --- a/packages/frontend-internal/src/wiring/InternalExtensionDefinition.ts +++ b/packages/frontend-internal/src/wiring/InternalExtensionDefinition.ts @@ -20,7 +20,7 @@ import { ExtensionDefinitionAttachTo, ExtensionDataValue, ExtensionDataRef, - ExtensionDefinition, + OverridableExtensionDefinition, ExtensionDefinitionParameters, ExtensionInput, PortableSchema, @@ -29,7 +29,7 @@ import { import { OpaqueType } from '@internal/opaque'; export const OpaqueExtensionDefinition = OpaqueType.create<{ - public: ExtensionDefinition; + public: OverridableExtensionDefinition; versions: | { readonly version: 'v1'; diff --git a/packages/frontend-plugin-api/report.api.md b/packages/frontend-plugin-api/report.api.md index c3dd12119f..f2fe60c82a 100644 --- a/packages/frontend-plugin-api/report.api.md +++ b/packages/frontend-plugin-api/report.api.md @@ -418,7 +418,7 @@ export function createExtension< UFactoryOutput, UParentInputs >, -): ExtensionDefinition<{ +): OverridableExtensionDefinition<{ config: string extends keyof TConfigSchema ? {} : { @@ -881,7 +881,7 @@ export interface ExtensionBlueprint< : T['params'] extends ExtensionBlueprintDefineParams ? 'Error: This blueprint uses advanced parameter types and requires you to pass parameters as using the following callback syntax: `.make({ params: defineParams => defineParams() })`' : T['params']; - }): ExtensionDefinition<{ + }): OverridableExtensionDefinition<{ kind: T['kind']; name: string | undefined extends TName ? undefined : TName; config: T['config']; @@ -953,7 +953,7 @@ export interface ExtensionBlueprint< : UNewOutput, UFactoryOutput >; - }): ExtensionDefinition<{ + }): OverridableExtensionDefinition<{ config: (string extends keyof TExtensionConfigSchema ? {} : { @@ -1088,117 +1088,14 @@ export type ExtensionDataValue = { }; // @public (undocumented) -export type ExtensionDefinition< - T extends ExtensionDefinitionParameters = ExtensionDefinitionParameters, -> = { +export interface ExtensionDefinition< + TParams extends ExtensionDefinitionParameters = ExtensionDefinitionParameters, +> { + // (undocumented) $$type: '@backstage/ExtensionDefinition'; - readonly T: T; - readonly inputs: { - [K in keyof T['inputs']]: ExtensionInput< - T['inputs'][K] extends ExtensionInput ? IData : never - >; - }; - override< - TExtensionConfigSchema extends { - [key in string]: (zImpl: typeof z) => z.ZodType; - }, - UFactoryOutput extends ExtensionDataValue, - UNewOutput extends ExtensionDataRef, - TExtraInputs extends { - [inputName in string]: ExtensionInput; - }, - TParamsInput extends AnyParamsInput_2>, - UParentInputs extends ExtensionDataRef, - >( - args: Expand< - { - attachTo?: ExtensionDefinitionAttachTo & - VerifyExtensionAttachTo< - ExtensionDataRef extends UNewOutput - ? NonNullable - : UNewOutput, - UParentInputs - >; - disabled?: boolean; - inputs?: TExtraInputs & { - [KName in keyof T['inputs']]?: `Error: Input '${KName & - string}' is already defined in parent definition`; - }; - output?: Array; - config?: { - schema: TExtensionConfigSchema & { - [KName in keyof T['config']]?: `Error: Config key '${KName & - string}' is already defined in parent schema`; - }; - }; - factory?( - originalFactory: < - TFactoryParamsReturn extends AnyParamsInput_2< - NonNullable - >, - >( - context?: Expand< - { - config?: T['config']; - inputs?: ResolvedInputValueOverrides>; - } & ([T['params']] extends [never] - ? {} - : { - params?: TFactoryParamsReturn extends ExtensionBlueprintDefineParams - ? TFactoryParamsReturn - : T['params'] extends ExtensionBlueprintDefineParams - ? 'Error: This blueprint uses advanced parameter types and requires you to pass parameters as using the following callback syntax: `originalFactory(defineParams => defineParams())`' - : Partial; - }) - >, - ) => ExtensionDataContainer>, - context: { - node: AppNode; - apis: ApiHolder; - config: T['config'] & { - [key in keyof TExtensionConfigSchema]: z.infer< - ReturnType - >; - }; - inputs: Expand>; - }, - ): Iterable; - } & ([T['params']] extends [never] - ? {} - : { - params?: TParamsInput extends ExtensionBlueprintDefineParams - ? TParamsInput - : T['params'] extends ExtensionBlueprintDefineParams - ? 'Error: This blueprint uses advanced parameter types and requires you to pass parameters as using the following callback syntax: `originalFactory(defineParams => defineParams())`' - : Partial; - }) - > & - VerifyExtensionFactoryOutput< - ExtensionDataRef extends UNewOutput - ? NonNullable - : UNewOutput, - UFactoryOutput - >, - ): ExtensionDefinition<{ - kind: T['kind']; - name: T['name']; - output: ExtensionDataRef extends UNewOutput ? T['output'] : UNewOutput; - inputs: T['inputs'] & TExtraInputs; - config: T['config'] & { - [key in keyof TExtensionConfigSchema]: z.infer< - ReturnType - >; - }; - configInput: T['configInput'] & - z.input< - z.ZodObject<{ - [key in keyof TExtensionConfigSchema]: ReturnType< - TExtensionConfigSchema[key] - >; - }> - >; - }>; -}; + // (undocumented) + readonly T: TParams; +} // @public export type ExtensionDefinitionAttachTo< @@ -1544,6 +1441,118 @@ export { OpenIdConnectApi }; export { openshiftAuthApiRef }; +// @public (undocumented) +export interface OverridableExtensionDefinition< + T extends ExtensionDefinitionParameters = ExtensionDefinitionParameters, +> extends ExtensionDefinition { + readonly inputs: { + [K in keyof T['inputs']]: ExtensionInput< + T['inputs'][K] extends ExtensionInput ? IData : never + >; + }; + // (undocumented) + override< + TExtensionConfigSchema extends { + [key in string]: (zImpl: typeof z) => z.ZodType; + }, + UFactoryOutput extends ExtensionDataValue, + UNewOutput extends ExtensionDataRef, + TExtraInputs extends { + [inputName in string]: ExtensionInput; + }, + TParamsInput extends AnyParamsInput_2>, + UParentInputs extends ExtensionDataRef, + >( + args: Expand< + { + attachTo?: ExtensionDefinitionAttachTo & + VerifyExtensionAttachTo< + ExtensionDataRef extends UNewOutput + ? NonNullable + : UNewOutput, + UParentInputs + >; + disabled?: boolean; + inputs?: TExtraInputs & { + [KName in keyof T['inputs']]?: `Error: Input '${KName & + string}' is already defined in parent definition`; + }; + output?: Array; + config?: { + schema: TExtensionConfigSchema & { + [KName in keyof T['config']]?: `Error: Config key '${KName & + string}' is already defined in parent schema`; + }; + }; + factory?( + originalFactory: < + TFactoryParamsReturn extends AnyParamsInput_2< + NonNullable + >, + >( + context?: Expand< + { + config?: T['config']; + inputs?: ResolvedInputValueOverrides>; + } & ([T['params']] extends [never] + ? {} + : { + params?: TFactoryParamsReturn extends ExtensionBlueprintDefineParams + ? TFactoryParamsReturn + : T['params'] extends ExtensionBlueprintDefineParams + ? 'Error: This blueprint uses advanced parameter types and requires you to pass parameters as using the following callback syntax: `originalFactory(defineParams => defineParams())`' + : Partial; + }) + >, + ) => ExtensionDataContainer>, + context: { + node: AppNode; + apis: ApiHolder; + config: T['config'] & { + [key in keyof TExtensionConfigSchema]: z.infer< + ReturnType + >; + }; + inputs: Expand>; + }, + ): Iterable; + } & ([T['params']] extends [never] + ? {} + : { + params?: TParamsInput extends ExtensionBlueprintDefineParams + ? TParamsInput + : T['params'] extends ExtensionBlueprintDefineParams + ? 'Error: This blueprint uses advanced parameter types and requires you to pass parameters as using the following callback syntax: `originalFactory(defineParams => defineParams())`' + : Partial; + }) + > & + VerifyExtensionFactoryOutput< + ExtensionDataRef extends UNewOutput + ? NonNullable + : UNewOutput, + UFactoryOutput + >, + ): OverridableExtensionDefinition<{ + kind: T['kind']; + name: T['name']; + output: ExtensionDataRef extends UNewOutput ? T['output'] : UNewOutput; + inputs: T['inputs'] & TExtraInputs; + config: T['config'] & { + [key in keyof TExtensionConfigSchema]: z.infer< + ReturnType + >; + }; + configInput: T['configInput'] & + z.input< + z.ZodObject<{ + [key in keyof TExtensionConfigSchema]: ReturnType< + TExtensionConfigSchema[key] + >; + }> + >; + }>; +} + // @public export interface OverridableFrontendPlugin< TRoutes extends { @@ -1563,7 +1572,9 @@ export interface OverridableFrontendPlugin< }, > extends FrontendPlugin { // (undocumented) - getExtension(id: TId): TExtensionMap[TId]; + getExtension( + id: TId, + ): OverridableExtensionDefinition; // (undocumented) withOverrides(options: { extensions: Array; diff --git a/packages/frontend-plugin-api/src/wiring/createExtension.ts b/packages/frontend-plugin-api/src/wiring/createExtension.ts index 0fec40f4c9..0268cadf51 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtension.ts +++ b/packages/frontend-plugin-api/src/wiring/createExtension.ts @@ -233,12 +233,17 @@ type AnyParamsInput = ) => ReturnType>); /** @public */ -export type ExtensionDefinition< - T extends ExtensionDefinitionParameters = ExtensionDefinitionParameters, -> = { +export interface ExtensionDefinition< + TParams extends ExtensionDefinitionParameters = ExtensionDefinitionParameters, +> { $$type: '@backstage/ExtensionDefinition'; - readonly T: T; + readonly T: TParams; +} +/** @public */ +export interface OverridableExtensionDefinition< + T extends ExtensionDefinitionParameters = ExtensionDefinitionParameters, +> extends ExtensionDefinition { /** * References to the inputs of this extension, which can be used to attach child extensions. */ @@ -327,7 +332,7 @@ export type ExtensionDefinition< : UNewOutput, UFactoryOutput >, - ): ExtensionDefinition<{ + ): OverridableExtensionDefinition<{ kind: T['kind']; name: T['name']; output: ExtensionDataRef extends UNewOutput ? T['output'] : UNewOutput; @@ -346,7 +351,7 @@ export type ExtensionDefinition< }> >; }>; -}; +} /** * @internal @@ -425,7 +430,7 @@ export function createExtension< UFactoryOutput, UParentInputs >, -): ExtensionDefinition<{ +): OverridableExtensionDefinition<{ config: string extends keyof TConfigSchema ? {} : { @@ -638,7 +643,7 @@ export function createExtension< return deduplicatedResult.values(); }, - }) as ExtensionDefinition; + }) as OverridableExtensionDefinition; }, }); } diff --git a/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts b/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts index f9a3731743..70b6209ae3 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts +++ b/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts @@ -19,7 +19,7 @@ import { Expand } from '@backstage/types'; import { OpaqueType } from '@internal/opaque'; import { ExtensionDefinitionAttachTo, - ExtensionDefinition, + OverridableExtensionDefinition, ResolvedExtensionInputs, VerifyExtensionFactoryOutput, createExtension, @@ -226,7 +226,7 @@ export interface ExtensionBlueprint< : T['params'] extends ExtensionBlueprintDefineParams ? 'Error: This blueprint uses advanced parameter types and requires you to pass parameters as using the following callback syntax: `.make({ params: defineParams => defineParams() })`' : T['params']; - }): ExtensionDefinition<{ + }): OverridableExtensionDefinition<{ kind: T['kind']; name: string | undefined extends TName ? undefined : TName; config: T['config']; @@ -303,7 +303,7 @@ export interface ExtensionBlueprint< : UNewOutput, UFactoryOutput >; - }): ExtensionDefinition<{ + }): OverridableExtensionDefinition<{ config: (string extends keyof TExtensionConfigSchema ? {} : { @@ -514,7 +514,7 @@ export function createExtensionBlueprint< unwrapParams(args.params, ctx, defineParams, options.kind), ctx, ) as Iterable>, - }) as ExtensionDefinition; + }) as OverridableExtensionDefinition; }, makeWithOverrides(args) { return createExtension({ @@ -572,7 +572,7 @@ export function createExtensionBlueprint< }, ) as Iterable>; }, - }) as ExtensionDefinition; + }) as OverridableExtensionDefinition; }, } as ExtensionBlueprint<{ kind: TKind; diff --git a/packages/frontend-plugin-api/src/wiring/createFrontendPlugin.ts b/packages/frontend-plugin-api/src/wiring/createFrontendPlugin.ts index 5555a0b47c..68b5826baa 100644 --- a/packages/frontend-plugin-api/src/wiring/createFrontendPlugin.ts +++ b/packages/frontend-plugin-api/src/wiring/createFrontendPlugin.ts @@ -18,7 +18,10 @@ import { OpaqueExtensionDefinition, OpaqueFrontendPlugin, } from '@internal/frontend'; -import { ExtensionDefinition } from './createExtension'; +import { + ExtensionDefinition, + OverridableExtensionDefinition, +} from './createExtension'; import { Extension, resolveExtensionDefinition, @@ -104,7 +107,9 @@ export interface OverridableFrontendPlugin< [id in string]: ExtensionDefinition; }, > extends FrontendPlugin { - getExtension(id: TId): TExtensionMap[TId]; + getExtension( + id: TId, + ): OverridableExtensionDefinition; withOverrides(options: { extensions: Array; diff --git a/packages/frontend-plugin-api/src/wiring/index.ts b/packages/frontend-plugin-api/src/wiring/index.ts index 1bbdf68b13..6ce1bb4998 100644 --- a/packages/frontend-plugin-api/src/wiring/index.ts +++ b/packages/frontend-plugin-api/src/wiring/index.ts @@ -15,12 +15,13 @@ */ export { coreExtensionData } from './coreExtensionData'; +export { createExtension } from './createExtension'; export { - createExtension, type ExtensionDefinition, type ExtensionDefinitionAttachTo, type ExtensionDefinitionParameters, type CreateExtensionOptions, + type OverridableExtensionDefinition, type ResolvedExtensionInput, type ResolvedExtensionInputs, } from './createExtension'; diff --git a/packages/ui/README.md b/packages/ui/README.md index 1a0fb84a0c..271b78fca4 100644 --- a/packages/ui/README.md +++ b/packages/ui/README.md @@ -16,3 +16,26 @@ yarn add @backstage/ui - [Backstage UI Documentation](https://ui.backstage.io) - [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md) - [Backstage Documentation](https://backstage.io/docs) + +## Writing Changesets for Components + +When creating changesets for component-specific changes, add component metadata to help maintain documentation: + +```markdown +--- +'@backstage/ui': patch +--- + +Fixed size prop handling for Avatar component. + +Affected components: Avatar +``` + +**Guidelines:** + +- **Component names**: Use PascalCase as they appear in imports (Avatar, ButtonIcon, SearchField) +- **Multiple components**: `Affected components: Button, ButtonLink, ButtonIcon` +- **General changes**: Omit the metadata line (build changes, package-level updates) +- **Placement**: The line can appear anywhere in the description + +The changelog sync tool will parse these tags and update the documentation site automatically. diff --git a/packages/ui/report.api.md b/packages/ui/report.api.md index 4f6087b0f0..30910724eb 100644 --- a/packages/ui/report.api.md +++ b/packages/ui/report.api.md @@ -58,6 +58,20 @@ export const Accordion: ForwardRefExoticComponent< AccordionProps & RefAttributes >; +// @public +export const AccordionDefinition: { + readonly classNames: { + readonly root: 'bui-Accordion'; + readonly trigger: 'bui-AccordionTrigger'; + readonly triggerButton: 'bui-AccordionTriggerButton'; + readonly triggerTitle: 'bui-AccordionTriggerTitle'; + readonly triggerSubtitle: 'bui-AccordionTriggerSubtitle'; + readonly triggerIcon: 'bui-AccordionTriggerIcon'; + readonly panel: 'bui-AccordionPanel'; + readonly group: 'bui-AccordionGroup'; + }; +}; + // @public (undocumented) export const AccordionGroup: ForwardRefExoticComponent< AccordionGroupProps & RefAttributes @@ -112,6 +126,18 @@ export const Avatar: ForwardRefExoticComponent< AvatarProps & RefAttributes >; +// @public +export const AvatarDefinition: { + readonly classNames: { + readonly root: 'bui-AvatarRoot'; + readonly image: 'bui-AvatarImage'; + readonly fallback: 'bui-AvatarFallback'; + }; + readonly dataAttributes: { + readonly size: readonly ['small', 'medium', 'large']; + }; +}; + // @public (undocumented) export interface AvatarProps extends React.ComponentPropsWithoutRef<'div'> { name: string; @@ -139,6 +165,37 @@ export const Box: ForwardRefExoticComponent< BoxProps & RefAttributes >; +// @public +export const BoxDefinition: { + readonly classNames: { + readonly root: 'bui-Box'; + }; + readonly utilityProps: [ + 'm', + 'mb', + 'ml', + 'mr', + 'mt', + 'mx', + 'my', + 'p', + 'pb', + 'pl', + 'pr', + 'pt', + 'px', + 'py', + 'position', + 'display', + 'width', + 'minWidth', + 'maxWidth', + 'height', + 'minHeight', + 'maxHeight', + ]; +}; + // @public (undocumented) export interface BoxProps extends SpaceProps { // (undocumented) @@ -177,11 +234,34 @@ export const Button: ForwardRefExoticComponent< ButtonProps & RefAttributes >; +// @public +export const ButtonDefinition: { + readonly classNames: { + readonly root: 'bui-Button'; + readonly content: 'bui-ButtonContent'; + readonly spinner: 'bui-ButtonSpinner'; + }; + readonly dataAttributes: { + readonly size: readonly ['small', 'medium', 'large']; + readonly variant: readonly ['primary', 'secondary', 'tertiary']; + readonly loading: readonly [true, false]; + }; +}; + // @public (undocumented) export const ButtonIcon: ForwardRefExoticComponent< ButtonIconProps & RefAttributes >; +// @public +export const ButtonIconDefinition: { + readonly classNames: { + readonly root: 'bui-ButtonIcon'; + readonly content: 'bui-ButtonIconContent'; + readonly spinner: 'bui-ButtonIconSpinner'; + }; +}; + // @public export interface ButtonIconProps extends ButtonProps_2 { // (undocumented) @@ -203,6 +283,13 @@ export const ButtonLink: ForwardRefExoticComponent< ButtonLinkProps & RefAttributes >; +// @public +export const ButtonLinkDefinition: { + readonly classNames: { + readonly root: 'bui-ButtonLink'; + }; +}; + // @public export interface ButtonLinkProps extends LinkProps_2 { // (undocumented) @@ -257,6 +344,16 @@ export interface CardBodyProps extends React.HTMLAttributes { children?: React.ReactNode; } +// @public +export const CardDefinition: { + readonly classNames: { + readonly root: 'bui-Card'; + readonly header: 'bui-CardHeader'; + readonly body: 'bui-CardBody'; + readonly footer: 'bui-CardFooter'; + }; +}; + // @public export const CardFooter: ForwardRefExoticComponent< CardFooterProps & RefAttributes @@ -297,7 +394,7 @@ export const CellProfile: (props: CellProfileProps) => JSX_2.Element; // @public (undocumented) export interface CellProfileProps extends CellProps_2 { // (undocumented) - color?: 'primary' | 'secondary'; + color?: TextColors; // (undocumented) description?: string; // (undocumented) @@ -311,7 +408,7 @@ export interface CellProfileProps extends CellProps_2 { // @public (undocumented) export interface CellProps extends CellProps_2 { // (undocumented) - color?: 'primary' | 'secondary'; + color?: TextColors; // (undocumented) description?: string; // (undocumented) @@ -327,6 +424,17 @@ export const Checkbox: ForwardRefExoticComponent< CheckboxProps & RefAttributes >; +// @public +export const CheckboxDefinition: { + readonly classNames: { + readonly root: 'bui-Checkbox'; + readonly indicator: 'bui-CheckboxIndicator'; + }; + readonly dataAttributes: { + readonly selected: readonly [true, false]; + }; +}; + // @public (undocumented) export interface CheckboxProps extends CheckboxProps_2 { // (undocumented) @@ -361,10 +469,6 @@ export type Columns = | '12' | 'auto'; -// @public -export type ComponentClassNames = - (typeof componentDefinitions)[T]['classNames']; - // @public export interface ComponentDefinition { // (undocumented) @@ -375,431 +479,19 @@ export interface ComponentDefinition { utilityProps?: string[]; } -// @public -export type ComponentDefinitionName = keyof typeof componentDefinitions; - -// @public -export const componentDefinitions: { - readonly Avatar: { - readonly classNames: { - readonly root: 'bui-AvatarRoot'; - readonly image: 'bui-AvatarImage'; - readonly fallback: 'bui-AvatarFallback'; - }; - readonly dataAttributes: { - readonly size: readonly ['small', 'medium', 'large']; - }; - }; - readonly Box: { - readonly classNames: { - readonly root: 'bui-Box'; - }; - readonly utilityProps: [ - 'm', - 'mb', - 'ml', - 'mr', - 'mt', - 'mx', - 'my', - 'p', - 'pb', - 'pl', - 'pr', - 'pt', - 'px', - 'py', - 'position', - 'display', - 'width', - 'minWidth', - 'maxWidth', - 'height', - 'minHeight', - 'maxHeight', - ]; - }; - readonly Button: { - readonly classNames: { - readonly root: 'bui-Button'; - readonly content: 'bui-ButtonContent'; - readonly spinner: 'bui-ButtonSpinner'; - }; - readonly dataAttributes: { - readonly size: readonly ['small', 'medium', 'large']; - readonly variant: readonly ['primary', 'secondary', 'tertiary']; - readonly loading: readonly [true, false]; - }; - }; - readonly ButtonIcon: { - readonly classNames: { - readonly root: 'bui-ButtonIcon'; - readonly content: 'bui-ButtonIconContent'; - readonly spinner: 'bui-ButtonIconSpinner'; - }; - }; - readonly ButtonLink: { - readonly classNames: { - readonly root: 'bui-ButtonLink'; - }; - }; - readonly Card: { - readonly classNames: { - readonly root: 'bui-Card'; - readonly header: 'bui-CardHeader'; - readonly body: 'bui-CardBody'; - readonly footer: 'bui-CardFooter'; - }; - }; - readonly Checkbox: { - readonly classNames: { - readonly root: 'bui-Checkbox'; - readonly indicator: 'bui-CheckboxIndicator'; - }; - readonly dataAttributes: { - readonly selected: readonly [true, false]; - }; - }; - readonly Container: { - readonly classNames: { - readonly root: 'bui-Container'; - }; - readonly utilityProps: ['my', 'mt', 'mb', 'py', 'pt', 'pb', 'display']; - }; - readonly Dialog: { - readonly classNames: { - readonly overlay: 'bui-DialogOverlay'; - readonly dialog: 'bui-Dialog'; - readonly header: 'bui-DialogHeader'; - readonly headerTitle: 'bui-DialogHeaderTitle'; - readonly body: 'bui-DialogBody'; - readonly footer: 'bui-DialogFooter'; - }; - }; - readonly Accordion: { - readonly classNames: { - readonly root: 'bui-Accordion'; - readonly trigger: 'bui-AccordionTrigger'; - readonly triggerButton: 'bui-AccordionTriggerButton'; - readonly triggerTitle: 'bui-AccordionTriggerTitle'; - readonly triggerSubtitle: 'bui-AccordionTriggerSubtitle'; - readonly triggerIcon: 'bui-AccordionTriggerIcon'; - readonly panel: 'bui-AccordionPanel'; - readonly group: 'bui-AccordionGroup'; - }; - }; - readonly FieldError: { - readonly classNames: { - readonly root: 'bui-FieldError'; - }; - }; - readonly FieldLabel: { - readonly classNames: { - readonly root: 'bui-FieldLabelWrapper'; - readonly label: 'bui-FieldLabel'; - readonly secondaryLabel: 'bui-FieldSecondaryLabel'; - readonly description: 'bui-FieldDescription'; - }; - }; - readonly Flex: { - readonly classNames: { - readonly root: 'bui-Flex'; - }; - readonly utilityProps: [ - 'm', - 'mb', - 'ml', - 'mr', - 'mt', - 'mx', - 'my', - 'p', - 'pb', - 'pl', - 'pr', - 'pt', - 'px', - 'py', - 'gap', - 'align', - 'justify', - 'direction', - ]; - }; - readonly Grid: { - readonly classNames: { - readonly root: 'bui-Grid'; - }; - readonly utilityProps: [ - 'columns', - 'gap', - 'm', - 'mb', - 'ml', - 'mr', - 'mt', - 'mx', - 'my', - 'p', - 'pb', - 'pl', - 'pr', - 'pt', - 'px', - 'py', - ]; - }; - readonly GridItem: { - readonly classNames: { - readonly root: 'bui-GridItem'; - }; - readonly utilityProps: ['colSpan', 'colEnd', 'colStart', 'rowSpan']; - }; - readonly Header: { - readonly classNames: { - readonly toolbar: 'bui-HeaderToolbar'; - readonly toolbarWrapper: 'bui-HeaderToolbarWrapper'; - readonly toolbarContent: 'bui-HeaderToolbarContent'; - readonly toolbarControls: 'bui-HeaderToolbarControls'; - readonly toolbarIcon: 'bui-HeaderToolbarIcon'; - readonly toolbarName: 'bui-HeaderToolbarName'; - readonly tabsWrapper: 'bui-HeaderTabsWrapper'; - }; - }; - readonly HeaderPage: { - readonly classNames: { - readonly root: 'bui-HeaderPage'; - readonly content: 'bui-HeaderPageContent'; - readonly breadcrumbs: 'bui-HeaderPageBreadcrumbs'; - readonly tabsWrapper: 'bui-HeaderPageTabsWrapper'; - readonly controls: 'bui-HeaderPageControls'; - }; - }; - readonly Heading: { - readonly classNames: { - readonly root: 'bui-Heading'; - }; - readonly dataAttributes: { - readonly variant: readonly ['title1', 'title2', 'title3', 'subtitle']; - readonly color: readonly ['primary', 'secondary', 'muted']; - readonly truncate: readonly [true, false]; - }; - }; - readonly Icon: { - readonly classNames: { - readonly root: 'bui-Icon'; - }; - }; - readonly Link: { - readonly classNames: { - readonly root: 'bui-Link'; - }; - readonly dataAttributes: { - readonly variant: readonly ['subtitle', 'body', 'caption', 'label']; - readonly weight: readonly ['regular', 'bold']; - readonly color: readonly [ - 'primary', - 'secondary', - 'danger', - 'warning', - 'success', - ]; - readonly truncate: readonly [true, false]; - }; - }; - readonly List: { - readonly classNames: { - readonly root: 'bui-List'; - readonly row: 'bui-ListRow'; - readonly label: 'bui-ListLabel'; - }; - }; - readonly Menu: { - readonly classNames: { - readonly root: 'bui-Menu'; - readonly popover: 'bui-MenuPopover'; - readonly content: 'bui-MenuContent'; - readonly section: 'bui-MenuSection'; - readonly sectionHeader: 'bui-MenuSectionHeader'; - readonly item: 'bui-MenuItem'; - readonly itemListBox: 'bui-MenuItemListBox'; - readonly itemListBoxCheck: 'bui-MenuItemListBoxCheck'; - readonly itemWrapper: 'bui-MenuItemWrapper'; - readonly itemContent: 'bui-MenuItemContent'; - readonly itemArrow: 'bui-MenuItemArrow'; - readonly separator: 'bui-MenuSeparator'; - readonly searchField: 'bui-MenuSearchField'; - readonly searchFieldInput: 'bui-MenuSearchFieldInput'; - readonly searchFieldClear: 'bui-MenuSearchFieldClear'; - readonly emptyState: 'bui-MenuEmptyState'; - }; - }; - readonly PasswordField: { - readonly classNames: { - readonly root: 'bui-PasswordField'; - readonly inputWrapper: 'bui-PasswordFieldInputWrapper'; - readonly input: 'bui-PasswordFieldInput'; - readonly inputIcon: 'bui-PasswordFieldIcon'; - readonly inputVisibility: 'bui-PasswordFieldVisibility'; - }; - readonly dataAttributes: { - readonly size: readonly ['small', 'medium']; - }; - }; - readonly Popover: { - readonly classNames: { - readonly root: 'bui-Popover'; - }; - }; - readonly RadioGroup: { - readonly classNames: { - readonly root: 'bui-RadioGroup'; - readonly content: 'bui-RadioGroupContent'; - readonly radio: 'bui-Radio'; - }; - }; - readonly SearchField: { - readonly classNames: { - readonly root: 'bui-SearchField'; - readonly clear: 'bui-SearchFieldClear'; - readonly inputWrapper: 'bui-SearchFieldInputWrapper'; - readonly input: 'bui-SearchFieldInput'; - readonly inputIcon: 'bui-SearchFieldInputIcon'; - }; - readonly dataAttributes: { - readonly startCollapsed: readonly [true, false]; - readonly size: readonly ['small', 'medium']; - }; - }; - readonly Select: { - readonly classNames: { - readonly root: 'bui-Select'; - readonly popover: 'bui-SelectPopover'; - readonly trigger: 'bui-SelectTrigger'; - readonly chevron: 'bui-SelectTriggerChevron'; - readonly value: 'bui-SelectValue'; - readonly list: 'bui-SelectList'; - readonly item: 'bui-SelectItem'; - readonly itemIndicator: 'bui-SelectItemIndicator'; - readonly itemLabel: 'bui-SelectItemLabel'; - readonly searchWrapper: 'bui-SelectSearchWrapper'; - readonly search: 'bui-SelectSearch'; - readonly searchClear: 'bui-SelectSearchClear'; - readonly noResults: 'bui-SelectNoResults'; - }; - readonly dataAttributes: { - readonly size: readonly ['small', 'medium']; - }; - }; - readonly Skeleton: { - readonly classNames: { - readonly root: 'bui-Skeleton'; - }; - }; - readonly Switch: { - readonly classNames: { - readonly root: 'bui-Switch'; - readonly indicator: 'bui-SwitchIndicator'; - }; - }; - readonly Table: { - readonly classNames: { - readonly table: 'bui-Table'; - readonly header: 'bui-TableHeader'; - readonly body: 'bui-TableBody'; - readonly row: 'bui-TableRow'; - readonly head: 'bui-TableHead'; - readonly headContent: 'bui-TableHeadContent'; - readonly headSortButton: 'bui-TableHeadSortButton'; - readonly caption: 'bui-TableCaption'; - readonly cell: 'bui-TableCell'; - readonly cellContentWrapper: 'bui-TableCellContentWrapper'; - readonly cellContent: 'bui-TableCellContent'; - readonly cellIcon: 'bui-TableCellIcon'; - readonly cellProfileAvatar: 'bui-TableCellProfileAvatar'; - readonly cellProfileAvatarImage: 'bui-TableCellProfileAvatarImage'; - readonly cellProfileAvatarFallback: 'bui-TableCellProfileAvatarFallback'; - readonly cellProfileName: 'bui-TableCellProfileName'; - readonly cellProfileLink: 'bui-TableCellProfileLink'; - }; - }; - readonly TablePagination: { - readonly classNames: { - readonly root: 'bui-TablePagination'; - readonly left: 'bui-TablePaginationLeft'; - readonly right: 'bui-TablePaginationRight'; - readonly select: 'bui-TablePaginationSelect'; - }; - }; - readonly Tabs: { - readonly classNames: { - readonly tabs: 'bui-Tabs'; - readonly tabList: 'bui-TabList'; - readonly tabListWrapper: 'bui-TabListWrapper'; - readonly tab: 'bui-Tab'; - readonly tabActive: 'bui-TabActive'; - readonly tabHovered: 'bui-TabHovered'; - readonly panel: 'bui-TabPanel'; - }; - }; - readonly TagGroup: { - readonly classNames: { - readonly group: 'bui-TagGroup'; - readonly list: 'bui-TagList'; - readonly tag: 'bui-Tag'; - readonly tagIcon: 'bui-TagIcon'; - readonly tagRemoveButton: 'bui-TagRemoveButton'; - }; - }; - readonly Text: { - readonly classNames: { - readonly root: 'bui-Text'; - }; - readonly dataAttributes: { - readonly variant: readonly ['subtitle', 'body', 'caption', 'label']; - readonly weight: readonly ['regular', 'bold']; - readonly color: readonly [ - 'primary', - 'secondary', - 'danger', - 'warning', - 'success', - ]; - readonly truncate: readonly [true, false]; - }; - }; - readonly TextField: { - readonly classNames: { - readonly root: 'bui-TextField'; - readonly inputWrapper: 'bui-InputWrapper'; - readonly input: 'bui-Input'; - readonly inputIcon: 'bui-InputIcon'; - readonly inputAction: 'bui-InputAction'; - }; - readonly dataAttributes: { - readonly invalid: readonly [true, false]; - readonly disabled: readonly [true, false]; - readonly size: readonly ['small', 'medium']; - }; - }; - readonly Tooltip: { - readonly classNames: { - readonly tooltip: 'bui-Tooltip'; - readonly arrow: 'bui-TooltipArrow'; - }; - }; - readonly VisuallyHidden: { - readonly classNames: { - readonly root: 'bui-VisuallyHidden'; - }; - }; -}; - // @public (undocumented) export const Container: ForwardRefExoticComponent< ContainerProps & RefAttributes >; +// @public +export const ContainerDefinition: { + readonly classNames: { + readonly root: 'bui-Container'; + }; + readonly utilityProps: ['my', 'mt', 'mb', 'py', 'pt', 'pb', 'display']; +}; + // @public (undocumented) export interface ContainerProps { // (undocumented) @@ -846,6 +538,18 @@ export interface DialogBodyProps { className?: string; } +// @public +export const DialogDefinition: { + readonly classNames: { + readonly overlay: 'bui-DialogOverlay'; + readonly dialog: 'bui-Dialog'; + readonly header: 'bui-DialogHeader'; + readonly headerTitle: 'bui-DialogHeaderTitle'; + readonly body: 'bui-DialogBody'; + readonly footer: 'bui-DialogFooter'; + }; +}; + // @public (undocumented) export const DialogFooter: ForwardRefExoticComponent< Omit< @@ -894,6 +598,16 @@ export const FieldLabel: ForwardRefExoticComponent< FieldLabelProps & RefAttributes >; +// @public +export const FieldLabelDefinition: { + readonly classNames: { + readonly root: 'bui-FieldLabelWrapper'; + readonly label: 'bui-FieldLabel'; + readonly secondaryLabel: 'bui-FieldSecondaryLabel'; + readonly description: 'bui-FieldDescription'; + }; +}; + // @public (undocumented) export interface FieldLabelProps extends Pick, 'className'> { @@ -909,6 +623,33 @@ export const Flex: ForwardRefExoticComponent< FlexProps & RefAttributes >; +// @public +export const FlexDefinition: { + readonly classNames: { + readonly root: 'bui-Flex'; + }; + readonly utilityProps: [ + 'm', + 'mb', + 'ml', + 'mr', + 'mt', + 'mx', + 'my', + 'p', + 'pb', + 'pl', + 'pr', + 'pt', + 'px', + 'py', + 'gap', + 'align', + 'justify', + 'direction', + ]; +}; + // @public (undocumented) export type FlexDirection = 'row' | 'column'; @@ -941,6 +682,39 @@ export const Grid: { >; }; +// @public +export const GridDefinition: { + readonly classNames: { + readonly root: 'bui-Grid'; + }; + readonly utilityProps: [ + 'columns', + 'gap', + 'm', + 'mb', + 'ml', + 'mr', + 'mt', + 'mx', + 'my', + 'p', + 'pb', + 'pl', + 'pr', + 'pt', + 'px', + 'py', + ]; +}; + +// @public +export const GridItemDefinition: { + readonly classNames: { + readonly root: 'bui-GridItem'; + }; + readonly utilityProps: ['colSpan', 'colEnd', 'colStart', 'rowSpan']; +}; + // @public (undocumented) export interface GridItemProps { // (undocumented) @@ -976,6 +750,19 @@ export interface GridProps extends SpaceProps { // @public export const Header: (props: HeaderProps) => JSX_2.Element; +// @public +export const HeaderDefinition: { + readonly classNames: { + readonly toolbar: 'bui-HeaderToolbar'; + readonly toolbarWrapper: 'bui-HeaderToolbarWrapper'; + readonly toolbarContent: 'bui-HeaderToolbarContent'; + readonly toolbarControls: 'bui-HeaderToolbarControls'; + readonly toolbarIcon: 'bui-HeaderToolbarIcon'; + readonly toolbarName: 'bui-HeaderToolbarName'; + readonly tabsWrapper: 'bui-HeaderTabsWrapper'; + }; +}; + // @public export const HeaderPage: (props: HeaderPageProps) => JSX_2.Element; @@ -987,6 +774,17 @@ export interface HeaderPageBreadcrumb { label: string; } +// @public +export const HeaderPageDefinition: { + readonly classNames: { + readonly root: 'bui-HeaderPage'; + readonly content: 'bui-HeaderPageContent'; + readonly breadcrumbs: 'bui-HeaderPageBreadcrumbs'; + readonly tabsWrapper: 'bui-HeaderPageTabsWrapper'; + readonly controls: 'bui-HeaderPageControls'; + }; +}; + // @public export interface HeaderPageProps { // (undocumented) @@ -1044,6 +842,25 @@ export const Link: ForwardRefExoticComponent< LinkProps & RefAttributes >; +// @public +export const LinkDefinition: { + readonly classNames: { + readonly root: 'bui-Link'; + }; + readonly dataAttributes: { + readonly variant: readonly ['subtitle', 'body', 'caption', 'label']; + readonly weight: readonly ['regular', 'bold']; + readonly color: readonly [ + 'primary', + 'secondary', + 'danger', + 'warning', + 'success', + ]; + readonly truncate: readonly [true, false]; + }; +}; + // @public (undocumented) export interface LinkProps extends LinkProps_2 { // (undocumented) @@ -1104,6 +921,28 @@ export interface MenuAutocompleteProps virtualized?: boolean; } +// @public +export const MenuDefinition: { + readonly classNames: { + readonly root: 'bui-Menu'; + readonly popover: 'bui-MenuPopover'; + readonly content: 'bui-MenuContent'; + readonly section: 'bui-MenuSection'; + readonly sectionHeader: 'bui-MenuSectionHeader'; + readonly item: 'bui-MenuItem'; + readonly itemListBox: 'bui-MenuItemListBox'; + readonly itemListBoxCheck: 'bui-MenuItemListBoxCheck'; + readonly itemWrapper: 'bui-MenuItemWrapper'; + readonly itemContent: 'bui-MenuItemContent'; + readonly itemArrow: 'bui-MenuItemArrow'; + readonly separator: 'bui-MenuSeparator'; + readonly searchField: 'bui-MenuSearchField'; + readonly searchFieldInput: 'bui-MenuSearchFieldInput'; + readonly searchFieldClear: 'bui-MenuSearchFieldClear'; + readonly emptyState: 'bui-MenuEmptyState'; + }; +}; + // @public (undocumented) export const MenuItem: (props: MenuItemProps) => JSX_2.Element; @@ -1204,6 +1043,15 @@ export const RadioGroup: ForwardRefExoticComponent< RadioGroupProps & RefAttributes >; +// @public +export const RadioGroupDefinition: { + readonly classNames: { + readonly root: 'bui-RadioGroup'; + readonly content: 'bui-RadioGroupContent'; + readonly radio: 'bui-Radio'; + }; +}; + // @public (undocumented) export interface RadioGroupProps extends Omit, @@ -1226,6 +1074,21 @@ export const SearchField: ForwardRefExoticComponent< SearchFieldProps & RefAttributes >; +// @public +export const SearchFieldDefinition: { + readonly classNames: { + readonly root: 'bui-SearchField'; + readonly clear: 'bui-SearchFieldClear'; + readonly inputWrapper: 'bui-SearchFieldInputWrapper'; + readonly input: 'bui-SearchFieldInput'; + readonly inputIcon: 'bui-SearchFieldInputIcon'; + }; + readonly dataAttributes: { + readonly startCollapsed: readonly [true, false]; + readonly size: readonly ['small', 'medium']; + }; +}; + // @public (undocumented) export interface SearchFieldProps extends SearchFieldProps_2, @@ -1241,6 +1104,28 @@ export const Select: ForwardRefExoticComponent< SelectProps<'multiple' | 'single'> & RefAttributes >; +// @public +export const SelectDefinition: { + readonly classNames: { + readonly root: 'bui-Select'; + readonly popover: 'bui-SelectPopover'; + readonly trigger: 'bui-SelectTrigger'; + readonly chevron: 'bui-SelectTriggerChevron'; + readonly value: 'bui-SelectValue'; + readonly list: 'bui-SelectList'; + readonly item: 'bui-SelectItem'; + readonly itemIndicator: 'bui-SelectItemIndicator'; + readonly itemLabel: 'bui-SelectItemLabel'; + readonly searchWrapper: 'bui-SelectSearchWrapper'; + readonly search: 'bui-SelectSearch'; + readonly searchClear: 'bui-SelectSearchClear'; + readonly noResults: 'bui-SelectNoResults'; + }; + readonly dataAttributes: { + readonly size: readonly ['small', 'medium']; + }; +}; + // @public (undocumented) export interface SelectProps extends SelectProps_2, @@ -1256,6 +1141,13 @@ export interface SelectProps // @public (undocumented) export const Skeleton: (props: SkeletonProps) => JSX_2.Element; +// @public +export const SkeletonDefinition: { + readonly classNames: { + readonly root: 'bui-Skeleton'; + }; +}; + // @public (undocumented) export interface SkeletonProps extends ComponentProps<'div'> { // (undocumented) @@ -1329,6 +1221,14 @@ export const Switch: ForwardRefExoticComponent< SwitchProps & RefAttributes >; +// @public +export const SwitchDefinition: { + readonly classNames: { + readonly root: 'bui-Switch'; + readonly indicator: 'bui-SwitchIndicator'; + }; +}; + // @public (undocumented) export interface SwitchProps extends SwitchProps_2 { label?: string; @@ -1345,6 +1245,29 @@ export const TableBody: ( props: TableBodyProps, ) => JSX_2.Element; +// @public +export const TableDefinition: { + readonly classNames: { + readonly table: 'bui-Table'; + readonly header: 'bui-TableHeader'; + readonly body: 'bui-TableBody'; + readonly row: 'bui-TableRow'; + readonly head: 'bui-TableHead'; + readonly headContent: 'bui-TableHeadContent'; + readonly headSortButton: 'bui-TableHeadSortButton'; + readonly caption: 'bui-TableCaption'; + readonly cell: 'bui-TableCell'; + readonly cellContentWrapper: 'bui-TableCellContentWrapper'; + readonly cellContent: 'bui-TableCellContent'; + readonly cellIcon: 'bui-TableCellIcon'; + readonly cellProfileAvatar: 'bui-TableCellProfileAvatar'; + readonly cellProfileAvatarImage: 'bui-TableCellProfileAvatarImage'; + readonly cellProfileAvatarFallback: 'bui-TableCellProfileAvatarFallback'; + readonly cellProfileName: 'bui-TableCellProfileName'; + readonly cellProfileLink: 'bui-TableCellProfileLink'; + }; +}; + // @public (undocumented) export const TableHeader: ( props: TableHeaderProps, @@ -1353,6 +1276,16 @@ export const TableHeader: ( // @public export function TablePagination(props: TablePaginationProps): JSX_2.Element; +// @public +export const TablePaginationDefinition: { + readonly classNames: { + readonly root: 'bui-TablePagination'; + readonly left: 'bui-TablePaginationLeft'; + readonly right: 'bui-TablePaginationRight'; + readonly select: 'bui-TablePaginationSelect'; + }; +}; + // @public (undocumented) export interface TablePaginationProps extends React.HTMLAttributes { @@ -1399,6 +1332,19 @@ export interface TabProps extends TabProps_2 { // @public export const Tabs: (props: TabsProps) => JSX_2.Element | null; +// @public +export const TabsDefinition: { + readonly classNames: { + readonly tabs: 'bui-Tabs'; + readonly tabList: 'bui-TabList'; + readonly tabListWrapper: 'bui-TabListWrapper'; + readonly tab: 'bui-Tab'; + readonly tabActive: 'bui-TabActive'; + readonly tabHovered: 'bui-TabHovered'; + readonly panel: 'bui-TabPanel'; + }; +}; + // @public export interface TabsProps extends TabsProps_2 {} @@ -1410,6 +1356,17 @@ export const TagGroup: ( props: TagGroupProps, ) => JSX_2.Element; +// @public +export const TagGroupDefinition: { + readonly classNames: { + readonly group: 'bui-TagGroup'; + readonly list: 'bui-TagList'; + readonly tag: 'bui-Tag'; + readonly tagIcon: 'bui-TagIcon'; + readonly tagRemoveButton: 'bui-TagRemoveButton'; + }; +}; + // @public export interface TagGroupProps extends Omit, @@ -1438,11 +1395,46 @@ export type TextColors = 'primary' | 'secondary'; // @public (undocumented) export type TextColorStatus = 'danger' | 'warning' | 'success'; +// @public +export const TextDefinition: { + readonly classNames: { + readonly root: 'bui-Text'; + }; + readonly dataAttributes: { + readonly variant: readonly ['subtitle', 'body', 'caption', 'label']; + readonly weight: readonly ['regular', 'bold']; + readonly color: readonly [ + 'primary', + 'secondary', + 'danger', + 'warning', + 'success', + ]; + readonly truncate: readonly [true, false]; + }; +}; + // @public (undocumented) export const TextField: ForwardRefExoticComponent< TextFieldProps & RefAttributes >; +// @public +export const TextFieldDefinition: { + readonly classNames: { + readonly root: 'bui-TextField'; + readonly inputWrapper: 'bui-InputWrapper'; + readonly input: 'bui-Input'; + readonly inputIcon: 'bui-InputIcon'; + readonly inputAction: 'bui-InputAction'; + }; + readonly dataAttributes: { + readonly invalid: readonly [true, false]; + readonly disabled: readonly [true, false]; + readonly size: readonly ['small', 'medium']; + }; +}; + // @public (undocumented) export interface TextFieldProps extends TextFieldProps_2, @@ -1502,6 +1494,14 @@ export const Tooltip: ForwardRefExoticComponent< TooltipProps & RefAttributes >; +// @public +export const TooltipDefinition: { + readonly classNames: { + readonly tooltip: 'bui-Tooltip'; + readonly arrow: 'bui-TooltipArrow'; + }; +}; + // @public (undocumented) export interface TooltipProps extends Omit { // (undocumented) @@ -1597,6 +1597,13 @@ export interface UtilityProps extends SpaceProps { // @public export const VisuallyHidden: (props: VisuallyHiddenProps) => JSX_2.Element; +// @public +export const VisuallyHiddenDefinition: { + readonly classNames: { + readonly root: 'bui-VisuallyHidden'; + }; +}; + // @public export interface VisuallyHiddenProps extends ComponentProps<'div'> { // (undocumented) diff --git a/packages/ui/src/components/Accordion/Accordion.tsx b/packages/ui/src/components/Accordion/Accordion.tsx index 3f35ab7554..f31b923490 100644 --- a/packages/ui/src/components/Accordion/Accordion.tsx +++ b/packages/ui/src/components/Accordion/Accordion.tsx @@ -31,6 +31,7 @@ import type { AccordionGroupProps, } from './types'; import { useStyles } from '../../hooks/useStyles'; +import { AccordionDefinition } from './definition'; import styles from './Accordion.module.css'; import { Flex } from '../Flex'; @@ -39,7 +40,7 @@ export const Accordion = forwardRef< React.ElementRef, AccordionProps >(({ className, ...props }, ref) => { - const { classNames, cleanedProps } = useStyles('Accordion', props); + const { classNames, cleanedProps } = useStyles(AccordionDefinition, props); return ( , AccordionTriggerProps >(({ className, title, subtitle, children, ...props }, ref) => { - const { classNames, cleanedProps } = useStyles('Accordion', props); + const { classNames, cleanedProps } = useStyles(AccordionDefinition, props); return ( , AccordionPanelProps >(({ className, ...props }, ref) => { - const { classNames, cleanedProps } = useStyles('Accordion', props); + const { classNames, cleanedProps } = useStyles(AccordionDefinition, props); return ( , AccordionGroupProps >(({ className, allowsMultiple = false, ...props }, ref) => { - const { classNames, cleanedProps } = useStyles('Accordion', props); + const { classNames, cleanedProps } = useStyles(AccordionDefinition, props); return ( ((props, ref) => { - const { classNames, dataAttributes, cleanedProps } = useStyles('Avatar', { - size: 'medium', - purpose: 'informative', - ...props, - }); + const { classNames, dataAttributes, cleanedProps } = useStyles( + AvatarDefinition, + { + size: 'medium', + purpose: 'informative', + ...props, + }, + ); const { className, src, name, purpose, ...rest } = cleanedProps; diff --git a/packages/ui/src/components/Avatar/definition.ts b/packages/ui/src/components/Avatar/definition.ts new file mode 100644 index 0000000000..8ad2c31bdc --- /dev/null +++ b/packages/ui/src/components/Avatar/definition.ts @@ -0,0 +1,32 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { ComponentDefinition } from '../../types'; + +/** + * Component definition for Avatar + * @public + */ +export const AvatarDefinition = { + classNames: { + root: 'bui-AvatarRoot', + image: 'bui-AvatarImage', + fallback: 'bui-AvatarFallback', + }, + dataAttributes: { + size: ['small', 'medium', 'large'] as const, + }, +} as const satisfies ComponentDefinition; diff --git a/packages/ui/src/components/Avatar/index.ts b/packages/ui/src/components/Avatar/index.ts index d5ab42beb2..38e896bdb4 100644 --- a/packages/ui/src/components/Avatar/index.ts +++ b/packages/ui/src/components/Avatar/index.ts @@ -15,4 +15,5 @@ */ export { Avatar } from './Avatar'; +export { AvatarDefinition } from './definition'; export type { AvatarProps } from './types'; diff --git a/packages/ui/src/components/Box/Box.tsx b/packages/ui/src/components/Box/Box.tsx index fdcee3d382..34c337824b 100644 --- a/packages/ui/src/components/Box/Box.tsx +++ b/packages/ui/src/components/Box/Box.tsx @@ -19,11 +19,12 @@ import { BoxProps } from './types'; import clsx from 'clsx'; import { useStyles } from '../../hooks/useStyles'; import styles from './Box.module.css'; +import { BoxDefinition } from './definition'; /** @public */ export const Box = forwardRef((props, ref) => { const { classNames, utilityClasses, style, cleanedProps } = useStyles( - 'Box', + BoxDefinition, props, ); diff --git a/packages/ui/src/components/Box/definition.ts b/packages/ui/src/components/Box/definition.ts new file mode 100644 index 0000000000..f5b6fc6553 --- /dev/null +++ b/packages/ui/src/components/Box/definition.ts @@ -0,0 +1,51 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { ComponentDefinition } from '../../types'; + +/** + * Component definition for Box + * @public + */ +export const BoxDefinition = { + classNames: { + root: 'bui-Box', + }, + utilityProps: [ + 'm', + 'mb', + 'ml', + 'mr', + 'mt', + 'mx', + 'my', + 'p', + 'pb', + 'pl', + 'pr', + 'pt', + 'px', + 'py', + 'position', + 'display', + 'width', + 'minWidth', + 'maxWidth', + 'height', + 'minHeight', + 'maxHeight', + ], +} as const satisfies ComponentDefinition; diff --git a/packages/ui/src/components/Box/index.tsx b/packages/ui/src/components/Box/index.tsx index d47e653dfd..a2b2861efb 100644 --- a/packages/ui/src/components/Box/index.tsx +++ b/packages/ui/src/components/Box/index.tsx @@ -14,4 +14,5 @@ * limitations under the License. */ export { Box } from './Box'; +export { BoxDefinition } from './definition'; export type * from './types'; diff --git a/packages/ui/src/components/Button/Button.tsx b/packages/ui/src/components/Button/Button.tsx index 45228ff6ef..f010e5e57d 100644 --- a/packages/ui/src/components/Button/Button.tsx +++ b/packages/ui/src/components/Button/Button.tsx @@ -20,16 +20,20 @@ import { Button as RAButton, ProgressBar } from 'react-aria-components'; import { RiLoader4Line } from '@remixicon/react'; import type { ButtonProps } from './types'; import { useStyles } from '../../hooks/useStyles'; +import { ButtonDefinition } from './definition'; import styles from './Button.module.css'; /** @public */ export const Button = forwardRef( (props: ButtonProps, ref: Ref) => { - const { classNames, dataAttributes, cleanedProps } = useStyles('Button', { - size: 'small', - variant: 'primary', - ...props, - }); + const { classNames, dataAttributes, cleanedProps } = useStyles( + ButtonDefinition, + { + size: 'small', + variant: 'primary', + ...props, + }, + ); const { children, className, iconStart, iconEnd, loading, ...rest } = cleanedProps; diff --git a/packages/ui/src/components/Button/definition.ts b/packages/ui/src/components/Button/definition.ts new file mode 100644 index 0000000000..a017157774 --- /dev/null +++ b/packages/ui/src/components/Button/definition.ts @@ -0,0 +1,34 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { ComponentDefinition } from '../../types'; + +/** + * Component definition for Button + * @public + */ +export const ButtonDefinition = { + classNames: { + root: 'bui-Button', + content: 'bui-ButtonContent', + spinner: 'bui-ButtonSpinner', + }, + dataAttributes: { + size: ['small', 'medium', 'large'] as const, + variant: ['primary', 'secondary', 'tertiary'] as const, + loading: [true, false] as const, + }, +} as const satisfies ComponentDefinition; diff --git a/packages/ui/src/components/Button/index.ts b/packages/ui/src/components/Button/index.ts index b9c497ae1f..e624fcedde 100644 --- a/packages/ui/src/components/Button/index.ts +++ b/packages/ui/src/components/Button/index.ts @@ -16,3 +16,4 @@ export * from './Button'; export * from './types'; +export { ButtonDefinition } from './definition'; diff --git a/packages/ui/src/components/ButtonIcon/ButtonIcon.tsx b/packages/ui/src/components/ButtonIcon/ButtonIcon.tsx index fecccd6a37..d3596da799 100644 --- a/packages/ui/src/components/ButtonIcon/ButtonIcon.tsx +++ b/packages/ui/src/components/ButtonIcon/ButtonIcon.tsx @@ -20,19 +20,25 @@ import { Button as RAButton, ProgressBar } from 'react-aria-components'; import { RiLoader4Line } from '@remixicon/react'; import type { ButtonIconProps } from './types'; import { useStyles } from '../../hooks/useStyles'; +import { ButtonDefinition } from '../Button/definition'; +import { ButtonIconDefinition } from './definition'; import stylesButtonIcon from './ButtonIcon.module.css'; import stylesButton from '../Button/Button.module.css'; /** @public */ export const ButtonIcon = forwardRef( (props: ButtonIconProps, ref: Ref) => { - const { classNames, dataAttributes, cleanedProps } = useStyles('Button', { - size: 'small', - variant: 'primary', - ...props, - }); + const { classNames, dataAttributes, cleanedProps } = useStyles( + ButtonDefinition, + { + size: 'small', + variant: 'primary', + ...props, + }, + ); - const { classNames: classNamesButtonIcon } = useStyles('ButtonIcon'); + const { classNames: classNamesButtonIcon } = + useStyles(ButtonIconDefinition); const { className, icon, loading, ...rest } = cleanedProps; diff --git a/packages/ui/src/components/ButtonIcon/definition.ts b/packages/ui/src/components/ButtonIcon/definition.ts new file mode 100644 index 0000000000..48d0a558ab --- /dev/null +++ b/packages/ui/src/components/ButtonIcon/definition.ts @@ -0,0 +1,29 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { ComponentDefinition } from '../../types'; + +/** + * Component definition for ButtonIcon + * @public + */ +export const ButtonIconDefinition = { + classNames: { + root: 'bui-ButtonIcon', + content: 'bui-ButtonIconContent', + spinner: 'bui-ButtonIconSpinner', + }, +} as const satisfies ComponentDefinition; diff --git a/packages/ui/src/components/ButtonIcon/index.tsx b/packages/ui/src/components/ButtonIcon/index.tsx index 686fd844e8..acede912ad 100644 --- a/packages/ui/src/components/ButtonIcon/index.tsx +++ b/packages/ui/src/components/ButtonIcon/index.tsx @@ -15,4 +15,5 @@ */ export * from './ButtonIcon'; +export { ButtonIconDefinition } from './definition'; export * from './types'; diff --git a/packages/ui/src/components/ButtonLink/ButtonLink.tsx b/packages/ui/src/components/ButtonLink/ButtonLink.tsx index 28a67105bb..db3c95ee54 100644 --- a/packages/ui/src/components/ButtonLink/ButtonLink.tsx +++ b/packages/ui/src/components/ButtonLink/ButtonLink.tsx @@ -20,6 +20,8 @@ import { Link as RALink, RouterProvider } from 'react-aria-components'; import { useNavigate, useHref } from 'react-router-dom'; import type { ButtonLinkProps } from './types'; import { useStyles } from '../../hooks/useStyles'; +import { ButtonDefinition } from '../Button/definition'; +import { ButtonLinkDefinition } from './definition'; import { isExternalLink } from '../../utils/isExternalLink'; import stylesButton from '../Button/Button.module.css'; @@ -28,13 +30,17 @@ export const ButtonLink = forwardRef( (props: ButtonLinkProps, ref: Ref) => { const navigate = useNavigate(); - const { classNames, dataAttributes, cleanedProps } = useStyles('Button', { - size: 'small', - variant: 'primary', - ...props, - }); + const { classNames, dataAttributes, cleanedProps } = useStyles( + ButtonDefinition, + { + size: 'small', + variant: 'primary', + ...props, + }, + ); - const { classNames: classNamesButtonLink } = useStyles('ButtonLink'); + const { classNames: classNamesButtonLink } = + useStyles(ButtonLinkDefinition); const { children, className, iconStart, iconEnd, href, ...rest } = cleanedProps; diff --git a/packages/ui/src/components/ButtonLink/definition.ts b/packages/ui/src/components/ButtonLink/definition.ts new file mode 100644 index 0000000000..daf3fae1ea --- /dev/null +++ b/packages/ui/src/components/ButtonLink/definition.ts @@ -0,0 +1,27 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { ComponentDefinition } from '../../types'; + +/** + * Component definition for ButtonLink + * @public + */ +export const ButtonLinkDefinition = { + classNames: { + root: 'bui-ButtonLink', + }, +} as const satisfies ComponentDefinition; diff --git a/packages/ui/src/components/ButtonLink/index.ts b/packages/ui/src/components/ButtonLink/index.ts index bbfc696c67..b98f84d489 100644 --- a/packages/ui/src/components/ButtonLink/index.ts +++ b/packages/ui/src/components/ButtonLink/index.ts @@ -15,4 +15,5 @@ */ export * from './ButtonLink'; +export { ButtonLinkDefinition } from './definition'; export * from './types'; diff --git a/packages/ui/src/components/Card/Card.tsx b/packages/ui/src/components/Card/Card.tsx index b942b70649..a3f4995588 100644 --- a/packages/ui/src/components/Card/Card.tsx +++ b/packages/ui/src/components/Card/Card.tsx @@ -17,6 +17,7 @@ import { forwardRef } from 'react'; import clsx from 'clsx'; import { useStyles } from '../../hooks/useStyles'; +import { CardDefinition } from './definition'; import type { CardProps, CardHeaderProps, @@ -31,7 +32,7 @@ import styles from './Card.module.css'; * @public */ export const Card = forwardRef((props, ref) => { - const { classNames, cleanedProps } = useStyles('Card', props); + const { classNames, cleanedProps } = useStyles(CardDefinition, props); const { className, ...rest } = cleanedProps; return ( @@ -50,7 +51,7 @@ export const Card = forwardRef((props, ref) => { */ export const CardHeader = forwardRef( (props, ref) => { - const { classNames, cleanedProps } = useStyles('Card', props); + const { classNames, cleanedProps } = useStyles(CardDefinition, props); const { className, ...rest } = cleanedProps; return ( @@ -74,7 +75,7 @@ export const CardHeader = forwardRef( */ export const CardBody = forwardRef( (props, ref) => { - const { classNames, cleanedProps } = useStyles('Card', props); + const { classNames, cleanedProps } = useStyles(CardDefinition, props); const { className, ...rest } = cleanedProps; return ( @@ -94,7 +95,7 @@ export const CardBody = forwardRef( */ export const CardFooter = forwardRef( (props, ref) => { - const { classNames, cleanedProps } = useStyles('Card', props); + const { classNames, cleanedProps } = useStyles(CardDefinition, props); const { className, ...rest } = cleanedProps; return ( diff --git a/packages/ui/src/components/Card/definition.ts b/packages/ui/src/components/Card/definition.ts new file mode 100644 index 0000000000..cd0c5f634b --- /dev/null +++ b/packages/ui/src/components/Card/definition.ts @@ -0,0 +1,30 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { ComponentDefinition } from '../../types'; + +/** + * Component definition for Card + * @public + */ +export const CardDefinition = { + classNames: { + root: 'bui-Card', + header: 'bui-CardHeader', + body: 'bui-CardBody', + footer: 'bui-CardFooter', + }, +} as const satisfies ComponentDefinition; diff --git a/packages/ui/src/components/Card/index.ts b/packages/ui/src/components/Card/index.ts index 4b710ee7f1..dc7dbd4ead 100644 --- a/packages/ui/src/components/Card/index.ts +++ b/packages/ui/src/components/Card/index.ts @@ -15,6 +15,7 @@ */ export { Card, CardHeader, CardBody, CardFooter } from './Card'; +export { CardDefinition } from './definition'; export type { CardProps, diff --git a/packages/ui/src/components/Checkbox/Checkbox.tsx b/packages/ui/src/components/Checkbox/Checkbox.tsx index 49019370a4..97a603daf2 100644 --- a/packages/ui/src/components/Checkbox/Checkbox.tsx +++ b/packages/ui/src/components/Checkbox/Checkbox.tsx @@ -18,6 +18,7 @@ import { forwardRef } from 'react'; import { Checkbox as RACheckbox } from 'react-aria-components'; import type { CheckboxProps } from './types'; import { useStyles } from '../../hooks/useStyles'; +import { CheckboxDefinition } from './definition'; import clsx from 'clsx'; import styles from './Checkbox.module.css'; import { RiCheckLine } from '@remixicon/react'; @@ -25,7 +26,7 @@ import { RiCheckLine } from '@remixicon/react'; /** @public */ export const Checkbox = forwardRef( (props, ref) => { - const { classNames } = useStyles('Checkbox'); + const { classNames } = useStyles(CheckboxDefinition); const { className, children, ...rest } = props; return ( diff --git a/packages/ui/src/components/Checkbox/definition.ts b/packages/ui/src/components/Checkbox/definition.ts new file mode 100644 index 0000000000..022f2a0af1 --- /dev/null +++ b/packages/ui/src/components/Checkbox/definition.ts @@ -0,0 +1,31 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { ComponentDefinition } from '../../types'; + +/** + * Component definition for Checkbox + * @public + */ +export const CheckboxDefinition = { + classNames: { + root: 'bui-Checkbox', + indicator: 'bui-CheckboxIndicator', + }, + dataAttributes: { + selected: [true, false] as const, + }, +} as const satisfies ComponentDefinition; diff --git a/packages/ui/src/components/Checkbox/index.ts b/packages/ui/src/components/Checkbox/index.ts index f6dfbf6beb..7c0cb5b414 100644 --- a/packages/ui/src/components/Checkbox/index.ts +++ b/packages/ui/src/components/Checkbox/index.ts @@ -14,4 +14,5 @@ * limitations under the License. */ export { Checkbox } from './Checkbox'; +export { CheckboxDefinition } from './definition'; export type { CheckboxProps } from './types'; diff --git a/packages/ui/src/components/Container/Container.tsx b/packages/ui/src/components/Container/Container.tsx index 9b15cd162e..7e3627f0b9 100644 --- a/packages/ui/src/components/Container/Container.tsx +++ b/packages/ui/src/components/Container/Container.tsx @@ -18,13 +18,14 @@ import { forwardRef } from 'react'; import { ContainerProps } from './types'; import clsx from 'clsx'; import { useStyles } from '../../hooks/useStyles'; +import { ContainerDefinition } from './definition'; import styles from './Container.module.css'; /** @public */ export const Container = forwardRef( (props, ref) => { const { classNames, utilityClasses, style, cleanedProps } = useStyles( - 'Container', + ContainerDefinition, props, ); diff --git a/packages/ui/src/components/Container/definition.ts b/packages/ui/src/components/Container/definition.ts new file mode 100644 index 0000000000..330e6adf2f --- /dev/null +++ b/packages/ui/src/components/Container/definition.ts @@ -0,0 +1,28 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { ComponentDefinition } from '../../types'; + +/** + * Component definition for Container + * @public + */ +export const ContainerDefinition = { + classNames: { + root: 'bui-Container', + }, + utilityProps: ['my', 'mt', 'mb', 'py', 'pt', 'pb', 'display'], +} as const satisfies ComponentDefinition; diff --git a/packages/ui/src/components/Container/index.tsx b/packages/ui/src/components/Container/index.tsx index 81614c352d..73d1a0ab6e 100644 --- a/packages/ui/src/components/Container/index.tsx +++ b/packages/ui/src/components/Container/index.tsx @@ -14,4 +14,5 @@ * limitations under the License. */ export { Container } from './Container'; +export { ContainerDefinition } from './definition'; export type { ContainerProps } from './types'; diff --git a/packages/ui/src/components/Dialog/Dialog.tsx b/packages/ui/src/components/Dialog/Dialog.tsx index 5dcd421b04..1c33588306 100644 --- a/packages/ui/src/components/Dialog/Dialog.tsx +++ b/packages/ui/src/components/Dialog/Dialog.tsx @@ -31,6 +31,7 @@ import type { import { RiCloseLine } from '@remixicon/react'; import { Button } from '../Button'; import { useStyles } from '../../hooks/useStyles'; +import { DialogDefinition } from './definition'; import { Flex } from '../Flex'; import styles from './Dialog.module.css'; @@ -42,7 +43,7 @@ export const DialogTrigger = (props: DialogTriggerProps) => { /** @public */ export const Dialog = forwardRef, DialogProps>( (props, ref) => { - const { classNames, cleanedProps } = useStyles('Dialog', props); + const { classNames, cleanedProps } = useStyles(DialogDefinition, props); const { className, children, width, height, style, ...rest } = cleanedProps; return ( @@ -84,7 +85,7 @@ export const DialogHeader = forwardRef< React.ElementRef<'div'>, DialogHeaderProps >((props, ref) => { - const { classNames, cleanedProps } = useStyles('Dialog', props); + const { classNames, cleanedProps } = useStyles(DialogDefinition, props); const { className, children, ...rest } = cleanedProps; return ( @@ -110,7 +111,7 @@ DialogHeader.displayName = 'DialogHeader'; /** @public */ export const DialogBody = forwardRef, DialogBodyProps>( (props, ref) => { - const { classNames, cleanedProps } = useStyles('Dialog', props); + const { classNames, cleanedProps } = useStyles(DialogDefinition, props); const { className, children, ...rest } = cleanedProps; return ( @@ -132,7 +133,7 @@ export const DialogFooter = forwardRef< React.ElementRef<'div'>, React.ComponentPropsWithoutRef<'div'> >((props, ref) => { - const { classNames, cleanedProps } = useStyles('Dialog', props); + const { classNames, cleanedProps } = useStyles(DialogDefinition, props); const { className, children, ...rest } = cleanedProps; return ( diff --git a/packages/ui/src/components/Dialog/definition.ts b/packages/ui/src/components/Dialog/definition.ts new file mode 100644 index 0000000000..d2fcb7bb4d --- /dev/null +++ b/packages/ui/src/components/Dialog/definition.ts @@ -0,0 +1,32 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { ComponentDefinition } from '../../types'; + +/** + * Component definition for Dialog + * @public + */ +export const DialogDefinition = { + classNames: { + overlay: 'bui-DialogOverlay', + dialog: 'bui-Dialog', + header: 'bui-DialogHeader', + headerTitle: 'bui-DialogHeaderTitle', + body: 'bui-DialogBody', + footer: 'bui-DialogFooter', + }, +} as const satisfies ComponentDefinition; diff --git a/packages/ui/src/components/Dialog/index.ts b/packages/ui/src/components/Dialog/index.ts index 8db1b29ff8..57dc8aae4b 100644 --- a/packages/ui/src/components/Dialog/index.ts +++ b/packages/ui/src/components/Dialog/index.ts @@ -14,4 +14,5 @@ * limitations under the License. */ export * from './Dialog'; +export { DialogDefinition } from './definition'; export * from './types'; diff --git a/packages/ui/src/components/FieldError/FieldError.tsx b/packages/ui/src/components/FieldError/FieldError.tsx index 4c4bfb9455..0016486fe7 100644 --- a/packages/ui/src/components/FieldError/FieldError.tsx +++ b/packages/ui/src/components/FieldError/FieldError.tsx @@ -22,11 +22,12 @@ import { import clsx from 'clsx'; import styles from './FieldError.module.css'; import { useStyles } from '../../hooks/useStyles'; +import { FieldErrorDefinition } from './definition'; /** @public */ export const FieldError = forwardRef( (props: FieldErrorProps, ref) => { - const { classNames, cleanedProps } = useStyles('FieldError', props); + const { classNames, cleanedProps } = useStyles(FieldErrorDefinition, props); const { className, ...rest } = cleanedProps; return ( diff --git a/packages/ui/src/components/FieldError/definition.ts b/packages/ui/src/components/FieldError/definition.ts new file mode 100644 index 0000000000..d7174dfc99 --- /dev/null +++ b/packages/ui/src/components/FieldError/definition.ts @@ -0,0 +1,27 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { ComponentDefinition } from '../../types'; + +/** + * Component definition for FieldError + * @public + */ +export const FieldErrorDefinition = { + classNames: { + root: 'bui-FieldError', + }, +} as const satisfies ComponentDefinition; diff --git a/packages/ui/src/components/FieldError/index.ts b/packages/ui/src/components/FieldError/index.ts index 5b61f83ace..1d3abf8398 100644 --- a/packages/ui/src/components/FieldError/index.ts +++ b/packages/ui/src/components/FieldError/index.ts @@ -15,3 +15,4 @@ */ export * from './FieldError'; +export { FieldErrorDefinition } from './definition'; diff --git a/packages/ui/src/components/FieldLabel/FieldLabel.tsx b/packages/ui/src/components/FieldLabel/FieldLabel.tsx index 5b27dd876f..3c685f9479 100644 --- a/packages/ui/src/components/FieldLabel/FieldLabel.tsx +++ b/packages/ui/src/components/FieldLabel/FieldLabel.tsx @@ -17,13 +17,14 @@ import { Label } from 'react-aria-components'; import { forwardRef } from 'react'; import type { FieldLabelProps } from './types'; import { useStyles } from '../../hooks/useStyles'; +import { FieldLabelDefinition } from './definition'; import styles from './FieldLabel.module.css'; import clsx from 'clsx'; /** @public */ export const FieldLabel = forwardRef( (props: FieldLabelProps, ref) => { - const { classNames, cleanedProps } = useStyles('FieldLabel', props); + const { classNames, cleanedProps } = useStyles(FieldLabelDefinition, props); const { className, label, diff --git a/packages/ui/src/components/FieldLabel/definition.ts b/packages/ui/src/components/FieldLabel/definition.ts new file mode 100644 index 0000000000..d6833a9478 --- /dev/null +++ b/packages/ui/src/components/FieldLabel/definition.ts @@ -0,0 +1,30 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { ComponentDefinition } from '../../types'; + +/** + * Component definition for FieldLabel + * @public + */ +export const FieldLabelDefinition = { + classNames: { + root: 'bui-FieldLabelWrapper', + label: 'bui-FieldLabel', + secondaryLabel: 'bui-FieldSecondaryLabel', + description: 'bui-FieldDescription', + }, +} as const satisfies ComponentDefinition; diff --git a/packages/ui/src/components/FieldLabel/index.ts b/packages/ui/src/components/FieldLabel/index.ts index b9cebb1bf7..0b4a8adf5f 100644 --- a/packages/ui/src/components/FieldLabel/index.ts +++ b/packages/ui/src/components/FieldLabel/index.ts @@ -15,4 +15,5 @@ */ export * from './FieldLabel'; +export { FieldLabelDefinition } from './definition'; export * from './types'; diff --git a/packages/ui/src/components/Flex/Flex.tsx b/packages/ui/src/components/Flex/Flex.tsx index 27564539bd..878bcfe0ea 100644 --- a/packages/ui/src/components/Flex/Flex.tsx +++ b/packages/ui/src/components/Flex/Flex.tsx @@ -18,12 +18,13 @@ import { forwardRef } from 'react'; import { FlexProps } from './types'; import clsx from 'clsx'; import { useStyles } from '../../hooks/useStyles'; +import { FlexDefinition } from './definition'; import styles from './Flex.module.css'; /** @public */ export const Flex = forwardRef((props, ref) => { const { classNames, utilityClasses, style, cleanedProps } = useStyles( - 'Flex', + FlexDefinition, { gap: '4', ...props }, ); diff --git a/packages/ui/src/components/Flex/definition.ts b/packages/ui/src/components/Flex/definition.ts new file mode 100644 index 0000000000..d6902e2f47 --- /dev/null +++ b/packages/ui/src/components/Flex/definition.ts @@ -0,0 +1,47 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { ComponentDefinition } from '../../types'; + +/** + * Component definition for Flex + * @public + */ +export const FlexDefinition = { + classNames: { + root: 'bui-Flex', + }, + utilityProps: [ + 'm', + 'mb', + 'ml', + 'mr', + 'mt', + 'mx', + 'my', + 'p', + 'pb', + 'pl', + 'pr', + 'pt', + 'px', + 'py', + 'gap', + 'align', + 'justify', + 'direction', + ], +} as const satisfies ComponentDefinition; diff --git a/packages/ui/src/components/Flex/index.ts b/packages/ui/src/components/Flex/index.ts index 4e4c883119..c9c5890ad9 100644 --- a/packages/ui/src/components/Flex/index.ts +++ b/packages/ui/src/components/Flex/index.ts @@ -14,4 +14,5 @@ * limitations under the License. */ export { Flex } from './Flex'; +export { FlexDefinition } from './definition'; export type { FlexProps } from './types'; diff --git a/packages/ui/src/components/Grid/Grid.tsx b/packages/ui/src/components/Grid/Grid.tsx index 61cd2fb7c7..aa30d25fc0 100644 --- a/packages/ui/src/components/Grid/Grid.tsx +++ b/packages/ui/src/components/Grid/Grid.tsx @@ -18,11 +18,12 @@ import { forwardRef } from 'react'; import clsx from 'clsx'; import type { GridItemProps, GridProps } from './types'; import { useStyles } from '../../hooks/useStyles'; +import { GridDefinition, GridItemDefinition } from './definition'; import styles from './Grid.module.css'; const GridRoot = forwardRef((props, ref) => { const { classNames, utilityClasses, style, cleanedProps } = useStyles( - 'Grid', + GridDefinition, { columns: 'auto', gap: '4', ...props }, ); @@ -45,7 +46,7 @@ const GridRoot = forwardRef((props, ref) => { const GridItem = forwardRef((props, ref) => { const { classNames, utilityClasses, style, cleanedProps } = useStyles( - 'GridItem', + GridItemDefinition, props, ); diff --git a/packages/ui/src/components/Grid/definition.ts b/packages/ui/src/components/Grid/definition.ts new file mode 100644 index 0000000000..201ef4dc66 --- /dev/null +++ b/packages/ui/src/components/Grid/definition.ts @@ -0,0 +1,56 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { ComponentDefinition } from '../../types'; + +/** + * Component definition for Grid + * @public + */ +export const GridDefinition = { + classNames: { + root: 'bui-Grid', + }, + utilityProps: [ + 'columns', + 'gap', + 'm', + 'mb', + 'ml', + 'mr', + 'mt', + 'mx', + 'my', + 'p', + 'pb', + 'pl', + 'pr', + 'pt', + 'px', + 'py', + ], +} as const satisfies ComponentDefinition; + +/** + * Component definition for GridItem + * @public + */ +export const GridItemDefinition = { + classNames: { + root: 'bui-GridItem', + }, + utilityProps: ['colSpan', 'colEnd', 'colStart', 'rowSpan'], +} as const satisfies ComponentDefinition; diff --git a/packages/ui/src/components/Grid/index.ts b/packages/ui/src/components/Grid/index.ts index 870ab55856..aa95e3370e 100644 --- a/packages/ui/src/components/Grid/index.ts +++ b/packages/ui/src/components/Grid/index.ts @@ -15,4 +15,5 @@ */ export { Grid } from './Grid'; +export { GridDefinition, GridItemDefinition } from './definition'; export type { GridProps, GridItemProps } from './types'; diff --git a/packages/ui/src/components/Header/Header.tsx b/packages/ui/src/components/Header/Header.tsx index 6f42820be4..56ec200e29 100644 --- a/packages/ui/src/components/Header/Header.tsx +++ b/packages/ui/src/components/Header/Header.tsx @@ -18,6 +18,7 @@ import type { HeaderProps } from './types'; import { HeaderToolbar } from './HeaderToolbar'; import { Tabs, TabList, Tab } from '../Tabs'; import { useStyles } from '../../hooks/useStyles'; +import { HeaderDefinition } from './definition'; import { type NavigateOptions } from 'react-router-dom'; import styles from './Header.module.css'; import clsx from 'clsx'; @@ -34,7 +35,7 @@ declare module 'react-aria-components' { * @public */ export const Header = (props: HeaderProps) => { - const { classNames, cleanedProps } = useStyles('Header', props); + const { classNames, cleanedProps } = useStyles(HeaderDefinition, props); const { className, tabs, diff --git a/packages/ui/src/components/Header/HeaderToolbar.tsx b/packages/ui/src/components/Header/HeaderToolbar.tsx index 373f3462be..6ba03ab3a6 100644 --- a/packages/ui/src/components/Header/HeaderToolbar.tsx +++ b/packages/ui/src/components/Header/HeaderToolbar.tsx @@ -16,6 +16,7 @@ import { Link } from 'react-aria-components'; import { useStyles } from '../../hooks/useStyles'; +import { HeaderDefinition } from './definition'; import { useRef } from 'react'; import { RiShapesLine } from '@remixicon/react'; import type { HeaderToolbarProps } from './types'; @@ -29,7 +30,7 @@ import clsx from 'clsx'; * @internal */ export const HeaderToolbar = (props: HeaderToolbarProps) => { - const { classNames, cleanedProps } = useStyles('Header', props); + const { classNames, cleanedProps } = useStyles(HeaderDefinition, props); const { className, icon, title, titleLink, customActions, hasTabs } = cleanedProps; diff --git a/packages/ui/src/components/Header/definition.ts b/packages/ui/src/components/Header/definition.ts new file mode 100644 index 0000000000..5969d7d8fa --- /dev/null +++ b/packages/ui/src/components/Header/definition.ts @@ -0,0 +1,33 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { ComponentDefinition } from '../../types'; + +/** + * Component definition for Header + * @public + */ +export const HeaderDefinition = { + classNames: { + toolbar: 'bui-HeaderToolbar', + toolbarWrapper: 'bui-HeaderToolbarWrapper', + toolbarContent: 'bui-HeaderToolbarContent', + toolbarControls: 'bui-HeaderToolbarControls', + toolbarIcon: 'bui-HeaderToolbarIcon', + toolbarName: 'bui-HeaderToolbarName', + tabsWrapper: 'bui-HeaderTabsWrapper', + }, +} as const satisfies ComponentDefinition; diff --git a/packages/ui/src/components/Header/index.tsx b/packages/ui/src/components/Header/index.tsx index b0ae2821b2..60685cfaa6 100644 --- a/packages/ui/src/components/Header/index.tsx +++ b/packages/ui/src/components/Header/index.tsx @@ -15,4 +15,5 @@ */ export { Header } from './Header'; +export { HeaderDefinition } from './definition'; export type { HeaderProps, HeaderTab } from './types'; diff --git a/packages/ui/src/components/HeaderPage/HeaderPage.tsx b/packages/ui/src/components/HeaderPage/HeaderPage.tsx index 6fcbbe258b..efa7ea8d58 100644 --- a/packages/ui/src/components/HeaderPage/HeaderPage.tsx +++ b/packages/ui/src/components/HeaderPage/HeaderPage.tsx @@ -19,6 +19,7 @@ import { Text } from '../Text'; import { RiArrowRightSLine } from '@remixicon/react'; import { Tabs, TabList, Tab } from '../Tabs'; import { useStyles } from '../../hooks/useStyles'; +import { HeaderPageDefinition } from './definition'; import { Container } from '../Container'; import { Link } from '../Link'; import { Fragment } from 'react/jsx-runtime'; @@ -31,7 +32,7 @@ import clsx from 'clsx'; * @public */ export const HeaderPage = (props: HeaderPageProps) => { - const { classNames, cleanedProps } = useStyles('HeaderPage', props); + const { classNames, cleanedProps } = useStyles(HeaderPageDefinition, props); const { className, title, tabs, customActions, breadcrumbs } = cleanedProps; return ( diff --git a/packages/ui/src/components/HeaderPage/definition.ts b/packages/ui/src/components/HeaderPage/definition.ts new file mode 100644 index 0000000000..be93aaae6a --- /dev/null +++ b/packages/ui/src/components/HeaderPage/definition.ts @@ -0,0 +1,31 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { ComponentDefinition } from '../../types'; + +/** + * Component definition for HeaderPage + * @public + */ +export const HeaderPageDefinition = { + classNames: { + root: 'bui-HeaderPage', + content: 'bui-HeaderPageContent', + breadcrumbs: 'bui-HeaderPageBreadcrumbs', + tabsWrapper: 'bui-HeaderPageTabsWrapper', + controls: 'bui-HeaderPageControls', + }, +} as const satisfies ComponentDefinition; diff --git a/packages/ui/src/components/HeaderPage/index.tsx b/packages/ui/src/components/HeaderPage/index.tsx index 040d226a1f..7b277149f1 100644 --- a/packages/ui/src/components/HeaderPage/index.tsx +++ b/packages/ui/src/components/HeaderPage/index.tsx @@ -15,4 +15,5 @@ */ export { HeaderPage } from './HeaderPage'; +export { HeaderPageDefinition } from './definition'; export type { HeaderPageProps, HeaderPageBreadcrumb } from './types'; diff --git a/packages/ui/src/components/Link/Link.tsx b/packages/ui/src/components/Link/Link.tsx index c121fd9551..56b0cae5bb 100644 --- a/packages/ui/src/components/Link/Link.tsx +++ b/packages/ui/src/components/Link/Link.tsx @@ -18,6 +18,7 @@ import { forwardRef } from 'react'; import { Link as AriaLink, RouterProvider } from 'react-aria-components'; import clsx from 'clsx'; import { useStyles } from '../../hooks/useStyles'; +import { LinkDefinition } from './definition'; import type { LinkProps } from './types'; import { useNavigate, useHref } from 'react-router-dom'; import { isExternalLink } from '../../utils/isExternalLink'; @@ -26,12 +27,15 @@ import styles from './Link.module.css'; /** @public */ export const Link = forwardRef((props, ref) => { const navigate = useNavigate(); - const { classNames, dataAttributes, cleanedProps } = useStyles('Link', { - variant: 'body', - weight: 'regular', - color: 'primary', - ...props, - }); + const { classNames, dataAttributes, cleanedProps } = useStyles( + LinkDefinition, + { + variant: 'body', + weight: 'regular', + color: 'primary', + ...props, + }, + ); const { className, href, ...restProps } = cleanedProps; diff --git a/packages/ui/src/components/Link/definition.ts b/packages/ui/src/components/Link/definition.ts new file mode 100644 index 0000000000..cece929f11 --- /dev/null +++ b/packages/ui/src/components/Link/definition.ts @@ -0,0 +1,33 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { ComponentDefinition } from '../../types'; + +/** + * Component definition for Link + * @public + */ +export const LinkDefinition = { + classNames: { + root: 'bui-Link', + }, + dataAttributes: { + variant: ['subtitle', 'body', 'caption', 'label'] as const, + weight: ['regular', 'bold'] as const, + color: ['primary', 'secondary', 'danger', 'warning', 'success'] as const, + truncate: [true, false] as const, + }, +} as const satisfies ComponentDefinition; diff --git a/packages/ui/src/components/Link/index.ts b/packages/ui/src/components/Link/index.ts index 1b38e89d62..7c17668029 100644 --- a/packages/ui/src/components/Link/index.ts +++ b/packages/ui/src/components/Link/index.ts @@ -15,4 +15,5 @@ */ export { Link } from './Link'; +export { LinkDefinition } from './definition'; export type { LinkProps } from './types'; diff --git a/packages/ui/src/components/Menu/Menu.tsx b/packages/ui/src/components/Menu/Menu.tsx index 6edbeaca20..12048776be 100644 --- a/packages/ui/src/components/Menu/Menu.tsx +++ b/packages/ui/src/components/Menu/Menu.tsx @@ -36,6 +36,7 @@ import { OverlayTriggerStateContext, } from 'react-aria-components'; import { useStyles } from '../../hooks/useStyles'; +import { MenuDefinition } from './definition'; import type { MenuTriggerProps, SubmenuTriggerProps, @@ -63,7 +64,7 @@ import clsx from 'clsx'; const rowHeight = 32; const MenuEmptyState = () => { - const { classNames } = useStyles('Menu'); + const { classNames } = useStyles(MenuDefinition); return (
@@ -84,7 +85,7 @@ export const SubmenuTrigger = (props: SubmenuTriggerProps) => { /** @public */ export const Menu = (props: MenuProps) => { - const { classNames, cleanedProps } = useStyles('Menu', props); + const { classNames, cleanedProps } = useStyles(MenuDefinition, props); const { className, placement = 'bottom start', @@ -166,7 +167,7 @@ export const Menu = (props: MenuProps) => { /** @public */ export const MenuListBox = (props: MenuListBoxProps) => { - const { classNames, cleanedProps } = useStyles('Menu', props); + const { classNames, cleanedProps } = useStyles(MenuDefinition, props); const { className, selectionMode = 'single', @@ -215,7 +216,7 @@ export const MenuListBox = (props: MenuListBoxProps) => { /** @public */ export const MenuAutocomplete = (props: MenuAutocompleteProps) => { - const { classNames, cleanedProps } = useStyles('Menu', props); + const { classNames, cleanedProps } = useStyles(MenuDefinition, props); const { className, placement = 'bottom start', @@ -294,7 +295,7 @@ export const MenuAutocomplete = (props: MenuAutocompleteProps) => { export const MenuAutocompleteListbox = ( props: MenuAutocompleteListBoxProps, ) => { - const { classNames, cleanedProps } = useStyles('Menu', props); + const { classNames, cleanedProps } = useStyles(MenuDefinition, props); const { className, selectionMode = 'single', @@ -370,7 +371,7 @@ export const MenuAutocompleteListbox = ( /** @public */ export const MenuItem = (props: MenuItemProps) => { - const { classNames, cleanedProps } = useStyles('Menu', props); + const { classNames, cleanedProps } = useStyles(MenuDefinition, props); const { className, iconStart, @@ -449,7 +450,7 @@ export const MenuItem = (props: MenuItemProps) => { /** @public */ export const MenuListBoxItem = (props: MenuListBoxItemProps) => { - const { classNames, cleanedProps } = useStyles('Menu', props); + const { classNames, cleanedProps } = useStyles(MenuDefinition, props); const { children, className, ...rest } = cleanedProps; return ( @@ -490,7 +491,7 @@ export const MenuListBoxItem = (props: MenuListBoxItemProps) => { /** @public */ export const MenuSection = (props: MenuSectionProps) => { - const { classNames, cleanedProps } = useStyles('Menu', props); + const { classNames, cleanedProps } = useStyles(MenuDefinition, props); const { children, className, title, ...rest } = cleanedProps; return ( @@ -517,7 +518,7 @@ export const MenuSection = (props: MenuSectionProps) => { /** @public */ export const MenuSeparator = (props: MenuSeparatorProps) => { - const { classNames, cleanedProps } = useStyles('Menu', props); + const { classNames, cleanedProps } = useStyles(MenuDefinition, props); const { className, ...rest } = cleanedProps; return ( diff --git a/packages/ui/src/components/Menu/definition.ts b/packages/ui/src/components/Menu/definition.ts new file mode 100644 index 0000000000..e4ba0d83ab --- /dev/null +++ b/packages/ui/src/components/Menu/definition.ts @@ -0,0 +1,42 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { ComponentDefinition } from '../../types'; + +/** + * Component definition for Menu + * @public + */ +export const MenuDefinition = { + classNames: { + root: 'bui-Menu', + popover: 'bui-MenuPopover', + content: 'bui-MenuContent', + section: 'bui-MenuSection', + sectionHeader: 'bui-MenuSectionHeader', + item: 'bui-MenuItem', + itemListBox: 'bui-MenuItemListBox', + itemListBoxCheck: 'bui-MenuItemListBoxCheck', + itemWrapper: 'bui-MenuItemWrapper', + itemContent: 'bui-MenuItemContent', + itemArrow: 'bui-MenuItemArrow', + separator: 'bui-MenuSeparator', + searchField: 'bui-MenuSearchField', + searchFieldInput: 'bui-MenuSearchFieldInput', + searchFieldClear: 'bui-MenuSearchFieldClear', + emptyState: 'bui-MenuEmptyState', + }, +} as const satisfies ComponentDefinition; diff --git a/packages/ui/src/components/Menu/index.ts b/packages/ui/src/components/Menu/index.ts index 00237712df..f42de8a7eb 100644 --- a/packages/ui/src/components/Menu/index.ts +++ b/packages/ui/src/components/Menu/index.ts @@ -26,6 +26,7 @@ export { MenuSection, MenuSeparator, } from './Menu'; +export { MenuDefinition } from './definition'; export type { MenuTriggerProps, SubmenuTriggerProps, diff --git a/packages/ui/src/components/PasswordField/PasswordField.tsx b/packages/ui/src/components/PasswordField/PasswordField.tsx index 412128ca32..c2cfdd1081 100644 --- a/packages/ui/src/components/PasswordField/PasswordField.tsx +++ b/packages/ui/src/components/PasswordField/PasswordField.tsx @@ -26,6 +26,7 @@ import { FieldError } from '../FieldError'; import type { PasswordFieldProps } from './types'; import { useStyles } from '../../hooks/useStyles'; +import { PasswordFieldDefinition } from './definition'; import { RiEyeLine, RiEyeOffLine } from '@remixicon/react'; import stylesPasswordField from './PasswordField.module.css'; @@ -50,7 +51,7 @@ export const PasswordField = forwardRef( classNames: classNamesPasswordField, dataAttributes, cleanedProps, - } = useStyles('PasswordField', { + } = useStyles(PasswordFieldDefinition, { size: 'small', ...props, }); diff --git a/packages/ui/src/components/PasswordField/definition.ts b/packages/ui/src/components/PasswordField/definition.ts new file mode 100644 index 0000000000..11272494b4 --- /dev/null +++ b/packages/ui/src/components/PasswordField/definition.ts @@ -0,0 +1,34 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { ComponentDefinition } from '../../types'; + +/** + * Component definition for PasswordField + * @public + */ +export const PasswordFieldDefinition = { + classNames: { + root: 'bui-PasswordField', + inputWrapper: 'bui-PasswordFieldInputWrapper', + input: 'bui-PasswordFieldInput', + inputIcon: 'bui-PasswordFieldIcon', + inputVisibility: 'bui-PasswordFieldVisibility', + }, + dataAttributes: { + size: ['small', 'medium'] as const, + }, +} as const satisfies ComponentDefinition; diff --git a/packages/ui/src/components/PasswordField/index.ts b/packages/ui/src/components/PasswordField/index.ts index df7874e1c2..705bf68c04 100644 --- a/packages/ui/src/components/PasswordField/index.ts +++ b/packages/ui/src/components/PasswordField/index.ts @@ -15,4 +15,5 @@ */ export * from './PasswordField'; +export { PasswordFieldDefinition } from './definition'; export * from './types'; diff --git a/packages/ui/src/components/Popover/definition.ts b/packages/ui/src/components/Popover/definition.ts new file mode 100644 index 0000000000..8b85180973 --- /dev/null +++ b/packages/ui/src/components/Popover/definition.ts @@ -0,0 +1,27 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { ComponentDefinition } from '../../types'; + +/** + * Component definition for Popover + * @public + */ +export const PopoverDefinition = { + classNames: { + root: 'bui-Popover', + }, +} as const satisfies ComponentDefinition; diff --git a/packages/ui/src/components/Popover/index.ts b/packages/ui/src/components/Popover/index.ts new file mode 100644 index 0000000000..1e31b8657b --- /dev/null +++ b/packages/ui/src/components/Popover/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { PopoverDefinition } from './definition'; diff --git a/packages/ui/src/components/RadioGroup/RadioGroup.tsx b/packages/ui/src/components/RadioGroup/RadioGroup.tsx index 355e181f37..de6cc3793b 100644 --- a/packages/ui/src/components/RadioGroup/RadioGroup.tsx +++ b/packages/ui/src/components/RadioGroup/RadioGroup.tsx @@ -23,6 +23,7 @@ import clsx from 'clsx'; import { FieldLabel } from '../FieldLabel'; import { FieldError } from '../FieldError'; import { useStyles } from '../../hooks/useStyles'; +import { RadioGroupDefinition } from './definition'; import styles from './RadioGroup.module.css'; import type { RadioGroupProps, RadioProps } from './types'; @@ -30,7 +31,7 @@ import type { RadioGroupProps, RadioProps } from './types'; /** @public */ export const RadioGroup = forwardRef( (props, ref) => { - const { classNames, cleanedProps } = useStyles('RadioGroup', props); + const { classNames, cleanedProps } = useStyles(RadioGroupDefinition, props); const { className, label, @@ -83,7 +84,7 @@ RadioGroup.displayName = 'RadioGroup'; export const Radio = forwardRef((props, ref) => { const { className, ...rest } = props; - const { classNames } = useStyles('RadioGroup'); + const { classNames } = useStyles(RadioGroupDefinition); return ( ( }, [label, ariaLabel, ariaLabelledBy]); const { classNames, dataAttributes, style, cleanedProps } = useStyles( - 'SearchField', + SearchFieldDefinition, { size: 'small', placeholder: 'Search', diff --git a/packages/ui/src/components/SearchField/definition.ts b/packages/ui/src/components/SearchField/definition.ts new file mode 100644 index 0000000000..7de1411bb4 --- /dev/null +++ b/packages/ui/src/components/SearchField/definition.ts @@ -0,0 +1,35 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { ComponentDefinition } from '../../types'; + +/** + * Component definition for SearchField + * @public + */ +export const SearchFieldDefinition = { + classNames: { + root: 'bui-SearchField', + clear: 'bui-SearchFieldClear', + inputWrapper: 'bui-SearchFieldInputWrapper', + input: 'bui-SearchFieldInput', + inputIcon: 'bui-SearchFieldInputIcon', + }, + dataAttributes: { + startCollapsed: [true, false] as const, + size: ['small', 'medium'] as const, + }, +} as const satisfies ComponentDefinition; diff --git a/packages/ui/src/components/SearchField/index.ts b/packages/ui/src/components/SearchField/index.ts index 288c3fe44a..9e01b47fc1 100644 --- a/packages/ui/src/components/SearchField/index.ts +++ b/packages/ui/src/components/SearchField/index.ts @@ -16,3 +16,4 @@ export * from './SearchField'; export * from './types'; +export { SearchFieldDefinition } from './definition'; diff --git a/packages/ui/src/components/Select/Select.tsx b/packages/ui/src/components/Select/Select.tsx index 0b133d07c5..04231d1cd9 100644 --- a/packages/ui/src/components/Select/Select.tsx +++ b/packages/ui/src/components/Select/Select.tsx @@ -19,6 +19,8 @@ import { Select as AriaSelect, Popover } from 'react-aria-components'; import clsx from 'clsx'; import { SelectProps } from './types'; import { useStyles } from '../../hooks/useStyles'; +import { SelectDefinition } from './definition'; +import { PopoverDefinition } from '../Popover/definition'; import { FieldLabel } from '../FieldLabel'; import { FieldError } from '../FieldError'; import styles from './Select.module.css'; @@ -31,12 +33,15 @@ export const Select = forwardRef< HTMLDivElement, SelectProps<'single' | 'multiple'> >((props, ref) => { - const { classNames: popoverClassNames } = useStyles('Popover'); - const { classNames, dataAttributes, cleanedProps } = useStyles('Select', { - size: 'small', - placeholder: 'Select an option', - ...props, - }); + const { classNames: popoverClassNames } = useStyles(PopoverDefinition); + const { classNames, dataAttributes, cleanedProps } = useStyles( + SelectDefinition, + { + size: 'small', + placeholder: 'Select an option', + ...props, + }, + ); const { className, diff --git a/packages/ui/src/components/Select/SelectContent.tsx b/packages/ui/src/components/Select/SelectContent.tsx index 42070321a3..7f63ad2a0a 100644 --- a/packages/ui/src/components/Select/SelectContent.tsx +++ b/packages/ui/src/components/Select/SelectContent.tsx @@ -24,6 +24,7 @@ import { useFilter } from 'react-aria'; import { RiCloseCircleLine } from '@remixicon/react'; import clsx from 'clsx'; import { useStyles } from '../../hooks/useStyles'; +import { SelectDefinition } from './definition'; import { SelectListBox } from './SelectListBox'; import styles from './Select.module.css'; import type { Option } from './types'; @@ -40,7 +41,7 @@ export function SelectContent({ options, }: SelectContentProps) { const { contains } = useFilter({ sensitivity: 'base' }); - const { classNames } = useStyles('Select'); + const { classNames } = useStyles(SelectDefinition); if (!searchable) { return ; diff --git a/packages/ui/src/components/Select/SelectListBox.tsx b/packages/ui/src/components/Select/SelectListBox.tsx index aa050ba766..3b14292729 100644 --- a/packages/ui/src/components/Select/SelectListBox.tsx +++ b/packages/ui/src/components/Select/SelectListBox.tsx @@ -18,6 +18,7 @@ import { ListBox, ListBoxItem, Text } from 'react-aria-components'; import { RiCheckLine } from '@remixicon/react'; import clsx from 'clsx'; import { useStyles } from '../../hooks/useStyles'; +import { SelectDefinition } from './definition'; import styles from './Select.module.css'; import type { Option } from './types'; @@ -26,7 +27,7 @@ interface SelectListBoxProps { } const NoResults = () => { - const { classNames } = useStyles('Select'); + const { classNames } = useStyles(SelectDefinition); return (
@@ -36,7 +37,7 @@ const NoResults = () => { }; export function SelectListBox({ options, ...props }: SelectListBoxProps) { - const { classNames } = useStyles('Select', props); + const { classNames } = useStyles(SelectDefinition, props); return ( diff --git a/packages/ui/src/components/Select/definition.ts b/packages/ui/src/components/Select/definition.ts new file mode 100644 index 0000000000..5a085cc770 --- /dev/null +++ b/packages/ui/src/components/Select/definition.ts @@ -0,0 +1,42 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { ComponentDefinition } from '../../types'; + +/** + * Component definition for Select + * @public + */ +export const SelectDefinition = { + classNames: { + root: 'bui-Select', + popover: 'bui-SelectPopover', + trigger: 'bui-SelectTrigger', + chevron: 'bui-SelectTriggerChevron', + value: 'bui-SelectValue', + list: 'bui-SelectList', + item: 'bui-SelectItem', + itemIndicator: 'bui-SelectItemIndicator', + itemLabel: 'bui-SelectItemLabel', + searchWrapper: 'bui-SelectSearchWrapper', + search: 'bui-SelectSearch', + searchClear: 'bui-SelectSearchClear', + noResults: 'bui-SelectNoResults', + }, + dataAttributes: { + size: ['small', 'medium'] as const, + }, +} as const satisfies ComponentDefinition; diff --git a/packages/ui/src/components/Select/index.ts b/packages/ui/src/components/Select/index.ts index 2cddf1fe62..786cc4d03f 100644 --- a/packages/ui/src/components/Select/index.ts +++ b/packages/ui/src/components/Select/index.ts @@ -16,3 +16,4 @@ export * from './Select'; export * from './types'; +export { SelectDefinition } from './definition'; diff --git a/packages/ui/src/components/Skeleton/Skeleton.tsx b/packages/ui/src/components/Skeleton/Skeleton.tsx index ca2f4ae493..c85a9b23cb 100644 --- a/packages/ui/src/components/Skeleton/Skeleton.tsx +++ b/packages/ui/src/components/Skeleton/Skeleton.tsx @@ -15,13 +15,14 @@ */ import { useStyles } from '../../hooks/useStyles'; +import { SkeletonDefinition } from './definition'; import { SkeletonProps } from './types'; import styles from './Skeleton.module.css'; import clsx from 'clsx'; /** @public */ export const Skeleton = (props: SkeletonProps) => { - const { classNames, cleanedProps } = useStyles('Skeleton', { + const { classNames, cleanedProps } = useStyles(SkeletonDefinition, { width: 80, height: 24, rounded: false, diff --git a/packages/ui/src/components/Skeleton/definition.ts b/packages/ui/src/components/Skeleton/definition.ts new file mode 100644 index 0000000000..42c4d6c444 --- /dev/null +++ b/packages/ui/src/components/Skeleton/definition.ts @@ -0,0 +1,27 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { ComponentDefinition } from '../../types'; + +/** + * Component definition for Skeleton + * @public + */ +export const SkeletonDefinition = { + classNames: { + root: 'bui-Skeleton', + }, +} as const satisfies ComponentDefinition; diff --git a/packages/ui/src/components/Skeleton/index.tsx b/packages/ui/src/components/Skeleton/index.tsx index f1e76b1851..ab44364f8b 100644 --- a/packages/ui/src/components/Skeleton/index.tsx +++ b/packages/ui/src/components/Skeleton/index.tsx @@ -16,3 +16,4 @@ export { Skeleton } from './Skeleton'; export type { SkeletonProps } from './types'; +export { SkeletonDefinition } from './definition'; diff --git a/packages/ui/src/components/Switch/Switch.tsx b/packages/ui/src/components/Switch/Switch.tsx index ffc1fdef05..b50db839df 100644 --- a/packages/ui/src/components/Switch/Switch.tsx +++ b/packages/ui/src/components/Switch/Switch.tsx @@ -18,13 +18,14 @@ import { forwardRef } from 'react'; import { Switch as AriaSwitch } from 'react-aria-components'; import type { SwitchProps } from './types'; import { useStyles } from '../../hooks/useStyles'; +import { SwitchDefinition } from './definition'; import styles from './Switch.module.css'; import clsx from 'clsx'; /** @public */ export const Switch = forwardRef( (props, ref) => { - const { classNames, cleanedProps } = useStyles('Switch', props); + const { classNames, cleanedProps } = useStyles(SwitchDefinition, props); const { className, label, ...rest } = cleanedProps; return ( diff --git a/packages/ui/src/components/Switch/definition.ts b/packages/ui/src/components/Switch/definition.ts new file mode 100644 index 0000000000..c8dd004991 --- /dev/null +++ b/packages/ui/src/components/Switch/definition.ts @@ -0,0 +1,28 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { ComponentDefinition } from '../../types'; + +/** + * Component definition for Switch + * @public + */ +export const SwitchDefinition = { + classNames: { + root: 'bui-Switch', + indicator: 'bui-SwitchIndicator', + }, +} as const satisfies ComponentDefinition; diff --git a/packages/ui/src/components/Switch/index.tsx b/packages/ui/src/components/Switch/index.tsx index 171969809d..72c08f5cb0 100644 --- a/packages/ui/src/components/Switch/index.tsx +++ b/packages/ui/src/components/Switch/index.tsx @@ -16,3 +16,4 @@ export * from './Switch'; export * from './types'; +export { SwitchDefinition } from './definition'; diff --git a/packages/ui/src/components/Table/components/Cell.tsx b/packages/ui/src/components/Table/components/Cell.tsx index ad0a92cb94..65be8482a7 100644 --- a/packages/ui/src/components/Table/components/Cell.tsx +++ b/packages/ui/src/components/Table/components/Cell.tsx @@ -20,12 +20,13 @@ import { Link } from '../../Link'; import { Cell as ReactAriaCell } from 'react-aria-components'; import type { CellProps } from '../types'; import { useStyles } from '../../../hooks/useStyles'; +import { TableDefinition } from '../definition'; import styles from '../Table.module.css'; /** @public */ const Cell = (props: CellProps) => { - const { classNames, cleanedProps } = useStyles<'Table', CellProps>('Table', { - color: 'primary', + const { classNames, cleanedProps } = useStyles(TableDefinition, { + color: 'primary' as const, ...props, }); const { className, title, description, color, leadingIcon, href, ...rest } = diff --git a/packages/ui/src/components/Table/components/CellProfile.tsx b/packages/ui/src/components/Table/components/CellProfile.tsx index 3f665dec02..4abef56e01 100644 --- a/packages/ui/src/components/Table/components/CellProfile.tsx +++ b/packages/ui/src/components/Table/components/CellProfile.tsx @@ -20,18 +20,16 @@ import { Text } from '../../Text/Text'; import { Link } from '../../Link/Link'; import { Avatar } from '../../Avatar'; import { useStyles } from '../../../hooks/useStyles'; +import { TableDefinition } from '../definition'; import { Cell as ReactAriaCell } from 'react-aria-components'; import styles from '../Table.module.css'; /** @public */ export const CellProfile = (props: CellProfileProps) => { - const { classNames, cleanedProps } = useStyles<'Table', CellProfileProps>( - 'Table', - { - color: 'primary', - ...props, - }, - ); + const { classNames, cleanedProps } = useStyles(TableDefinition, { + color: 'primary' as const, + ...props, + }); const { className, src, name, href, description, color, ...rest } = cleanedProps; diff --git a/packages/ui/src/components/Table/components/Column.tsx b/packages/ui/src/components/Table/components/Column.tsx index 6ebd263d3f..f534da565a 100644 --- a/packages/ui/src/components/Table/components/Column.tsx +++ b/packages/ui/src/components/Table/components/Column.tsx @@ -16,6 +16,7 @@ import { Column as ReactAriaColumn } from 'react-aria-components'; import { useStyles } from '../../../hooks/useStyles'; +import { TableDefinition } from '../definition'; import styles from '../Table.module.css'; import clsx from 'clsx'; import { ColumnProps } from '../types'; @@ -23,10 +24,7 @@ import { RiArrowUpLine, RiArrowDownLine } from '@remixicon/react'; /** @public */ export const Column = (props: ColumnProps) => { - const { classNames, cleanedProps } = useStyles<'Table', ColumnProps>( - 'Table', - props, - ); + const { classNames, cleanedProps } = useStyles(TableDefinition, props); const { children, ...rest } = cleanedProps; return ( diff --git a/packages/ui/src/components/Table/components/Row.tsx b/packages/ui/src/components/Table/components/Row.tsx index 70c8330e68..106f97baff 100644 --- a/packages/ui/src/components/Table/components/Row.tsx +++ b/packages/ui/src/components/Table/components/Row.tsx @@ -24,6 +24,7 @@ import { RouterProvider, } from 'react-aria-components'; import { useStyles } from '../../../hooks/useStyles'; +import { TableDefinition } from '../definition'; import { useNavigate } from 'react-router-dom'; import { useHref } from 'react-router-dom'; import { isExternalLink } from '../../../utils/isExternalLink'; @@ -32,10 +33,7 @@ import clsx from 'clsx'; /** @public */ export function Row(props: RowProps) { - const { classNames, cleanedProps } = useStyles<'Table', RowProps>( - 'Table', - props, - ); + const { classNames, cleanedProps } = useStyles(TableDefinition, props); const { id, columns, children, href, ...rest } = cleanedProps; const navigate = useNavigate(); const isExternal = isExternalLink(href); diff --git a/packages/ui/src/components/Table/components/Table.tsx b/packages/ui/src/components/Table/components/Table.tsx index a430b9cff2..ffd0ab231d 100644 --- a/packages/ui/src/components/Table/components/Table.tsx +++ b/packages/ui/src/components/Table/components/Table.tsx @@ -15,6 +15,7 @@ */ import { useStyles } from '../../../hooks/useStyles'; +import { TableDefinition } from '../definition'; import { Table as ReactAriaTable, type TableProps, @@ -24,10 +25,7 @@ import clsx from 'clsx'; /** @public */ export const Table = (props: TableProps) => { - const { classNames, cleanedProps } = useStyles<'Table', TableProps>( - 'Table', - props, - ); + const { classNames, cleanedProps } = useStyles(TableDefinition, props); return ( (props: TableBodyProps) => { - const { classNames, cleanedProps } = useStyles<'Table', TableBodyProps>( - 'Table', - props, - ); + const { classNames, cleanedProps } = useStyles(TableDefinition, props); return ( (props: TableHeaderProps) => { let { selectionBehavior, selectionMode, allowsDragging } = useTableOptions(); - const { classNames, cleanedProps } = useStyles<'Table', TableHeaderProps>( - 'Table', - props, - ); + const { classNames, cleanedProps } = useStyles(TableDefinition, props); const { columns, children, ...rest } = cleanedProps; return ( diff --git a/packages/ui/src/components/Table/definition.ts b/packages/ui/src/components/Table/definition.ts new file mode 100644 index 0000000000..8ec9dfb1f0 --- /dev/null +++ b/packages/ui/src/components/Table/definition.ts @@ -0,0 +1,43 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { ComponentDefinition } from '../../types'; + +/** + * Component definition for Table + * @public + */ +export const TableDefinition = { + classNames: { + table: 'bui-Table', + header: 'bui-TableHeader', + body: 'bui-TableBody', + row: 'bui-TableRow', + head: 'bui-TableHead', + headContent: 'bui-TableHeadContent', + headSortButton: 'bui-TableHeadSortButton', + caption: 'bui-TableCaption', + cell: 'bui-TableCell', + cellContentWrapper: 'bui-TableCellContentWrapper', + cellContent: 'bui-TableCellContent', + cellIcon: 'bui-TableCellIcon', + cellProfileAvatar: 'bui-TableCellProfileAvatar', + cellProfileAvatarImage: 'bui-TableCellProfileAvatarImage', + cellProfileAvatarFallback: 'bui-TableCellProfileAvatarFallback', + cellProfileName: 'bui-TableCellProfileName', + cellProfileLink: 'bui-TableCellProfileLink', + }, +} as const satisfies ComponentDefinition; diff --git a/packages/ui/src/components/Table/index.ts b/packages/ui/src/components/Table/index.ts index fb4ec6147d..8d6603ee00 100644 --- a/packages/ui/src/components/Table/index.ts +++ b/packages/ui/src/components/Table/index.ts @@ -30,3 +30,5 @@ export type { UseTablePagination, UseTablePaginationConfig, } from './hooks/types'; + +export { TableDefinition } from './definition'; diff --git a/packages/ui/src/components/Table/types.ts b/packages/ui/src/components/Table/types.ts index 293e76fdca..be9e860a0c 100644 --- a/packages/ui/src/components/Table/types.ts +++ b/packages/ui/src/components/Table/types.ts @@ -18,12 +18,13 @@ import { CellProps as ReactAriaCellProps, ColumnProps as AriaColumnProps, } from 'react-aria-components'; +import type { TextColors } from '../../types'; /** @public */ export interface CellProps extends ReactAriaCellProps { title: string; description?: string; - color?: 'primary' | 'secondary'; + color?: TextColors; leadingIcon?: React.ReactNode | null; href?: string; } @@ -34,7 +35,7 @@ export interface CellProfileProps extends ReactAriaCellProps { name?: string; href?: string; description?: string; - color?: 'primary' | 'secondary'; + color?: TextColors; } /** @public */ diff --git a/packages/ui/src/components/TablePagination/TablePagination.tsx b/packages/ui/src/components/TablePagination/TablePagination.tsx index ebd585a0c3..fd891be073 100644 --- a/packages/ui/src/components/TablePagination/TablePagination.tsx +++ b/packages/ui/src/components/TablePagination/TablePagination.tsx @@ -18,6 +18,7 @@ import clsx from 'clsx'; import { Text, ButtonIcon, Select } from '../..'; import type { TablePaginationProps } from './types'; import { useStyles } from '../../hooks/useStyles'; +import { TablePaginationDefinition } from './definition'; import styles from './TablePagination.module.css'; import { RiArrowLeftSLine, RiArrowRightSLine } from '@remixicon/react'; @@ -27,7 +28,7 @@ import { RiArrowLeftSLine, RiArrowRightSLine } from '@remixicon/react'; * @public */ export function TablePagination(props: TablePaginationProps) { - const { classNames, cleanedProps } = useStyles('TablePagination', { + const { classNames, cleanedProps } = useStyles(TablePaginationDefinition, { showPageSizeOptions: true, ...props, }); diff --git a/packages/ui/src/components/TablePagination/definition.ts b/packages/ui/src/components/TablePagination/definition.ts new file mode 100644 index 0000000000..d72a706da1 --- /dev/null +++ b/packages/ui/src/components/TablePagination/definition.ts @@ -0,0 +1,30 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { ComponentDefinition } from '../../types'; + +/** + * Component definition for TablePagination + * @public + */ +export const TablePaginationDefinition = { + classNames: { + root: 'bui-TablePagination', + left: 'bui-TablePaginationLeft', + right: 'bui-TablePaginationRight', + select: 'bui-TablePaginationSelect', + }, +} as const satisfies ComponentDefinition; diff --git a/packages/ui/src/components/TablePagination/index.ts b/packages/ui/src/components/TablePagination/index.ts index 9fb26ad728..42642fb162 100644 --- a/packages/ui/src/components/TablePagination/index.ts +++ b/packages/ui/src/components/TablePagination/index.ts @@ -16,3 +16,4 @@ export { TablePagination } from './TablePagination'; export type { TablePaginationProps } from './types'; +export { TablePaginationDefinition } from './definition'; diff --git a/packages/ui/src/components/Tabs/Tabs.tsx b/packages/ui/src/components/Tabs/Tabs.tsx index f627199b4b..5c44fae8af 100644 --- a/packages/ui/src/components/Tabs/Tabs.tsx +++ b/packages/ui/src/components/Tabs/Tabs.tsx @@ -42,6 +42,7 @@ import { TabProps as AriaTabProps, } from 'react-aria-components'; import { useStyles } from '../../hooks/useStyles'; +import { TabsDefinition } from './definition'; import styles from './Tabs.module.css'; import clsx from 'clsx'; @@ -84,7 +85,7 @@ const isTabActive = ( * @public */ export const Tabs = (props: TabsProps) => { - const { classNames, cleanedProps } = useStyles('Tabs', props); + const { classNames, cleanedProps } = useStyles(TabsDefinition, props); const { className, children, ...rest } = cleanedProps; const tabsRef = useRef(null); const tabRefs = useRef>(new Map()); @@ -168,7 +169,7 @@ export const Tabs = (props: TabsProps) => { * @public */ export const TabList = (props: TabListProps) => { - const { classNames, cleanedProps } = useStyles('Tabs', props); + const { classNames, cleanedProps } = useStyles(TabsDefinition, props); const { className, children, ...rest } = cleanedProps; const { setHoveredKey, tabRefs, tabsRef, hoveredKey, prevHoveredKey } = useTabsContext(); @@ -219,7 +220,7 @@ export const TabList = (props: TabListProps) => { * @public */ export const Tab = (props: TabProps) => { - const { classNames, cleanedProps } = useStyles('Tabs', props); + const { classNames, cleanedProps } = useStyles(TabsDefinition, props); const { className, href, @@ -249,7 +250,7 @@ export const Tab = (props: TabProps) => { * @public */ export const TabPanel = (props: TabPanelProps) => { - const { classNames, cleanedProps } = useStyles('Tabs', props); + const { classNames, cleanedProps } = useStyles(TabsDefinition, props); const { className, children, ...rest } = cleanedProps; return ( diff --git a/packages/ui/src/components/Tabs/TabsIndicators.tsx b/packages/ui/src/components/Tabs/TabsIndicators.tsx index 6347c5c55c..2aa4f72508 100644 --- a/packages/ui/src/components/Tabs/TabsIndicators.tsx +++ b/packages/ui/src/components/Tabs/TabsIndicators.tsx @@ -16,6 +16,7 @@ import { TabListStateContext } from 'react-aria-components'; import { useStyles } from '../../hooks/useStyles'; +import { TabsDefinition } from './definition'; import { useContext, useEffect, useCallback, useRef } from 'react'; import type { TabsIndicatorsProps } from './types'; import styles from './Tabs.module.css'; @@ -28,7 +29,7 @@ import clsx from 'clsx'; */ export const TabsIndicators = (props: TabsIndicatorsProps) => { const { tabRefs, tabsRef, hoveredKey, prevHoveredKey } = props; - const { classNames } = useStyles('Tabs'); + const { classNames } = useStyles(TabsDefinition); const state = useContext(TabListStateContext); const prevSelectedKey = useRef(null); diff --git a/packages/ui/src/components/Tabs/definition.ts b/packages/ui/src/components/Tabs/definition.ts new file mode 100644 index 0000000000..10e9247372 --- /dev/null +++ b/packages/ui/src/components/Tabs/definition.ts @@ -0,0 +1,33 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { ComponentDefinition } from '../../types'; + +/** + * Component definition for Tabs + * @public + */ +export const TabsDefinition = { + classNames: { + tabs: 'bui-Tabs', + tabList: 'bui-TabList', + tabListWrapper: 'bui-TabListWrapper', + tab: 'bui-Tab', + tabActive: 'bui-TabActive', + tabHovered: 'bui-TabHovered', + panel: 'bui-TabPanel', + }, +} as const satisfies ComponentDefinition; diff --git a/packages/ui/src/components/Tabs/index.ts b/packages/ui/src/components/Tabs/index.ts index 38a6f20ea7..009d515294 100644 --- a/packages/ui/src/components/Tabs/index.ts +++ b/packages/ui/src/components/Tabs/index.ts @@ -22,3 +22,4 @@ export type { TabProps, TabMatchStrategy, } from './types'; +export { TabsDefinition } from './definition'; diff --git a/packages/ui/src/components/TagGroup/TagGroup.tsx b/packages/ui/src/components/TagGroup/TagGroup.tsx index 04f3027f02..54557e5849 100644 --- a/packages/ui/src/components/TagGroup/TagGroup.tsx +++ b/packages/ui/src/components/TagGroup/TagGroup.tsx @@ -26,6 +26,7 @@ import type { ReactNode } from 'react'; import { RiCloseCircleLine } from '@remixicon/react'; import clsx from 'clsx'; import { useStyles } from '../../hooks/useStyles'; +import { TagGroupDefinition } from './definition'; import { isExternalLink } from '../../utils/isExternalLink'; import { useNavigate, useHref } from 'react-router-dom'; import styles from './TagGroup.module.css'; @@ -36,7 +37,7 @@ import styles from './TagGroup.module.css'; * @public */ export const TagGroup = (props: TagGroupProps) => { - const { classNames, cleanedProps } = useStyles('TagGroup', props); + const { classNames, cleanedProps } = useStyles(TagGroupDefinition, props); const { items, children, renderEmptyState, ...rest } = cleanedProps; return ( @@ -61,7 +62,7 @@ export const TagGroup = (props: TagGroupProps) => { * @public */ export const Tag = (props: TagProps) => { - const { classNames, cleanedProps } = useStyles('TagGroup', { + const { classNames, cleanedProps } = useStyles(TagGroupDefinition, { size: 'small', ...props, }); diff --git a/packages/ui/src/components/TagGroup/definition.ts b/packages/ui/src/components/TagGroup/definition.ts new file mode 100644 index 0000000000..8ad3d17805 --- /dev/null +++ b/packages/ui/src/components/TagGroup/definition.ts @@ -0,0 +1,31 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { ComponentDefinition } from '../../types'; + +/** + * Component definition for TagGroup + * @public + */ +export const TagGroupDefinition = { + classNames: { + group: 'bui-TagGroup', + list: 'bui-TagList', + tag: 'bui-Tag', + tagIcon: 'bui-TagIcon', + tagRemoveButton: 'bui-TagRemoveButton', + }, +} as const satisfies ComponentDefinition; diff --git a/packages/ui/src/components/TagGroup/index.ts b/packages/ui/src/components/TagGroup/index.ts index b7434ce574..7c58cf69fc 100644 --- a/packages/ui/src/components/TagGroup/index.ts +++ b/packages/ui/src/components/TagGroup/index.ts @@ -16,3 +16,4 @@ export { TagGroup, Tag } from './TagGroup'; export type { TagGroupProps, TagProps } from './types'; +export { TagGroupDefinition } from './definition'; diff --git a/packages/ui/src/components/Text/Text.tsx b/packages/ui/src/components/Text/Text.tsx index 5b09d10663..857ae3ef0e 100644 --- a/packages/ui/src/components/Text/Text.tsx +++ b/packages/ui/src/components/Text/Text.tsx @@ -20,6 +20,7 @@ import type { ElementType } from 'react'; import type { TextProps } from './types'; import { useStyles } from '../../hooks/useStyles'; import styles from './Text.module.css'; +import { TextDefinition } from './definition'; function TextComponent( props: TextProps, @@ -27,12 +28,15 @@ function TextComponent( ) { const Component = props.as || 'span'; - const { classNames, dataAttributes, cleanedProps } = useStyles('Text', { - variant: 'body-medium', - weight: 'regular', - color: 'primary', - ...props, - }); + const { classNames, dataAttributes, cleanedProps } = useStyles( + TextDefinition, + { + variant: 'body-medium', + weight: 'regular', + color: 'primary', + ...props, + }, + ); const { className, truncate, ...restProps } = cleanedProps; diff --git a/packages/ui/src/components/Text/definition.ts b/packages/ui/src/components/Text/definition.ts new file mode 100644 index 0000000000..dbbfd6b72a --- /dev/null +++ b/packages/ui/src/components/Text/definition.ts @@ -0,0 +1,33 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { ComponentDefinition } from '../../types'; + +/** + * Component definition for Text + * @public + */ +export const TextDefinition = { + classNames: { + root: 'bui-Text', + }, + dataAttributes: { + variant: ['subtitle', 'body', 'caption', 'label'] as const, + weight: ['regular', 'bold'] as const, + color: ['primary', 'secondary', 'danger', 'warning', 'success'] as const, + truncate: [true, false] as const, + }, +} as const satisfies ComponentDefinition; diff --git a/packages/ui/src/components/Text/index.ts b/packages/ui/src/components/Text/index.ts index 423288a8a4..df6ac23eb4 100644 --- a/packages/ui/src/components/Text/index.ts +++ b/packages/ui/src/components/Text/index.ts @@ -16,3 +16,4 @@ export * from './Text'; export * from './types'; +export { TextDefinition } from './definition'; diff --git a/packages/ui/src/components/TextField/TextField.tsx b/packages/ui/src/components/TextField/TextField.tsx index 632f5e9f86..24c038fdb8 100644 --- a/packages/ui/src/components/TextField/TextField.tsx +++ b/packages/ui/src/components/TextField/TextField.tsx @@ -21,6 +21,7 @@ import { FieldLabel } from '../FieldLabel'; import { FieldError } from '../FieldError'; import type { TextFieldProps } from './types'; import { useStyles } from '../../hooks/useStyles'; +import { TextFieldDefinition } from './definition'; import styles from './TextField.module.css'; /** @public */ @@ -41,7 +42,7 @@ export const TextField = forwardRef( }, [label, ariaLabel, ariaLabelledBy]); const { classNames, dataAttributes, style, cleanedProps } = useStyles( - 'TextField', + TextFieldDefinition, { size: 'small', ...props, diff --git a/packages/ui/src/components/TextField/definition.ts b/packages/ui/src/components/TextField/definition.ts new file mode 100644 index 0000000000..c1cab8095d --- /dev/null +++ b/packages/ui/src/components/TextField/definition.ts @@ -0,0 +1,36 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { ComponentDefinition } from '../../types'; + +/** + * Component definition for TextField + * @public + */ +export const TextFieldDefinition = { + classNames: { + root: 'bui-TextField', + inputWrapper: 'bui-InputWrapper', + input: 'bui-Input', + inputIcon: 'bui-InputIcon', + inputAction: 'bui-InputAction', + }, + dataAttributes: { + invalid: [true, false] as const, + disabled: [true, false] as const, + size: ['small', 'medium'] as const, + }, +} as const satisfies ComponentDefinition; diff --git a/packages/ui/src/components/TextField/index.ts b/packages/ui/src/components/TextField/index.ts index 95a838fb46..a9d061047d 100644 --- a/packages/ui/src/components/TextField/index.ts +++ b/packages/ui/src/components/TextField/index.ts @@ -16,3 +16,4 @@ export * from './TextField'; export * from './types'; +export { TextFieldDefinition } from './definition'; diff --git a/packages/ui/src/components/Tooltip/Tooltip.tsx b/packages/ui/src/components/Tooltip/Tooltip.tsx index fc8b25547b..9099f1eef2 100644 --- a/packages/ui/src/components/Tooltip/Tooltip.tsx +++ b/packages/ui/src/components/Tooltip/Tooltip.tsx @@ -24,6 +24,7 @@ import { import clsx from 'clsx'; import { TooltipProps } from './types'; import { useStyles } from '../../hooks/useStyles'; +import { TooltipDefinition } from './definition'; import styles from './Tooltip.module.css'; /** @public */ @@ -36,7 +37,7 @@ export const TooltipTrigger = (props: TooltipTriggerComponentProps) => { /** @public */ export const Tooltip = forwardRef( (props, ref) => { - const { classNames, cleanedProps } = useStyles('Tooltip', props); + const { classNames, cleanedProps } = useStyles(TooltipDefinition, props); const { className, children, ...rest } = cleanedProps; return ( diff --git a/packages/ui/src/components/Tooltip/definition.ts b/packages/ui/src/components/Tooltip/definition.ts new file mode 100644 index 0000000000..a5b3d61ea8 --- /dev/null +++ b/packages/ui/src/components/Tooltip/definition.ts @@ -0,0 +1,28 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { ComponentDefinition } from '../../types'; + +/** + * Component definition for Tooltip + * @public + */ +export const TooltipDefinition = { + classNames: { + tooltip: 'bui-Tooltip', + arrow: 'bui-TooltipArrow', + }, +} as const satisfies ComponentDefinition; diff --git a/packages/ui/src/components/Tooltip/index.ts b/packages/ui/src/components/Tooltip/index.ts index 613631091b..43bd385c65 100644 --- a/packages/ui/src/components/Tooltip/index.ts +++ b/packages/ui/src/components/Tooltip/index.ts @@ -16,3 +16,4 @@ export { TooltipTrigger, Tooltip } from './Tooltip'; export type { TooltipProps } from './types'; +export { TooltipDefinition } from './definition'; diff --git a/packages/ui/src/components/VisuallyHidden/VisuallyHidden.tsx b/packages/ui/src/components/VisuallyHidden/VisuallyHidden.tsx index 305f8fc424..cfc796ef9e 100644 --- a/packages/ui/src/components/VisuallyHidden/VisuallyHidden.tsx +++ b/packages/ui/src/components/VisuallyHidden/VisuallyHidden.tsx @@ -15,6 +15,7 @@ */ import { useStyles } from '../../hooks/useStyles'; +import { VisuallyHiddenDefinition } from './definition'; import { VisuallyHiddenProps } from './types'; import styles from './VisuallyHidden.module.css'; import clsx from 'clsx'; @@ -29,7 +30,10 @@ import clsx from 'clsx'; * @public */ export const VisuallyHidden = (props: VisuallyHiddenProps) => { - const { classNames, cleanedProps } = useStyles('VisuallyHidden', props); + const { classNames, cleanedProps } = useStyles( + VisuallyHiddenDefinition, + props, + ); const { className, ...rest } = cleanedProps; return ( diff --git a/packages/ui/src/components/VisuallyHidden/definition.ts b/packages/ui/src/components/VisuallyHidden/definition.ts new file mode 100644 index 0000000000..5be52f89ec --- /dev/null +++ b/packages/ui/src/components/VisuallyHidden/definition.ts @@ -0,0 +1,27 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { ComponentDefinition } from '../../types'; + +/** + * Component definition for VisuallyHidden + * @public + */ +export const VisuallyHiddenDefinition = { + classNames: { + root: 'bui-VisuallyHidden', + }, +} as const satisfies ComponentDefinition; diff --git a/packages/ui/src/components/VisuallyHidden/index.ts b/packages/ui/src/components/VisuallyHidden/index.ts index 6946ec00e5..c3668df403 100644 --- a/packages/ui/src/components/VisuallyHidden/index.ts +++ b/packages/ui/src/components/VisuallyHidden/index.ts @@ -16,3 +16,4 @@ export { VisuallyHidden } from './VisuallyHidden'; export type { VisuallyHiddenProps } from './types'; +export { VisuallyHiddenDefinition } from './definition'; diff --git a/packages/ui/src/definitions.ts b/packages/ui/src/definitions.ts new file mode 100644 index 0000000000..a0dc412697 --- /dev/null +++ b/packages/ui/src/definitions.ts @@ -0,0 +1,57 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Component definitions barrel export + * @packageDocumentation + */ + +export { AccordionDefinition } from './components/Accordion/definition'; +export { AvatarDefinition } from './components/Avatar/definition'; +export { BoxDefinition } from './components/Box/definition'; +export { ButtonDefinition } from './components/Button/definition'; +export { ButtonIconDefinition } from './components/ButtonIcon/definition'; +export { ButtonLinkDefinition } from './components/ButtonLink/definition'; +export { CardDefinition } from './components/Card/definition'; +export { CheckboxDefinition } from './components/Checkbox/definition'; +export { ContainerDefinition } from './components/Container/definition'; +export { DialogDefinition } from './components/Dialog/definition'; +export { FieldErrorDefinition } from './components/FieldError/definition'; +export { FieldLabelDefinition } from './components/FieldLabel/definition'; +export { FlexDefinition } from './components/Flex/definition'; +export { + GridDefinition, + GridItemDefinition, +} from './components/Grid/definition'; +export { HeaderDefinition } from './components/Header/definition'; +export { HeaderPageDefinition } from './components/HeaderPage/definition'; +export { LinkDefinition } from './components/Link/definition'; +export { MenuDefinition } from './components/Menu/definition'; +export { PasswordFieldDefinition } from './components/PasswordField/definition'; +export { PopoverDefinition } from './components/Popover/definition'; +export { RadioGroupDefinition } from './components/RadioGroup/definition'; +export { SearchFieldDefinition } from './components/SearchField/definition'; +export { SelectDefinition } from './components/Select/definition'; +export { SkeletonDefinition } from './components/Skeleton/definition'; +export { SwitchDefinition } from './components/Switch/definition'; +export { TableDefinition } from './components/Table/definition'; +export { TablePaginationDefinition } from './components/TablePagination/definition'; +export { TabsDefinition } from './components/Tabs/definition'; +export { TagGroupDefinition } from './components/TagGroup/definition'; +export { TextDefinition } from './components/Text/definition'; +export { TextFieldDefinition } from './components/TextField/definition'; +export { TooltipDefinition } from './components/Tooltip/definition'; +export { VisuallyHiddenDefinition } from './components/VisuallyHidden/definition'; diff --git a/packages/ui/src/hooks/useStyles.ts b/packages/ui/src/hooks/useStyles.ts index b141eca582..cc05f5f362 100644 --- a/packages/ui/src/hooks/useStyles.ts +++ b/packages/ui/src/hooks/useStyles.ts @@ -14,8 +14,7 @@ * limitations under the License. */ import { useBreakpoint, breakpoints } from './useBreakpoint'; -import { componentDefinitions } from '../utils/componentDefinitions'; -import type { ComponentDefinitionName, ComponentClassNames } from '../types'; +import type { ComponentDefinition } from '../types'; import { utilityClassMap } from '../utils/utilityClassMap'; /** @@ -55,26 +54,25 @@ function resolveResponsiveValue( /** * React hook to get class names and data attributes for a component with responsive support - * @param componentName - The name of the component + * @param componentDefinition - The component's definition object * @param props - All component props * @returns Object with classNames, dataAttributes, utilityClasses, style, and cleanedProps */ export function useStyles< - T extends ComponentDefinitionName, + T extends ComponentDefinition, P extends Record = Record, >( - componentName: T, + componentDefinition: T, props: P = {} as P, ): { - classNames: ComponentClassNames; + classNames: T['classNames']; dataAttributes: Record; utilityClasses: string; style: React.CSSProperties; cleanedProps: P; } { const { breakpoint } = useBreakpoint(); - const componentDefinition = componentDefinitions[componentName]; - const classNames = componentDefinition.classNames as ComponentClassNames; + const classNames = componentDefinition.classNames; const utilityPropNames = ('utilityProps' in componentDefinition ? componentDefinition.utilityProps diff --git a/packages/ui/src/index.ts b/packages/ui/src/index.ts index baa4c3e5dc..03ae3245e3 100644 --- a/packages/ui/src/index.ts +++ b/packages/ui/src/index.ts @@ -59,6 +59,3 @@ export * from './types'; // Hooks export { useBreakpoint } from './hooks/useBreakpoint'; - -// Component Definitions -export * from './utils/componentDefinitions'; diff --git a/packages/ui/src/types.ts b/packages/ui/src/types.ts index db23974186..7166194091 100644 --- a/packages/ui/src/types.ts +++ b/packages/ui/src/types.ts @@ -14,8 +14,6 @@ * limitations under the License. */ -import { componentDefinitions } from './utils/componentDefinitions'; - /** @public */ export type Breakpoint = 'initial' | 'xs' | 'sm' | 'md' | 'lg' | 'xl'; @@ -175,16 +173,3 @@ export interface ComponentDefinition { dataAttributes?: DataAttributesMap; utilityProps?: string[]; } - -/** - * Type utilities for extracting information from the component styles - * @public - */ -export type ComponentDefinitionName = keyof typeof componentDefinitions; - -/** - * Helper type to extract class names for a component - * @public - */ -export type ComponentClassNames = - (typeof componentDefinitions)[T]['classNames']; diff --git a/packages/ui/src/utils/componentDefinitions.ts b/packages/ui/src/utils/componentDefinitions.ts deleted file mode 100644 index cc45dbefe1..0000000000 --- a/packages/ui/src/utils/componentDefinitions.ts +++ /dev/null @@ -1,425 +0,0 @@ -/* - * Copyright 2024 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import type { ComponentDefinition } from '../types'; - -/** - * Component definitions for the Backstage UI library - * @public - */ -export const componentDefinitions = { - Avatar: { - classNames: { - root: 'bui-AvatarRoot', - image: 'bui-AvatarImage', - fallback: 'bui-AvatarFallback', - }, - dataAttributes: { - size: ['small', 'medium', 'large'] as const, - }, - }, - Box: { - classNames: { - root: 'bui-Box', - }, - utilityProps: [ - 'm', - 'mb', - 'ml', - 'mr', - 'mt', - 'mx', - 'my', - 'p', - 'pb', - 'pl', - 'pr', - 'pt', - 'px', - 'py', - 'position', - 'display', - 'width', - 'minWidth', - 'maxWidth', - 'height', - 'minHeight', - 'maxHeight', - ], - }, - Button: { - classNames: { - root: 'bui-Button', - content: 'bui-ButtonContent', - spinner: 'bui-ButtonSpinner', - }, - dataAttributes: { - size: ['small', 'medium', 'large'] as const, - variant: ['primary', 'secondary', 'tertiary'] as const, - loading: [true, false] as const, - }, - }, - ButtonIcon: { - classNames: { - root: 'bui-ButtonIcon', - content: 'bui-ButtonIconContent', - spinner: 'bui-ButtonIconSpinner', - }, - }, - ButtonLink: { - classNames: { - root: 'bui-ButtonLink', - }, - }, - Card: { - classNames: { - root: 'bui-Card', - header: 'bui-CardHeader', - body: 'bui-CardBody', - footer: 'bui-CardFooter', - }, - }, - Checkbox: { - classNames: { - root: 'bui-Checkbox', - indicator: 'bui-CheckboxIndicator', - }, - dataAttributes: { - selected: [true, false] as const, - }, - }, - Container: { - classNames: { - root: 'bui-Container', - }, - utilityProps: ['my', 'mt', 'mb', 'py', 'pt', 'pb', 'display'], - }, - Dialog: { - classNames: { - overlay: 'bui-DialogOverlay', - dialog: 'bui-Dialog', - header: 'bui-DialogHeader', - headerTitle: 'bui-DialogHeaderTitle', - body: 'bui-DialogBody', - footer: 'bui-DialogFooter', - }, - }, - Accordion: { - classNames: { - root: 'bui-Accordion', - trigger: 'bui-AccordionTrigger', - triggerButton: 'bui-AccordionTriggerButton', - triggerTitle: 'bui-AccordionTriggerTitle', - triggerSubtitle: 'bui-AccordionTriggerSubtitle', - triggerIcon: 'bui-AccordionTriggerIcon', - panel: 'bui-AccordionPanel', - group: 'bui-AccordionGroup', - }, - }, - FieldError: { - classNames: { - root: 'bui-FieldError', - }, - }, - FieldLabel: { - classNames: { - root: 'bui-FieldLabelWrapper', - label: 'bui-FieldLabel', - secondaryLabel: 'bui-FieldSecondaryLabel', - description: 'bui-FieldDescription', - }, - }, - Flex: { - classNames: { - root: 'bui-Flex', - }, - utilityProps: [ - 'm', - 'mb', - 'ml', - 'mr', - 'mt', - 'mx', - 'my', - 'p', - 'pb', - 'pl', - 'pr', - 'pt', - 'px', - 'py', - 'gap', - 'align', - 'justify', - 'direction', - ], - }, - Grid: { - classNames: { - root: 'bui-Grid', - }, - utilityProps: [ - 'columns', - 'gap', - 'm', - 'mb', - 'ml', - 'mr', - 'mt', - 'mx', - 'my', - 'p', - 'pb', - 'pl', - 'pr', - 'pt', - 'px', - 'py', - ], - }, - GridItem: { - classNames: { - root: 'bui-GridItem', - }, - utilityProps: ['colSpan', 'colEnd', 'colStart', 'rowSpan'], - }, - Header: { - classNames: { - toolbar: 'bui-HeaderToolbar', - toolbarWrapper: 'bui-HeaderToolbarWrapper', - toolbarContent: 'bui-HeaderToolbarContent', - toolbarControls: 'bui-HeaderToolbarControls', - toolbarIcon: 'bui-HeaderToolbarIcon', - toolbarName: 'bui-HeaderToolbarName', - tabsWrapper: 'bui-HeaderTabsWrapper', - }, - }, - HeaderPage: { - classNames: { - root: 'bui-HeaderPage', - content: 'bui-HeaderPageContent', - breadcrumbs: 'bui-HeaderPageBreadcrumbs', - tabsWrapper: 'bui-HeaderPageTabsWrapper', - controls: 'bui-HeaderPageControls', - }, - }, - Heading: { - classNames: { - root: 'bui-Heading', - }, - dataAttributes: { - variant: ['title1', 'title2', 'title3', 'subtitle'] as const, - color: ['primary', 'secondary', 'muted'] as const, - truncate: [true, false] as const, - }, - }, - Icon: { - classNames: { - root: 'bui-Icon', - }, - }, - Link: { - classNames: { - root: 'bui-Link', - }, - dataAttributes: { - variant: ['subtitle', 'body', 'caption', 'label'] as const, - weight: ['regular', 'bold'] as const, - color: ['primary', 'secondary', 'danger', 'warning', 'success'] as const, - truncate: [true, false] as const, - }, - }, - List: { - classNames: { - root: 'bui-List', - row: 'bui-ListRow', - label: 'bui-ListLabel', - }, - }, - Menu: { - classNames: { - root: 'bui-Menu', - popover: 'bui-MenuPopover', - content: 'bui-MenuContent', - section: 'bui-MenuSection', - sectionHeader: 'bui-MenuSectionHeader', - item: 'bui-MenuItem', - itemListBox: 'bui-MenuItemListBox', - itemListBoxCheck: 'bui-MenuItemListBoxCheck', - itemWrapper: 'bui-MenuItemWrapper', - itemContent: 'bui-MenuItemContent', - itemArrow: 'bui-MenuItemArrow', - separator: 'bui-MenuSeparator', - searchField: 'bui-MenuSearchField', - searchFieldInput: 'bui-MenuSearchFieldInput', - searchFieldClear: 'bui-MenuSearchFieldClear', - emptyState: 'bui-MenuEmptyState', - }, - }, - PasswordField: { - classNames: { - root: 'bui-PasswordField', - inputWrapper: 'bui-PasswordFieldInputWrapper', - input: 'bui-PasswordFieldInput', - inputIcon: 'bui-PasswordFieldIcon', - inputVisibility: 'bui-PasswordFieldVisibility', - }, - dataAttributes: { - size: ['small', 'medium'] as const, - }, - }, - Popover: { - classNames: { - root: 'bui-Popover', - }, - }, - RadioGroup: { - classNames: { - root: 'bui-RadioGroup', - content: 'bui-RadioGroupContent', - radio: 'bui-Radio', - }, - }, - SearchField: { - classNames: { - root: 'bui-SearchField', - clear: 'bui-SearchFieldClear', - inputWrapper: 'bui-SearchFieldInputWrapper', - input: 'bui-SearchFieldInput', - inputIcon: 'bui-SearchFieldInputIcon', - }, - dataAttributes: { - startCollapsed: [true, false] as const, - size: ['small', 'medium'] as const, - }, - }, - Select: { - classNames: { - root: 'bui-Select', - popover: 'bui-SelectPopover', - trigger: 'bui-SelectTrigger', - chevron: 'bui-SelectTriggerChevron', - value: 'bui-SelectValue', - list: 'bui-SelectList', - item: 'bui-SelectItem', - itemIndicator: 'bui-SelectItemIndicator', - itemLabel: 'bui-SelectItemLabel', - searchWrapper: 'bui-SelectSearchWrapper', - search: 'bui-SelectSearch', - searchClear: 'bui-SelectSearchClear', - noResults: 'bui-SelectNoResults', - }, - dataAttributes: { - size: ['small', 'medium'] as const, - }, - }, - Skeleton: { - classNames: { - root: 'bui-Skeleton', - }, - }, - Switch: { - classNames: { - root: 'bui-Switch', - indicator: 'bui-SwitchIndicator', - }, - }, - Table: { - classNames: { - table: 'bui-Table', - header: 'bui-TableHeader', - body: 'bui-TableBody', - row: 'bui-TableRow', - head: 'bui-TableHead', - headContent: 'bui-TableHeadContent', - headSortButton: 'bui-TableHeadSortButton', - caption: 'bui-TableCaption', - cell: 'bui-TableCell', - cellContentWrapper: 'bui-TableCellContentWrapper', - cellContent: 'bui-TableCellContent', - cellIcon: 'bui-TableCellIcon', - cellProfileAvatar: 'bui-TableCellProfileAvatar', - cellProfileAvatarImage: 'bui-TableCellProfileAvatarImage', - cellProfileAvatarFallback: 'bui-TableCellProfileAvatarFallback', - cellProfileName: 'bui-TableCellProfileName', - cellProfileLink: 'bui-TableCellProfileLink', - }, - }, - TablePagination: { - classNames: { - root: 'bui-TablePagination', - left: 'bui-TablePaginationLeft', - right: 'bui-TablePaginationRight', - select: 'bui-TablePaginationSelect', - }, - }, - Tabs: { - classNames: { - tabs: 'bui-Tabs', - tabList: 'bui-TabList', - tabListWrapper: 'bui-TabListWrapper', - tab: 'bui-Tab', - tabActive: 'bui-TabActive', - tabHovered: 'bui-TabHovered', - panel: 'bui-TabPanel', - }, - }, - TagGroup: { - classNames: { - group: 'bui-TagGroup', - list: 'bui-TagList', - tag: 'bui-Tag', - tagIcon: 'bui-TagIcon', - tagRemoveButton: 'bui-TagRemoveButton', - }, - }, - Text: { - classNames: { - root: 'bui-Text', - }, - dataAttributes: { - variant: ['subtitle', 'body', 'caption', 'label'] as const, - weight: ['regular', 'bold'] as const, - color: ['primary', 'secondary', 'danger', 'warning', 'success'] as const, - truncate: [true, false] as const, - }, - }, - TextField: { - classNames: { - root: 'bui-TextField', - inputWrapper: 'bui-InputWrapper', - input: 'bui-Input', - inputIcon: 'bui-InputIcon', - inputAction: 'bui-InputAction', - }, - dataAttributes: { - invalid: [true, false] as const, - disabled: [true, false] as const, - size: ['small', 'medium'] as const, - }, - }, - Tooltip: { - classNames: { - tooltip: 'bui-Tooltip', - arrow: 'bui-TooltipArrow', - }, - }, - VisuallyHidden: { - classNames: { - root: 'bui-VisuallyHidden', - }, - }, -} as const satisfies Record; diff --git a/plugins/api-docs/report-alpha.api.md b/plugins/api-docs/report-alpha.api.md index 43c45c1a1d..7d134dcb6d 100644 --- a/plugins/api-docs/report-alpha.api.md +++ b/plugins/api-docs/report-alpha.api.md @@ -12,11 +12,11 @@ import { EntityCardType } from '@backstage/plugin-catalog-react/alpha'; import { EntityPredicate } from '@backstage/plugin-catalog-react/alpha'; import { ExtensionBlueprintParams } from '@backstage/frontend-plugin-api'; import { ExtensionDataRef } from '@backstage/frontend-plugin-api'; -import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; import { ExtensionInput } from '@backstage/frontend-plugin-api'; import { ExternalRouteRef } from '@backstage/frontend-plugin-api'; import { IconComponent } from '@backstage/core-plugin-api'; import { JSX as JSX_2 } from 'react'; +import { OverridableExtensionDefinition } from '@backstage/frontend-plugin-api'; import { OverridableFrontendPlugin } from '@backstage/frontend-plugin-api'; import { RouteRef } from '@backstage/frontend-plugin-api'; import { TranslationRef } from '@backstage/frontend-plugin-api'; @@ -63,7 +63,7 @@ const _default: OverridableFrontendPlugin< registerApi: ExternalRouteRef; }, { - 'api:api-docs/config': ExtensionDefinition<{ + 'api:api-docs/config': OverridableExtensionDefinition<{ kind: 'api'; name: 'config'; config: {}; @@ -78,7 +78,7 @@ const _default: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'entity-card:api-docs/consumed-apis': ExtensionDefinition<{ + 'entity-card:api-docs/consumed-apis': OverridableExtensionDefinition<{ kind: 'entity-card'; name: 'consumed-apis'; config: { @@ -119,7 +119,7 @@ const _default: OverridableFrontendPlugin< type?: EntityCardType; }; }>; - 'entity-card:api-docs/consuming-components': ExtensionDefinition<{ + 'entity-card:api-docs/consuming-components': OverridableExtensionDefinition<{ kind: 'entity-card'; name: 'consuming-components'; config: { @@ -160,7 +160,7 @@ const _default: OverridableFrontendPlugin< type?: EntityCardType; }; }>; - 'entity-card:api-docs/definition': ExtensionDefinition<{ + 'entity-card:api-docs/definition': OverridableExtensionDefinition<{ kind: 'entity-card'; name: 'definition'; config: { @@ -201,7 +201,7 @@ const _default: OverridableFrontendPlugin< type?: EntityCardType; }; }>; - 'entity-card:api-docs/has-apis': ExtensionDefinition<{ + 'entity-card:api-docs/has-apis': OverridableExtensionDefinition<{ kind: 'entity-card'; name: 'has-apis'; config: { @@ -242,7 +242,7 @@ const _default: OverridableFrontendPlugin< type?: EntityCardType; }; }>; - 'entity-card:api-docs/provided-apis': ExtensionDefinition<{ + 'entity-card:api-docs/provided-apis': OverridableExtensionDefinition<{ kind: 'entity-card'; name: 'provided-apis'; config: { @@ -283,7 +283,7 @@ const _default: OverridableFrontendPlugin< type?: EntityCardType; }; }>; - 'entity-card:api-docs/providing-components': ExtensionDefinition<{ + 'entity-card:api-docs/providing-components': OverridableExtensionDefinition<{ kind: 'entity-card'; name: 'providing-components'; config: { @@ -324,7 +324,7 @@ const _default: OverridableFrontendPlugin< type?: EntityCardType; }; }>; - 'entity-content:api-docs/apis': ExtensionDefinition<{ + 'entity-content:api-docs/apis': OverridableExtensionDefinition<{ kind: 'entity-content'; name: 'apis'; config: { @@ -384,7 +384,7 @@ const _default: OverridableFrontendPlugin< filter?: string | EntityPredicate | ((entity: Entity) => boolean); }; }>; - 'entity-content:api-docs/definition': ExtensionDefinition<{ + 'entity-content:api-docs/definition': OverridableExtensionDefinition<{ kind: 'entity-content'; name: 'definition'; config: { @@ -444,7 +444,7 @@ const _default: OverridableFrontendPlugin< filter?: string | EntityPredicate | ((entity: Entity) => boolean); }; }>; - 'nav-item:api-docs': ExtensionDefinition<{ + 'nav-item:api-docs': OverridableExtensionDefinition<{ kind: 'nav-item'; name: undefined; config: {}; @@ -465,7 +465,7 @@ const _default: OverridableFrontendPlugin< routeRef: RouteRef; }; }>; - 'page:api-docs': ExtensionDefinition<{ + 'page:api-docs': OverridableExtensionDefinition<{ config: { initiallySelectedFilter: 'all' | 'owned' | 'starred' | undefined; } & { diff --git a/plugins/app-visualizer/report.api.md b/plugins/app-visualizer/report.api.md index 1283df5486..f3b7e6ae61 100644 --- a/plugins/app-visualizer/report.api.md +++ b/plugins/app-visualizer/report.api.md @@ -5,9 +5,9 @@ ```ts import { AnyRouteRefParams } from '@backstage/frontend-plugin-api'; import { ExtensionDataRef } from '@backstage/frontend-plugin-api'; -import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; import { IconComponent } from '@backstage/core-plugin-api'; import { JSX as JSX_2 } from 'react'; +import { OverridableExtensionDefinition } from '@backstage/frontend-plugin-api'; import { OverridableFrontendPlugin } from '@backstage/frontend-plugin-api'; import { RouteRef } from '@backstage/frontend-plugin-api'; @@ -16,7 +16,7 @@ const visualizerPlugin: OverridableFrontendPlugin< {}, {}, { - 'nav-item:app-visualizer': ExtensionDefinition<{ + 'nav-item:app-visualizer': OverridableExtensionDefinition<{ kind: 'nav-item'; name: undefined; config: {}; @@ -37,7 +37,7 @@ const visualizerPlugin: OverridableFrontendPlugin< routeRef: RouteRef; }; }>; - 'page:app-visualizer': ExtensionDefinition<{ + 'page:app-visualizer': OverridableExtensionDefinition<{ kind: 'page'; name: undefined; config: { diff --git a/plugins/app/report.api.md b/plugins/app/report.api.md index 595cc9bc19..bd8c05bfe4 100644 --- a/plugins/app/report.api.md +++ b/plugins/app/report.api.md @@ -12,12 +12,12 @@ import { ComponentType } from 'react'; import { ConfigurableExtensionDataRef } from '@backstage/frontend-plugin-api'; import { ExtensionBlueprintParams } from '@backstage/frontend-plugin-api'; import { ExtensionDataRef } from '@backstage/frontend-plugin-api'; -import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; import { ExtensionInput } from '@backstage/frontend-plugin-api'; import { IconComponent } from '@backstage/core-plugin-api'; import { IconComponent as IconComponent_2 } from '@backstage/frontend-plugin-api'; import { JSX as JSX_2 } from 'react'; import { NavContentComponent } from '@backstage/frontend-plugin-api'; +import { OverridableExtensionDefinition } from '@backstage/frontend-plugin-api'; import { OverridableFrontendPlugin } from '@backstage/frontend-plugin-api'; import { ReactNode } from 'react'; import { RouteRef } from '@backstage/frontend-plugin-api'; @@ -31,7 +31,7 @@ const appPlugin: OverridableFrontendPlugin< {}, {}, { - app: ExtensionDefinition<{ + app: OverridableExtensionDefinition<{ config: {}; configInput: {}; output: ExtensionDataRef; @@ -48,7 +48,7 @@ const appPlugin: OverridableFrontendPlugin< kind: undefined; name: undefined; }>; - 'app/layout': ExtensionDefinition<{ + 'app/layout': OverridableExtensionDefinition<{ config: {}; configInput: {}; output: ExtensionDataRef; @@ -72,7 +72,7 @@ const appPlugin: OverridableFrontendPlugin< kind: undefined; name: 'layout'; }>; - 'app/nav': ExtensionDefinition<{ + 'app/nav': OverridableExtensionDefinition<{ config: {}; configInput: {}; output: ExtensionDataRef; @@ -108,7 +108,7 @@ const appPlugin: OverridableFrontendPlugin< kind: undefined; name: 'nav'; }>; - 'app/root': ExtensionDefinition<{ + 'app/root': OverridableExtensionDefinition<{ config: {}; configInput: {}; output: ExtensionDataRef; @@ -165,7 +165,7 @@ const appPlugin: OverridableFrontendPlugin< kind: undefined; name: 'root'; }>; - 'app/routes': ExtensionDefinition<{ + 'app/routes': OverridableExtensionDefinition<{ config: {}; configInput: {}; output: ExtensionDataRef; @@ -190,7 +190,7 @@ const appPlugin: OverridableFrontendPlugin< kind: undefined; name: 'routes'; }>; - 'api:app/alert': ExtensionDefinition<{ + 'api:app/alert': OverridableExtensionDefinition<{ kind: 'api'; name: 'alert'; config: {}; @@ -205,7 +205,7 @@ const appPlugin: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'api:app/analytics': ExtensionDefinition<{ + 'api:app/analytics': OverridableExtensionDefinition<{ config: {}; configInput: {}; output: ExtensionDataRef; @@ -232,7 +232,7 @@ const appPlugin: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'api:app/app-language': ExtensionDefinition<{ + 'api:app/app-language': OverridableExtensionDefinition<{ kind: 'api'; name: 'app-language'; config: {}; @@ -247,7 +247,7 @@ const appPlugin: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'api:app/app-theme': ExtensionDefinition<{ + 'api:app/app-theme': OverridableExtensionDefinition<{ config: {}; configInput: {}; output: ExtensionDataRef; @@ -270,7 +270,7 @@ const appPlugin: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'api:app/atlassian-auth': ExtensionDefinition<{ + 'api:app/atlassian-auth': OverridableExtensionDefinition<{ kind: 'api'; name: 'atlassian-auth'; config: {}; @@ -285,7 +285,7 @@ const appPlugin: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'api:app/bitbucket-auth': ExtensionDefinition<{ + 'api:app/bitbucket-auth': OverridableExtensionDefinition<{ kind: 'api'; name: 'bitbucket-auth'; config: {}; @@ -300,7 +300,7 @@ const appPlugin: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'api:app/bitbucket-server-auth': ExtensionDefinition<{ + 'api:app/bitbucket-server-auth': OverridableExtensionDefinition<{ kind: 'api'; name: 'bitbucket-server-auth'; config: {}; @@ -315,7 +315,7 @@ const appPlugin: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'api:app/components': ExtensionDefinition<{ + 'api:app/components': OverridableExtensionDefinition<{ kind: 'api'; name: 'components'; config: {}; @@ -330,7 +330,7 @@ const appPlugin: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'api:app/dialog': ExtensionDefinition<{ + 'api:app/dialog': OverridableExtensionDefinition<{ kind: 'api'; name: 'dialog'; config: {}; @@ -345,7 +345,7 @@ const appPlugin: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'api:app/discovery': ExtensionDefinition<{ + 'api:app/discovery': OverridableExtensionDefinition<{ kind: 'api'; name: 'discovery'; config: {}; @@ -360,7 +360,7 @@ const appPlugin: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'api:app/error': ExtensionDefinition<{ + 'api:app/error': OverridableExtensionDefinition<{ kind: 'api'; name: 'error'; config: {}; @@ -375,7 +375,7 @@ const appPlugin: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'api:app/feature-flags': ExtensionDefinition<{ + 'api:app/feature-flags': OverridableExtensionDefinition<{ kind: 'api'; name: 'feature-flags'; config: {}; @@ -390,7 +390,7 @@ const appPlugin: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'api:app/fetch': ExtensionDefinition<{ + 'api:app/fetch': OverridableExtensionDefinition<{ kind: 'api'; name: 'fetch'; config: {}; @@ -405,7 +405,7 @@ const appPlugin: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'api:app/github-auth': ExtensionDefinition<{ + 'api:app/github-auth': OverridableExtensionDefinition<{ kind: 'api'; name: 'github-auth'; config: {}; @@ -420,7 +420,7 @@ const appPlugin: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'api:app/gitlab-auth': ExtensionDefinition<{ + 'api:app/gitlab-auth': OverridableExtensionDefinition<{ kind: 'api'; name: 'gitlab-auth'; config: {}; @@ -435,7 +435,7 @@ const appPlugin: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'api:app/google-auth': ExtensionDefinition<{ + 'api:app/google-auth': OverridableExtensionDefinition<{ kind: 'api'; name: 'google-auth'; config: {}; @@ -450,7 +450,7 @@ const appPlugin: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'api:app/icons': ExtensionDefinition<{ + 'api:app/icons': OverridableExtensionDefinition<{ config: {}; configInput: {}; output: ExtensionDataRef; @@ -479,7 +479,7 @@ const appPlugin: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'api:app/microsoft-auth': ExtensionDefinition<{ + 'api:app/microsoft-auth': OverridableExtensionDefinition<{ kind: 'api'; name: 'microsoft-auth'; config: {}; @@ -494,7 +494,7 @@ const appPlugin: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'api:app/oauth-request': ExtensionDefinition<{ + 'api:app/oauth-request': OverridableExtensionDefinition<{ kind: 'api'; name: 'oauth-request'; config: {}; @@ -509,7 +509,7 @@ const appPlugin: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'api:app/okta-auth': ExtensionDefinition<{ + 'api:app/okta-auth': OverridableExtensionDefinition<{ kind: 'api'; name: 'okta-auth'; config: {}; @@ -524,7 +524,7 @@ const appPlugin: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'api:app/onelogin-auth': ExtensionDefinition<{ + 'api:app/onelogin-auth': OverridableExtensionDefinition<{ kind: 'api'; name: 'onelogin-auth'; config: {}; @@ -539,7 +539,7 @@ const appPlugin: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'api:app/openshift-auth': ExtensionDefinition<{ + 'api:app/openshift-auth': OverridableExtensionDefinition<{ kind: 'api'; name: 'openshift-auth'; config: {}; @@ -554,7 +554,7 @@ const appPlugin: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'api:app/permission': ExtensionDefinition<{ + 'api:app/permission': OverridableExtensionDefinition<{ kind: 'api'; name: 'permission'; config: {}; @@ -569,7 +569,7 @@ const appPlugin: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'api:app/scm-auth': ExtensionDefinition<{ + 'api:app/scm-auth': OverridableExtensionDefinition<{ kind: 'api'; name: 'scm-auth'; config: {}; @@ -584,7 +584,7 @@ const appPlugin: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'api:app/scm-integrations': ExtensionDefinition<{ + 'api:app/scm-integrations': OverridableExtensionDefinition<{ kind: 'api'; name: 'scm-integrations'; config: {}; @@ -599,7 +599,7 @@ const appPlugin: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'api:app/storage': ExtensionDefinition<{ + 'api:app/storage': OverridableExtensionDefinition<{ kind: 'api'; name: 'storage'; config: {}; @@ -614,7 +614,7 @@ const appPlugin: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'api:app/swappable-components': ExtensionDefinition<{ + 'api:app/swappable-components': OverridableExtensionDefinition<{ config: {}; configInput: {}; output: ExtensionDataRef; @@ -646,7 +646,7 @@ const appPlugin: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'api:app/translations': ExtensionDefinition<{ + 'api:app/translations': OverridableExtensionDefinition<{ config: {}; configInput: {}; output: ExtensionDataRef; @@ -680,7 +680,7 @@ const appPlugin: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'api:app/vmware-cloud-auth': ExtensionDefinition<{ + 'api:app/vmware-cloud-auth': OverridableExtensionDefinition<{ kind: 'api'; name: 'vmware-cloud-auth'; config: {}; @@ -695,7 +695,7 @@ const appPlugin: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'app-root-element:app/alert-display': ExtensionDefinition<{ + 'app-root-element:app/alert-display': OverridableExtensionDefinition<{ config: { transientTimeoutMs: number; anchorOrigin: { @@ -728,7 +728,7 @@ const appPlugin: OverridableFrontendPlugin< element: JSX.Element; }; }>; - 'app-root-element:app/dialog-display': ExtensionDefinition<{ + 'app-root-element:app/dialog-display': OverridableExtensionDefinition<{ config: {}; configInput: {}; output: ExtensionDataRef; @@ -747,7 +747,7 @@ const appPlugin: OverridableFrontendPlugin< element: JSX.Element; }; }>; - 'app-root-element:app/oauth-request-dialog': ExtensionDefinition<{ + 'app-root-element:app/oauth-request-dialog': OverridableExtensionDefinition<{ kind: 'app-root-element'; name: 'oauth-request-dialog'; config: {}; @@ -758,7 +758,7 @@ const appPlugin: OverridableFrontendPlugin< element: JSX.Element; }; }>; - 'component:app/core-error-display': ExtensionDefinition<{ + 'component:app/core-error-display': OverridableExtensionDefinition<{ kind: 'component'; name: 'core-error-display'; config: {}; @@ -814,7 +814,7 @@ const appPlugin: OverridableFrontendPlugin< : never; }>; }>; - 'component:app/core-not-found-error-page': ExtensionDefinition<{ + 'component:app/core-not-found-error-page': OverridableExtensionDefinition<{ kind: 'component'; name: 'core-not-found-error-page'; config: {}; @@ -870,7 +870,7 @@ const appPlugin: OverridableFrontendPlugin< : never; }>; }>; - 'component:app/core-progress': ExtensionDefinition<{ + 'component:app/core-progress': OverridableExtensionDefinition<{ kind: 'component'; name: 'core-progress'; config: {}; @@ -926,7 +926,7 @@ const appPlugin: OverridableFrontendPlugin< : never; }>; }>; - 'sign-in-page:app': ExtensionDefinition<{ + 'sign-in-page:app': OverridableExtensionDefinition<{ kind: 'sign-in-page'; name: undefined; config: {}; @@ -941,7 +941,7 @@ const appPlugin: OverridableFrontendPlugin< loader: () => Promise>; }; }>; - 'theme:app/dark': ExtensionDefinition<{ + 'theme:app/dark': OverridableExtensionDefinition<{ kind: 'theme'; name: 'dark'; config: {}; @@ -952,7 +952,7 @@ const appPlugin: OverridableFrontendPlugin< theme: AppTheme; }; }>; - 'theme:app/light': ExtensionDefinition<{ + 'theme:app/light': OverridableExtensionDefinition<{ kind: 'theme'; name: 'light'; config: {}; diff --git a/plugins/auth/report.api.md b/plugins/auth/report.api.md index 4c7d2d4a11..1d346a9ce4 100644 --- a/plugins/auth/report.api.md +++ b/plugins/auth/report.api.md @@ -5,8 +5,8 @@ ```ts import { AnyRouteRefParams } from '@backstage/frontend-plugin-api'; import { ExtensionDataRef } from '@backstage/frontend-plugin-api'; -import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; import { JSX as JSX_2 } from 'react'; +import { OverridableExtensionDefinition } from '@backstage/frontend-plugin-api'; import { OverridableFrontendPlugin } from '@backstage/frontend-plugin-api'; import { RouteRef } from '@backstage/frontend-plugin-api'; @@ -17,7 +17,7 @@ const _default: OverridableFrontendPlugin< }, {}, { - 'page:auth': ExtensionDefinition<{ + 'page:auth': OverridableExtensionDefinition<{ kind: 'page'; name: undefined; config: { diff --git a/plugins/catalog-graph/report-alpha.api.md b/plugins/catalog-graph/report-alpha.api.md index 0d06beacc4..285b8b3119 100644 --- a/plugins/catalog-graph/report-alpha.api.md +++ b/plugins/catalog-graph/report-alpha.api.md @@ -11,10 +11,10 @@ import { EntityCardType } from '@backstage/plugin-catalog-react/alpha'; import { EntityPredicate } from '@backstage/plugin-catalog-react/alpha'; import { ExtensionBlueprintParams } from '@backstage/frontend-plugin-api'; import { ExtensionDataRef } from '@backstage/frontend-plugin-api'; -import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; import { ExtensionInput } from '@backstage/frontend-plugin-api'; import { ExternalRouteRef } from '@backstage/frontend-plugin-api'; import { JSX as JSX_2 } from 'react'; +import { OverridableExtensionDefinition } from '@backstage/frontend-plugin-api'; import { OverridableFrontendPlugin } from '@backstage/frontend-plugin-api'; import { RouteRef } from '@backstage/frontend-plugin-api'; import { TranslationRef } from '@backstage/frontend-plugin-api'; @@ -60,7 +60,7 @@ const _default: OverridableFrontendPlugin< }>; }, { - 'api:catalog-graph': ExtensionDefinition<{ + 'api:catalog-graph': OverridableExtensionDefinition<{ kind: 'api'; name: undefined; config: {}; @@ -75,7 +75,7 @@ const _default: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'entity-card:catalog-graph/relations': ExtensionDefinition<{ + 'entity-card:catalog-graph/relations': OverridableExtensionDefinition<{ config: { kinds: string[] | undefined; relations: string[] | undefined; @@ -148,7 +148,7 @@ const _default: OverridableFrontendPlugin< type?: EntityCardType; }; }>; - 'page:catalog-graph': ExtensionDefinition<{ + 'page:catalog-graph': OverridableExtensionDefinition<{ config: { selectedKinds: string[] | undefined; selectedRelations: string[] | undefined; diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index e3a646d895..cffe9a230d 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -66,6 +66,7 @@ "@backstage/integration-react": "workspace:^", "@backstage/plugin-catalog-common": "workspace:^", "@backstage/plugin-catalog-react": "workspace:^", + "@backstage/plugin-permission-react": "workspace:^", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.61", diff --git a/plugins/catalog-import/report-alpha.api.md b/plugins/catalog-import/report-alpha.api.md index 051e38cd19..5dfa90388a 100644 --- a/plugins/catalog-import/report-alpha.api.md +++ b/plugins/catalog-import/report-alpha.api.md @@ -8,8 +8,8 @@ import { AnyRouteRefParams } from '@backstage/frontend-plugin-api'; import { ApiFactory } from '@backstage/core-plugin-api'; import { ExtensionBlueprintParams } from '@backstage/frontend-plugin-api'; import { ExtensionDataRef } from '@backstage/frontend-plugin-api'; -import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; import { JSX as JSX_2 } from 'react'; +import { OverridableExtensionDefinition } from '@backstage/frontend-plugin-api'; import { OverridableFrontendPlugin } from '@backstage/frontend-plugin-api'; import { RouteRef } from '@backstage/frontend-plugin-api'; import { TranslationRef } from '@backstage/core-plugin-api/alpha'; @@ -94,7 +94,7 @@ const _default: OverridableFrontendPlugin< }, {}, { - 'api:catalog-import': ExtensionDefinition<{ + 'api:catalog-import': OverridableExtensionDefinition<{ kind: 'api'; name: undefined; config: {}; @@ -109,7 +109,7 @@ const _default: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'page:catalog-import': ExtensionDefinition<{ + 'page:catalog-import': OverridableExtensionDefinition<{ kind: 'page'; name: undefined; config: { diff --git a/plugins/catalog-import/src/alpha.tsx b/plugins/catalog-import/src/alpha.tsx index ab9d06ef19..2d9e5deaba 100644 --- a/plugins/catalog-import/src/alpha.tsx +++ b/plugins/catalog-import/src/alpha.tsx @@ -35,6 +35,8 @@ import { import { CatalogImportClient, catalogImportApiRef } from './api'; import { rootRouteRef } from './plugin'; import { catalogApiRef } from '@backstage/plugin-catalog-react'; +import { RequirePermission } from '@backstage/plugin-permission-react'; +import { catalogEntityCreatePermission } from '@backstage/plugin-catalog-common/alpha'; export * from './translation'; @@ -46,7 +48,11 @@ const catalogImportPage = PageBlueprint.make({ routeRef: convertLegacyRouteRef(rootRouteRef), loader: () => import('./components/ImportPage').then(m => - compatWrapper(), + compatWrapper( + + + , + ), ), }, }); diff --git a/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx b/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx index 8ef1707bb1..f7090f330b 100644 --- a/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx +++ b/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx @@ -498,6 +498,29 @@ describe('', () => { }); }); + it('applies frontend-only filters without refetching', async () => { + const { result } = renderHook(() => useEntityList(), { + wrapper: createWrapper({ pagination }), + }); + + await waitFor(() => { + expect(result.current.backendEntities.length).toBe(2); + expect(result.current.filters.kind?.value).toBe('component'); + }); + + act(() => + result.current.updateFilters({ + user: EntityUserFilter.all(), + }), + ); + + await waitFor(() => { + expect(result.current.filters.user?.value).toBe('all'); + expect(result.current.entities.length).toBe(2); + }); + expect(mockCatalogApi.queryEntities).toHaveBeenCalledTimes(1); + }); + it('resolves query param filter values', async () => { const query = qs.stringify({ filters: { kind: 'component', type: 'service' }, @@ -801,6 +824,29 @@ describe(``, () => { }); }); + it('applies frontend-only filters without refetching', async () => { + const { result } = renderHook(() => useEntityList(), { + wrapper: createWrapper({ pagination }), + }); + + await waitFor(() => { + expect(result.current.backendEntities.length).toBe(2); + expect(result.current.filters.kind?.value).toBe('component'); + }); + + act(() => + result.current.updateFilters({ + user: EntityUserFilter.all(), + }), + ); + + await waitFor(() => { + expect(result.current.filters.user?.value).toBe('all'); + expect(result.current.entities.length).toBe(2); + }); + expect(mockCatalogApi.queryEntities).toHaveBeenCalledTimes(1); + }); + it('resolves query param filter values', async () => { const query = qs.stringify({ filters: { kind: 'component', type: 'service' }, diff --git a/plugins/catalog-react/src/hooks/useEntityListProvider.tsx b/plugins/catalog-react/src/hooks/useEntityListProvider.tsx index 319740e70e..8c4927ad0a 100644 --- a/plugins/catalog-react/src/hooks/useEntityListProvider.tsx +++ b/plugins/catalog-react/src/hooks/useEntityListProvider.tsx @@ -249,11 +249,11 @@ export const EntityListProvider = ( ? { ...requestedFilters, owners: undefined } : requestedFilters; const compacted = compact(Object.values(adjustedFilters)); + const entityFilter = reduceEntityFilters(compacted); if (paginationMode !== 'none') { if (cursor) { if (cursor !== outputState.appliedCursor) { - const entityFilter = reduceEntityFilters(compacted); const response = await catalogApi.queryEntities({ cursor, limit, @@ -267,58 +267,42 @@ export const EntityListProvider = ( totalItems: response.totalItems, }; } - } else { - const entityFilter = reduceEntityFilters(compacted); - const backendFilter = reduceCatalogFilters(compacted); - const previousBackendFilter = reduceCatalogFilters( - compact(Object.values(outputState.appliedFilters)), - ); - - if ( - (paginationMode === 'offset' && - (outputState.limit !== limit || outputState.offset !== offset)) || - !isEqual(previousBackendFilter, backendFilter) - ) { - const response = await catalogApi.queryEntities({ - ...backendFilter, - limit, - offset, - }); - return { - appliedFilters: requestedFilters, - backendEntities: response.items, - entities: response.items.filter(entityFilter), - pageInfo: response.pageInfo, - totalItems: response.totalItems, - limit, - offset, - }; - } + const entities = outputState.backendEntities.filter(entityFilter); + return { + appliedFilters: requestedFilters, + appliedCursor: outputState.appliedCursor, + backendEntities: outputState.backendEntities, + entities, + pageInfo: outputState.pageInfo, + totalItems: outputState.totalItems, + limit: outputState.limit, + offset: outputState.offset, + }; } - } else { - const entityFilter = reduceEntityFilters(compacted); - const backendFilter = reduceBackendCatalogFilters(compacted); - const { orderFields } = reduceCatalogFilters(compacted); - const previousBackendFilter = reduceBackendCatalogFilters( + + const backendFilter = reduceCatalogFilters(compacted); + const previousBackendFilter = reduceCatalogFilters( compact(Object.values(outputState.appliedFilters)), ); - // TODO(mtlewis): currently entities will never be requested unless - // there's at least one filter, we should allow an initial request - // to happen with no filters. - if (!isEqual(previousBackendFilter, backendFilter)) { - // TODO(timbonicus): should limit fields here, but would need filter - // fields + table columns - const response = await catalogApi.getEntities({ - filter: backendFilter, - order: orderFields, + if ( + (paginationMode === 'offset' && + (outputState.limit !== limit || outputState.offset !== offset)) || + !isEqual(previousBackendFilter, backendFilter) + ) { + const response = await catalogApi.queryEntities({ + ...backendFilter, + limit, + offset, }); - const entities = response.items.filter(entityFilter); return { appliedFilters: requestedFilters, backendEntities: response.items, - entities, - totalItems: entities.length, + entities: response.items.filter(entityFilter), + pageInfo: response.pageInfo, + totalItems: response.totalItems, + limit, + offset, }; } const entities = outputState.backendEntities.filter(entityFilter); @@ -326,10 +310,44 @@ export const EntityListProvider = ( appliedFilters: requestedFilters, backendEntities: outputState.backendEntities, entities, + pageInfo: outputState.pageInfo, + totalItems: outputState.totalItems, + limit: outputState.limit, + offset: outputState.offset, + }; + } + + const backendFilter = reduceBackendCatalogFilters(compacted); + const { orderFields } = reduceCatalogFilters(compacted); + const previousBackendFilter = reduceBackendCatalogFilters( + compact(Object.values(outputState.appliedFilters)), + ); + + // TODO(mtlewis): currently entities will never be requested unless + // there's at least one filter, we should allow an initial request + // to happen with no filters. + if (!isEqual(previousBackendFilter, backendFilter)) { + // TODO(timbonicus): should limit fields here, but would need filter + // fields + table columns + const response = await catalogApi.getEntities({ + filter: backendFilter, + order: orderFields, + }); + const entities = response.items.filter(entityFilter); + return { + appliedFilters: requestedFilters, + backendEntities: response.items, + entities, totalItems: entities.length, }; } - return undefined; + const entities = outputState.backendEntities.filter(entityFilter); + return { + appliedFilters: requestedFilters, + backendEntities: outputState.backendEntities, + entities, + totalItems: entities.length, + }; }, [ catalogApi, diff --git a/plugins/catalog-unprocessed-entities/report-alpha.api.md b/plugins/catalog-unprocessed-entities/report-alpha.api.md index 17d28ee165..5518f6d273 100644 --- a/plugins/catalog-unprocessed-entities/report-alpha.api.md +++ b/plugins/catalog-unprocessed-entities/report-alpha.api.md @@ -8,9 +8,9 @@ import { AnyRouteRefParams } from '@backstage/frontend-plugin-api'; import { ApiFactory } from '@backstage/frontend-plugin-api'; import { ExtensionBlueprintParams } from '@backstage/frontend-plugin-api'; import { ExtensionDataRef } from '@backstage/frontend-plugin-api'; -import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; import { IconComponent } from '@backstage/core-plugin-api'; import { JSX as JSX_2 } from 'react'; +import { OverridableExtensionDefinition } from '@backstage/frontend-plugin-api'; import { OverridableFrontendPlugin } from '@backstage/frontend-plugin-api'; import { RouteRef } from '@backstage/frontend-plugin-api'; @@ -21,7 +21,7 @@ const _default: OverridableFrontendPlugin< }, {}, { - 'api:catalog-unprocessed-entities': ExtensionDefinition<{ + 'api:catalog-unprocessed-entities': OverridableExtensionDefinition<{ kind: 'api'; name: undefined; config: {}; @@ -36,7 +36,7 @@ const _default: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'nav-item:catalog-unprocessed-entities': ExtensionDefinition<{ + 'nav-item:catalog-unprocessed-entities': OverridableExtensionDefinition<{ kind: 'nav-item'; name: undefined; config: {}; @@ -57,7 +57,7 @@ const _default: OverridableFrontendPlugin< routeRef: RouteRef; }; }>; - 'page:catalog-unprocessed-entities': ExtensionDefinition<{ + 'page:catalog-unprocessed-entities': OverridableExtensionDefinition<{ kind: 'page'; name: undefined; config: { diff --git a/plugins/catalog/report-alpha.api.md b/plugins/catalog/report-alpha.api.md index fee768978d..6f63f50b0b 100644 --- a/plugins/catalog/report-alpha.api.md +++ b/plugins/catalog/report-alpha.api.md @@ -15,12 +15,12 @@ import { EntityContextMenuItemParams } from '@backstage/plugin-catalog-react/alp import { EntityPredicate } from '@backstage/plugin-catalog-react/alpha'; import { ExtensionBlueprintParams } from '@backstage/frontend-plugin-api'; import { ExtensionDataRef } from '@backstage/frontend-plugin-api'; -import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; import { ExtensionInput } from '@backstage/frontend-plugin-api'; import { ExternalRouteRef } from '@backstage/frontend-plugin-api'; import { IconComponent } from '@backstage/core-plugin-api'; import { IconLinkVerticalProps } from '@backstage/core-components'; import { JSX as JSX_2 } from 'react'; +import { OverridableExtensionDefinition } from '@backstage/frontend-plugin-api'; import { OverridableFrontendPlugin } from '@backstage/frontend-plugin-api'; import { RouteRef } from '@backstage/frontend-plugin-api'; import { SearchResultItemExtensionComponent } from '@backstage/plugin-search-react/alpha'; @@ -137,7 +137,7 @@ const _default: OverridableFrontendPlugin< unregisterRedirect: ExternalRouteRef; }, { - 'api:catalog': ExtensionDefinition<{ + 'api:catalog': OverridableExtensionDefinition<{ kind: 'api'; name: undefined; config: {}; @@ -152,7 +152,7 @@ const _default: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'api:catalog/entity-presentation': ExtensionDefinition<{ + 'api:catalog/entity-presentation': OverridableExtensionDefinition<{ kind: 'api'; name: 'entity-presentation'; config: {}; @@ -167,7 +167,7 @@ const _default: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'api:catalog/starred-entities': ExtensionDefinition<{ + 'api:catalog/starred-entities': OverridableExtensionDefinition<{ kind: 'api'; name: 'starred-entities'; config: {}; @@ -182,7 +182,7 @@ const _default: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'catalog-filter:catalog/kind': ExtensionDefinition<{ + 'catalog-filter:catalog/kind': OverridableExtensionDefinition<{ config: { initialFilter: string; }; @@ -205,7 +205,7 @@ const _default: OverridableFrontendPlugin< loader: () => Promise; }; }>; - 'catalog-filter:catalog/lifecycle': ExtensionDefinition<{ + 'catalog-filter:catalog/lifecycle': OverridableExtensionDefinition<{ kind: 'catalog-filter'; name: 'lifecycle'; config: {}; @@ -216,7 +216,7 @@ const _default: OverridableFrontendPlugin< loader: () => Promise; }; }>; - 'catalog-filter:catalog/list': ExtensionDefinition<{ + 'catalog-filter:catalog/list': OverridableExtensionDefinition<{ config: { initialFilter: 'all' | 'owned' | 'starred'; }; @@ -239,7 +239,7 @@ const _default: OverridableFrontendPlugin< loader: () => Promise; }; }>; - 'catalog-filter:catalog/mode': ExtensionDefinition<{ + 'catalog-filter:catalog/mode': OverridableExtensionDefinition<{ config: { mode: 'all' | 'owners-only' | undefined; }; @@ -262,7 +262,7 @@ const _default: OverridableFrontendPlugin< loader: () => Promise; }; }>; - 'catalog-filter:catalog/namespace': ExtensionDefinition<{ + 'catalog-filter:catalog/namespace': OverridableExtensionDefinition<{ kind: 'catalog-filter'; name: 'namespace'; config: {}; @@ -273,7 +273,7 @@ const _default: OverridableFrontendPlugin< loader: () => Promise; }; }>; - 'catalog-filter:catalog/processing-status': ExtensionDefinition<{ + 'catalog-filter:catalog/processing-status': OverridableExtensionDefinition<{ kind: 'catalog-filter'; name: 'processing-status'; config: {}; @@ -284,7 +284,7 @@ const _default: OverridableFrontendPlugin< loader: () => Promise; }; }>; - 'catalog-filter:catalog/tag': ExtensionDefinition<{ + 'catalog-filter:catalog/tag': OverridableExtensionDefinition<{ kind: 'catalog-filter'; name: 'tag'; config: {}; @@ -295,7 +295,7 @@ const _default: OverridableFrontendPlugin< loader: () => Promise; }; }>; - 'catalog-filter:catalog/type': ExtensionDefinition<{ + 'catalog-filter:catalog/type': OverridableExtensionDefinition<{ kind: 'catalog-filter'; name: 'type'; config: {}; @@ -306,7 +306,7 @@ const _default: OverridableFrontendPlugin< loader: () => Promise; }; }>; - 'entity-card:catalog/about': ExtensionDefinition<{ + 'entity-card:catalog/about': OverridableExtensionDefinition<{ config: { filter: EntityPredicate | undefined; type: 'content' | 'summary' | 'info' | undefined; @@ -373,7 +373,7 @@ const _default: OverridableFrontendPlugin< type?: EntityCardType; }; }>; - 'entity-card:catalog/depends-on-components': ExtensionDefinition<{ + 'entity-card:catalog/depends-on-components': OverridableExtensionDefinition<{ kind: 'entity-card'; name: 'depends-on-components'; config: { @@ -414,7 +414,7 @@ const _default: OverridableFrontendPlugin< type?: EntityCardType; }; }>; - 'entity-card:catalog/depends-on-resources': ExtensionDefinition<{ + 'entity-card:catalog/depends-on-resources': OverridableExtensionDefinition<{ kind: 'entity-card'; name: 'depends-on-resources'; config: { @@ -455,7 +455,7 @@ const _default: OverridableFrontendPlugin< type?: EntityCardType; }; }>; - 'entity-card:catalog/has-components': ExtensionDefinition<{ + 'entity-card:catalog/has-components': OverridableExtensionDefinition<{ kind: 'entity-card'; name: 'has-components'; config: { @@ -496,7 +496,7 @@ const _default: OverridableFrontendPlugin< type?: EntityCardType; }; }>; - 'entity-card:catalog/has-resources': ExtensionDefinition<{ + 'entity-card:catalog/has-resources': OverridableExtensionDefinition<{ kind: 'entity-card'; name: 'has-resources'; config: { @@ -537,7 +537,7 @@ const _default: OverridableFrontendPlugin< type?: EntityCardType; }; }>; - 'entity-card:catalog/has-subcomponents': ExtensionDefinition<{ + 'entity-card:catalog/has-subcomponents': OverridableExtensionDefinition<{ kind: 'entity-card'; name: 'has-subcomponents'; config: { @@ -578,7 +578,7 @@ const _default: OverridableFrontendPlugin< type?: EntityCardType; }; }>; - 'entity-card:catalog/has-subdomains': ExtensionDefinition<{ + 'entity-card:catalog/has-subdomains': OverridableExtensionDefinition<{ kind: 'entity-card'; name: 'has-subdomains'; config: { @@ -619,7 +619,7 @@ const _default: OverridableFrontendPlugin< type?: EntityCardType; }; }>; - 'entity-card:catalog/has-systems': ExtensionDefinition<{ + 'entity-card:catalog/has-systems': OverridableExtensionDefinition<{ kind: 'entity-card'; name: 'has-systems'; config: { @@ -660,7 +660,7 @@ const _default: OverridableFrontendPlugin< type?: EntityCardType; }; }>; - 'entity-card:catalog/labels': ExtensionDefinition<{ + 'entity-card:catalog/labels': OverridableExtensionDefinition<{ kind: 'entity-card'; name: 'labels'; config: { @@ -701,7 +701,7 @@ const _default: OverridableFrontendPlugin< type?: EntityCardType; }; }>; - 'entity-card:catalog/links': ExtensionDefinition<{ + 'entity-card:catalog/links': OverridableExtensionDefinition<{ kind: 'entity-card'; name: 'links'; config: { @@ -742,7 +742,7 @@ const _default: OverridableFrontendPlugin< type?: EntityCardType; }; }>; - 'entity-content:catalog/overview': ExtensionDefinition<{ + 'entity-content:catalog/overview': OverridableExtensionDefinition<{ config: { path: string | undefined; title: string | undefined; @@ -856,7 +856,7 @@ const _default: OverridableFrontendPlugin< filter?: string | EntityPredicate | ((entity: Entity) => boolean); }; }>; - 'entity-context-menu-item:catalog/copy-entity-url': ExtensionDefinition<{ + 'entity-context-menu-item:catalog/copy-entity-url': OverridableExtensionDefinition<{ kind: 'entity-context-menu-item'; name: 'copy-entity-url'; config: { @@ -877,7 +877,7 @@ const _default: OverridableFrontendPlugin< inputs: {}; params: EntityContextMenuItemParams; }>; - 'entity-context-menu-item:catalog/inspect-entity': ExtensionDefinition<{ + 'entity-context-menu-item:catalog/inspect-entity': OverridableExtensionDefinition<{ kind: 'entity-context-menu-item'; name: 'inspect-entity'; config: { @@ -898,7 +898,7 @@ const _default: OverridableFrontendPlugin< inputs: {}; params: EntityContextMenuItemParams; }>; - 'entity-context-menu-item:catalog/unregister-entity': ExtensionDefinition<{ + 'entity-context-menu-item:catalog/unregister-entity': OverridableExtensionDefinition<{ kind: 'entity-context-menu-item'; name: 'unregister-entity'; config: { @@ -919,7 +919,7 @@ const _default: OverridableFrontendPlugin< inputs: {}; params: EntityContextMenuItemParams; }>; - 'entity-icon-link:catalog/view-source': ExtensionDefinition<{ + 'entity-icon-link:catalog/view-source': OverridableExtensionDefinition<{ kind: 'entity-icon-link'; name: 'view-source'; config: { @@ -958,7 +958,7 @@ const _default: OverridableFrontendPlugin< filter?: EntityPredicate | ((entity: Entity) => boolean); }; }>; - 'nav-item:catalog': ExtensionDefinition<{ + 'nav-item:catalog': OverridableExtensionDefinition<{ kind: 'nav-item'; name: undefined; config: {}; @@ -979,7 +979,7 @@ const _default: OverridableFrontendPlugin< routeRef: RouteRef; }; }>; - 'page:catalog': ExtensionDefinition<{ + 'page:catalog': OverridableExtensionDefinition<{ config: { pagination: | boolean @@ -1031,7 +1031,7 @@ const _default: OverridableFrontendPlugin< routeRef?: RouteRef; }; }>; - 'page:catalog/entity': ExtensionDefinition<{ + 'page:catalog/entity': OverridableExtensionDefinition<{ config: { groups: | Record< @@ -1152,7 +1152,7 @@ const _default: OverridableFrontendPlugin< routeRef?: RouteRef; }; }>; - 'search-result-list-item:catalog': ExtensionDefinition<{ + 'search-result-list-item:catalog': OverridableExtensionDefinition<{ kind: 'search-result-list-item'; name: undefined; config: { diff --git a/plugins/catalog/src/alpha/DefaultEntityContentLayout.tsx b/plugins/catalog/src/alpha/DefaultEntityContentLayout.tsx index 77b84af275..d0bb4aeb8d 100644 --- a/plugins/catalog/src/alpha/DefaultEntityContentLayout.tsx +++ b/plugins/catalog/src/alpha/DefaultEntityContentLayout.tsx @@ -15,7 +15,6 @@ */ import { Fragment } from 'react'; -import Grid from '@material-ui/core/Grid'; import { makeStyles, Theme } from '@material-ui/core/styles'; import { EntityContentLayoutProps } from '@backstage/plugin-catalog-react/alpha'; import { EntitySwitch } from '../components/EntitySwitch'; @@ -42,6 +41,16 @@ const useStyles = makeStyles< flexFlow: 'column nowrap', gap: theme.spacing(3), }, + warningArea: { + display: 'flex', + flexDirection: 'column', + gap: theme.spacing(2), + marginBottom: theme.spacing(3), + '&:empty': { + marginBottom: 0, + display: 'none', + }, + }, mainContent: { display: 'flex', flexFlow: 'column', @@ -52,7 +61,7 @@ const useStyles = makeStyles< infoArea: { display: 'flex', flexFlow: 'column nowrap', - alignItems: 'flex-start', + alignItems: 'stretch', gap: theme.spacing(3), minWidth: 0, '& > *': { @@ -62,10 +71,11 @@ const useStyles = makeStyles< }, summaryArea: { minWidth: 0, - margin: theme.spacing(1.5), // To counteract MUI negative grid margin + margin: theme.spacing(1), // To counteract MUI negative grid margin }, summaryCard: { flex: '0 0 auto', + width: '100%', '& + &': { marginLeft: theme.spacing(3), }, @@ -96,7 +106,7 @@ const useStyles = makeStyles< }, summaryArea: { gridArea: 'summary', - marginBottom: theme.spacing(3), + margin: theme.spacing(1), // To counteract MUI negative grid margin }, infoArea: { gridArea: 'info', @@ -117,37 +127,12 @@ const useStyles = makeStyles< display: 'none', }, }, + summaryCard: { + width: 'auto', + }, }, })); -const entityWarningContent = ( - <> - - - - - - - - - - - - - - - - - - - - - - - - -); - export function DefaultEntityContentLayout(props: EntityContentLayoutProps) { const { cards } = props; @@ -165,7 +150,25 @@ export function DefaultEntityContentLayout(props: EntityContentLayoutProps) { return ( <> - {entityWarningContent} +
+ + + + + + + + + + + + + + + + + +
{infoCards.length > 0 ? (
diff --git a/plugins/devtools/report-alpha.api.md b/plugins/devtools/report-alpha.api.md index 7696267c35..c114924f4a 100644 --- a/plugins/devtools/report-alpha.api.md +++ b/plugins/devtools/report-alpha.api.md @@ -8,9 +8,9 @@ import { AnyRouteRefParams } from '@backstage/frontend-plugin-api'; import { ApiFactory } from '@backstage/frontend-plugin-api'; import { ExtensionBlueprintParams } from '@backstage/frontend-plugin-api'; import { ExtensionDataRef } from '@backstage/frontend-plugin-api'; -import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; import { IconComponent } from '@backstage/core-plugin-api'; import { JSX as JSX_2 } from 'react'; +import { OverridableExtensionDefinition } from '@backstage/frontend-plugin-api'; import { OverridableFrontendPlugin } from '@backstage/frontend-plugin-api'; import { RouteRef } from '@backstage/frontend-plugin-api'; @@ -21,7 +21,7 @@ const _default: OverridableFrontendPlugin< }, {}, { - 'api:devtools': ExtensionDefinition<{ + 'api:devtools': OverridableExtensionDefinition<{ kind: 'api'; name: undefined; config: {}; @@ -36,7 +36,7 @@ const _default: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'nav-item:devtools': ExtensionDefinition<{ + 'nav-item:devtools': OverridableExtensionDefinition<{ kind: 'nav-item'; name: undefined; config: {}; @@ -57,7 +57,7 @@ const _default: OverridableFrontendPlugin< routeRef: RouteRef; }; }>; - 'page:devtools': ExtensionDefinition<{ + 'page:devtools': OverridableExtensionDefinition<{ kind: 'page'; name: undefined; config: { diff --git a/plugins/home/report-alpha.api.md b/plugins/home/report-alpha.api.md index 8dbbb99b5d..58ceef751d 100644 --- a/plugins/home/report-alpha.api.md +++ b/plugins/home/report-alpha.api.md @@ -9,9 +9,9 @@ import { ApiFactory } from '@backstage/frontend-plugin-api'; import { ConfigurableExtensionDataRef } from '@backstage/frontend-plugin-api'; import { ExtensionBlueprintParams } from '@backstage/frontend-plugin-api'; import { ExtensionDataRef } from '@backstage/frontend-plugin-api'; -import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; import { ExtensionInput } from '@backstage/frontend-plugin-api'; import { JSX as JSX_2 } from 'react'; +import { OverridableExtensionDefinition } from '@backstage/frontend-plugin-api'; import { OverridableFrontendPlugin } from '@backstage/frontend-plugin-api'; import { RouteRef } from '@backstage/frontend-plugin-api'; import { TranslationRef } from '@backstage/frontend-plugin-api'; @@ -23,7 +23,7 @@ const _default: OverridableFrontendPlugin< }, {}, { - 'api:home/visits': ExtensionDefinition<{ + 'api:home/visits': OverridableExtensionDefinition<{ kind: 'api'; name: 'visits'; config: {}; @@ -38,7 +38,7 @@ const _default: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'app-root-element:home/visit-listener': ExtensionDefinition<{ + 'app-root-element:home/visit-listener': OverridableExtensionDefinition<{ kind: 'app-root-element'; name: 'visit-listener'; config: {}; @@ -49,7 +49,7 @@ const _default: OverridableFrontendPlugin< element: JSX.Element; }; }>; - 'page:home': ExtensionDefinition<{ + 'page:home': OverridableExtensionDefinition<{ config: { path: string | undefined; }; diff --git a/plugins/kubernetes/report-alpha.api.md b/plugins/kubernetes/report-alpha.api.md index 9bcbeb4ede..571e09d546 100644 --- a/plugins/kubernetes/report-alpha.api.md +++ b/plugins/kubernetes/report-alpha.api.md @@ -11,8 +11,8 @@ import { Entity } from '@backstage/catalog-model'; import { EntityPredicate } from '@backstage/plugin-catalog-react/alpha'; import { ExtensionBlueprintParams } from '@backstage/frontend-plugin-api'; import { ExtensionDataRef } from '@backstage/frontend-plugin-api'; -import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; import { JSX as JSX_2 } from 'react'; +import { OverridableExtensionDefinition } from '@backstage/frontend-plugin-api'; import { OverridableFrontendPlugin } from '@backstage/frontend-plugin-api'; import { RouteRef } from '@backstage/frontend-plugin-api'; import { TranslationRef } from '@backstage/core-plugin-api/alpha'; @@ -24,7 +24,7 @@ const _default: OverridableFrontendPlugin< }, {}, { - 'api:kubernetes': ExtensionDefinition<{ + 'api:kubernetes': OverridableExtensionDefinition<{ kind: 'api'; name: undefined; config: {}; @@ -39,7 +39,7 @@ const _default: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'api:kubernetes/auth-providers': ExtensionDefinition<{ + 'api:kubernetes/auth-providers': OverridableExtensionDefinition<{ kind: 'api'; name: 'auth-providers'; config: {}; @@ -54,7 +54,7 @@ const _default: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'api:kubernetes/cluster-link-formatter': ExtensionDefinition<{ + 'api:kubernetes/cluster-link-formatter': OverridableExtensionDefinition<{ kind: 'api'; name: 'cluster-link-formatter'; config: {}; @@ -69,7 +69,7 @@ const _default: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'api:kubernetes/proxy': ExtensionDefinition<{ + 'api:kubernetes/proxy': OverridableExtensionDefinition<{ kind: 'api'; name: 'proxy'; config: {}; @@ -84,7 +84,7 @@ const _default: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'entity-content:kubernetes/kubernetes': ExtensionDefinition<{ + 'entity-content:kubernetes/kubernetes': OverridableExtensionDefinition<{ kind: 'entity-content'; name: 'kubernetes'; config: { @@ -144,7 +144,7 @@ const _default: OverridableFrontendPlugin< filter?: string | EntityPredicate | ((entity: Entity) => boolean); }; }>; - 'page:kubernetes': ExtensionDefinition<{ + 'page:kubernetes': OverridableExtensionDefinition<{ kind: 'page'; name: undefined; config: { diff --git a/plugins/mui-to-bui/report.api.md b/plugins/mui-to-bui/report.api.md index 593130ea86..519f0c1bc7 100644 --- a/plugins/mui-to-bui/report.api.md +++ b/plugins/mui-to-bui/report.api.md @@ -6,9 +6,9 @@ import { AnyRouteRefParams } from '@backstage/frontend-plugin-api'; import { BackstagePlugin } from '@backstage/core-plugin-api'; import { ExtensionDataRef } from '@backstage/frontend-plugin-api'; -import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; import { JSX as JSX_2 } from 'react'; import { JSX as JSX_3 } from 'react/jsx-runtime'; +import { OverridableExtensionDefinition } from '@backstage/frontend-plugin-api'; import { OverridableFrontendPlugin } from '@backstage/frontend-plugin-api'; import { RouteRef } from '@backstage/frontend-plugin-api'; import { RouteRef as RouteRef_2 } from '@backstage/core-plugin-api'; @@ -31,7 +31,7 @@ const _default: OverridableFrontendPlugin< }, {}, { - 'page:mui-to-bui': ExtensionDefinition<{ + 'page:mui-to-bui': OverridableExtensionDefinition<{ kind: 'page'; name: undefined; config: { diff --git a/plugins/notifications-backend-module-slack/src/lib/SlackNotificationProcessor.ts b/plugins/notifications-backend-module-slack/src/lib/SlackNotificationProcessor.ts index 96d4b2ff3e..f9b00c9a58 100644 --- a/plugins/notifications-backend-module-slack/src/lib/SlackNotificationProcessor.ts +++ b/plugins/notifications-backend-module-slack/src/lib/SlackNotificationProcessor.ts @@ -148,12 +148,12 @@ export class SlackNotificationProcessor implements NotificationProcessor { let successCount = 0; let failureCount = 0; - results.forEach(result => { + results.forEach((result, index) => { if (result.status === 'fulfilled') { successCount++; } else { this.logger.error( - `Failed to send Slack channel notification: ${result.reason.message}`, + `Failed to send Slack channel notification to ${opts[index].channel}: ${result.reason.message}`, ); failureCount++; } diff --git a/plugins/notifications/report-alpha.api.md b/plugins/notifications/report-alpha.api.md index bec9d5ae13..713d4c3998 100644 --- a/plugins/notifications/report-alpha.api.md +++ b/plugins/notifications/report-alpha.api.md @@ -8,8 +8,8 @@ import { AnyRouteRefParams } from '@backstage/frontend-plugin-api'; import { ApiFactory } from '@backstage/frontend-plugin-api'; import { ExtensionBlueprintParams } from '@backstage/frontend-plugin-api'; import { ExtensionDataRef } from '@backstage/frontend-plugin-api'; -import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; import { JSX as JSX_2 } from 'react'; +import { OverridableExtensionDefinition } from '@backstage/frontend-plugin-api'; import { OverridableFrontendPlugin } from '@backstage/frontend-plugin-api'; import { RouteRef } from '@backstage/frontend-plugin-api'; @@ -20,7 +20,7 @@ const _default: OverridableFrontendPlugin< }, {}, { - 'api:notifications': ExtensionDefinition<{ + 'api:notifications': OverridableExtensionDefinition<{ kind: 'api'; name: undefined; config: {}; @@ -35,7 +35,7 @@ const _default: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'page:notifications': ExtensionDefinition<{ + 'page:notifications': OverridableExtensionDefinition<{ kind: 'page'; name: undefined; config: { diff --git a/plugins/org/report-alpha.api.md b/plugins/org/report-alpha.api.md index 8cefd7dd11..3e113868a6 100644 --- a/plugins/org/report-alpha.api.md +++ b/plugins/org/report-alpha.api.md @@ -7,10 +7,10 @@ import { Entity } from '@backstage/catalog-model'; import { EntityCardType } from '@backstage/plugin-catalog-react/alpha'; import { EntityPredicate } from '@backstage/plugin-catalog-react/alpha'; import { ExtensionDataRef } from '@backstage/frontend-plugin-api'; -import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; import { ExtensionInput } from '@backstage/frontend-plugin-api'; import { ExternalRouteRef } from '@backstage/frontend-plugin-api'; import { JSX as JSX_2 } from 'react'; +import { OverridableExtensionDefinition } from '@backstage/frontend-plugin-api'; import { OverridableFrontendPlugin } from '@backstage/frontend-plugin-api'; import { TranslationRef } from '@backstage/frontend-plugin-api'; @@ -21,7 +21,7 @@ const _default: OverridableFrontendPlugin< catalogIndex: ExternalRouteRef; }, { - 'entity-card:org/group-profile': ExtensionDefinition<{ + 'entity-card:org/group-profile': OverridableExtensionDefinition<{ kind: 'entity-card'; name: 'group-profile'; config: { @@ -62,7 +62,7 @@ const _default: OverridableFrontendPlugin< type?: EntityCardType; }; }>; - 'entity-card:org/members-list': ExtensionDefinition<{ + 'entity-card:org/members-list': OverridableExtensionDefinition<{ config: { initialRelationAggregation: 'direct' | 'aggregated' | undefined; showAggregateMembersToggle: boolean | undefined; @@ -117,7 +117,7 @@ const _default: OverridableFrontendPlugin< type?: EntityCardType; }; }>; - 'entity-card:org/ownership': ExtensionDefinition<{ + 'entity-card:org/ownership': OverridableExtensionDefinition<{ config: { initialRelationAggregation: 'direct' | 'aggregated' | undefined; showAggregateMembersToggle: boolean | undefined; @@ -172,7 +172,7 @@ const _default: OverridableFrontendPlugin< type?: EntityCardType; }; }>; - 'entity-card:org/user-profile': ExtensionDefinition<{ + 'entity-card:org/user-profile': OverridableExtensionDefinition<{ config: { maxRelations: number | undefined; hideIcons: boolean; diff --git a/plugins/scaffolder-react/report-alpha.api.md b/plugins/scaffolder-react/report-alpha.api.md index 6f81cd8a32..7497902e5b 100644 --- a/plugins/scaffolder-react/report-alpha.api.md +++ b/plugins/scaffolder-react/report-alpha.api.md @@ -15,7 +15,6 @@ import { Dispatch } from 'react'; import { ExtensionBlueprint } from '@backstage/frontend-plugin-api'; import { ExtensionBlueprintParams } from '@backstage/frontend-plugin-api'; import { ExtensionDataRef } from '@backstage/frontend-plugin-api'; -import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; import { ExtensionInput } from '@backstage/frontend-plugin-api'; import { FieldExtensionComponentProps } from '@backstage/plugin-scaffolder-react'; import { FieldExtensionOptions } from '@backstage/plugin-scaffolder-react'; @@ -27,6 +26,7 @@ import { JsonObject } from '@backstage/types'; import { JsonValue } from '@backstage/types'; import { JSX as JSX_2 } from 'react/jsx-runtime'; import { LayoutOptions } from '@backstage/plugin-scaffolder-react'; +import { OverridableExtensionDefinition } from '@backstage/frontend-plugin-api'; import { Overrides } from '@material-ui/core/styles/overrides'; import { PropsWithChildren } from 'react'; import { ReactElement } from 'react'; @@ -205,7 +205,7 @@ export type FormFieldExtensionData< }; // @alpha (undocumented) -export const formFieldsApi: ExtensionDefinition<{ +export const formFieldsApi: OverridableExtensionDefinition<{ config: {}; configInput: {}; output: ExtensionDataRef; diff --git a/plugins/scaffolder/report-alpha.api.md b/plugins/scaffolder/report-alpha.api.md index a5dd2a22d1..b6c5af9f17 100644 --- a/plugins/scaffolder/report-alpha.api.md +++ b/plugins/scaffolder/report-alpha.api.md @@ -13,7 +13,6 @@ import { Entity } from '@backstage/catalog-model'; import { EntityPredicate } from '@backstage/plugin-catalog-react/alpha'; import { ExtensionBlueprintParams } from '@backstage/frontend-plugin-api'; import { ExtensionDataRef } from '@backstage/frontend-plugin-api'; -import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; import { ExtensionInput } from '@backstage/frontend-plugin-api'; import { ExternalRouteRef } from '@backstage/frontend-plugin-api'; import { FieldExtensionOptions } from '@backstage/plugin-scaffolder-react'; @@ -25,6 +24,7 @@ import { IconComponent } from '@backstage/core-plugin-api'; import { IconLinkVerticalProps } from '@backstage/core-components'; import { JSX as JSX_2 } from 'react'; import { LayoutOptions } from '@backstage/plugin-scaffolder-react'; +import { OverridableExtensionDefinition } from '@backstage/frontend-plugin-api'; import { OverridableFrontendPlugin } from '@backstage/frontend-plugin-api'; import { PathParams } from '@backstage/core-plugin-api'; import { ReviewStepProps } from '@backstage/plugin-scaffolder-react'; @@ -58,7 +58,7 @@ const _default: OverridableFrontendPlugin< }>; }, { - 'api:scaffolder': ExtensionDefinition<{ + 'api:scaffolder': OverridableExtensionDefinition<{ kind: 'api'; name: undefined; config: {}; @@ -73,7 +73,7 @@ const _default: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'api:scaffolder/form-decorators': ExtensionDefinition<{ + 'api:scaffolder/form-decorators': OverridableExtensionDefinition<{ config: {}; configInput: {}; output: ExtensionDataRef; @@ -100,7 +100,7 @@ const _default: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'api:scaffolder/form-fields': ExtensionDefinition<{ + 'api:scaffolder/form-fields': OverridableExtensionDefinition<{ config: {}; configInput: {}; output: ExtensionDataRef; @@ -127,7 +127,7 @@ const _default: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'entity-icon-link:scaffolder/launch-template': ExtensionDefinition<{ + 'entity-icon-link:scaffolder/launch-template': OverridableExtensionDefinition<{ kind: 'entity-icon-link'; name: 'launch-template'; config: { @@ -166,7 +166,7 @@ const _default: OverridableFrontendPlugin< filter?: EntityPredicate | ((entity: Entity) => boolean); }; }>; - 'nav-item:scaffolder': ExtensionDefinition<{ + 'nav-item:scaffolder': OverridableExtensionDefinition<{ kind: 'nav-item'; name: undefined; config: {}; @@ -187,7 +187,7 @@ const _default: OverridableFrontendPlugin< routeRef: RouteRef; }; }>; - 'page:scaffolder': ExtensionDefinition<{ + 'page:scaffolder': OverridableExtensionDefinition<{ config: { path: string | undefined; }; @@ -226,7 +226,7 @@ const _default: OverridableFrontendPlugin< routeRef?: RouteRef; }; }>; - 'scaffolder-form-field:scaffolder/entity-name-picker': ExtensionDefinition<{ + 'scaffolder-form-field:scaffolder/entity-name-picker': OverridableExtensionDefinition<{ kind: 'scaffolder-form-field'; name: 'entity-name-picker'; config: {}; @@ -241,7 +241,7 @@ const _default: OverridableFrontendPlugin< field: () => Promise; }; }>; - 'scaffolder-form-field:scaffolder/entity-picker': ExtensionDefinition<{ + 'scaffolder-form-field:scaffolder/entity-picker': OverridableExtensionDefinition<{ kind: 'scaffolder-form-field'; name: 'entity-picker'; config: {}; @@ -256,7 +256,7 @@ const _default: OverridableFrontendPlugin< field: () => Promise; }; }>; - 'scaffolder-form-field:scaffolder/entity-tags-picker': ExtensionDefinition<{ + 'scaffolder-form-field:scaffolder/entity-tags-picker': OverridableExtensionDefinition<{ kind: 'scaffolder-form-field'; name: 'entity-tags-picker'; config: {}; @@ -271,7 +271,7 @@ const _default: OverridableFrontendPlugin< field: () => Promise; }; }>; - 'scaffolder-form-field:scaffolder/multi-entity-picker': ExtensionDefinition<{ + 'scaffolder-form-field:scaffolder/multi-entity-picker': OverridableExtensionDefinition<{ kind: 'scaffolder-form-field'; name: 'multi-entity-picker'; config: {}; @@ -286,7 +286,7 @@ const _default: OverridableFrontendPlugin< field: () => Promise; }; }>; - 'scaffolder-form-field:scaffolder/my-groups-picker': ExtensionDefinition<{ + 'scaffolder-form-field:scaffolder/my-groups-picker': OverridableExtensionDefinition<{ kind: 'scaffolder-form-field'; name: 'my-groups-picker'; config: {}; @@ -301,7 +301,7 @@ const _default: OverridableFrontendPlugin< field: () => Promise; }; }>; - 'scaffolder-form-field:scaffolder/owned-entity-picker': ExtensionDefinition<{ + 'scaffolder-form-field:scaffolder/owned-entity-picker': OverridableExtensionDefinition<{ kind: 'scaffolder-form-field'; name: 'owned-entity-picker'; config: {}; @@ -316,7 +316,7 @@ const _default: OverridableFrontendPlugin< field: () => Promise; }; }>; - 'scaffolder-form-field:scaffolder/owner-picker': ExtensionDefinition<{ + 'scaffolder-form-field:scaffolder/owner-picker': OverridableExtensionDefinition<{ kind: 'scaffolder-form-field'; name: 'owner-picker'; config: {}; @@ -331,7 +331,7 @@ const _default: OverridableFrontendPlugin< field: () => Promise; }; }>; - 'scaffolder-form-field:scaffolder/repo-branch-picker': ExtensionDefinition<{ + 'scaffolder-form-field:scaffolder/repo-branch-picker': OverridableExtensionDefinition<{ kind: 'scaffolder-form-field'; name: 'repo-branch-picker'; config: {}; @@ -346,7 +346,7 @@ const _default: OverridableFrontendPlugin< field: () => Promise; }; }>; - 'scaffolder-form-field:scaffolder/repo-url-picker': ExtensionDefinition<{ + 'scaffolder-form-field:scaffolder/repo-url-picker': OverridableExtensionDefinition<{ kind: 'scaffolder-form-field'; name: 'repo-url-picker'; config: {}; @@ -378,7 +378,7 @@ export class DefaultScaffolderFormDecoratorsApi } // @alpha (undocumented) -export const formDecoratorsApi: ExtensionDefinition<{ +export const formDecoratorsApi: OverridableExtensionDefinition<{ config: {}; configInput: {}; output: ExtensionDataRef; diff --git a/plugins/search/report-alpha.api.md b/plugins/search/report-alpha.api.md index 9a385c6fae..5ac036ca68 100644 --- a/plugins/search/report-alpha.api.md +++ b/plugins/search/report-alpha.api.md @@ -9,10 +9,10 @@ import { ApiFactory } from '@backstage/core-plugin-api'; import { ConfigurableExtensionDataRef } from '@backstage/frontend-plugin-api'; import { ExtensionBlueprintParams } from '@backstage/frontend-plugin-api'; import { ExtensionDataRef } from '@backstage/frontend-plugin-api'; -import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; import { ExtensionInput } from '@backstage/frontend-plugin-api'; import { IconComponent } from '@backstage/core-plugin-api'; import { JSX as JSX_2 } from 'react'; +import { OverridableExtensionDefinition } from '@backstage/frontend-plugin-api'; import { OverridableFrontendPlugin } from '@backstage/frontend-plugin-api'; import { RouteRef } from '@backstage/frontend-plugin-api'; import { SearchFilterExtensionComponent } from '@backstage/plugin-search-react/alpha'; @@ -27,7 +27,7 @@ const _default: OverridableFrontendPlugin< }, {}, { - 'api:search': ExtensionDefinition<{ + 'api:search': OverridableExtensionDefinition<{ kind: 'api'; name: undefined; config: {}; @@ -42,7 +42,7 @@ const _default: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'nav-item:search': ExtensionDefinition<{ + 'nav-item:search': OverridableExtensionDefinition<{ kind: 'nav-item'; name: undefined; config: {}; @@ -63,7 +63,7 @@ const _default: OverridableFrontendPlugin< routeRef: RouteRef; }; }>; - 'page:search': ExtensionDefinition<{ + 'page:search': OverridableExtensionDefinition<{ config: { noTrack: boolean; } & { @@ -143,7 +143,7 @@ const _default: OverridableFrontendPlugin< export default _default; // @alpha (undocumented) -export const searchApi: ExtensionDefinition<{ +export const searchApi: OverridableExtensionDefinition<{ kind: 'api'; name: undefined; config: {}; @@ -160,7 +160,7 @@ export const searchApi: ExtensionDefinition<{ }>; // @alpha (undocumented) -export const searchNavItem: ExtensionDefinition<{ +export const searchNavItem: OverridableExtensionDefinition<{ kind: 'nav-item'; name: undefined; config: {}; @@ -183,7 +183,7 @@ export const searchNavItem: ExtensionDefinition<{ }>; // @alpha (undocumented) -export const searchPage: ExtensionDefinition<{ +export const searchPage: OverridableExtensionDefinition<{ config: { noTrack: boolean; } & { diff --git a/plugins/signals/report-alpha.api.md b/plugins/signals/report-alpha.api.md index 91bd2b6726..b1cae370ed 100644 --- a/plugins/signals/report-alpha.api.md +++ b/plugins/signals/report-alpha.api.md @@ -7,7 +7,7 @@ import { AnyApiFactory } from '@backstage/frontend-plugin-api'; import { ApiFactory } from '@backstage/frontend-plugin-api'; import { ExtensionBlueprintParams } from '@backstage/frontend-plugin-api'; import { ExtensionDataRef } from '@backstage/frontend-plugin-api'; -import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; +import { OverridableExtensionDefinition } from '@backstage/frontend-plugin-api'; import { OverridableFrontendPlugin } from '@backstage/frontend-plugin-api'; // @alpha (undocumented) @@ -15,7 +15,7 @@ const _default: OverridableFrontendPlugin< {}, {}, { - 'api:signals': ExtensionDefinition<{ + 'api:signals': OverridableExtensionDefinition<{ kind: 'api'; name: undefined; config: {}; diff --git a/plugins/techdocs/report-alpha.api.md b/plugins/techdocs/report-alpha.api.md index 076b2c0cfe..8a17625ac2 100644 --- a/plugins/techdocs/report-alpha.api.md +++ b/plugins/techdocs/report-alpha.api.md @@ -12,11 +12,11 @@ import { Entity } from '@backstage/catalog-model'; import { EntityPredicate } from '@backstage/plugin-catalog-react/alpha'; import { ExtensionBlueprintParams } from '@backstage/frontend-plugin-api'; import { ExtensionDataRef } from '@backstage/frontend-plugin-api'; -import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; import { ExtensionInput } from '@backstage/frontend-plugin-api'; import { IconComponent } from '@backstage/core-plugin-api'; import { IconLinkVerticalProps } from '@backstage/core-components'; import { JSX as JSX_2 } from 'react'; +import { OverridableExtensionDefinition } from '@backstage/frontend-plugin-api'; import { OverridableFrontendPlugin } from '@backstage/frontend-plugin-api'; import { RouteRef } from '@backstage/frontend-plugin-api'; import { SearchResultItemExtensionComponent } from '@backstage/plugin-search-react/alpha'; @@ -37,7 +37,7 @@ const _default: OverridableFrontendPlugin< }, {}, { - 'api:techdocs': ExtensionDefinition<{ + 'api:techdocs': OverridableExtensionDefinition<{ kind: 'api'; name: undefined; config: {}; @@ -52,7 +52,7 @@ const _default: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'api:techdocs/storage': ExtensionDefinition<{ + 'api:techdocs/storage': OverridableExtensionDefinition<{ kind: 'api'; name: 'storage'; config: {}; @@ -67,7 +67,7 @@ const _default: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'empty-state:techdocs/entity-content': ExtensionDefinition<{ + 'empty-state:techdocs/entity-content': OverridableExtensionDefinition<{ config: {}; configInput: {}; output: ExtensionDataRef< @@ -90,7 +90,7 @@ const _default: OverridableFrontendPlugin< kind: 'empty-state'; name: 'entity-content'; }>; - 'entity-content:techdocs': ExtensionDefinition<{ + 'entity-content:techdocs': OverridableExtensionDefinition<{ config: { path: string | undefined; title: string | undefined; @@ -175,7 +175,7 @@ const _default: OverridableFrontendPlugin< filter?: string | EntityPredicate | ((entity: Entity) => boolean); }; }>; - 'entity-icon-link:techdocs/read-docs': ExtensionDefinition<{ + 'entity-icon-link:techdocs/read-docs': OverridableExtensionDefinition<{ kind: 'entity-icon-link'; name: 'read-docs'; config: { @@ -214,7 +214,7 @@ const _default: OverridableFrontendPlugin< filter?: EntityPredicate | ((entity: Entity) => boolean); }; }>; - 'nav-item:techdocs': ExtensionDefinition<{ + 'nav-item:techdocs': OverridableExtensionDefinition<{ kind: 'nav-item'; name: undefined; config: {}; @@ -235,7 +235,7 @@ const _default: OverridableFrontendPlugin< routeRef: RouteRef; }; }>; - 'page:techdocs': ExtensionDefinition<{ + 'page:techdocs': OverridableExtensionDefinition<{ kind: 'page'; name: undefined; config: { @@ -262,7 +262,7 @@ const _default: OverridableFrontendPlugin< routeRef?: RouteRef; }; }>; - 'page:techdocs/reader': ExtensionDefinition<{ + 'page:techdocs/reader': OverridableExtensionDefinition<{ config: { path: string | undefined; }; @@ -301,7 +301,7 @@ const _default: OverridableFrontendPlugin< routeRef?: RouteRef; }; }>; - 'search-result-list-item:techdocs': ExtensionDefinition<{ + 'search-result-list-item:techdocs': OverridableExtensionDefinition<{ config: { title: string | undefined; lineClamp: number; @@ -345,7 +345,7 @@ const _default: OverridableFrontendPlugin< export default _default; // @alpha (undocumented) -export const techDocsSearchResultListItemExtension: ExtensionDefinition<{ +export const techDocsSearchResultListItemExtension: OverridableExtensionDefinition<{ config: { title: string | undefined; lineClamp: number; diff --git a/plugins/user-settings/report-alpha.api.md b/plugins/user-settings/report-alpha.api.md index 1c8e844d05..a900e5600c 100644 --- a/plugins/user-settings/report-alpha.api.md +++ b/plugins/user-settings/report-alpha.api.md @@ -6,10 +6,10 @@ import { AnyRouteRefParams } from '@backstage/frontend-plugin-api'; import { ConfigurableExtensionDataRef } from '@backstage/frontend-plugin-api'; import { ExtensionDataRef } from '@backstage/frontend-plugin-api'; -import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; import { ExtensionInput } from '@backstage/frontend-plugin-api'; import { IconComponent } from '@backstage/core-plugin-api'; import { JSX as JSX_2 } from 'react'; +import { OverridableExtensionDefinition } from '@backstage/frontend-plugin-api'; import { OverridableFrontendPlugin } from '@backstage/frontend-plugin-api'; import { RouteRef } from '@backstage/frontend-plugin-api'; import { TranslationRef } from '@backstage/core-plugin-api/alpha'; @@ -21,7 +21,7 @@ const _default: OverridableFrontendPlugin< }, {}, { - 'nav-item:user-settings': ExtensionDefinition<{ + 'nav-item:user-settings': OverridableExtensionDefinition<{ kind: 'nav-item'; name: undefined; config: {}; @@ -42,7 +42,7 @@ const _default: OverridableFrontendPlugin< routeRef: RouteRef; }; }>; - 'page:user-settings': ExtensionDefinition<{ + 'page:user-settings': OverridableExtensionDefinition<{ config: { path: string | undefined; }; @@ -82,7 +82,7 @@ const _default: OverridableFrontendPlugin< export default _default; // @alpha (undocumented) -export const settingsNavItem: ExtensionDefinition<{ +export const settingsNavItem: OverridableExtensionDefinition<{ kind: 'nav-item'; name: undefined; config: {}; diff --git a/yarn.lock b/yarn.lock index 6fef5116f5..ebd5079f62 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5253,6 +5253,7 @@ __metadata: "@backstage/plugin-catalog": "workspace:^" "@backstage/plugin-catalog-common": "workspace:^" "@backstage/plugin-catalog-react": "workspace:^" + "@backstage/plugin-permission-react": "workspace:^" "@backstage/test-utils": "workspace:^" "@material-ui/core": "npm:^4.12.2" "@material-ui/icons": "npm:^4.9.1" @@ -8355,11 +8356,11 @@ __metadata: linkType: hard "@dagrejs/dagre@npm:^1.1.4": - version: 1.1.5 - resolution: "@dagrejs/dagre@npm:1.1.5" + version: 1.1.8 + resolution: "@dagrejs/dagre@npm:1.1.8" dependencies: "@dagrejs/graphlib": "npm:2.2.4" - checksum: 10/c00abd1e04d19f90ad8dfa0a4e16365371bc4309affead3827a1b39f6b0b946643b8af0b1e5519011deca3fda4c7471b27e9ebb03423309a94f95ac0b881ac4f + checksum: 10/648f60b8d6c05ec3367d1c7a4f2da32b7c26273e40234ce37bace606cd1e4f882ef7947452a0f0df4b34f1bbbc9f3cbae29f0f6af19fbffb8bc9f5e9b97fc3e8 languageName: node linkType: hard @@ -11190,10 +11191,10 @@ __metadata: languageName: node linkType: hard -"@module-federation/error-codes@npm:0.21.2": - version: 0.21.2 - resolution: "@module-federation/error-codes@npm:0.21.2" - checksum: 10/04b6a80a6c1b6aa4d5e4396f0c02d46af8bf8c11bec55d4e409854a8f22e40599f2e1fa9ad9f93081893e48679af3850ecd42d05776c06b5cd8516aaefc0aded +"@module-federation/error-codes@npm:0.21.4": + version: 0.21.4 + resolution: "@module-federation/error-codes@npm:0.21.4" + checksum: 10/18b0ecdba0de4cd5b202f1f5e5aa76273de0e4513ba91b8e39a2a5b00ff6471f694c88d591624b0913a0c3b4c9a6112da29dc7eebbdc562e5455b591f1d70b31 languageName: node linkType: hard @@ -11261,13 +11262,13 @@ __metadata: languageName: node linkType: hard -"@module-federation/runtime-core@npm:0.21.2": - version: 0.21.2 - resolution: "@module-federation/runtime-core@npm:0.21.2" +"@module-federation/runtime-core@npm:0.21.4": + version: 0.21.4 + resolution: "@module-federation/runtime-core@npm:0.21.4" dependencies: - "@module-federation/error-codes": "npm:0.21.2" - "@module-federation/sdk": "npm:0.21.2" - checksum: 10/8bbd20aa7b6a40fcb7d0083cc169657fa18618372bd01c204e01f13acb4b9765c409e4c22100b5891201ddae2c6a5e2aab86cbc3e00f4411d32c7b9c6faec0cd + "@module-federation/error-codes": "npm:0.21.4" + "@module-federation/sdk": "npm:0.21.4" + checksum: 10/b90fe4147cd3302ea6b02098ff2bed7437425609ba0eb4d7b649b3643837810239f06f532af092a53f9b47e8fae1aeef84cfd964431fa4ab2fd4a800ad796d23 languageName: node linkType: hard @@ -11281,13 +11282,13 @@ __metadata: languageName: node linkType: hard -"@module-federation/runtime-tools@npm:0.21.2": - version: 0.21.2 - resolution: "@module-federation/runtime-tools@npm:0.21.2" +"@module-federation/runtime-tools@npm:0.21.4": + version: 0.21.4 + resolution: "@module-federation/runtime-tools@npm:0.21.4" dependencies: - "@module-federation/runtime": "npm:0.21.2" - "@module-federation/webpack-bundler-runtime": "npm:0.21.2" - checksum: 10/81070ce02e0508568ce51075617799d5ffac178ae5ad618cb07a806800995af0395993683ec71ec90680b112eca359e39af5d5035dada8264b8cf5b3e6b3a3fc + "@module-federation/runtime": "npm:0.21.4" + "@module-federation/webpack-bundler-runtime": "npm:0.21.4" + checksum: 10/1e453268122070e5512c1d74cb8b4efb87cd2c1b46daba1736dfee16b2e8332a779f8168dcb3f84e17eade31f965168df63dae487ccfb74b0469c32af1895675 languageName: node linkType: hard @@ -11301,14 +11302,14 @@ __metadata: languageName: node linkType: hard -"@module-federation/runtime@npm:0.21.2": - version: 0.21.2 - resolution: "@module-federation/runtime@npm:0.21.2" +"@module-federation/runtime@npm:0.21.4": + version: 0.21.4 + resolution: "@module-federation/runtime@npm:0.21.4" dependencies: - "@module-federation/error-codes": "npm:0.21.2" - "@module-federation/runtime-core": "npm:0.21.2" - "@module-federation/sdk": "npm:0.21.2" - checksum: 10/acec411a4b354001d2c8beb12ff8d8d857ec9251b21158f3ba78ba7e24999a85a30d290cab9f5f6cd9876347b2878bc291d69a756cd1d104f1067186f4a0ad91 + "@module-federation/error-codes": "npm:0.21.4" + "@module-federation/runtime-core": "npm:0.21.4" + "@module-federation/sdk": "npm:0.21.4" + checksum: 10/ae262bfe1643a381e571d7dff459108da3046eea04cc3dae85dce745dd294ef8a30f70098ffa602c266b8c5878c859dd2fcde787773303dac35f77fa6ed32ae4 languageName: node linkType: hard @@ -11323,10 +11324,10 @@ __metadata: languageName: node linkType: hard -"@module-federation/sdk@npm:0.21.2": - version: 0.21.2 - resolution: "@module-federation/sdk@npm:0.21.2" - checksum: 10/e71a85bc4daf16cbe065c4ee8c36d6652b0d9a2cd5cc4fc53494f1c7f1111a67a08c4817e5738a7e4f66b7f60769abceb955c23bf94eb3205d2646002852b10f +"@module-federation/sdk@npm:0.21.4": + version: 0.21.4 + resolution: "@module-federation/sdk@npm:0.21.4" + checksum: 10/74c9ee2a057babf4f2638f8644a6eee6bd2c76441440dcc3855fb01a0e527e88518b8cc9c2d6d8f6b28858e34e40a3a966c03bb5d42897b9ea9163985edfa159 languageName: node linkType: hard @@ -11348,13 +11349,13 @@ __metadata: languageName: node linkType: hard -"@module-federation/webpack-bundler-runtime@npm:0.21.2": - version: 0.21.2 - resolution: "@module-federation/webpack-bundler-runtime@npm:0.21.2" +"@module-federation/webpack-bundler-runtime@npm:0.21.4": + version: 0.21.4 + resolution: "@module-federation/webpack-bundler-runtime@npm:0.21.4" dependencies: - "@module-federation/runtime": "npm:0.21.2" - "@module-federation/sdk": "npm:0.21.2" - checksum: 10/ac99d3ad623d52640cf776dbd4dd1382368926e19607f0fdc204b61b645a0bf9bde7f9fabd64edc83e04079fb4b3abff7c1feec80ecd36caa6a1d9d1824271c6 + "@module-federation/runtime": "npm:0.21.4" + "@module-federation/sdk": "npm:0.21.4" + checksum: 10/a4f2a7ca7765651023af88f38ded9580b553cd8c6a88bc9056ec4dc58656a3d438f0498750462f424bf3aeaa5a3c7b6fd8189b7c7c76d084736474455838cb55 languageName: node linkType: hard @@ -16633,11 +16634,11 @@ __metadata: linkType: hard "@remixicon/react@npm:^4.6.0": - version: 4.6.0 - resolution: "@remixicon/react@npm:4.6.0" + version: 4.7.0 + resolution: "@remixicon/react@npm:4.7.0" peerDependencies: react: ">=18.2.0" - checksum: 10/d92c8131734062fca8d82d55dd8f3f4e28cb72c5eefda528c8aba5f3298f0c847342eecdbd7787d6da5af21b699d735f6cf27f151f0c982c1c9f06a78b235c94 + checksum: 10/9ecee093dd4aec3744bcc7562eddb987bf9c7c059787dfecfbcc25a64c2f4833dc815dff715aa2a7f75011d65f877b3751a401d19cf2d725b5bcc685587d37f4 languageName: node linkType: hard @@ -16929,92 +16930,92 @@ __metadata: languageName: node linkType: hard -"@rspack/binding-darwin-arm64@npm:1.6.1": - version: 1.6.1 - resolution: "@rspack/binding-darwin-arm64@npm:1.6.1" +"@rspack/binding-darwin-arm64@npm:1.6.3": + version: 1.6.3 + resolution: "@rspack/binding-darwin-arm64@npm:1.6.3" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@rspack/binding-darwin-x64@npm:1.6.1": - version: 1.6.1 - resolution: "@rspack/binding-darwin-x64@npm:1.6.1" +"@rspack/binding-darwin-x64@npm:1.6.3": + version: 1.6.3 + resolution: "@rspack/binding-darwin-x64@npm:1.6.3" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@rspack/binding-linux-arm64-gnu@npm:1.6.1": - version: 1.6.1 - resolution: "@rspack/binding-linux-arm64-gnu@npm:1.6.1" +"@rspack/binding-linux-arm64-gnu@npm:1.6.3": + version: 1.6.3 + resolution: "@rspack/binding-linux-arm64-gnu@npm:1.6.3" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@rspack/binding-linux-arm64-musl@npm:1.6.1": - version: 1.6.1 - resolution: "@rspack/binding-linux-arm64-musl@npm:1.6.1" +"@rspack/binding-linux-arm64-musl@npm:1.6.3": + version: 1.6.3 + resolution: "@rspack/binding-linux-arm64-musl@npm:1.6.3" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@rspack/binding-linux-x64-gnu@npm:1.6.1": - version: 1.6.1 - resolution: "@rspack/binding-linux-x64-gnu@npm:1.6.1" +"@rspack/binding-linux-x64-gnu@npm:1.6.3": + version: 1.6.3 + resolution: "@rspack/binding-linux-x64-gnu@npm:1.6.3" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@rspack/binding-linux-x64-musl@npm:1.6.1": - version: 1.6.1 - resolution: "@rspack/binding-linux-x64-musl@npm:1.6.1" +"@rspack/binding-linux-x64-musl@npm:1.6.3": + version: 1.6.3 + resolution: "@rspack/binding-linux-x64-musl@npm:1.6.3" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@rspack/binding-wasm32-wasi@npm:1.6.1": - version: 1.6.1 - resolution: "@rspack/binding-wasm32-wasi@npm:1.6.1" +"@rspack/binding-wasm32-wasi@npm:1.6.3": + version: 1.6.3 + resolution: "@rspack/binding-wasm32-wasi@npm:1.6.3" dependencies: "@napi-rs/wasm-runtime": "npm:1.0.7" conditions: cpu=wasm32 languageName: node linkType: hard -"@rspack/binding-win32-arm64-msvc@npm:1.6.1": - version: 1.6.1 - resolution: "@rspack/binding-win32-arm64-msvc@npm:1.6.1" +"@rspack/binding-win32-arm64-msvc@npm:1.6.3": + version: 1.6.3 + resolution: "@rspack/binding-win32-arm64-msvc@npm:1.6.3" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@rspack/binding-win32-ia32-msvc@npm:1.6.1": - version: 1.6.1 - resolution: "@rspack/binding-win32-ia32-msvc@npm:1.6.1" +"@rspack/binding-win32-ia32-msvc@npm:1.6.3": + version: 1.6.3 + resolution: "@rspack/binding-win32-ia32-msvc@npm:1.6.3" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@rspack/binding-win32-x64-msvc@npm:1.6.1": - version: 1.6.1 - resolution: "@rspack/binding-win32-x64-msvc@npm:1.6.1" +"@rspack/binding-win32-x64-msvc@npm:1.6.3": + version: 1.6.3 + resolution: "@rspack/binding-win32-x64-msvc@npm:1.6.3" conditions: os=win32 & cpu=x64 languageName: node linkType: hard -"@rspack/binding@npm:1.6.1": - version: 1.6.1 - resolution: "@rspack/binding@npm:1.6.1" +"@rspack/binding@npm:1.6.3": + version: 1.6.3 + resolution: "@rspack/binding@npm:1.6.3" dependencies: - "@rspack/binding-darwin-arm64": "npm:1.6.1" - "@rspack/binding-darwin-x64": "npm:1.6.1" - "@rspack/binding-linux-arm64-gnu": "npm:1.6.1" - "@rspack/binding-linux-arm64-musl": "npm:1.6.1" - "@rspack/binding-linux-x64-gnu": "npm:1.6.1" - "@rspack/binding-linux-x64-musl": "npm:1.6.1" - "@rspack/binding-wasm32-wasi": "npm:1.6.1" - "@rspack/binding-win32-arm64-msvc": "npm:1.6.1" - "@rspack/binding-win32-ia32-msvc": "npm:1.6.1" - "@rspack/binding-win32-x64-msvc": "npm:1.6.1" + "@rspack/binding-darwin-arm64": "npm:1.6.3" + "@rspack/binding-darwin-x64": "npm:1.6.3" + "@rspack/binding-linux-arm64-gnu": "npm:1.6.3" + "@rspack/binding-linux-arm64-musl": "npm:1.6.3" + "@rspack/binding-linux-x64-gnu": "npm:1.6.3" + "@rspack/binding-linux-x64-musl": "npm:1.6.3" + "@rspack/binding-wasm32-wasi": "npm:1.6.3" + "@rspack/binding-win32-arm64-msvc": "npm:1.6.3" + "@rspack/binding-win32-ia32-msvc": "npm:1.6.3" + "@rspack/binding-win32-x64-msvc": "npm:1.6.3" dependenciesMeta: "@rspack/binding-darwin-arm64": optional: true @@ -17036,23 +17037,23 @@ __metadata: optional: true "@rspack/binding-win32-x64-msvc": optional: true - checksum: 10/374f234febba8305821f61645257278dd8fdf5961ca49b1605ea4535a8e40102db2afa96474464cec98bfa321bcb9beded78e7c1a9c130b1321a516a7c36ef7e + checksum: 10/c2ae95df065a3fc00fe81b8aef72dc1a4b80db274656e0c03db82fd12fba2d3a40514a741e0c0d3422d896d49eb34863d81b5c23d29df6d5f692e5b15a916510 languageName: node linkType: hard "@rspack/core@npm:^1.4.11": - version: 1.6.1 - resolution: "@rspack/core@npm:1.6.1" + version: 1.6.3 + resolution: "@rspack/core@npm:1.6.3" dependencies: - "@module-federation/runtime-tools": "npm:0.21.2" - "@rspack/binding": "npm:1.6.1" - "@rspack/lite-tapable": "npm:1.0.1" + "@module-federation/runtime-tools": "npm:0.21.4" + "@rspack/binding": "npm:1.6.3" + "@rspack/lite-tapable": "npm:1.1.0" peerDependencies: "@swc/helpers": ">=0.5.1" peerDependenciesMeta: "@swc/helpers": optional: true - checksum: 10/6ba8ffff547e0185b9ab397d13d19304130e08050a82ebbf11d86b6b557b6a3cff2adc2bfeb21a737801cfcc0ba9391f2efccd3149409f22a0218b87e6af0951 + checksum: 10/01bb10cf18331b2d6af841bc33bd15c1a01f01c5b16fd9b598e6b013ff138f91a9124c39f85530fd2a66dd693d0fa1252fc0331f0be9d7f2452c315c0a6e619a languageName: node linkType: hard @@ -17071,10 +17072,10 @@ __metadata: languageName: node linkType: hard -"@rspack/lite-tapable@npm:1.0.1, @rspack/lite-tapable@npm:^1.0.1": - version: 1.0.1 - resolution: "@rspack/lite-tapable@npm:1.0.1" - checksum: 10/240b7832965bca5a52d1f03a8539dab5810958ce24b5a670405b2505d81350f10d668f4055648f5918bc18ac033e637bcb7f92189345f0f2f671b546019c2f9e +"@rspack/lite-tapable@npm:1.1.0, @rspack/lite-tapable@npm:^1.0.1": + version: 1.1.0 + resolution: "@rspack/lite-tapable@npm:1.1.0" + checksum: 10/41ff73fe5e1b8dccaad746c9c1bd36dd67649e1ad35776f311b5ba94333a397704e11158579e25a6a7e677c51abe35e66987b1b000faef48d4e4ad2470fea150 languageName: node linkType: hard @@ -20456,11 +20457,12 @@ __metadata: linkType: hard "@types/compression@npm:^1.7.5": - version: 1.7.5 - resolution: "@types/compression@npm:1.7.5" + version: 1.8.1 + resolution: "@types/compression@npm:1.8.1" dependencies: "@types/express": "npm:*" - checksum: 10/9d65485bfb8e20035dedbbbebea06ea0c0554ac7bedb11ec3f2c6582cb082d121a10a03b4803b56315ae31705043eddf97eaf49c3dad6f9e39f7875b27c8feb4 + "@types/node": "npm:*" + checksum: 10/cd746c830a5c981568d36989c3c43a55caf1872b54e3f9891b82fba04501de11882091df3ece11fbede2de01179c99d08639a08831e06c3966873f928407c01a languageName: node linkType: hard @@ -21686,11 +21688,11 @@ __metadata: linkType: hard "@types/rollup-plugin-peer-deps-external@npm:^2.2.0": - version: 2.2.5 - resolution: "@types/rollup-plugin-peer-deps-external@npm:2.2.5" - dependencies: - rollup: "npm:^0.63.4" - checksum: 10/3f0d130fc15c80eac737391e180e77597da1200ff1f6d28a44f785a0de7f29144df805ab5b020ba38b243af6959e9da0757efa4141c4e737cd04eebe50f59c07 + version: 2.2.6 + resolution: "@types/rollup-plugin-peer-deps-external@npm:2.2.6" + peerDependencies: + rollup: "*" + checksum: 10/9fcee30d60d9d8de0f4bbf7694c254a18798b0ff415563a60fb2ed8c6c46423c64e1a977e0344b8393c26221dbd6e74d9e872c2694b518fcf149ba85d94e7eac languageName: node linkType: hard @@ -24169,9 +24171,9 @@ __metadata: linkType: hard "ansi-regex@npm:*, ansi-regex@npm:^6.0.1": - version: 6.1.0 - resolution: "ansi-regex@npm:6.1.0" - checksum: 10/495834a53b0856c02acd40446f7130cb0f8284f4a39afdab20d5dc42b2e198b1196119fe887beed8f9055c4ff2055e3b2f6d4641d0be018cdfb64fedf6fc1aac + version: 6.2.2 + resolution: "ansi-regex@npm:6.2.2" + checksum: 10/9b17ce2c6daecc75bcd5966b9ad672c23b184dc3ed9bf3c98a0702f0d2f736c15c10d461913568f2cf527a5e64291c7473358885dd493305c84a1cfed66ba94f languageName: node linkType: hard @@ -25216,13 +25218,13 @@ __metadata: linkType: hard "better-sqlite3@npm:^12.0.0": - version: 12.2.0 - resolution: "better-sqlite3@npm:12.2.0" + version: 12.4.1 + resolution: "better-sqlite3@npm:12.4.1" dependencies: bindings: "npm:^1.5.0" node-gyp: "npm:latest" prebuild-install: "npm:^7.1.1" - checksum: 10/2662e321237624d5813a7b97528dfc11fc5110b068d57f4096de82d7136e7e4a4b722a2a4266ddfb5095070712fd3d2542f6212ccb68e2d3eb2042498269e1cf + checksum: 10/e8133786677e88a2526c965658178e2e057e4b40ff554895a71ecb5e617e062fea619f31389ffbd6fc1f3396ef598812302be56c32e0f01fcb82610785d18186 languageName: node linkType: hard @@ -26876,17 +26878,17 @@ __metadata: linkType: hard "compression@npm:^1.7.4": - version: 1.7.5 - resolution: "compression@npm:1.7.5" + version: 1.8.1 + resolution: "compression@npm:1.8.1" dependencies: bytes: "npm:3.1.2" compressible: "npm:~2.0.18" debug: "npm:2.6.9" negotiator: "npm:~0.6.4" - on-headers: "npm:~1.0.2" + on-headers: "npm:~1.1.0" safe-buffer: "npm:5.2.1" vary: "npm:~1.1.2" - checksum: 10/c69cf6da151db6f9db2e242b6a0039ad41975ee886c385cff2920c5f8f7050678e0ee9a021437af033536c451791de529de376851b8d31fee42ca2d6adca03f0 + checksum: 10/e7552bfbd780f2003c6fe8decb44561f5cc6bc82f0c61e81122caff5ec656f37824084f52155b1e8ef31d7656cecbec9a2499b7a68e92e20780ffb39b479abb7 languageName: node linkType: hard @@ -27216,9 +27218,9 @@ __metadata: linkType: hard "core-js@npm:^3.6.5": - version: 3.39.0 - resolution: "core-js@npm:3.39.0" - checksum: 10/a3d34e669783dfc878e545f1983f60d9ff48a3867cd1d7ff8839b849e053002a208c7c14a5ca354b8e0b54982901e2f83dc87c3d9b95de0a94b4071d1c74e5f6 + version: 3.46.0 + resolution: "core-js@npm:3.46.0" + checksum: 10/82993ca487c6cbbf8bbf00e45eeb9705eb63dc2f9c90d7f35696733efbc3f4b52426e1f8dbef0f0b68ea16caa21e4f44cc5490e08120e1cad4a72b031ed8adaa languageName: node linkType: hard @@ -27421,12 +27423,12 @@ __metadata: linkType: hard "cron@npm:^3.0.0": - version: 3.3.2 - resolution: "cron@npm:3.3.2" + version: 3.5.0 + resolution: "cron@npm:3.5.0" dependencies: "@types/luxon": "npm:~3.4.0" luxon: "npm:~3.5.0" - checksum: 10/6be3309a2c56c75a90862987649e45d6ae17b45ef7949cc1ef3b5559665193efde2880c2729bf84ff4c9dc64a6e210d525e1e4f0a7ece4abe3acb9de2726386a + checksum: 10/0e667d87c9acc162db835439bff2664483f1fcbd471ae30a26c7426c736fa1798d27067cc4d0294d8a27890a1bc6c9deeefe47811cc339f11a8ba8288f51886d languageName: node linkType: hard @@ -40239,13 +40241,6 @@ __metadata: languageName: node linkType: hard -"on-headers@npm:~1.0.2": - version: 1.0.2 - resolution: "on-headers@npm:1.0.2" - checksum: 10/870766c16345855e2012e9422ba1ab110c7e44ad5891a67790f84610bd70a72b67fdd71baf497295f1d1bf38dd4c92248f825d48729c53c0eae5262fb69fa171 - languageName: node - linkType: hard - "on-headers@npm:~1.1.0": version: 1.1.0 resolution: "on-headers@npm:1.1.0" @@ -44789,18 +44784,6 @@ __metadata: languageName: node linkType: hard -"rollup@npm:^0.63.4": - version: 0.63.5 - resolution: "rollup@npm:0.63.5" - dependencies: - "@types/estree": "npm:0.0.39" - "@types/node": "npm:*" - bin: - rollup: ./bin/rollup - checksum: 10/c52ad022bb732ea0e962b3ec45779d9d0523f75283bded8d0c97788f97946781d617b971e7e732ad7a63af60aad76ca534c415d8b101c7ff7d3f5cc879aba025 - languageName: node - linkType: hard - "rollup@npm:^4.27.3, rollup@npm:^4.43.0": version: 4.46.2 resolution: "rollup@npm:4.46.2"